Streaming (SSE)

The native API streams over Server-Sent Events with a two-step protocol: you spawn a turn, then subscribe to its durable event log. The split makes the stream resumable — a dropped connection reconnects and replays from where it left off, and the same turn can be watched from multiple tabs.

Looking for a one-line drop-in?

If you only need plain streamed text and already use the OpenAI SDK, the OpenAI-Compatible endpoint streams in a single request and is the simpler path. This page documents the native protocol and its full event set.

The protocol

1

Spawn the turn

POST /api/v1/sessions/stream does not stream — it returns 202 Accepted with the identifiers of the turn that was spawned in the background.

curl -X POST "https://samreshuuu.ru/api/v1/sessions/stream" \ -H "Authorization: Bearer sk-org-your_api_key" \ -H "Content-Type: application/json" \ -d '{ "message": "Summarize the key points of this contract" }'
{ "session_id": "ses_abc123", "message_id": "msg_def456", "kind": "new_turn" }
2

Subscribe to the event log

GET /api/v1/sessions/{session_id}/messages/{message_id}/stream returns text/event-stream and replays every event for that turn. Each frame carries an id: — keep the last one to resume.

curl -N "https://samreshuuu.ru/api/v1/sessions/ses_abc123/messages/msg_def456/stream" \ -H "Authorization: Bearer sk-org-your_api_key"
id: 1709-0 data: {"type": "start", "session_id": "ses_abc123"} id: 1710-0 data: {"type": "delta", "content": "Here are the key points of the contract:\n\n"} id: 1711-0 data: {"type": "tool_started", "tool_name": "web_search", "label": "Searching the web", "iteration": 1} id: 1715-0 data: {"type": "complete", "session_id": "ses_abc123", "final_response": "Here are the key points...", "total_input_tokens": 150, "total_output_tokens": 89}

Request fields

The POST /sessions/stream body accepts:

FieldTypeDescription
messagerequiredstringThe user turn. Either message or document_ids is required.
session_idstringReuse a session_id to continue a prior conversation. Omit to start fresh — the response returns the new id.
agent_idstringRun the turn under a specific agent profile and its granted connectors. See Agents.
document_idsarrayAttach previously uploaded documents to the turn by id.

Event types

Every frame is data: followed by a JSON object with a type discriminator. These are the stable, public event types — handle the ones you need and ignore any type you don't recognize; the set is additive.

TypeMeaning
startTurn began. Carries session_id.
deltaIncremental assistant text — append content for live rendering.
tool_startedA tool call began. Carries tool_name, label, iteration.
tool_completedTool finished. Carries success, message, duration_ms.
artifact_startA file/artifact began streaming. Carries artifact_id, artifact_type, title.
artifact_deltaA chunk of artifact content (content_chunk, chunk_index).
artifact_completeArtifact finished. Carries version, content_type, optional download_url.
artifact_updateA previously completed artifact was revised.
completeTerminal success. Carries final_response, token counts, and artifacts.
errorTerminal failure. Carries error code, message, retryable, user_message.
canceledTurn stopped. Carries reason (user_stop, timeout, …) and any partial_response.
pausedTurn suspended awaiting a wake (form, timer, or rate-limit). The stream closes cleanly — resume later with the same ids.
form_requestThe agent needs input. Carries form_kind (clarify | integration | channel_connect | approval), form_id, and a payload.

The canonical answer is on the complete event

Render delta text live for UX, but the authoritative answer is complete.final_response — not the concatenation of deltas. The agent may revise mid-stream, so deltas are interstitial narrative, while final_response equals the persisted message.

Transient diagnostic events (thinking, heartbeat, retry_notification, browser_frame) may also appear; they are not part of the stable contract and are safe to skip.

Resuming a dropped stream

The subscribe endpoint is idempotent and multi-tab safe. To resume after a disconnect, send the last frame id back — either as the Last-Event-ID header or a ?since= query parameter — and the server replays only what you missed.

curl -N "https://samreshuuu.ru/api/v1/sessions/ses_abc123/messages/msg_def456/stream?since=1711-0" \ -H "Authorization: Bearer sk-org-your_api_key"

Answering a form_request

When a form_request arrives, the turn pauses (you may also see a paused event). Send the user's answer back as a normal POST /sessions/stream with the same session_id — the platform routes it to the waiting form instead of starting a new turn, and the original turn resumes on its existing stream.

Stopping a turn

POST /api/v1/sessions/{session_id}/stop cancels the active turn. It is idempotent and always returns 204; the stream then emits a canceled event with reason: "user_stop".

curl -X POST "https://samreshuuu.ru/api/v1/sessions/ses_abc123/stop" \ -H "Authorization: Bearer sk-org-your_api_key"

FAQ

Why is native streaming a two-step protocol?

You first POST /sessions/stream to spawn the turn (it returns 202 with ids), then subscribe to its durable event log over SSE. The split makes the stream resumable after a dropped connection and safe to watch from multiple tabs.

How do I resume a dropped stream?

Send the last frame id back — as the Last-Event-ID header or a ?since= query parameter — and the server replays only the events you missed.

Which event carries the authoritative answer?

The complete event's final_response, not the concatenation of delta frames. The agent may revise mid-stream, so deltas are interstitial narrative while final_response equals the persisted message.

What should I do with event types I don't recognize?

Ignore them. The event taxonomy is additive — handle the types you need and skip the rest, including transient diagnostics such as thinking and heartbeat.

Frequently asked questions

Why is native streaming a two-step protocol?

You first POST /sessions/stream to spawn the turn (it returns 202 with ids), then subscribe to its durable event log over SSE. The split makes the stream resumable after a dropped connection and safe to watch from multiple tabs.

How do I resume a dropped stream?

Send the last frame id back — as the Last-Event-ID header or a ?since= query parameter — and the server replays only the events you missed.

Which event carries the authoritative answer?

The complete event's final_response, not the concatenation of delta frames. The agent may revise mid-stream, so deltas are interstitial narrative while final_response equals the persisted message.

What should I do with event types I don't recognize?

Ignore them. The event taxonomy is additive — handle the types you need and skip the rest, including transient diagnostics such as thinking and heartbeat.

Was this page helpful?