Skip to content

Streaming Events

agent.query() returns an async generator of SDK messages.

for await (const message of agent.query("What is 2+2?")) {
switch (message.type) {
case "system":
console.log("session", message.session_id);
break;
case "stream_event":
console.log("raw stream event", message.event);
break;
case "assistant":
console.log("assistant message", message.message);
break;
case "user":
console.log("tool result", message.tool_use_result);
break;
case "result":
console.log("final", message.result);
break;
}
}
Type Description
system Session initialization metadata.
stream_event Raw provider stream events, emitted when streaming is enabled.
assistant Assistant message after model assembly.
user Tool result message sent back to the model.
result Final success, API error, abort, or max-turn result.

stream_event messages arrive while the model is still responding rather than in a burst after the turn ends, so they can drive incremental UI directly. assistant arrives once the model response for that turn is assembled, and user arrives after the whole tool batch has finished.

The SDK produces the next event only after the consumer takes the current one. Slow work inside the for await body delays later events without dropping or reordering them, so keep expensive handling off the loop itself.

The event stream is built for live UI. These guarantees are part of the public contract:

  • The prompt is not echoed. agent.query("...") never yields a user event containing your prompt; the prompt goes into the internal history only. If you need the full transcript — the prompt, tool results, and messages injected by a team runtime — subscribe a ContextTracer instead. Its user_message / assistant_message events record everything; the event stream does not.
  • assistant fires once per model turn, after that turn’s response is fully assembled. message is an AssistantModelMessage: content holds text and tool_use blocks, stopReason says why the model stopped, and providerResponseId / model carry provider metadata when the model client reports them.
  • user appears only after a whole tool batch has finished executing — one event per batch, never one per tool. message.content is always ToolResultBlock[]. tool_use_result is a convenience view over the same results: with a single tool it is that result’s content (string | ContentBlock[]); with several tools it is the array of result blocks. The first tool error, if any, is also surfaced on error, and an aborted batch still yields a user event with error set.
  • result is the terminal event, emitted exactly once per query. subtype is "success" for a normal end, "interrupted" when Agent.interrupt() ends the query cleanly (completed turns stay in history and is_error remains false), or one of "error", "error_max_turns", "error_abort", "error_timeout". Even on success, check stop_reason for "max_tokens" — the text may be a truncated fragment.