Tracing Resume Cost Through a Stopped Fan-Out
A saved workflow migrates database access code file by file. Its
script fans out with pipeline() over eight files, starting one agent
per file in this order as soon as each previous agent's request has
been dispatched: orders.ts, users.ts, products.ts, reviews.ts,
payments.ts, shipping.ts, inventory.ts, refunds.ts.
By the time you stop the run, orders.ts, users.ts, and
products.ts have all finished successfully. reviews.ts is still
running. payments.ts, shipping.ts, and inventory.ts have also
already finished (they were faster, smaller files). refunds.ts
hadn't started yet.
- When you resume this run, which agents return cached results without rerunning, and which agents rerun? Name each file explicitly and explain the rule that determines the outcome for each one.
- A teammate on your team argues this is a bug: "
payments.ts,shipping.ts, andinventory.tsalready finished — rerunning them wastes money for no reason." Explain why this is how resume is designed to work, not a bug, referencing what the alternative would have to guarantee to avoid it. - Propose a concrete change to how this specific workflow is written that would reduce the cost of a future stop-and-resume, without changing what the workflow ultimately accomplishes.
1. Which agents are cached vs. rerun:
Resume follows two rules: an agent still running when you stopped isn't saved and reruns; and replay follows start order, so caching stops at the first agent that hadn't finished by the time you stopped, with everything that started after that point rerunning too — even entries that had actually completed.
orders.ts— cached. Started first, finished before the stop.users.ts— cached. Started second, finished before the stop.products.ts— cached. Started third, finished before the stop.reviews.ts— reruns. It was still running when you stopped — rule one directly.payments.ts— reruns, despite having finished. It started afterreviews.ts, and replay stops caching at the first unfinished agent in start order — rule two.shipping.ts— reruns, same reason: started afterreviews.ts.inventory.ts— reruns, same reason: started afterreviews.ts.refunds.ts— reruns. It hadn't started at all, so there's nothing to have cached.
So five of the eight agents rerun (reviews.ts through refunds.ts),
even though six of the eight had actually finished by the time you
stopped — payments.ts, shipping.ts, and inventory.ts are
recomputed unnecessarily from a pure "was the work already done"
standpoint.
2. Why this is the design, not a bug:
The alternative — caching every agent that happened to finish,
regardless of start order — would require the runtime to guarantee
that finishing early means finishing correctly and independently of
whatever the in-flight agent (reviews.ts) was doing or might still
affect. That's not a safe guarantee to make in general: workflow
agents can share state through the filesystem they're editing (a
shared type definition, a shared config file, an import another file
depends on), so an agent that started after reviews.ts began could,
in principle, have read or built on a partial or since-changed state
that a full run would resolve differently. Start-order replay avoids
having to model or verify data dependencies file by file — it takes
the conservative, simple-to-reason-about position that once any
agent from a batch is incomplete, nothing that started alongside or
after it is trusted to have seen the world in its final form. It's
the same "prefer a predictable, occasionally wasteful rule over a
smarter rule with un-auditable edge cases" instinct that shows up
elsewhere in Claude Code's design (e.g. Edit's exact-match
requirement) — cost, not correctness, is what's being traded here.
3. A concrete mitigation:
Make each per-file migration agent's unit of work smaller and more
numerous, or make the overall run stoppable at natural boundaries
rather than one continuous fan-out. Concretely: instead of firing all
eight file agents in one pipeline() call, batch them — say, three or
four files per pipeline() call, with each batch's results confirmed
(or explicitly saved/committed) before starting the next batch. Then
stopping mid-run only ever risks rerunning the files in the current
batch, not the whole tail of the run — orders.ts through
products.ts finishing as one batch and being durably committed means
a later stop during the reviews.ts-refunds.ts batch can't force a
rerun of already-committed work from an earlier batch. This trades a
small amount of orchestration complexity (explicit batch boundaries)
for materially cheaper stop-and-resume behavior on a long fan-out —
directly applying the "many small agents preserve more progress than
a few long-lived ones" principle one level up, at the batch rather
than the single-agent level.
Share this question