traces¶
The traces block controls which execution data the harness captures during a
run and makes available to judges. Each toggle
is an independent boolean; all four default to true, so the block is
entirely optional.
traces:
stdout: true # capture stdout.log
stderr: true # capture stderr.log
events: false # parse stream-json into events.json (verbose)
metrics: true # capture exit code, tokens, cost, duration
Fields¶
| Field | Default | Captures | Written to |
|---|---|---|---|
stdout |
true |
Raw agent standard output | stdout.log |
stderr |
true |
Raw agent standard error | stderr.log |
events |
true |
Structured events (tool calls, reasoning, results) parsed from the stream-json stdout | events.json |
metrics |
true |
Exit code, duration, token usage, cost, turn count, permission denials | run_result.json |
Omitting the block keeps everything on
traces is optional. When absent, TracesConfig defaults apply and all
four artifacts are captured. Set a field to false only to opt out of
a specific capture.
How captures reach judges¶
Judges are Python/LLM scorers that receive an outputs record per case
(see judges). The traces toggles decide
which keys that record contains.
flowchart LR
A[Agent run] --> B[stdout.log]
A --> C[stderr.log]
A --> D[run_result.json]
B -->|traces.events| E[events.json]
B -->|traces.stdout| O[outputs.stdout]
C -->|traces.stderr| O2[outputs.stderr]
D -->|traces.metrics| M[outputs.cost_usd / num_turns / ...]
E --> J[conversation / tool_trace]
O --> JD[Judges]
O2 --> JD
M --> JD
J --> JD
metrics gates the execution-metadata keys¶
When metrics: true (and the run has a run_result.json), the case record is
enriched with execution-metadata keys pulled from run_result.json
(per-case values fall back to run-level values):
Key in outputs |
Meaning |
|---|---|
exit_code |
Exit code of the invocation. 0 = clean run; the runner reports 1 for failures it detects even when the agent process exited 0 (e.g. background tasks killed at the CLI bg-wait ceiling, unknown slash command); -1 = timeout |
duration_s |
Wall-clock duration in seconds |
token_usage |
Input/output token counts |
cost_usd |
Dollar cost of the invocation |
num_turns |
Number of agent turns |
permission_denialsis persisted inrun_result.jsonbut is not added to the judgeoutputsrecord — a check judge that needs it can read the per-case copy atPath(outputs["case_dir"]) / "run_result.json".
A cost- or efficiency-oriented judge reads these directly:
judges:
- name: cost_reasonable
description: Verify cost stays under $0.50 per case
check: |
cost = outputs.get("cost_usd", 0)
if cost and cost > 0.50:
return False, f"Cost ${cost:.2f} exceeds limit"
return True, f"Cost ${cost:.2f}"
Setting metrics: false hides these keys from judges
With metrics: false, the exit_code, duration_s, token_usage,
cost_usd, and num_turns keys are not added to the outputs record.
Any judge that reads outputs.get("cost_usd") or outputs.get("num_turns")
then sees the default (e.g. 0/None) rather than the real value. Keep
metrics: true whenever you gate on cost or turn count — including
reward composition and
thresholds that depend on
efficiency judges.
stdout / stderr¶
stdout: true and stderr: true make the raw stdout.log and stderr.log
available to judges (e.g. for grepping error strings or inspecting agent
narration). When the structured events.json is missing, the harness also
falls back to reconstructing the conversation from stdout.log.
The events toggle¶
events: true parses the runner's stream-json stdout into a structured
events.json (tool calls, reasoning steps, results). This drives the derived
conversation and tool_trace values that LLM judges render via
{{ conversation }} and {{ tool_trace }}.
Judges receive the typed event list
The parsed events are exposed to judges as a structured
outputs["events"] list — inline check judges can iterate it directly,
and builtin process judges (for example process/consulted_docs) are
built on it. Both Claude Code stream-json and Codex exec --json output
are translated into the same flat event schema. Because the stream is
verbose, many configs still set events: false
(as the canonical eval.yaml
does) unless a judge needs behavioral tracing.
See also¶
- judges — how the
outputsrecord is consumed - outputs — file artifacts and tool calls (separate from traces)
- tracing concepts — how traces flow into MLflow
- runs directory — where
stdout.log,events.json, andrun_result.jsonlive