Skip to documentation
Anywe

Streaming interaction replies

Streaming is an optional evolution of the normal reply contract: a one-shot agent that never sets these fields is unaffected. A streaming agent posts multiple replies for one delivery, each a full snapshot rather than a fragment.

One streamed delivery
  1. Agent

    sends partial

  2. Platform

    writes draft

  3. Browser

    gets SSE event

  4. Client

    fetches draft

  5. Agent

    sends final

  6. Platform

    writes message

Partial protocol

Every non-final post has partial: true, echoes the platform-issued dispatch_seq, and carries a monotonically increasing seq. Each new blocks array is a full cumulative snapshot, never a token delta, so a lost or reordered partial is recoverable: a later snapshot restates the full current view instead of requiring the client to splice fragments together.

JSON
{
  "version": "1",
  "in_reply_to_delivery_id": "dlv_01ARZ3NDEKTSV4RRFFQ69G5FAV",
  "dispatch_seq": 1,
  "partial": true,
  "seq": 3,
  "blocks": [
    { "type": "text", "text": "Checking fare rules before I answer..." }
  ]
}

Only five block types may appear in a partial: text, thinking, tool_use, tool_result, and intent. Every other type is final-only, even if it would otherwise be valid, including intent itself in reverse: it is valid ONLY in a partial, and a final carrying it is refused. This is an allow-list, so a newly published block type is forbidden in partials by default, not legal until it is explicitly denied.

Snapshot rules

text may grow from snapshot to snapshot. A completed thinking, tool_use, or tool_result block must instead remain field-identical in every later snapshot of the same dispatch_seq, correlated by signature, id, and tool_use_id. A later partial that mutates or drops one of these is rejected; a fresh dispatch_seq is a new attempt and is unconstrained by the one before it.

thinking and tool_use are accumulate-then-emit: their required signature or complete JSON input must exist before the block appears at all. The allow-list permits the completed block in a snapshot; it does not turn an incomplete SDK delta into a valid one.

Draft delivery

Each accepted partial updates a draft. The browser receives an identifier-only messagePartial SSE event carrying the draft's messageId and seq, then re-fetches the caller-scoped draft; the event itself carries no block content, because access must be evaluated at read time. SSE fan-out may coalesce above roughly five notifications per second for one stream, but every accepted partial still writes the current draft, so a skipped notification just means the next one fetches a newer snapshot.

Finalization

The final reply is authoritative and may contain any currently agent-sendable block type. stop_reason is optional, final-only display state for a non-clean ending; it does not change delivery retry semantics. A final event supersedes the draft with the immutable message, and clients fetch again through their normal message path.