Skip to main content
Every interaction produces a trace — a structured record of the agent’s reasoning for that turn. You can fetch it after the fact through the trace endpoints, or receive it inline with the reply by setting include_trace on a send.
To see a trace before you write code, open the Traces tab of the Apollo Agent Tester with your publishable key — it renders both shapes readably and shows the raw JSON.
Two ways to fetch traces on the messaging surface: The interactionId is the message.id from a send-message response.

Two shapes, one field to tell them apart

A trace’s shape depends on the runtime the agent runs on. Every trace carries a runtime field that says which one you got: Branch on runtime before reading anything else — in the SDK (3.4.0 and later) Trace is a discriminated union, so the branch narrows the type:
For a runtime v2 agent the interaction endpoint also needs the thread — pass thread_id (a runtime v2 turn is identified by its thread and its id). Without it the API answers 400 bad_request: “thread_id is required to read a runtime v2 interaction’s trace: pass ?thread_id=<the thread it belongs to>, or request the trace inline with include_trace on send.” Runtime v1 interactions are read by their id alone; a thread_id passed anyway is ignored. See Errors.

Get a thread’s traces

cURL
Returns a page of trace objects — { results, meta, links } — one per interaction, oldest first. Use page[size], page[after] and page[before] to walk long threads.

Get one interaction’s trace

cURL

Get the trace with the reply

Set include_trace: true on a send (or a stream, or a rerun) and the reply carries the same trace object as message.trace_info — no second request. It is off by default: a trace can be large.
cURL
On a stream, the final message event’s data.trace_info carries it; on a rerun, the regenerated reply carries the trace of the replayed turn. When a request didn’t ask for it, trace_info is null. Transcript reads (GET /threads/{threadId}/messages) never carry traces — use the trace endpoints for history.

The runtime v2 trace

The trace of an agent on the current runtime is the runtime’s own record of the turn, published as a typed set of sections. They are named in your program’s vocabulary — the same nouns you author in program.yaml, vocabulary.yaml, situations.yaml and sources.yaml — so each section reads back to the capability, policy, fact, source or record it is about.
'v2'
Always "v2" on this shape.
string
The end-user message the turn started from.
integer
The turn’s number in the thread, from 1.
object
The program version the turn ran: id, version.
array
The facts the agent took from the message this turn — each with the fact (its id in vocabulary.yaml), the value it understood and how it took it.
array
The facts the turn established — fact, value, and from (where it came from, e.g. a source read or an earlier turn).
array
Every source the turn read or wrote — the source id from sources.yaml, the operation (read / write), its outcome (e.g. found, success, empty, error), why when the outcome needs a reason, how many rows a read returned, and for a knowledge source the candidate passages it returned (evidence[], each with passage_id, document, section, a bounded excerpt and whether it was selected).
array
The knowledge passages provably used in the final reply — source, passage_id, document, section. A subset of the evidence under sources: retrieved is not the same as used.
array
The citations the reply provably carries, each with the passage it names and the components (document, section) the reply stated. This is what to show an end user as “sources”.
array
The policies the turn evaluated on the way to acting — the capability, the policy, the subject (record instance) it was judged on, whether it held, its polarity, and because.
array
The mechanical checks the reply was graded on before it was sent — the check, whether it passed, a note, and the kind of thing it graded (reply, turn, …). A check with passed: false did not withhold the reply: the breach is recorded, and the note says why.
array
The capabilities the turn carried out, by id.
string | null
When the turn refused the request, the policy that refused it (for example refund.must_hold).
object
The reply as composed: text, whether it hedged, the handover it escalated to (if any), whether a model voiced it, and the suggestions offered.
string
The turn in plain sentences — a readable account of everything above.
The published runtime v2 trace is a typed subset of the runtime’s full record: sections are added deliberately, and existing ones keep their names and types, so the SDK types are safe to build on. Values the program declares sensitive are masked in the trace; everything else the agent learned during the turn is recorded — mark facts sensitive in vocabulary.yaml to keep them out.

Show sources to end users

The question every chat surface asks. For an agent on the current runtime the answer is two sections of the trace, in this order:
  1. citations_used — the passages the reply provably cites. Each names the document and section (and the source and passage_id behind them), plus the components the reply stated. This is the list to render as “Sources”.
  2. passages_used — the passages the reply drew on without citing them verbatim. Use it as the fallback when citations_used is empty.
sources[].evidence is everything the retrieval returned, selected or not — useful for debugging relevance, not for the end user. An agent whose turn read no knowledge source (a places lookup, a records read, small talk) has both lists empty; the did capabilities and refused_by tell you what the turn was instead.

The runtime v1 trace

'v1'
Always "v1" on this shape.
object
The end-user message the turn started from (input.message).
object
What the agent understood: the detected intents and the guardrails outcome (passed, reason).
array
The decisions the agent took while handling the message — one entry per step.
array
Parameters the agent computed during the turn (code, title, scope).
array
Every rule evaluated: its code, whether it triggered, and the per-condition reason breakdown.
object
How the agent answered: the response type and message, follow-up suggestions, what it was asking_for, any block_message, and rendered jsx_widgets.
On a runtime v1 WebSocket session, the final message envelope embeds the same trace as data.trace_info when the session was opened with include_trace=true.
Trace fields are additive: new fields may appear as the reasoning engine evolves, so treat unknown fields as informational rather than errors.

Errors

Errors use the standard envelope (error.code, error.message, error.request_id).

Traces on the management surface

The same traces are available under /management/v1 for back-office tooling — GET /management/v1/threads/{threadId}/trace and GET /management/v1/interactions/{interactionId}/trace (with thread_id for runtime v2 interactions) — authenticated with a management credential. See Management → Threads.