SSE Protocol
Server-Sent Events streaming protocol reference
SSE Protocol
DorkOS uses Server-Sent Events (SSE) for two purposes: real-time message streaming and cross-client session synchronization.
Message Streaming
When a client sends a message, the server responds with an SSE stream:
POST /api/sessions/:id/messages
Content-Type: application/json
{ "content": "Hello, Claude", "cwd": "/path/to/project" }Response (Content-Type: text/event-stream):
data: {"type":"text_delta","delta":"Hello"}
data: {"type":"text_delta","delta":"! How can"}
data: {"type":"text_delta","delta":" I help?"}
data: {"type":"done"}Event Types
Text Events
Prop
Type
Tool Events
Prop
Type
Interactive Events
Prop
Type
Control Events
Prop
Type
Relay Events
When DORKOS_RELAY_ENABLED is true, the SSE stream includes additional event types:
Prop
Type
Responding to Interactive Events
When approval_required is received, the client must approve or deny:
# Approve
POST /api/sessions/:id/approve
Content-Type: application/json
{ "toolCallId": "tc_123" }
# Deny
POST /api/sessions/:id/deny
Content-Type: application/json
{ "toolCallId": "tc_123" }Failing to respond to an approval_required event will block the agent. The SSE stream remains open until the tool call is approved or denied.
When question_prompt is received, submit the user's answer:
POST /api/sessions/:id/submit-answers
Content-Type: application/json
{ "toolCallId": "tc_123", "answers": { "0": "option_a" } }Session Sync Protocol
Clients can subscribe to real-time session changes via a persistent SSE connection:
GET /api/sessions/:id/streamSync Events
Prop
Type
When a sync_update is received, clients should re-fetch message history. The GET /api/sessions/:id/messages endpoint supports ETag caching (If-None-Match / 304) for efficient polling.
When Relay is enabled, the SSE stream also carries relay_message, relay_receipt, and message_delivered events alongside standard sync events.
Session Locking
The POST /api/sessions/:id/messages endpoint uses session locking to prevent concurrent writes.
Prop
Type
- If a session is locked by another client, the server returns
409with{ error: "Session locked", code: "SESSION_LOCKED", lockedBy, lockedAt } - Locks auto-expire after 5 minutes
- Locks are released when SSE connections close
Connection Lifecycle
Open the SSE connection
Client sends POST /api/sessions/:id/messages with message content. The response is a text/event-stream.
Process streamed events
Server streams events as they arrive from the Claude Agent SDK. The client processes each event and updates its UI in real time.
Handle interactive events
If approval_required or question_prompt events arrive, the client must respond via the appropriate endpoint before the stream continues.
Stream completes
On the done event, the message stream ends. The client can now send another message or close the connection.
Subscribe for ongoing sync
For real-time updates (including changes from other clients or CLI), open a persistent SSE connection via GET /api/sessions/:id/stream.