Parallel Fan-Out and Join
Open mutually independent work at the same time, and wait to join it back together at the one point where nothing can be decided until every result is in. The hard part isn't the opening — it's where to wait, when to stop, and what to do with a branch that failed, and no tool decides those for you.
Problem
Ask "look into these three libraries and tell me which to use," and they usually get investigated one after another. But that ordering doesn't exist because each step consumes the previous one's output. It exists because that's how the request was phrased. The three investigations never reference each other. Ordering dependency and data dependency have been conflated.
The cost of that conflation isn't only latency. Read all three in a single context and three investigations' worth of clutter piles up in the same place, so by the time the comparison happens the first one read has faded. Not splitting the work damages both the wall clock and the context.
Yet the moment the work is split, three questions appear that didn't exist before. When does the joining happen? If one branch out of three fails, is the whole thing discarded? What ends an open-ended search? Tools supply the mechanism for opening branches in parallel; answering these three is left to the practice.
Context
Applies when:
- The branches don't need each other's results — three libraries to investigate, four review perspectives, the same question asked of several repositories
- Each branch's result compresses into a summary — the joining side doesn't have to receive full text
- The judgment only becomes possible after joining — comparison, ranking, or synthesis sits at the end
Doesn't apply when:
- Every branch must share the same context, or the branches depend heavily on each other. This isn't speculation — it's a limit the Official docs name explicitly, and the same source goes as far as saying most coding tasks contain fewer truly parallelizable parts than research does (source in the Practice section)
- There are only one or two branches. Designing the fan-out and the join costs something in itself. The round trips of opening and joining can exceed the cost of just reading in sequence
- The cost can't be paid. More branches means more interactions with the model. The price tag belongs to The Break-Even Point of Delegation
Boundaries with adjacent patterns:
- Read-and-Discard Isolation — that pattern handles the inside of a single branch (what to discard, what to bring back as a summary). This pattern handles how many branches there are and how they get bundled
- The Break-Even Point of Delegation — that pattern is the price tag on whether to delegate; this one is the arrangement after delegation has been decided
- Session Boundary Design — both touch "when to stop," but the trigger differs. That pattern's trigger is context degradation; this pattern's trigger is new results having dried up
- Computation as Code — at the join point, merging, deduplicating, and normalizing results are settled procedures. That pattern takes over that portion
Solution
First, separate ordering dependency from data dependency. Of the steps written as "then do this," which ones actually read the previous output? The ones that don't have no reason to be in a row. Only a person who knows the substance of the work can make this distinction; the tool simply follows the order it was given.
Second, put the waiting point only where nothing can be decided until every result is in. Comparison, ranking, and synthesis qualify. Conversely, if something can proceed each time one branch reports, that isn't a waiting point. Every additional waiting point pushes the shape back toward sequential and erases the reason for splitting. Splitting and joining are a pair: split without deciding how to join, and the joining place never gets decided at all.
Third, decide in advance what a failed branch means. If one of three fails, may the judgment proceed on the remaining two, or is a judgment without all three meaningless? The nature of the work decides this — not the tool's default. If "we could only look at two of the three libraries" is an acceptable basis for the choice, the branch can be cut loose; if it isn't, the whole thing gets redone. ⚠ Within the range checked, neither vendor's primary sources recommend this "cut it loose and continue" (Absence Confirmed; search terms and range in the Practice section). There are nearby statements, but they are about resuming from where a failure occurred — not about cutting a branch loose.
Fourth, give an open-ended search a stopping rule from outside. Requests of the form "collect everything that might be relevant" have no natural end. One way to stop: check whether what comes back duplicates what's already held, and call it off once a stretch produces nothing but duplicates. ⚠ This too is absent from the primary sources (Absence Confirmed). What's nearby is "let the model judge whether enough information has been gathered," which is a different thing from imposing a mechanical stopping condition from outside. The former depends on the model's judgment; the latter doesn't.
Of the four, tools help with the first and partway into the second. The third and fourth are, within the range checked, territory where nobody has written a recommendation, so whoever is doing the work has to decide. Run without deciding, and the default behaviour becomes the policy.
Trade-offs
Benefits
- Wall clock shrinks to the slowest single branch instead of the sum
- Branches' clutter doesn't mix. Only summaries arrive at the join, so the first investigation hasn't faded by the time of the comparison
- Tools and permissions can differ per branch. The joining side doesn't need to know how each branch went about it
Costs
- Consumption goes up. Each branch generates its own interactions with the model. Both vendors state this in Official docs (Practice section). The price tag belongs to The Break-Even Point of Delegation
- Branches don't know about each other. If two of them investigate the same thing, that can't be noticed while they run — only once they join
- Deciding the shape takes effort. Where to wait, what a failed branch means, and when to stop have to be decided per task. For a two-branch job, that effort costs more than it saves
GitHub Copilot in Practice
The mechanism for opening branches in parallel exists on several surfaces. Recommendations about joining, failure, and stopping do not exist within the range checked. Below, the mechanisms surface by surface, then the range over which the absences were confirmed.
Copilot CLI — instruct parallelism with /fleet
Parallelism can be requested from the human side (source: Running tasks in parallel with the /fleet command, retrieved 2026-07-16) Official:
Context window: Each subagent has its own context window, separate from the main agent and other subagents. This allows each subagent to focus on its specific task without being overwhelmed by the full context of the larger task.
The same page also states the cost Official:
Each subagent can interact with the LLM independently of the main agent, so splitting work up into smaller tasks that are run by subagents may result in more LLM interactions than if the work was handled by the main agent. Using
/fleetin a prompt may therefore cause more GitHub AI Credits to be consumed.
VS Code — the branch contract comes from the human
On the surface where the main agent spawns subagents, the official docs say to state what each branch is to do and to return (source: Subagents in Visual Studio Code, retrieved 2026-07-16) Official:
To optimize subagent performance, clearly define the task and expected output.
That is the design of the join point itself. If the shape the joining side receives isn't fixed, waiting for everything still doesn't make it comparable. But note that the original says only "define it clearly" — it says nothing about where to wait.
The other vendor — joining appears as a description of an implementation
The counterpart primary source (source: How we built our multi-agent research system, retrieved 2026-07-27; 180,431 bytes retrieved in full with curl) states that the current implementation of the research system runs subagents synchronously, waiting for each set to complete before proceeding, with synthesis performed by the lead agent Official. ⚠ The scope is a research system — it is not written as a general design guideline for agents.
The same source names the cases where this doesn't apply, which is the basis for this page's Context section Official:
Further, some domains that require all agents to share the same context or involve many dependencies between agents are not a good fit for multi-agent systems today. For instance, most coding tasks involve fewer truly parallelizable tasks than research, and LLM agents are not yet great at coordinating and delegating to other agents in real time.
⚠ The same source also gives token consumption multipliers, but this page doesn't carry those numbers. The Break-Even Point of Delegation is where they belong. This page states only the direction: it goes up.
What wasn't there (with range)
On 2026-07-27, two subagents separate from the one that fetched the source material retrieved and checked 17 primary sources: eight on the GitHub side (/fleet, three Copilot CLI custom agent references, and VS Code's subagents, agents concepts, overview, and custom agents — all retrieved in full as raw markdown from the official repositories) and nine on the other side (Claude Code best practices, sub-agents, and hooks; the Agent SDK subagents reference; Agent Skills best practices; structured outputs; prompt chaining; the tool use overview; and the research system article above — all retrieved in full).
| What was looked for | Search terms | Result |
|---|---|---|
| Cutting a failed branch loose and continuing | partial / isolat / error propagation / graceful / rather than failing | In the research system article, partial 0 hits, isolat 0 hits. ⚠ What was found is "resume from where the error occurred" and "retries with regular checkpoints" — not cutting loose |
| Stopping via deduplication and a run of empty results | deduplic / new result / stop condition / stopping / converg / termination | In the same article, deduplic 0 hits, new result 0 hits, stop condition 0 hits, converg 0 hits. ⚠ What was found is "let it judge whether enough information has been gathered" and "scale effort to query complexity" — not a mechanical stopping condition |
| An established name for the waiting point | barrier / join | No use as a name could be confirmed. Joining appears as "wait" and "synthesize," and as the ordering of an implementation |
This is Absence Confirmed. It doesn't mean "you shouldn't do this," and it doesn't mean "the capability is missing" — only that no recommendation appeared within the 17 sources checked. This catalogue infers nothing about behaviour from that.
Also Known As
| Name | Source |
|---|---|
| Parallel Fan-Out and Join | Descriptive — this catalogue's descriptive name; no primary source uses it |
Subagent / /fleet | Primary — but these name the mechanism that opens a branch, not this pattern (sources in the Practice section) |
⚠ Don't cite "join," which this catalogue used in the name, as an official term. Across the 17 sources checked, no established name for the waiting point was found. The same goes for the diagrammatic vocabulary the source material uses (nodes and edges, barriers) — treat all of it as this catalogue's coinage.
The reason not to borrow a mechanism's name for a practice is the same one given in Read-and-Discard Isolation. The practice holds even where no parallel mechanism exists — investigating in several separate sessions at once and writing the results back into one place has the same shape regardless of tooling.
Related
- Read-and-Discard Isolation — a single branch of this pattern is that pattern. That one handles the inside of a branch (what to discard, what to bring back as a summary); this one handles how many branches there are and how they get bundled. Only summaries reach the join point because that pattern is doing its work
- The Break-Even Point of Delegation — that pattern holds the price tag. Both vendors' Official docs state that more branches means more interactions with the model (Practice section), and the multipliers and the break-even estimate belong there. This page states only the direction
- Session Boundary Design — the trigger for "when to stop" differs. That pattern's trigger is context degradation; this one's is new results having dried up. Same act of calling it off, different needle being watched
- Computation as Code — it takes over the inside of the join point. Of the bundling work, merging, deduplicating, and normalizing are settled procedures with no reason to be left to inference. ⚠ Note that pattern claims determinism, not that it's cheaper
- Making the Output Contract Explicit — deciding what each branch returns is a precondition for bundling. That pattern handles the shape of output a human receives; here the same problem appears as the shape the joining side receives
- Making the Verification Target Explicit — if what each branch is confirming is left vague, joining them still doesn't make them comparable
- If reading just one more next: The Break-Even Point of Delegation — having decided the shape, it's next to see what the shape costs