Skip to main content

Traces

The execution record of a run — one node per agent session, nested by sub-agent call, and the control that erases its content.

Overview​

A trace is created for you whenever an agent runs. One trace covers one agent's execution session; when that agent calls another agent as a tool, the callee gets its own trace with parent_trace_id pointing back, so a multi-agent run is a tree rather than a flat log. Every generation carries the trace_id it belongs to.

Two reads and one erasure, which is the whole surface: list or get a trace, fetch the tree rooted above it (optionally with each node's generations embedded), and purge a run's content while leaving its audit skeleton behind.

This module is a verbatim mirror of the runtime: every field, method, status code and error shape is the runtime's own, re-rooted under the project in the path.

See the OpenAPI spec for the full endpoint and schema reference, or browse it rendered under API Reference → Traces.

Data Model​

Trace​

FieldTypeDescription
idstringPublic trace ID (trace_ prefix).
project_idstringThe owning project.
agent_idstringThe agent whose session this trace records.
file_idstring, nullableThe stored file holding the serialized steps — null until the trace is saved (saving is fire-and-forget).
step_countintegerSteps recorded in this trace.
parent_trace_idstring, nullableThe trace whose sub-agent call started this one; null on a root.
root_trace_idstring, nullableThe root of the whole tree; null when this trace is itself the root.
errorobject, nullableStructured payload recorded when a generation in this trace failed (code, message, meta).
content_redacted_atstring (date-time), nullableNon-null once the content was purged — see Purging a run's content.
content_redacted_by_principal_typestring, nullableuser or api_key.
content_redacted_by_principal_idstring, nullableWhich principal purged it — for key auth, the API key's own id.
created_atstring (date-time)

TraceTreeNode​

The tree response is a Trace plus two extras:

FieldTypeDescription
childrenarray of TraceTreeNodeTraces triggered by sub-agent calls from this node.
generationsarray of GenerationThe node's generations. Present only with include=generations.

Key Concepts​

Reading a multi-agent run​

GET /v1/projects/{project_id}/traces/{trace_id}/tree takes any trace in a tree — root or child — resolves the root, and returns the whole tree from there. So "show me this run" needs one call and the id you happen to be holding, not a walk up parent_trace_id. Debug a failed run starts there when a sub-agent stops on an error.

Add include=generations to embed each node's generations, including the sub-agent generations linked through initiator_generation_id. That is the cheapest way to get from "which agent did what" to "what did it actually say": each embedded generation's id is what GET /v1/projects/{project_id}/generations/{generation_id}/transcript reads step by step.

Purging a run's content​

DELETE /v1/projects/{project_id}/traces/{trace_id}/content deletes the steps object and clears the content fields, cascading to every descendant trace and to all of their generations. The cascade is the point: a descendant holds its own steps object covering the same run, so erasing only the trace you asked about would leave the content readable one level down.

What survives is an auditable skeleton — ids, timestamps, step counts, and the generations' usage attribution — stamped with content_redacted_at and the principal that acted. A purged trace therefore reads back as a skeleton rather than a 404: the erasure is provable, which a missing row would not be. The call is idempotent, and it keeps the original content_redacted_at on a second purge.

Two related controls live on the project: a retention window purges content past it on a daily sweep, and trace_content_mode: none — also settable per agent — never writes content at all, which is the stronger guarantee. Run a zero-retention agent reads back the skeleton such a run leaves.

Who may do what​

Every route needs any project member.

Reading the steps object directly

file_id names the stored file holding the serialized steps, so GET /v1/projects/{project_id}/files/{file_id}/download will fetch it. It is the raw serialization, not a documented format — read a run through the tree and each generation's transcript when you want the contract, and reach for the object only when you need what it happens to contain.

Examples​

List the project's traces​

naturali list-traces \
--project-id proj_V1StGXR8Z5jdHi6B \
--limit 20

Get one trace​

naturali get-trace \
--project-id proj_V1StGXR8Z5jdHi6B \
--trace-id trace_V1StGXR8Z5jdHi6B

Read a whole run, generations included​

naturali get-trace-tree \
--project-id proj_V1StGXR8Z5jdHi6B \
--trace-id trace_V1StGXR8Z5jdHi6B \
--include generations

Purge a run's content​

naturali purge-trace-content \
--project-id proj_V1StGXR8Z5jdHi6B \
--trace-id trace_V1StGXR8Z5jdHi6B