# API The server exposes two communication channels: a REST API for configuration queries and mutations, and a WebSocket endpoint for real-time agent execution with streaming responses. ## REST Endpoints All REST routes are prefixed with `/api`. The following table lists every endpoint registered in `server/src/routes/index.ts`. ### Agents | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/agents` | List all agents (excludes `app`, `workflow`, and `terminal` task types) | | `GET` | `/api/agent/:id` | Get a single agent spec by name/ID | ### Workflows | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/workflows` | List all workflows | | `GET` | `/api/workflow/:id` | Get a single workflow by name/ID | ### Backends | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/backends` | List all inference backends (e.g., `browser`, `openai`) | | `GET` | `/api/backend/:name` | Set the default backend by name | ### Tools | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | `/api/tools` | Get tool definitions for a list of tool names (accepts array of tool name strings in body) | ### Models | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/models/:backend` | List available models for a specific backend | | `GET` | `/api/models/presets/read` | List model sampling presets | | `POST` | `/api/models/preset/update` | Create or update a model preset | | `DELETE` | `/api/models/preset/delete/:name` | Delete a model preset by name | ### Agent Settings | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/agentsettings` | Get per-agent inference configuration | | `POST` | `/api/agentsettings/update` | Update agent settings (body: `{ name, settings }`) | ### Server State & Configuration | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/state` | Get current server state (returns 202 if no config found) | | `GET` | `/api/conf` | Get the current configuration | | `GET` | `/api/conf/create` | Create configuration file if it doesn't exist | ### Plugins & Folders | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | `/api/plugins/install` | Install npm plugins (body: array of package names) | | `POST` | `/api/folders/add` | Add feature search folders (body: array of folder paths) | ### App Config | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/app/:name/conf` | Get or create the app config file for a specific app | | `POST` | `/api/app/:name/update` | Update the app config file for a specific app | ### Workspace | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/workspace` | Get workspace info | | `POST` | `/api/workspace` | Create or update a workspace | | `POST` | `/api/workspace/update` | Set the default workspace (body: Workspace object) | ### Settings | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/api/settings` | Get application settings | ### Health Check | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/ping` | Server health check — returns `{ ok: true }` | ## WebSocket Endpoint Connect to `/ws` for real-time agent and workflow execution with streaming token output. ### Connection ``` ws://localhost:5184/ws ``` ### Client Message Format (`WsClientMsg`) Send JSON messages to the server: ```typescript interface WsClientMsg { command: string; // Agent or workflow name type: 'command' | 'system'; feature?: FeatureType; // 'agent' | 'workflow' payload?: any; // Prompt and execution context options?: Record; // Execution options (abort controller, variables, etc.) } ``` **Executing an agent:** ```typescript const msg: WsClientMsg = { type: "command", command: "my-agent", feature: "agent", payload: { prompt: "Write a poem" }, options: {} }; websocket.send(JSON.stringify(msg)); ``` **Executing a workflow:** ```typescript const msg: WsClientMsg = { type: "command", command: "my-workflow", feature: "workflow", payload: { input: "data" }, options: {} }; websocket.send(JSON.stringify(msg)); ``` **System commands:** ```typescript // Stop current execution const stopMsg: WsClientMsg = { type: "system", command: "stop" }; websocket.send(JSON.stringify(stopMsg)); // Confirm or reject a tool call const confirmMsg: WsClientMsg = { type: "system", command: "confirmtool", payload: { confirm: true, id: "tool-call-uuid" } }; websocket.send(JSON.stringify(confirmMsg)); ``` ### Server Message Types (`WsRawServerMsg`) The server streams JSON messages of type `WsRawServerMsg`: ```typescript interface WsRawServerMsg { type: string; from: string; msg: string; } ``` | Type | Description | |------|-------------| | `error` | Error message | | `startemit` | Inference started (includes processing stats) | | `token` | Generated token | | `thinkingtoken` | Thinking/reasoning token | | `turnstart` | New conversation turn began | | `turnend` | Turn completed (includes HistoryTurn) | | `assistant` | Assistant text output | | `think` | Model thinking content | | `thinkingstart` | Thinking block started | | `thinkingend` | Thinking block ended | | `toolcallinprogress` | Tool execution in progress | | `promptprocessingprogress` | Prompt processing stats | | `toolcalltoken` | Token from tool call | | `toolsturnstart` | Tools turn started | | `toolsturnend` | Tools turn ended | | `toolcall` | Tool call initiated | | `toolcallend` | Tool call completed | | `toolcallconfirm` | Awaiting tool confirmation from client | | `finalresult` | Final inference result | | `endemit` | Inference complete | ### Example: Full Agent Execution Flow ```typescript const ws = new WebSocket('ws://localhost:5184/ws'); ws.onmessage = (event) => { const msg = JSON.parse(event.data); switch (msg.type) { case 'token': process.stdout.write(msg.msg); break; case 'thinkingtoken': console.log(`\x1b[2m${msg.msg}\x1b[0m`); break; case 'toolcall': const payload = JSON.parse(msg.msg); console.log(`Tool call: ${payload.tc.name}`); break; case 'endemit': const result = JSON.parse(msg.msg); console.log('\nDone:', result); ws.close(); break; case 'error': console.error('Error:', msg.msg); ws.close(); break; } }; ws.onopen = () => { ws.send(JSON.stringify({ type: "command", command: "my-agent", feature: "agent", payload: { prompt: "Hello, world!" }, options: {} })); }; ``` Next: Client Usage