--runs sweeps never overwrite each other.
trace.jsonl
The record of what actually happened, one JSON object per line, in order. It is written to stand alone: it opens with the task, the resolved config and every tool name that was offered, and closes with the agent’s output, how the run ended, and how it was graded.
callId pairs a call with its result, so interleaved or concurrent calls stay attributable.
The trace is always written. A run that dies before its first tool call still produces a readable account of what it was asked to do and how it failed.
When debugging, read
trace.jsonl first. It tells you whether the model picked the wrong tool, sent bad arguments, or looped — which result.json alone cannot.state-diff.json
What the rollout changed, as a shallow structural diff:
added, removed and changed. Top-level scalars report their before and after.
Arrays whose rows carry a string id are diffed as collections too — which is what makes append-only logs like auditLog visible instead of silently absent.
An empty diff alongside a failure is diagnostic on its own: the agent read but never wrote.
result.json
Checks, reward, the agent’s output, and the tool error count. Covered in Scoring.
run.json
Everything the rollout was configured with, plus timings:
Two files carry no timestamps
result.json and state-diff.json contain no timestamps and no run ids, by design. That makes them an exact regression oracle: any difference between two runs of the same task with the same agent is a real behavioural change, not noise.
This is what lets you record a run as a baseline and byte-compare against it later:
.silo/ is generated
Runs accumulate. .silo/ is runtime data, not source — add it to .gitignore and commit only the baselines you deliberately record.
Silo