output is the flat text — the right answer for a pipeline, a webhook, a curl call, or
anything that just wants the result. It is always present and it is not going anywhere.
transcript is the same run as an ordered sequence you can render: blocks of assistant
prose, the tools the model used, and emit payloads where the model produced
them. It is what a chat UI needs and what a flat string cannot express.
Why a flat string isn’t enough
Two things get lost when a run collapses to one string. Text runs together at tool boundaries. Providers split one logical block of prose into several messages — Anthropic does it around citations, sometimes mid-word — sooutput
joins them with nothing at all. That is correct, and it is also why a model that says
“I’ll look that up.”, calls a tool, then says “Here’s what I found…” comes back as
I'll look that up.Here's what I found…. A tool call is a real boundary and the string
has no way to say so.
Tool activity is invisible. A chat UI wants a bubble, then a “used web_search” chip,
then another bubble. Nothing in a string carries that.
The transcript fixes both by construction: adjacent prose is already merged, and a tool
sits between the blocks either side of it.
The shape
type:
A tool item’s
status is ok, error, or pending. Pending is a real state on a
finished fetch: an async tool — a prompt or workflow call, a
knowledge search — can still be running when you read the run.
queries and citations on a tool item are only ever populated by the built-in
web search; every other tool leaves them empty.
Tool items carry no arguments, no results and no call ids, on purpose. Results can be
enormous, arguments can carry user data, and a chip needs neither.
transcript, exactly as it has a null output and an empty
emitted.
Rendering it
Live and fetched agree
The same shape arrives on the token stream as a run is generated, so one component renders it mid-flight and after a refetch. Tools PromptJuggler runs for you — HTTP, script, knowledge search, prompt and workflow calls — stream as chips with a livepending → ok/error status.
The stream is built from text deltas and end-of-turn events, so whatever a provider attaches
to a whole message, or does inside its own turn, is only known once that turn has finished.
Four details follow from that. The text is the same either way in all of them, and the
fetched transcript is the exact one:
What this does not replace
output and emitted are unchanged and always present.
- Reach for
outputwhen you want the answer and nothing else — most integrations. - Reach for
emittedwhen you want the run’s structured results without walking a list — a pipeline or a webhook follow-up. - Reach for
transcriptwhen you are rendering the run to a person.