SSE Events
Server-Sent Events for streaming updates.
SSE (Server-Sent Events) are used for streaming AI responses and real-time updates from the server.
Chat Events
During a chat interaction, the system emits a stream of typed events.
Channel distinction: The server's
POST /chatSSE stream emitsChatChunkDTOobjects with types:text,tool_call,tool_result,error,done. The desktop app's IPC layer (chat:event) extends this with additional types (thinking,title-updated,tool_confirm) that are generated in the desktop main process — they are not part of the server SSE stream.
Server SSE Event Types (ChatChunkDTO)
| Type | Fields | Description |
|---|---|---|
text | text: string | A chunk of streaming text from the LLM. Append to the current response. |
tool_call | toolCall: { id, name, args, serverHandled? } | The LLM invoked a tool. |
tool_result | toolResult: { callId, result } | A tool call completed. |
error | error: string | Fatal error — stream ends. |
done | usage: { inputTokens, outputTokens } | Stream complete. |
Desktop IPC-only Event Types
These types exist only in the desktop chat:event IPC channel, not in the server SSE stream:
| Type | Fields | Description |
|---|---|---|
thinking | — | Processing heartbeat (desktop only). |
title-updated | title: string | Session title generated (desktop only). |
tool_confirm | confirmId, risk, explanation | Awaiting user tool approval (desktop only). |
contextUsage | (on done event) | Token usage appended by desktop to the done event. |
Server SSE Event Shape
interface ChatChunkDTO {
type: 'text' | 'tool_call' | 'tool_result' | 'error' | 'done'
text?: string
error?: string
toolCall?: { id: string; name: string; args: Record<string, unknown>; serverHandled?: boolean }
toolResult?: { callId: string; result: unknown }
usage?: { inputTokens: number; outputTokens: number }
}Typical Event Sequence
A simple text response:
thinking → text → text → text → doneA response that calls tools:
thinking → text → tool_call → tool_result → thinking → text → text → doneMultiple tool calls in one turn:
thinking → tool_call → tool_call → tool_result → tool_result → thinking → text → doneRendering Guidance
When building a chat UI that consumes these events:
- On
thinking— Show a subtle loading indicator (e.g., animated dots with "Thinking" label). Remove it when the nexttextortool_callevent arrives. - On
text— Append to the current text segment. If the previous segment was athinkingindicator, replace it with a text bubble. - On
tool_call— Show an activity badge with the tool name and a spinner. Display alongside text segments, not replacing them. - On
tool_result— Mark the corresponding tool call badge as complete (spinner to checkmark). Optionally show the result preview on expand. - On
done— Finalize: combine all text segments into the persisted message, clear streaming state. IfcontextUsageis present, update the context meter UI. - On
error— Save any partial text as a message, then display the error.
Context Usage
The done event may include a contextUsage field with the current context window consumption. Use this to display a context meter:
usedTokens— how many tokens the conversation is usingmaxTokens— the model's context window limit (e.g., 200,000 for Claude models)percentage— usage as a percentage
When percentage exceeds 80%, the engine may auto-compact older messages to free space. The next done event will reflect the reduced usage.
Server-Handled Tool Calls
Some tool calls are executed server-side by the AI provider (e.g., Anthropic's web search). These follow the same event flow as regular tool calls but with key differences:
- The
tool_callevent has the same shape, but the engine does not execute the tool — the provider handles it - The
tool_resultevent is emitted by the provider once the server-side execution completes - The engine's agentic loop does not re-run for server-handled calls — they resolve within a single provider turn
Web search event sequence:
thinking → tool_call (web_search) → tool_result (search complete) → text → text → doneFrom the UI's perspective, server-handled tools look identical to regular tools — you show a spinner, then a checkmark. The difference is only in the engine layer.
Tool Name Formatting
Tool names follow conventions that can be formatted for display:
cosmo_tasks_create— Cosmo built-in tool. Format as "Tasks: Create"cosmo_artifacts_move— Format as "Artifacts: Move"mcp__notion__search— MCP connector tool. Format as "Notion: Search"web_search— Provider built-in tool. Format as "Web Search"