Exploring the Ohwise Backend API

April 16, 2025

Introduction

In the world of AI-powered platforms, Ohwise stands out by allowing users to build, configure, and orchestrate multiple AI agents—each with their own tasks and real-time interactions. The backend API is the core that powers agent CRUD operations, task management, and live chat features.

In this post, we’ll walk through:

  1. Key Concepts: Agents, Tasks, and WebSocketService
  2. RESTful Endpoints: How to create, read, update, and delete agents/tasks
  3. Real-Time Messaging: Using WebSocketService to enable live chat and agent-driven events
  4. Sample Workflow: Creating an agent, designing its graph, adding tasks, and testing via WebSocket

By the end, you’ll have a clear understanding of how to integrate with the Ohwise backend and build dynamic AI-driven applications.


1. Core Concepts

1.1 Agents

An Agent in Ohwise is a configurable AI entity that can:

  • Have metadata (name, description, publish status)
  • Contain a graph: a JSON representation of tasks (nodes) and directed edges (workflows)
  • Define answer_config: parameters controlling how it answers (e.g., LLM provider settings)

Example graph snippet:

{ "nodes": [ { "id": "n1", "label": "Greet User" }, { "id": "n2", "label": "Fetch Account Status" } ], "edges": [ { "from": "n1", "to": "n2" } ], "current_node_id": "n1" }

Use Cases:

  • A customer support bot that first greets the user, then checks their account status.
  • A tutoring agent that picks a topic, retrieves learning materials, and quizzes the student.

1.2 Tasks

A Task is a discrete piece of work within an agent’s graph. Each task includes:

  • task_name: e.g., “Greet User Task”
  • task_content: e.g., a prompt or script, “Hello, how can I assist you today?”
  • task_config: JSON specifying provider type (e.g., openai, mysql) and details (model name, parameters)

Example task_config:

{ "provider_type": "openai", "provider_details": { "model": "gpt-4", "parameters": { "max_tokens": 150 } } }

Tasks can:

  • Prompt an LLM for natural-language processing
  • Execute a SQL query to fetch data from a database
  • Call an external HTTP API

By combining tasks into a graph, you create a workflow where the output of one task can feed into the next.


1.3 WebSocketService

For real-time communication, Ohwise offers a WebSocketService class built on Socket.IO. Using this, your frontend can:

  • Join a chat group (room)
  • Send messages that optionally trigger agent execution (e.g., run current task, upstream tasks, downstream tasks, or the entire agent DAG)
  • Receive intermediate reasoning events or final answers from agents
  • Cleanly disconnect when leaving the chat

Key Methods:

  1. startWebSocket(agents, users, threadId, chatSource, handlers)

    • Connects to the server and joins a group.
    • Registers callbacks (onMessage, onReasoning, onAnswer, onError).
  2. sendMessage(user_id, message, runOption, taskId?)

    • Emits a send_message event with thread_id, group_id, user_id, message_id, content, runOption, taskId.
    • If runOption is provided, triggers agent execution on the backend.
  3. stopWebSocket()

    • Leaves the group and disconnects.

This setup is perfect for building chat interfaces where an agent’s tasks are orchestrated live based on user input—helpful for customer support, tutoring, multi-agent experiments, and more.


2. RESTful Endpoints

Let’s explore the main groups of endpoints: Agents (§2.1–§2.9) and Tasks (§3.1–§3.8).


2.1 Agents CRUD

2.1.1 Create an Agent (POST /api/agent)

Request:

POST /api/agent Authorization: Bearer <access_token> Content-Type: application/json { "agent_name": "Support Bot", "agent_description": "Bot to handle customer queries", "publish_status": "private" }

Response (201):

