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:
- Thinking frames require chat
includeThinking(default off). - Tool lifecycle frames require chat
includeToolCalls(default off). - Both require the request to opt in with:
X-Sim-Stream-Protocol: agent-events-v1Legacy 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).
| Frame | Meaning |
|---|---|
{ "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
chunkframes live, token by token. If the turn then resolves to tool calls, achunk_resetframe tells the client to discard that block’s streamed text — the final turn re-streams live after tools settle. Appendchunk, honorchunk_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. Honoringchunk_resetis 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 runsstream: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.
| Family | Thinking | Live tools |
|---|---|---|
| Anthropic / Azure Anthropic | Yes (incl. redacted blocks in traces). The newest Claude generations omit full thinking; Sim requests summarized thinking for them on streaming runs | Yes |
| Gemini / Vertex | Yes when a thinking level is set (thought summaries requested on agent-events runs) | Yes |
| OpenAI Responses | Reasoning 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_content | Live loop where wired (e.g. Groq, DeepSeek) |
| Bedrock | Not invented | Yes 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.