Tracing & Debugging
Inspect execution traces with timing, tokens, and cost breakdowns.
After a flow executes, retrieve detailed execution traces with step-by-step timing, token usage, and cost breakdowns.
Get a trace
After execution, fetch the trace using the execution ID. A Trace contains a flowRun summary and a list of steps. Step totals (cost, duration) are aggregated client-side from the steps array — there is no total_cost_usd on the trace object itself.
The Trace object exposes:
flow_run/flowRun: ARunSummary(id,flow_id,status,trigger_type,started_at,completed_at,duration_ms,step_count)steps: A list ofStepTraceobjects (latest attempt per step)
Pass trace=True (Python) / trace: true (Node) on execute to ensure the server captures input/output snapshots; without it, traces still include timing, tokens and cost.
Inspect steps
Iterate over the per-step traces. Each StepTrace is identified by step_id (there is no name field on StepTrace — name only appears on streaming StepCompleted events).
Each StepTrace includes:
step_id/stepId: Unique step identifier within the flowattempt: Attempt number (1 = first try; >1 if the step was retried server-side)loop_index/loopIndex: Loop iteration index for steps inside a loop (otherwisenull)status:"running" | "completed" | "failed" | "skipped"started_at/completed_at(ISO timestamps) andduration_ms/durationMsmodel_used/modelUsed: LLM model identifier when the step ran an LLM blocktokens:TokenBreakdownwithprompt,completion,total(all integers)cost_usd/costUsd: Estimated cost as a decimal string (e.g."0.001234"). Parse withfloat(...)/parseFloat(...)before formatting. The string form preserves full precision and avoids float drift.input_context/output_context/error_context: Captured snapshots (only whentrace=Trueon execution, or for failed steps)input_size_bytes,output_size_bytes,truncated: Snapshot metadata
Inspect token usage
The TokenBreakdown is a flat three-field model — it mirrors what the server records per LLM call (no separate cache fields at the SDK level; cache accounting is rolled into prompt server-side).
Track retries across attempts
Trace.steps only contains the latest attempt per step. To inspect every retry for a given step, call step_trace(step_id, attempt="all") — it returns a StepAttempts collection.
StepAttempts exposes:
step_id/stepId: The step being inspectedattempts: A list ofStepTraceobjects — one per attempt, ordered byattemptnumber
Live tracing
For long-running flows, live_trace() (Python) / liveTrace() (Node) replays trace history from the database then live-tails new events from the server. It yields typed StreamEvent objects — the same event union you'd get from flow.events() (RunStarted, StepStarted, StepCompleted, FlowCompleted, …), not full Trace snapshots.
The iterator terminates when the server closes the connection after the run reaches a terminal state. If you need a full Trace snapshot after streaming, call run.trace() once live_trace() returns.
Compare runs
To benchmark cost or latency between executions, aggregate over trace.steps:
Export traces
Traces are fully serializable to JSON:
Use this to archive execution history or feed into monitoring systems.
Next steps
- Error handling: See Errors & retries