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.
Agent
sends partial
Platform
writes draft
Browser
gets SSE event
Client
fetches draft
Agent
sends final
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.
{
"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.