Dashboard and API

cos serve runs a web dashboard and a small JSON and WebSocket API on 127.0.0.1.

cos serve starts the dashboard at http://127.0.0.1:9120. Use it to chat with any profile, approve tool calls, stop running turns, browse sessions and see costs. Everything it does goes through the API below, so scripts can do the same.

Routes

Route Returns
GET / The dashboard page
GET /api/profiles Profiles with tags, provider, model, skills and effective tools
GET /api/sessions?profile=&limit= Sessions, newest first, without child sessions. limit defaults to 50, max 500.
GET /api/sessions/{id} One session’s messages, turns (including children) and tool calls with approvals
GET /api/plugins Names of the running plugins
GET /api/approvals Ids of approvals waiting for an answer
WS /api/ws Chat, approvals, stop and live events
Plugin routes For example CommonBill’s GET /api/costs

Errors come back as HTTP 500 with {"error": "…"}.

GET /api/profiles

Response
[
  {
    "id": "Household",
    "loaded": true,
    "provider": "mock",
    "model": "mock-1",
    "tags": ["area:household"],
    "skills": "",
    "tools": ["delegate_task", "memory", "session_search"],
    "created_at": "2026-10-27T00:50:42.568734Z"
  }
]

tools is what the agent really gets: the profile’s tools list, or every installed tool.

GET /api/sessions

Response
[
  {
    "id": "01a17ad6-8926-7622-a9a6-52f6cdc0808f",
    "profile_id": "Household",
    "source": "cli",
    "title": "hello there",
    "tags": [],
    "parent_session_id": null,
    "context_snapshot": "MEMORY (your notes) — 0% used, 0/2200 chars\n(empty)\n\nUSER (about the person) — 0% used, 0/1375 chars\n(empty)",
    "created_at": "2026-10-27T00:50:42.600115Z",
    "updated_at": "2026-10-27T00:50:43.124892Z"
  }
]

context_snapshot is the frozen context tier of the session’s prompt.

WebSocket

Connect to ws://127.0.0.1:9120/api/ws. Every message is JSON with a type.

Client to server

JSON
{ "type": "chat", "profile": "Household", "session_id": null, "text": "hello", "tags": ["project:kitchen"] }
{ "type": "approve", "id": "<approval id>", "approved": true }
{ "type": "stop", "session_id": "<session id>" }
Message Does
chat Sends a message. session_id: null starts a new session. tags is optional and applies to a new session.
approve Answers a pending approval
stop Cancels the running turn of a session

Server to client

Message When
{"type": "event", "kind", "turn", "payload", "at"} Live events as a turn runs. kind is the hook point: on_session_start, pre_api_request, post_api_request, api_request_error, post_tool_call, pre_approval_request, post_approval_response, subagent_start, subagent_stop, post_llm_call, agent_loop_stopped, on_session_end.
{"type": "reply", …} The turn finished. Carries profile_id, session_id, turn_id, status and text.
{"type": "error", "message"} Something failed, for example approval not pending

Approval requests arrive as events. Answer them with an approve message.

The dashboard design

The page follows Air + Glass, from the Project Silk palette: mostly Pearl and Frost with 1px lines, and glass over soft Mist shapes only where you talk to the agent, the chat panel and approval prompts. The Costs panel appears only when CommonBill is enabled.

Edit this page on GitHub

Esc