Lifecycle
A booted agent is a live resource. It holds a capsule subprocess, an open session log, and whatever its modules connected to at setup. Something has to shut it down.
In a fleet script, that something is the CLI.
const { barry, checker } = await Fleet({
barry: "../barry",
checker: "../checker",
})
await barry.request("...") // if this throws, both agents still shut down
axon run owns the process. When the script finishes — returns, throws, or is
interrupted — the CLI shuts down every agent that was booted, then exits. You do not
write teardown, and there is no handle you have to remember to hold.
This is why destructuring is safe. const { barry, checker } = await Fleet(...) throws
away the fleet object itself, which in most APIs would mean throwing away the only way
to clean up. Here the lifetime belongs to the run, not to a variable.
The shape of a run
axon run review.axon.ts
│
├─ resolve every reference ← fails here if an agent is missing
├─ boot them in parallel ← capsules start, modules connect
├─ run the script ← your code
└─ shut them all down ← always, including on failure
Shutdown is error-isolated: one agent failing to close never leaves the others running. Every session log is flushed regardless, so a script that crashed still leaves a complete trace of what each agent did before it.
Boot is parallel, shutdown is complete
The two halves have different priorities and behave differently.
Boot optimises for latency and fails fast. References resolve first, all of them, before anything starts — so a typo in the fourth agent's name fails before the first agent's capsule exists. Then the whole set boots at once.
Shutdown optimises for completeness. It runs for every agent even when one throws, and it flushes logs unconditionally. A failed shutdown is reported after everything has been attempted, never as a reason to skip the rest.
What survives
The runtime is ephemeral; the folder is not.
Each agent writes its session to its own data/sessions/ as a JSONL trace — every
request, every tool call, every result. When a fleet script finishes, those traces are
what remains. Three agents in a fleet leave three traces, in three folders, each
readable on its own.
Anything an agent wrote to data/ during the run persists too, on the same terms as any
other session. A fleet script that has an agent accumulate knowledge is writing to that
agent's folder, and the next run — fleet or TUI or deployed — reads it back.
What does not survive is conversation. A handle's context lasts as long as the handle:
// run 1
const { barry } = await Fleet({ barry: "../barry" })
await barry.request("we're refactoring the auth module")
await barry.request("start with the token parser") // barry remembers
// run 2 — a new process, a new session
const { barry } = await Fleet({ barry: "../barry" })
await barry.request("how's the refactor going?") // barry does not remember
Within a run, consecutive calls share full context. Across runs, they do not. If an
agent needs to carry something between runs, it belongs in data/ — written
deliberately, read at boot. See
State & Memory.
Long-running scripts
Nothing stops a fleet script from staying up — a loop, a queue consumer, a watcher. Boot the fleet once at the top and keep the handles for the life of the process:
const { triage } = await Fleet({ triage: "../triage" })
for await (const issue of watchIssues()) {
const result = await triage.request(`triage this issue:\n\n${issue.body}`)
await postComment(issue.number, result.text)
}
One boot, many requests, one shared context that accumulates across every issue. If that accumulation is not what you want — and for triage it usually isn't, since issue nine should not be coloured by issue eight — the answer is a fresh handle per unit of work, not a longer prompt.
Booting inside an agent
An agent-scoped script never boots anything. It runs inside a runtime that is already
up, and that runtime's lifetime is owned by whatever started it — the TUI session, the
axon run that invoked it, the deployed process serving requests.
await Axon() inside src/scripts/ returns that running instance. It does not create a
second one, and there is nothing to shut down.
Next: Patterns — the shapes fleet scripts tend to take.