Skip to main content

Traces

The audit trail: what one agent did inside an execution, and every sub-agent call it started.

Overview

A trace is project-scoped: the platform writes it as a side effect of a real execution, and the record itself is never deleted, because it is the audit trail the platform sells. Its content — the step payload — can be purged on request; see Purging trace content below. A trace's children are the traces its sub-agent calls started, forming a tree; each Generation inside a trace is one model loop.

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.
project_idstringThe owning project.
agent_idstringThe agent this trace belongs to.
parent_trace_idstring, nullableThe trace that started this one, for sub-agent calls.
root_trace_idstring, nullableThe top-level trace of this execution tree.
step_countintegerNumber of recorded steps.
has_stepsbooleanWhether the full step payload (tool calls, inputs/outputs, cost) has been saved and is fetchable — see Reading a trace's steps below.
errorobject, nullableStructured error if the trace failed.
content_redacted_atstring (date-time), nullableWhen this trace's content was purged — see Purging trace content. Null when nothing has been purged.
created_atstring (date-time)

TraceSteps

FieldTypeDescription
trace_idstring, nullableThe trace these steps belong to.
stepsarray of objectOne entry per step, oldest first, exactly as the runtime recorded it — tool calls, their arguments, results and cost.

Key Concepts

Trace ancestry

GET /v1/projects/{project_id}/traces/{trace_id}/tree returns the full ancestry tree rooted at a trace — every child trace a sub-agent call started, recursively.

Generations within a trace

GET /v1/projects/{project_id}/traces/{trace_id}/generations lists every generation recorded under a trace.

Reading a trace's steps

GET /v1/projects/{project_id}/traces/{trace_id}/steps returns the step-by-step record of what the agent actually did: every tool call, its arguments, its result, and its cost. steps is passed through as the runtime recorded it rather than reshaped into a fixed schema, since its shape belongs to the model-loop runtime, not to this API.

Saving the payload is fire-and-forget on the runtime, so calling this immediately after a generation finishes can 404 with steps_not_available for a brief window even though the trace itself already exists — retry once has_steps on the trace is true.

A trace with no payload at all answers steps_redacted instead: its content was purged, or its agent runs in zero-retention and nothing was ever written. The two codes exist so a polling client can tell them apart — retrying steps_not_available succeeds once the write lands, and retrying steps_redacted never does. The response carries content_redacted_at in details, the same marker the trace itself reports.

Purging trace content

DELETE /v1/projects/{project_id}/traces/{trace_id}/content deletes the trace's step payload and clears its recorded error, cascading to every descendant trace in its execution tree and to their generations. The rows survive as auditable skeletons — ids, timestamps and step counts are preserved — with content_redacted_at set as verifiable proof the content is gone. A purged trace still reads back with GET /v1/projects/{project_id}/traces/{trace_id}; a 404 there would prove nothing about what was erased.

The call is idempotent: purging an already-purged trace succeeds and leaves the original content_redacted_at in place.

Examples

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

Reading the steps

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

Purging content

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