Agent stream events

Agent blocks can emit more than answer text while they run: provider-exposed thinking (or reasoning summaries) and a tool-call lifecycle (name + status). Sim delivers those as typed events on an opt-in stream protocol.

Sim does not invent thinking for providers that do not stream it. Bedrock Converse, many OpenAI-compat models, and non-reasoning chat models stay text-only (plus tools when a live tool loop is wired).

Protocol opt-in vs. event gates (public chat / simple SSE)

Sending the header is a statement about the client: it understands v1 framing, so answer text can stream live and be retracted with chunk_reset. That alone does not expose anything — it only changes cadence, and it applies even when both event policies are off.

Thinking and tool frames need the header plus their own deployment policy:

  1. Thinking frames require chat includeThinking (default off).
  2. Tool lifecycle frames require chat includeToolCalls (default off).
  3. Both require the request to opt in with:
X-Sim-Stream-Protocol: agent-events-v1

Legacy clients that omit the header keep today’s text-only SSE even if either deployment policy is enabled. The hosted chat UI always sends the header for its own deployments, so hosted chats stream token by token regardless of the toggles.

Simple SSE frame shapes

Answer text stays on chunk. Thinking and tools never reuse chunk (so older clients that append every chunk into the answer cannot leak thinking).

FrameMeaning
{ "blockId", "chunk": "…" }Answer text. Legacy clients receive settled final-turn text in one piece; opted-in clients receive it live as the model generates (see below)
{ "blockId", "event": "chunk_reset" }Opted-in only: discard the block’s streamed answer text — it belonged to a turn that resolved to tool calls
{ "blockId", "event": "thinking", "data": "…" }Thinking / reasoning summary delta
{ "blockId", "event": "tool", "phase": "start"|"end", "id", "name", "status?" }Tool lifecycle (no args / results)
{ "event": "final", "data": … }Terminal result envelope for a settled execution. data.success may be false with data.error when the workflow itself failed
{ "event": "error", "error": "…" }Terminal stream failure (timeout, client abort, processing error) — followed by [DONE], never by final
{ "event": "stream_error", "blockId?", "error" }Non-terminal mid-block read issue; the stream keeps going
data: "[DONE]"Stream closed (JSON-encoded sentinel; always follows the terminal final or error frame)

Live answer text and intermediate turns

During a live tool loop, the model can’t be classified mid-turn: text it emits may turn out to be the final answer or preamble before a tool call (the stop reason arrives only at turn end).

  • Opted-in clients (protocol header; no event policy required) receive answer text as chunk frames live, token by token. If the turn then resolves to tool calls, a chunk_reset frame tells the client to discard that block’s streamed text — the final turn re-streams live after tools settle. Append chunk, honor chunk_reset, and the displayed answer always converges to the block’s final content.
  • Legacy clients (no header) never see provisional text: only settled final-turn text is emitted as chunk, delivered in one piece when the turn completes. Honoring chunk_reset is what buys live cadence, so send the header if you want it.

Logs, memory, and the block’s content output always contain final-turn text only — intermediate preamble is never persisted.

Abort

Client disconnect or Stop aborts the provider stream. In-flight tools settle as cancelled. Cancel is distinct from execution timeout.

Reconnect

Canvas execution-events stream:chunk, stream:chunk_reset, stream:thinking, and stream:tool are live-only (not buffered for reconnect replay), same as answer chunks. Guaranteed seq replay is out of scope.

Canvas (draft Run)

When you click Run in the builder, the execution-events SSE path forwards the same sink. The canvas is always opted in — it does not send (or need) the X-Sim-Stream-Protocol header; the dual gate applies only to the public chat / simple SSE surface:

  • stream:thinking{ blockId, text }
  • stream:tool{ blockId, phase, id, name, status? }
  • stream:chunk — answer text, live on agent-events runs
  • stream:chunk_reset{ blockId }; discard the block’s streamed text (intermediate turn)

The terminal output panel shows Thinking / Tools chrome above the block output when those events arrive. PII redaction on block output still disables live forwarding (executor rule).

Chat deployment toggles

In Deploy → Chat, enable Include thinking for provider-exposed thinking and Include tool calls for tool names and lifecycle status. The switches are independent, and both event types still require the protocol header. Neither switch affects answer-text cadence.

Tool arguments and results are never exposed to a public chat — not in lifecycle frames, and not through the terminal final envelope, where the block's own tool calls are reduced to the same name-and-lifecycle shape. The authenticated workflow API still returns full tool results. Redeploy or update the chat after changing Agent models or tools.

Capability honesty (high level)

Per-model support is generated from the model registry on the Agent block page; the table below summarizes by provider family.

FamilyThinkingLive tools
Anthropic / Azure AnthropicYes (incl. redacted blocks in traces). The newest Claude generations omit full thinking; Sim requests summarized thinking for them on streaming runsYes
Gemini / VertexYes when a thinking level is set (thought summaries requested on agent-events runs)Yes
OpenAI ResponsesReasoning summaries when streamed (requires OpenAI organization verification; unverified orgs fall back to no summaries)Yes
OpenAI-compat (Groq, DeepSeek, …)Only if vendor streams reasoning / reasoning_contentLive loop where wired (e.g. Groq, DeepSeek)
BedrockNot inventedYes when streaming tool loop is used

Example (public chat)

curl -N -X POST 'http://localhost:3000/api/chat/your-slug' \
  -H 'Content-Type: application/json' \
  -H 'X-Sim-Stream-Protocol: agent-events-v1' \
  -d '{"input":"Think briefly, then say hi"}'

See also Chat deployment for access control and the event settings.

On this page