Skip to main content
Every prompt run returns its answer twice, in two shapes for two jobs. 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 — so output 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

Three kinds of item, discriminated by 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.
A failed run has an empty 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. Every chip streams in the position the fetched transcript gives it — tools PromptJuggler runs for you (HTTP, script, knowledge search, prompt and workflow calls) with a live pendingok/error status, and the ones the provider runs inside its own turn (web search, remote MCP) as they happen. A web_search chip reports the queries it ran and the citations it found as it resolves, so a live chip and a refetched one say the same thing. One thing a fetched run adds: a text item’s citations. A provider attaches those to the finished message rather than to the deltas it was streamed as, so they are empty live and populated on a fetch. The text itself is identical and every item is in the same place — fetch the run when you want to footnote the prose. (A chip’s own citations are unaffected.) One placement note, worth knowing if you run web search on Gemini: Gemini reports its grounding for the turn as a whole rather than at the point it searched, so the web_search chip sits after the turn’s text — live and fetched alike. Anthropic and OpenAI report the search itself, and their chip sits where the model ran it.

What this does not replace

output and emitted are unchanged and always present.
  • Reach for output when you want the answer and nothing else — most integrations.
  • Reach for emitted when you want the run’s structured results without walking a list — a pipeline or a webhook follow-up.
  • Reach for transcript when you are rendering the run to a person.
All three derive from the same run, so they cannot disagree.