Only Some Work Is Fleet-Shaped

Read19 min · Scope → Isolate → Supervise → Land · Updated 2026-09-13

You end this lesson with: fleet/task-template.md — an agent-sized task spec, plus your own backlog split into parallel and sequential.

Chapters

  1. What is actually going on
    01
  2. The rule and its condition
    02
  3. Worked case
    03
  4. Faded case
    04
  5. Open case
    05
  6. Where this breaks
    06
view

Lesson 02. Only Some Work Is Fleet-Shaped

Anchorwell, a four-engineer devtools startup, dispatched five agents at one feature: a checkout redesign that touched the cart component, the pricing service, the order API, and three call sites of a shared PriceBreakdown type nobody had written yet. Four of the five agents spent their first twenty minutes guessing at that type's shape, because the fifth agent, the one actually defining it, was still mid-task. Two guessed the same field name with different casing. When the fifth agent finished, three of the four rewrote their work against the real interface. The fourth had already opened its PR against the guessed shape, and it merged before anyone noticed the mismatch, so two versions of the same field lived in the codebase by lunch. The day's token bill ran five times a single agent's normal load. By evening, exactly one of the five diffs had landed clean. Throughput went down. The bill went up. Decide now: was five agents too many, or was this task never parallel to begin with?

This lesson's deliverable is fleet/task-template.md, an agent-sized task spec plus your own backlog split into parallel and sequential work. It is the second document of Scope, the stage that decides whether a task is fleet-shaped before you spend an agent-hour finding out the hard way.

What is actually going on

A backlog item sized for a sprint is not automatically five agent-sized tasks; splitting it well is a decomposition problem before it is a dispatch problem. Graph Engineering owns the general theory of turning work into a dependency graph, and this lesson does not re-derive it: the only test that matters here is whether two tasks touch the same artifact.

Two conditions decide whether agents can run at the same time without stepping on each other. The tasks must touch disjoint files, and they must not share an interface that nobody has defined yet. Miss the second condition and file-level independence buys you nothing, because every agent that reads an undefined type is really reading a guess, and five guesses at the same shape rarely agree. Anchorwell's checkout task failed on exactly that condition: four files, four agents, one type none of them owned.

The fix is not "run fewer agents." It is to make the interface a task of its own, finish it first, then fan out. One agent writes PriceBreakdown, commits it, and only then do the three consumers start. The picture below is that fix, drawn as a sequence: an interface committed once, read by three, instead of five agents each inventing their own copy.

diagram
drawing
The interface is written once by one agent before the other three read it, instead of five agents each guessing its shape.

Nothing in that picture depends on how many agents you have. It depends on whether the interface exists yet. That is the whole mechanism this lesson teaches: one writer per artifact, many advisors, never many writers on the same undefined thing.

Getting the split right is necessary and not sufficient. Even a correctly split batch of parallel tasks costs more tokens than the same work done by one agent in sequence, because each parallel agent carries its own copy of the system prompt and repository context instead of sharing one warm session. Lesson 03 prices that difference; this lesson only asks whether the split is safe, not whether it is cheap. Treat the two questions as separate: a task can pass the split test and still be the wrong task to run in parallel once you know what it costs.

The rule and its condition

Split by artifact boundary, not by task size. Two files that fit in one afternoon are still a collision if they share an undefined interface; two files that would each take a day are safely parallel if they do not. Ask two questions before you dispatch anything: do the tasks touch disjoint files, and do they share an interface nobody has written yet. The answer sorts every task into one of three shapes.

ShapeWhenWho writes whatCost of getting it wrong
ParallelDisjoint files, no shared undefined interfaceOne writer per file, dispatched togetherWasted tokens on a real collision, caught at merge
Contract-firstDisjoint files, a shared interface neither has writtenOne agent writes the interface as its own task, then the rest fan outEvery consumer guesses, and the guesses disagree, exactly as at Anchorwell
SequentialOne task's output is another's inputOne agent finishes before the next startsRunning them together burns tokens on work that has to be redone anyway
diagram
drawing
Task size never appears in this decision; only file overlap and interface state decide it.

