Two background agents finish within a minute of each other. The first added rate limiting to your API and, while it was in there, reorganized the route registrations. The second added webhook handlers and registered them in the same file. Each diff is clean alone; together they cannot land, because the same stretch of routes.ts exists in two incompatible versions. You spend the evening hand-merging machine output, the exact work you ran two agents to escape.
The failure was in how the work was split, not in the agents: it was divided by feature even though both features still wrote to the same file. Why one agent stops being enough covered when to reach for a fleet. This chapter is about the split itself, how to divide work so the pieces never collide.
Give every work item a three-part contract
The unit you hand to a fleet is not a task in the to-do-list sense. It is a work item with a contract, and that contract has three clauses.
- Gets. The inputs and context the agent receives: the files it may read, the spec section it implements, the sample data, and the decisions it must treat as fixed.
- Returns. The deliverable and its form: a file at an agreed path, a pull request against a named branch, a JSON object in a fixed schema. Form is binding because something downstream, a merge step, another agent, or you, consumes the return without a conversation.
- Must not touch. The adjacent things this item would plausibly modify but may not: files outside its slice, settled decisions it may not reopen, neighboring scope it may not absorb.
The third clause is not the standing safety net from Guardrails: keep secrets, money, and data safe, which applies to every run. It records the specific things this one item is likely to bump into, and that precision is what lets you catch collisions on paper.
Contracts matter because the alternative is constant back-and-forth, and Brooks's law tells you what that costs: the communication channels on a job grow with roughly the square of the headcount. Fleets pay that cost even more steeply than human teams, because every clarification between two items is a round-trip that you have to mediate yourself. A fleet only scales when the contract already holds every answer the agent would otherwise stop to ask for.
The test for the whole split is simple: two strangers should be able to finish two items without exchanging a single message.
Split along the lines where pieces share nothing
Most deliverables have natural dividing lines.
- By file. Each item owns one file or folder: one parser per format, one component per screen. No two diffs can overlap.
- By section. Each item writes one assigned section against a shared outline, and the merge is assembly plus a single pass for voice.
- By entity. One item per customer, endpoint, competitor, or data source. Research, audits, and migrations usually cut here.
- By time-slice. One item per week of logs, per quarter of transactions, per release.
The pattern is older than agents. MapReduce, the framework Google published in 2004 for splitting batch jobs across clusters, made it standard: a map phase of independent pieces, then a reduce phase that merges them, with the merge designed before anything runs. Teams tend to remember the map and forget the reduce. Deciding how the returns will combine is part of the split, not a cleanup step to improvise later, so if you cannot say how the pieces merge before the first agent spawns, the split is not finished.
Sort work into parallel, sequential, or shared-context
- Parallel work has no dependencies between items, so all the agents can run at once. Fleets are built for this kind of work, and the dividing lines above are where you find it.
- Sequential work has an order to it: item B's gets include item A's returns. The contract still makes each handoff checkable, but the items form a pipeline rather than a fan-out, and elapsed time adds up stage by stage.
- Shared-context work does not split at all. Some work is a single chain of interlocking decisions: an architecture sketch, a refactor that threads through everything, writing that needs one voice. Split it and each run answers the open questions differently, producing pieces that read fine alone but contradict each other once you merge them, so keep this kind of work in one thread where running a fleet would only produce the wrong result faster.
Agents collide when two of them can write to the same thing
The opening collision shows the cause behind nearly every fleet pileup: two items that can both write to the same thing, whether that is a file, a config, or a schema. The fix is to give each item territory it alone owns, its own file, folder, or branch, with no write target in two contracts.
The industry has settled on this pattern. GitHub's Copilot coding agent takes one assigned issue and returns one pull request for human review: the issue is the item, the branch behind it is the territory, and the review is where one human decides each merge rather than letting two agents collide.
How small to make each item
This trade-off goes wrong in both directions. Every item carries a fixed overhead no matter its size: spawning it, loading its gets, and the gathering and review you owe every return. Split a day into dozens of tiny items and that overhead alone eats the day, paid over and over for a few minutes of real work each. Split it into two giant items and each one's context fills up past the point where it is useful, the same context engineering problem you ran a fleet to escape, now happening twice.
The working size is roughly the issue again: a bounded, nameable change one person could take away and finish alone, returning a diff a reviewer can hold in one sitting. A few checks keep you in that range.
- If the three clauses do not fit in a few lines, the item is too big or you do not understand it yet.
- If writing the contract takes longer than doing the work, the item is too small, so fold it into a neighbor.
- If you cannot review a return without opening another item's return, the items are not independent at any size, so fix where you split rather than how small.
Try it now
The drill is paper only; no agents run yet.
Pick one real deliverable. Something on your plate this week that is too big for one session, like a feature with several endpoints or a data migration.
Write the cut-list. Five to eight items, each as the three short contract lines from earlier: gets, returns, and must-not-touch, with the returns pinned down to path and format.
Run the collision check. Compare the must-not-touch lines across items. Any entry that appears twice is a predicted collision, so re-cut until none repeats, either moving the shared thing inside one item or pulling it out into a merge step you run yourself.
Classify each item. Mark each parallel, sequential, or shared-context, noting which return feeds which gets. Shared-context items come off the list and stay in your own thread.
Finish with the stranger test. For each pair of parallel items, ask whether two strangers could do both without exchanging a message. Where the answer is no, the missing message is an unwritten contract clause, so add it to gets or returns and test again. Keep the list; it becomes raw material when you write your Orchestration Plan and run your first fleet.
Chapter Summary
- How you split the work sets the ceiling for the whole fleet: clean contracts need almost no coordination, while one shared file turns you into a referee for the evening.
- Give every work item a contract with three clauses: gets, returns, and must-not-touch.
- Split along the lines where pieces share nothing: by file, by section, by entity, or by time-slice.
- Decide how the returns will merge before you spawn the first agent. The merge is part of the split, not a cleanup step for later.
- Two agents that can write to the same file, config, or schema will collide, so give each item its own territory and let nothing be written by two items at once.
- Sort each item as parallel, sequential, or shared-context, and keep shared-context work in a single thread instead of handing it to a fleet.
- Size each item like a GitHub issue: small enough to review in one sitting, big enough that writing its contract is faster than just doing the work.
- The test for a good split is whether two strangers could finish two items without exchanging a single message.
- Next up is Patterns: fan-outs, pipelines, and judge panels, which covers how to arrange the pieces once you have them.
Sources
- Dean, J., and Ghemawat, S. (2004). MapReduce: Simplified Data Processing on Large Clusters. OSDI.
- Brooks, F. P. (1975). The Mythical Man-Month: Essays on Software Engineering. Addison-Wesley.
- GitHub documentation on the Copilot coding agent (2025).