Search the documentation

Pick a page and open it with Enter.

Chat Stream

Answer as SSE — including thinking and tools.

POST/api/v1/chat/stream

Same request body as /chat, but the response is a text/event-stream. Only this way do thinking, tool calls, and the answer arrive live token by token — always use this endpoint for the chat UI.

Frame format

Each frame is a line data: {json}, separated by blank lines. Each JSON carries a type. The stream always ends with data: [DONE].

Frame types

reasoning{ delta }

Model is thinking (reasoning models only, comes first). Append delta, show it greyed out / collapsed.

content{ delta }

A chunk of the actual answer. Append delta and render as Markdown.

tool_call{ tool, call_id, arguments }

A tool is being called. arguments is an object for a readable line.

tool_result{ tool, call_id, ok, preview, length }

Result. ok=false = failure (red), preview = message. Link to the tool_call by call_id, not by order.

errorevent: error · { error: { code, message } }

Abort after the stream started — as its own event: error event.

Example stream

text
data: {"type":"reasoning","delta":"I should search first …"}

data: {"type":"tool_call","tool":"web_search","call_id":"call_01","arguments":{"query":"current SSE specification"}}

data: {"type":"tool_result","tool":"web_search","call_id":"call_01","ok":true,"preview":"1. WHATWG HTML Living Standard … 2. MDN …","length":1840}

data: {"type":"content","delta":"Server-Sent Events "}

data: {"type":"content","delta":"are a one-way channel …"}

data: [DONE]

Errors mid-stream

The HTTP status is already 200, so the error arrives as event: error with the same error object as everywhere else.

text
event: error
data: {"type":"error","error":{"code":"provider_timeout","message":"The upstream provider did not respond in time."}}

data: [DONE]