The middle branch is the one teams skip, because "disjoint files" looks like enough evidence to fan out. It is not. A shared, undefined interface turns four independent-looking tasks into four writers of the same thing, and the diff that merges first wins by accident rather than by design.

Worked case

Anchorwell rebuilt their backlog the following week using the split test, and it changed how they sized work, not just how they scheduled it. Six tickets sat in the queue: rename a config key across two files, add rate limiting to three unrelated API routes, migrate a database column, write a new PriceBreakdown type and three consumers of it, fix a flaky test, and refactor a shared logging wrapper used by both the cart and pricing services.

Decide now: which of the six run together, which run one after another, and which need a contract task inserted first?

The rename (two files, no shared undefined interface) is parallel with itself split into two single-file tasks; there is nothing to contract. Rate limiting on three unrelated routes is parallel outright: three files, three writers, no shared type. The database migration is sequential on its own consumer code, because the column has to exist before anything reads it. The PriceBreakdown work is the contract-first case from the opening, now written up properly. The flaky test fix is a single task, trivially parallel with everything else because it touches one file nothing else depends on. The logging wrapper refactor is the one Anchorwell got wrong the first time: cart and pricing both import it, and "refactor the wrapper" and "update both call sites" were written as one ticket. Split that way, one agent ends up editing three files with two different consumers reading a wrapper mid-change. The fix is the same contract-first shape as the pricing type: refactor the wrapper as its own task, land it, then the two call-site updates run in parallel against the finished interface.

Each surviving task then gets a written spec, not a one-line ticket. Anchorwell's template for the rate-limiting task looked like this:

markdown
# Task: add rate limiting to /orders

Goal: 429 after 100 requests/minute per API key, matching the limiter
already used on /checkout.
Files it may touch: src/routes/orders.ts, src/middleware/rate-limit.ts (read-only)
Interfaces it must not invent: use the existing RateLimiter class from
rate-limit.ts; do not add a new limiter implementation.
Done test: `bun test routes/orders.rate-limit.test.ts` passes; a 101st
request in the test returns 429.
Ceiling: 30 minutes wall-clock, 150K tokens. If either is hit, stop and
report what is blocking, do not keep retrying.

The ceiling line is not decoration. Anchorwell's own account of building a multi-agent research system found that token usage alone explained roughly 80% of the variance in how well a run performed, and that a genuinely multi-agent run can cost on the order of fifteen times the tokens of one agent doing an equivalent single-pass task (Anthropic engineering: building a multi-agent research system, observed 2026-09-11). A task with no stated ceiling does not fail cheaply; it fails by quietly consuming ten times its expected budget before anyone checks. The same writeup names a second discipline worth borrowing directly: the agent that owns the decomposition never delegates the job of reconciling results back down to a subagent. Whoever wrote PriceBreakdown as a contract-first task is also the one who resolves any disagreement about its shape; that responsibility does not get handed to whichever consumer finishes first.

A runtime's own operational limits are a second kind of ceiling, and they belong in the same field. GitHub's Copilot coding agent stops a cloud session at a fixed wall-clock limit of 59 minutes, a hard cap that cannot be extended from inside the run (GitHub Copilot cloud agent docs, observed 2026-09-11). A task sized to need ninety minutes of continuous tool use is not fleet-shaped for that runtime regardless of how cleanly its files split; it needs to be cut into two tasks with a handoff between them, or moved to a runtime without that ceiling.

One more sizing question sits underneath all of this: how much do you let one agent own before you check in. Anchorwell's rate-limiting tickets are a clean case for one-agent-per-task: narrow scope, fast review, cheap to discard if one goes wrong. A larger, multi-file feature owned end-to-end by a single agent over several hours is a different bet, and the two are worth naming separately rather than treating "give it to an agent" as one decision.

One agent, one narrow taskOne agent, one whole feature
Review burdenLow and frequentHigh and infrequent
Cost if it goes wrongLow: discard one small diffHigh: hours of drifted work to unwind
Parallel-friendlyYes, this is the default shape in the table aboveRarely: feature-scoped runs tend to serialize on shared files anyway
What it needsA written task spec and a done testThe checkpoint discipline Module 4 covers, because a long unsupervised run can drift off spec for hours before anyone reads the diff

