Debugging
Debugging one agent is reading its trace. Debugging several is the same skill applied N times, plus one new problem: working out which trace to read.
Every agent traces itself
Each agent writes its own session to its own data/sessions/ as a JSONL trace — every
request, every tool call, every result, every error. Three agents in a script produce
three traces in three folders.
That is a consequence of the boundary, not an oversight. Agents don't share memory, so they don't share a log. Each trace is complete and readable on its own, which means you can debug one agent's behaviour without untangling it from the others.
const { barry } = await Fleet({ barry: "../barry" })
console.log(barry.session.id) // which trace to read
Print the session IDs at the top of any multi-agent script. It costs one line and it is the difference between finding the right file in seconds and grepping by timestamp.
Watching live
session.entries is the live log — readable while the agent is working:
const before = barry.session.entries.length
await barry.request("audit the repo")
const produced = barry.session.entries.slice(before)
on() subscribes to what the agent emits as it emits it, which is how you build a live
view over several agents at once:
for (const [name, agent] of Object.entries({ barry, checker })) {
agent.on("text", ({ content }) => process.stdout.write(`[${name}] ${content}`))
}
Prefixing by name is the cheap version of the correlated view — enough to follow two agents interleaving in a terminal.
Reading the trace
The trace records what the model actually saw and did, tick by tick — the assembled context, the output, the code that ran, the results. When an agent does something unexpected, this is where the answer is, and it is usually in the context rather than the response: the agent did the right thing with the wrong information.
Entry types are documented under Entries. The ones you
reach for most: axon:agent:message for what it said, capsule:stdin and
capsule:stdout for what it ran, capsule:denied for what policy stopped.
Which agent is wrong?
With several agents, the first question is where the failure entered. A pipeline makes this tractable, because each stage's input is a value in your script:
const findings = await scout.request("find every caller")
console.log("--- findings ---\n", findings.text) // check before passing on
const plan = await planner.request(`plan a refactor.\n\n${findings.text}`)
Most multi-agent bugs are not agent bugs. They are prompt bugs at a handoff — one agent produced something reasonable, and the next agent received it without the context needed to interpret it. Printing what crosses each boundary finds this faster than reading either trace.
Isolating one agent
Because agents are independent, you can run one on its own with the same input and see whether it misbehaves outside the composition:
axon # boot it in the TUI, talk to it directly
axon run review --file src/x.ts # run its own script headlessly
If it behaves alone and misbehaves in the fleet, the problem is what you handed it. If it misbehaves alone, it is an agent problem — debug it as one agent.
Determinism
Multi-agent runs vary between executions, which makes a bug that appeared once hard to reproduce. Pin what you can:
Use the mock engine for the parts under test. It makes agent responses deterministic, so a failing composition fails the same way twice. See Testing.
Pin registry versions. An unpinned fleet member can change under you between runs;
@arclabs/linter@1.2.0 cannot.
Keep handoffs in variables. Text passed between agents through a named variable is inspectable, loggable, and replayable. Inline template strings are none of those.
Known gap: no unified run view
There is currently no single artifact representing "this run across all its agents." Traces are per-agent and joined by hand.
Correlating a whole run — one view showing every agent's activity on a shared timeline — is what the fleet extension is for, and it is the natural next step for the tracing pipeline. Until then, printing session IDs and prefixing live output is the practical substitute.
Next: Patterns — the shapes this work tends to take.