{ "success": true, "info": "agent created", "data": { "agent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "agent_name": "Support Bot", "agent_description": "Bot to handle customer queries", "publish_status": "private" } }

2.1.2 Get All Agents (GET /api/agent)

Request:

GET /api/agent Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "agent list", "data": [ { "agent_id": "123e4567-e89b-12d3-a456-426614174000", "agent_name": "Agent A", "agent_description": "Description here", "publish_status": "published", "answer_config": {} }, { "agent_id": "456e7890-e89b-12d3-a456-426614174000", "agent_name": "Agent B", "agent_description": "Another description", "publish_status": "private", "answer_config": {} } ] }

2.1.3 Get Single Agent (GET /api/agent/{agent_id})

Request:

GET /api/agent/f47ac10b-58cc-4372-a567-0e02b2c3d479 Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "single agent info", "data": { "agent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "agent_name": "Support Bot", "agent_description": "Bot to handle customer queries", "publish_status": "private", "answer_config": {} } }

2.1.4 Update Agent (PUT /api/agent/{agent_id})

Request:

PUT /api/agent/f47ac10b-58cc-4372-a567-0e02b2c3d479 Authorization: Bearer <access_token> Content-Type: application/json { "agent_name": "Support Bot v2", "agent_description": "Updated description", "publish_status": "published", "answer_config": { "model": { "parameters": { "balanced": { "top_p": 0.85, "max_tokens": 4096, "temperature": 0.7 } }, "provider_id": "Prompt", "provider_name": "Prompt", "tab_selection": "balanced", "selected_value": "Prompt" }, "provider_type": "model" } }

Response (200):

{ "success": true, "info": "agent updated successfully", "data": { "agent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "agent_name": "Support Bot v2", "agent_description": "Updated description", "publish_status": "published", "answer_config": { "model": { "parameters": { "balanced": { "top_p": 0.85, "max_tokens": 4096, "temperature": 0.7 } }, "provider_id": "Prompt", "provider_name": "Prompt", "tab_selection": "balanced", "selected_value": "Prompt" }, "provider_type": "model" } } }

2.1.5 Delete Agent (DELETE /api/agent/{agent_id})

Request:

DELETE /api/agent/f47ac10b-58cc-4372-a567-0e02b2c3d479 Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "agent deleted successfully", "data": { "agent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "agent_name": "Support Bot v2", "agent_description": "Updated description", "publish_status": "published", "answer_config": {} } }

2.1.6 Get Agent Design (GET /api/agent/{agent_id}/design)

Request:

GET /api/agent/f47ac10b-58cc-4372-a567-0e02b2c3d479/design Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "Agent design details", "data": { "agent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "agent_name": "Support Bot v2", "agent_description": "Updated description", "publish_status": "published", "graph": { "nodes": [ { "id": "n1", "label": "Greet User" }, { "id": "n2", "label": "Fetch Account Status" } ], "edges": [ { "from": "n1", "to": "n2" } ], "current_node_id": "n1" } } }

2.1.7 Update Agent Design (PUT /api/agent/{agent_id}/design)

Request:

PUT /api/agent/f47ac10b-58cc-4372-a567-0e02b2c3d479/design Authorization: Bearer <access_token> Content-Type: application/json { "graph": { "nodes": [ { "id": "n1", "label": "Greet User" }, { "id": "n2", "label": "Fetch Account Status" } ], "edges": [ { "from": "n1", "to": "n2" } ], "current_node_id": "n1" } }

Response (200):

{ "success": true, "info": "Agent design updated", "data": { "agent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "agent_name": "Support Bot v2", "agent_description": "Updated description", "publish_status": "published", "graph": { "nodes": [ { "id": "n1", "label": "Greet User" }, { "id": "n2", "label": "Fetch Account Status" } ], "edges": [ { "from": "n1", "to": "n2" } ], "current_node_id": "n1" } } }

2.2 Task CRUD

2.2.1 Create Task (POST /api/task/{task_id})

Request:

POST /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e Authorization: Bearer <access_token> Content-Type: application/json { "task_name": "Greet User Task", "task_config": { "provider_type": "openai", "provider_details": { "model": "gpt-4", "parameters": { "max_tokens": 150 } } }, "task_content": "Hello, how can I assist you today?" }

Response (201):

{ "success": true, "info": "Task created", "data": { "task_id": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e", "task_name": "Greet User Task", "task_config": { "provider_type": "openai", "provider_details": { "model": "gpt-4", "parameters": { "max_tokens": 150 } } }, "task_content": "Hello, how can I assist you today?" } }

2.2.2 Get Task Details (GET /api/task/{task_id})

Request:

GET /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "Task details", "data": { "task_id": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e", "task_name": "Greet User Task", "task_config": { "provider_type": "openai", "provider_details": { "model": "gpt-4", "parameters": { "max_tokens": 150 } } }, "task_content": "Hello, how can I assist you today?" } }

2.2.3 Update Task Name (PUT /api/task/{task_id}/name)

Request:

PUT /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e/name Authorization: Bearer <access_token> Content-Type: application/json { "task_name": "Welcome Task" }

Response (200):

{ "success": true, "info": "Task name updated", "data": { "task_id": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e", "task_name": "Welcome Task", "task_config": {}, "task_content": "Hello, how can I assist you today?" } }

2.2.4 Get Task Content (GET /api/task/{task_id}/content)

Request:

GET /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e/content Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "Task content details", "data": { "task_id": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e", "task_content": "Hello, how can I assist you today?" } }

2.2.5 Update Task Content (PUT /api/task/{task_id}/content)

Request:

PUT /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e/content Authorization: Bearer <access_token> Content-Type: application/json { "task_content": "Hi there! How can I help today?" }

Response (200):

{ "success": true, "info": "Task content updated", "data": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e" }

2.2.6 Get Task Config (GET /api/task/{task_id}/config)

Request:

GET /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e/config Authorization: Bearer <access_token>

Response (200):

{ "success": true, "info": "Task config details", "data": { "task_id": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e", "task_config": { "provider_type": "openai", "provider_details": { "model": "gpt-4", "parameters": { "max_tokens": 150 } } } } }

2.2.7 Update Task Config (PUT /api/task/{task_id}/config)

Request:

PUT /api/task/5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e/config Authorization: Bearer <access_token> Content-Type: application/json { "task_config": { "provider_type": "openai", "provider_details": { "model": "gpt-4o", "parameters": { "top_p": 0.9, "max_tokens": 200, "temperature": 0.2 } } } }

Response (200):

{ "success": true, "info": "Task config updated", "data": "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e" }

2.3 Task Error Responses

  • 404 Not Found: Requested task does not exist.
  • 500 Internal Server Error: Unexpected server error.

3. WebSocketService in Practice

Here’s how you can integrate real-time chat and agent actions:

  1. Initialize WebSocket Connection

    webSocketService.startWebSocket( ["f47ac10b-58cc-4372-a567-0e02b2c3d479"], // agent IDs ["user123", "user456"], // user IDs "threadABC", // thread ID 1, // chatSource = 1 (chat) { onMessage: (msg) => console.log("Received chat:", msg), onReasoning: (reason) => console.log("Agent reasoning:", reason), onAnswer: (ans) => console.log("Agent answer:", ans), onError: (err) => console.error("WebSocket error:", err), } );
  2. Send a Chat Message (Triggering Agent Execution)

    webSocketService.sendMessage( "user123", "What is the status of my order?", "current", // run only the current task "5e1f2a9c-3d4f-4a5d-b6e7-8f9a0b1c2d3e" // ID of "Fetch Account Status" task );
  3. Receive Intermediate Reasoning and Final Answer

    • onReasoning callback fires as the agent processes steps (e.g., fetching data).
    • onAnswer callback fires when the agent returns a final response.
  4. Stop WebSocket When Done

    webSocketService.stopWebSocket();

4. Putting It All Together: Sample Workflow

Imagine you want to build a “Customer Support Bot” that:

  1. Greets the user.
  2. Retrieves the user’s account status from a database.
  3. Returns a personalized message based on that status.

4.1 Step 1: Create the Agent

POST /api/agent Authorization: Bearer <access_token> Content-Type: application/json { "agent_name": "Customer Support Bot", "agent_description": "Handles user greetings and account lookups", "publish_status": "private" }

Response:

{ "success": true, "info": "agent created", "data": { "agent_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab", "agent_name": "Customer Support Bot", "agent_description": "Handles user greetings and account lookups", "publish_status": "private" } }

4.2 Step 2: Create Tasks

4.2.1 Greet User Task

POST /api/task/11111111-2222-3333-4444-555555555555 Authorization: Bearer <access_token> Content-Type: application/json { "task_name": "Greet User Task", "task_config": { "provider_type": "openai", "provider_details": { "model": "gpt-4", "parameters": { "max_tokens": 50 } } }, "task_content": "Hello {{user_name}}, welcome back! How can I assist you today?" }

Response:

{ "success": true, "info": "Task created", "data": { "task_id": "11111111-2222-3333-4444-555555555555", "task_name": "Greet User Task", "task_config": {}, "task_content": "Hello {{user_name}}, welcome back! How can I assist you today?" } }

4.2.2 Fetch Account Status Task

POST /api/task/66666666-7777-8888-9999-000000000000 Authorization: Bearer <access_token> Content-Type: application/json { "task_name": "Fetch Account Status Task", "task_config": { "provider_type": "postgresql", "provider_details": { "connection_string": "<DB_CONN_STRING>", "query": "SELECT status FROM accounts WHERE user_id = '{{user_id}}';" } }, "task_content": "" // Content not needed for a pure SQL task }

Response:

{ "success": true, "info": "Task created", "data": { "task_id": "66666666-7777-8888-9999-000000000000", "task_name": "Fetch Account Status Task", "task_config": { "provider_type": "postgresql", "provider_details": { "connection_string": "<DB_CONN_STRING>", "query": "SELECT status FROM accounts WHERE user_id = '{{user_id}}';" } }, "task_content": "" } }

4.3 Step 3: Design the Agent Graph

PUT /api/agent/a1b2c3d4-5678-90ab-cdef-1234567890ab/design Authorization: Bearer <access_token> Content-Type: application/json { "graph": { "nodes": [ { "id": "11111111-2222-3333-4444-555555555555", "label": "Greet User" }, { "id": "66666666-7777-8888-9999-000000000000", "label": "Fetch Account Status" } ], "edges": [ { "from": "11111111-2222-3333-4444-555555555555", "to": "66666666-7777-8888-9999-000000000000" } ], "current_node_id": "11111111-2222-3333-4444-555555555555" } }

Response:

{ "success": true, "info": "Agent design updated", "data": { "agent_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab", "agent_name": "Customer Support Bot", "agent_description": "Handles user greetings and account lookups", "publish_status": "private", "graph": { "nodes": [ { "id": "11111111-2222-3333-4444-555555555555", "label": "Greet User" }, { "id": "66666666-7777-8888-9999-000000000000", "label": "Fetch Account Status" } ], "edges": [ { "from": "11111111-2222-3333-4444-555555555555", "to": "66666666-7777-8888-9999-000000000000" } ], "current_node_id": "11111111-2222-3333-4444-555555555555" } } }

4.4 Step 4: Test via WebSocket

  1. Connect to WebSocket:

    webSocketService.startWebSocket( ["a1b2c3d4-5678-90ab-cdef-1234567890ab"], // agent ID ["user123"], // single user "thread1", // thread ID 1, // chatSource = 1 (chat) { onMessage: (msg) => console.log("Chat:", msg), onReasoning: (reason) => console.log("Reasoning:", reason), onAnswer: (ans) => console.log("Answer:", ans), onError: (err) => console.error("Error:", err), } );
  2. Send Message to Run Current Task:

    webSocketService.sendMessage( "user123", "Hello, I'm user123!", "current", "11111111-2222-3333-4444-555555555555" );
    • This triggers the “Greet User Task” first.
    • Once that completes, the backend sees the graph edge → “Fetch Account Status Task.”
    • Backend executes the SQL query with {{user_id}} = "user123".
    • Reasoning events might fire as partial results arrive, followed by a final answer with combined output (e.g., “Hello user123! Your account status is Active.”).
  3. Disconnect once done:

    webSocketService.stopWebSocket();

5. Conclusion

The Ohwise Backend API empowers developers to:

  • Manage AI Agents: Create, retrieve, update, and delete agents.
  • Design Workflows: Define directed graphs of tasks that represent complex multi-step processes.
  • Configure Tasks: Attach models, databases, or APIs to each task, customizing parameters, queries, or prompts.
  • Real-Time Interaction: Leverage WebSocketService to build chat interfaces where agents can reason step-by-step and return final answers.

With this API, you can rapidly build sophisticated AI-driven applications—customer support bots, tutoring systems, business intelligence agents, and more—while maintaining flexibility, scalability, and real-time capabilities.

Join the Discussion

Share your thoughts and insights about this project.