Default to the narrow shape. Reserve the wider one for work you are prepared to watch, not for a backlog item that simply looked too tangled to split.

Faded case

Skip to the open case if this is familiar.

Anchorwell's second backlog batch, the following sprint: rewrite the onboarding email copy (one file, src/emails/onboarding.ts), add a /health endpoint (one new file, no dependencies), extract a shared formatCurrency helper that three billing screens currently duplicate slightly differently, and update those three billing screens to use it once it exists.

The first two are a clean pair: disjoint files, nothing shared, dispatch together. The billing work is where the decision is left to you. Three screens currently each have their own slightly different currency-formatting logic. The ticket as written says "consolidate currency formatting across billing." Decide the shape for the consolidation work, and say what happens if you dispatch all four billing-related tasks (the extraction plus the three screen updates) as one parallel batch instead.

Open case

A three-person team has one backlog item: "add CSV export to the reports page." It touches a new export button component, a serialization function that two of the three report types already share, and a backend endpoint that streams the file. The third report type needs a currency-rounding decision nobody on the team has made yet, and that decision affects the serialization function all three report types will eventually call. Split this into tasks, state the shape of each, and write the ceiling field for the piece most likely to run long. The quiz's first question grades your split.

Where this breaks

The split test answers "can these run together" and says nothing about whether they should stay together once they are running. A contract-first interface can itself be contested: two engineers disagree about what PriceBreakdown should contain, and the agent writing it has no way to know that from the ticket alone. Sizing by file overlap also misses semantic coupling: two files that share no import can still share an invariant, like an assumption about which service owns a piece of state, and nothing in this lesson's test catches that. Module 4 covers the case where two individually correct changes are jointly wrong; this lesson only prevents the version where they are jointly wrong because they were never independent to begin with.

The ceiling field is a stated budget, not a guarantee. An agent that quietly summarizes and continues past a filling context window can drift off the original spec well before it reports anything is wrong, and a wall-clock or token ceiling catches that late, if at all. Treat the ceiling as the point where you check in, not as proof the work stayed on task.

And the split test says nothing about who reviews what comes back. A backlog correctly sorted into ten parallel tasks still produces ten diffs that need reading, and sorting work well is not the same problem as having the review capacity to accept it. Lesson 11 names that ceiling directly; this lesson only keeps you from creating more diffs than the split itself required.

Key Takeaways

  • Split by artifact boundary, never by task size; a shared undefined interface beats disjoint files every time.
  • Write the contract as its own task before you fan out consumers against it.
  • State a ceiling on every task: wall-clock, tokens, or the runtime's own hard limit, whichever binds first.
  • Keep synthesis with whoever owns the decomposition; never hand reconciliation down to a subagent.
  • Prefer narrow, one-agent-per-task tickets; reserve wide feature ownership for work you can watch closely.

What You Have Now

fleet/task-template.md, an agent-sized task spec plus your own backlog split into parallel and sequential, sits in your growing Fleet Kit next to fleet/topology.md from Lesson 01. It closes Scope's second question: not just where you sit on the four axes, but which of your own tickets are actually safe to hand to more than one agent at once. Lesson 03 prices every row of that split; Module 2 isolates whatever you marked parallel so the agents running it do not collide the way Anchorwell's did.

Further Reading

Exercises

  1. Take five tickets from your own backlog and run the two-question split test on each. Write the shape (parallel, contract-first, sequential) and the one sentence that justifies it.
  2. Write a full fleet/task-template.md entry, in the format shown in the worked case, for the ticket in your backlog most likely to run long. State a real ceiling: your runtime's actual wall-clock limit if it has one, and a token figure from a comparable past run.
  3. Find one ticket in your backlog that looks parallel on file overlap alone. Check it against the second question (a shared undefined interface) and decide whether it needs a contract-first task inserted before you dispatch it.

Check your understanding


Reading is free — your progress isn't being saved

Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.

30-day money-back guarantee. One-time payment — lifetime access and updates.