Skip to main content

Payloads

In progress — not available yet

Real-time streaming is not enabled on accounts yet. See the overview for what to do instead.

What lands on each node: incremental chunks, the run status a composer keys off, and the finalized message.

Streaming Chunks

Listen on streaming/{conversationId}/{messageSequence}. Each write replaces the whole node, so you receive the accumulated chunks array plus a meta object every time.

{
"meta": {
"run_id": "64403669-5989-4ec3-ad9c-d84223f9679f",
"status": "streaming", // "streaming" | "complete" | "error"
"started_at": "2026-04-23T22:43:44.700Z",
"finished_at": null,
"error_message": null
},
"chunks": [
{ "content": "I can ", "type": "STREAM_CHUNK_TYPE_TEXT", "timestamp": "…", "is_final": false },
{ "content": "help ", "type": "STREAM_CHUNK_TYPE_TEXT", "timestamp": "…", "is_final": false },
{ "content": "with…", "type": "STREAM_CHUNK_TYPE_TEXT", "timestamp": "…", "is_final": true, "finish_reason": "stop" }
]
}

Chunk fields

FieldMeaning
contentThe token text (or reasoning/tool-call fragment) for this chunk
typeSTREAM_CHUNK_TYPE_TEXT, STREAM_CHUNK_TYPE_REASONING, or STREAM_CHUNK_TYPE_TOOL_CALL
is_finaltrue on the last chunk of the message
finish_reasonstop, tool_calls, length, or error — present on the final chunk

The chunks array is indexed by position and may contain gaps (nulls) mid-stream as writes arrive out of order — always render by accumulating non-null entries in order, don't assume the array is dense.

Filter chunk types for display: render STREAM_CHUNK_TYPE_TEXT into the message bubble; treat STREAM_CHUNK_TYPE_REASONING and STREAM_CHUNK_TYPE_TOOL_CALL separately (or hide them). When reasoning is enabled, reasoning chunks arrive first, then text chunks.

Detecting completion

A stream is done when any of these is true — check meta.status first, it is authoritative:

  1. meta.status == "complete" (or "error"), or
  2. the last chunk has is_final: true with a finish_reason, or
  3. conversations/{conversationId}/status returns to a non-generating state.

Conversation Status

Listen on conversations/{conversationId}/status for a single last-write-wins node that tracks what the conversation is doing. Use it to drive a busy indicator and to de-duplicate out-of-order writes via seq.

{
"state": "CONVERSATION_ACTIVITY_STATE_GENERATING",
"run_id": "64403669-5989-4ec3-ad9c-d84223f9679f",
"seq": "7", // int64 as string
"since": "2026-04-23T22:43:44.712Z",
"error": null // { "code": "...", "message": "..." } on failure
}
state valueMeaning
CONVERSATION_ACTIVITY_STATE_IDLENothing running — safe to send the next message
CONVERSATION_ACTIVITY_STATE_QUEUEDGeneration accepted, not started yet
CONVERSATION_ACTIVITY_STATE_GENERATINGModel is producing tokens
CONVERSATION_ACTIVITY_STATE_EXECUTING_TOOLSRunning tool calls
CONVERSATION_ACTIVITY_STATE_COMPACTINGCompacting context
CONVERSATION_ACTIVITY_STATE_ERRORLast run failed — see error

Finalized Messages

Once a turn settles, the full message is written under events/{eventName}/{conversationId}/messages (event name llm_v1_common_v1_conversationmessagepublishedevent). Fields here use snake_case:

{
"message": {
"role": 2,
"content": [ { "type": "CONTENT_PART_TYPE_TEXT", "content": "I can assist you with…" } ],
"generated_by": "64403669-5989-4ec3-ad9c-d84223f9679f",
"sequence": 8,
"tool_calls": [
{ "id": "call_abc123", "name": "get_weather", "status": "…",
"is_client_tool": false, "arguments_json": "{\"city\":\"NYC\"}" }
]
},
"eventContext": { "correlation_id": "…", "event_id": "…", "event_name": "…", "emitted_at": "…", "version": "1" }
}

Run lifecycle markers ({ "runId": "...", "status": "..." }) appear under events/{eventName}/{conversationId}/runs for the generation-started and generation-completed events.