Building a Multi-Agent Research System with Isolated Contexts
▶ Watch on YouTube & subscribe to The Stack Underflow
Give one agent a hard research question and watch it drown. By the time it has fetched 40 sources, run a dozen tool calls, evaluated counterarguments, and started writing, the context window looks like a junk drawer. Earlier facts get crowded out. Contradictions appear — not because the underlying sources disagree, but because the model can no longer reliably attend to all of its own prior reasoning at once. Output quality degrades in direct proportion to how full the context is.
The instinct is to reach for a bigger model or a larger context window. Both help at the margins. Neither fixes the root problem, which is architectural: you are asking one agent to be a researcher, an analyst, a fact-checker, and a writer simultaneously, in a single shared workspace. The right fix is context isolation — splitting that work across multiple agents, each with its own clean window, each returning only what the next layer needs.
The one-sentence version: Split research across isolated subagents with scoped tools, have each one return a structured claim-to-source mapping, and funnel those into a synthesis agent that can only compose — never fetch — so every citation in the final report is provably real.
Why One Agent Fails at Scale
The context window is the model’s working memory: everything it can attend to in a single forward pass. As of mid-2026, Claude models like Claude Opus 4.8 and Claude Sonnet 4.6 support up to 1 million tokens — but raw capacity is not the same as reliable attention. Research by Anthropic’s engineering team on their own multi-agent research system (published June 2025) found that a single-agent setup on complex queries showed degraded coherence well before the window filled, simply because the signal-to-noise ratio of the context dropped too low (Anthropic Engineering, 2025).
The failure mode looks like this:
Single agent context after deep research:
[system prompt]
[user query]
[search 1 results — 3000 tokens]
[tool: fetch page A — 4500 tokens]
[tool: fetch page B — 6200 tokens] <-- dead end, irrelevant
[tool: fetch page C — 5800 tokens]
[intermediate reasoning — 800 tokens]
[search 2 results — 2400 tokens]
... 12 more rounds ...
[WRITE THE REPORT NOW] <-- model attends to last few k
By the write step, the early evidence is buried under everything that came after. The model “knows” what it found, but its attention weights favor recency. Citations get confabulated. Contradictions between early and late findings go unresolved.
The Four-Component Architecture
The solution is to stop asking one agent to hold the whole mess. You break the pipeline into four components with explicit data contracts between them.
+---------------------------+
| Coordinator |
| (dispatches, assembles) |
+------+------+------+------+
| | |
+---------+ +---+---+ +---------+
| | |
+------+------+ +------+------+ +------+------+
| Subagent A | | Subagent B | | Subagent C |
| Primary Srcs | | Recent News | | Counterargs |
| search+fetch | | search+fetch | | search+fetch |
+------+-------+ +------+-------+ +------+-------+
| | |
+------+--------+------+------+
|
+------+------+
| Synthesizer |
| (no fetch, |
| compose only)|
+-------------+
Coordinator — receives the original query, decomposes it into research angles, dispatches work to subagents, collects their structured outputs, and hands the assembled payload to the synthesizer. It does no research itself. Its context stays narrow.
Subagents A, B, C — each tackles one dimension of the question in its own isolated context window. They run in parallel, so total wall-clock time is bounded by the slowest agent, not the sum of all three. Typical split:
| Subagent | Angle | Retrieval strategy |
|---|---|---|
| A — Primary Sources | Foundational evidence, canonical papers, official docs | search + fetch for authoritative domains |
| B — Recent Developments | News, blog posts, recent announcements | search with date-filtered queries |
| C — Counterarguments | Critiques, dissent, limitations | search for challenge-framing queries |
Synthesizer — receives only the distilled, structured outputs from the coordinator. Its search and fetch tools are disabled. It can only compose. This constraint is load-bearing — it is what makes provenance provable.
Isolated Context Bubbles
The phrase context isolation means something precise here: each subagent’s intermediate work — the failed searches, the irrelevant pages, the noisy tool results — stays sealed inside its own context bubble. Only the distilled result travels upward to the coordinator.
This is exactly how the Claude Agent SDK implements subagents (documented at docs.anthropic.com): each subagent runs in its own fresh conversation. Intermediate tool calls and results stay inside the subagent; only its final message returns to the parent.
Subagent B internal context (sealed):
[subagent system prompt]
[query: "recent news on constitutional AI, last 90 days"]
[search: "constitutional AI 2026" -- 14 results]
[fetch: article 1 -- 3200 tokens, mostly off-topic]
[fetch: article 2 -- 2800 tokens, relevant]
[fetch: article 3 -- 4100 tokens, partially relevant]
[reasoning over fetched material]
[RETURN: claim+source mapping] <-- ONLY THIS leaves the bubble
Coordinator context (clean):
[coordinator system prompt]
[original user query]
[subagent A result: {claims: [...]}]
[subagent B result: {claims: [...]}] <-- small, structured
[subagent C result: {claims: [...]}]
The coordinator’s window stays clean enough to reason reliably about what the researchers found — without ever seeing the messy process they used to find it.
| Layer | What it sees | What it does NOT see |
|---|---|---|
| Coordinator | Subagent distilled claim-source payloads | Raw tool calls, failed searches, fetched HTML |
| Subagent | Its own full research context | Other subagents’ work entirely |
| Synthesizer | Structured claim+source mappings from coordinator | Anything outside what coordinator assembled |
Scoped Tools Per Role
Tool scoping is the architectural rule that each agent gets only the tools its role requires — and no more. Researchers need search and fetch. The synthesizer needs neither.
// Subagent configuration
{
"model": "claude-sonnet-4-6",
"tools": ["search", "fetch"],
"system": "You are a research specialist. Return only
structured claim-source mappings, not prose."
}
// Synthesizer configuration
{
"model": "claude-opus-4-8",
"tools": [],
"system": "You receive pre-verified claim-source mappings.
Compose them into a coherent report. Do not
introduce any claim not present in your input."
}
Why does this matter for more than security? If the synthesizer could call fetch, it might quietly introduce claims that were never verified by the subagents. The citation chain breaks. The provenance guarantee — that every claim in the final report traces back to a source a subagent actually retrieved — becomes unverifiable. Disabling the tools is not a restriction, it is a contract enforcement mechanism.
| Role | Tools enabled | Why |
|---|---|---|
| Subagent (researcher) | search, fetch | Needs to retrieve and evaluate sources |
| Coordinator | (none, or task management only) | Dispatches and assembles — does not research |
| Synthesizer | (none) | Compose-only: provenance contract requires it |
Provenance-Preserving Output Contracts
Provenance is the ability to trace every claim in the final report back to the specific source a subagent actually retrieved. It survives synthesis only if the data contract between layers is structured — not free-form prose.
When a subagent finishes, it returns a JSON payload in which each claim is explicitly paired with its source:
{
"subagent": "B",
"angle": "recent-news",
"claims": [
{
"claim": "Claude Opus 4.8 supports parallel subagent runs
lasting multiple hours in a single session.",
"source": "https://www.anthropic.com/news/claude-opus-4-8",
"quote": "Claude can plan the work and then run hundreds of
parallel subagents in a single session...",
"retrieved": "2026-06-20"
}
]
}
The coordinator assembles these payloads from all three subagents and passes the merged structure to the synthesizer. The synthesizer weaves the claims into prose while preserving inline citations. The final report carries real citations — not confabulated ones — because the synthesizer had no ability to introduce anything else.
This is what Anthropic’s engineering team calls the provenance contract: structure the inter-agent data exchange so that attribution survives the summarization step, rather than getting laundered away into generic prose. Without it, you have a research pipeline that sounds authoritative but whose citations you cannot actually verify.
Verifying That Isolation Held
You can prove the bubbles stayed sealed. The test is simple: scan the coordinator’s messages array and assert that zero subagent tool_use or tool_result blocks appear in it. If they do appear, a subagent’s raw context leaked upward and the isolation is broken — you are back to the single-agent flooding problem, just with more components.
def assert_bubbles_sealed(coordinator_messages: list) -> None:
"""
Asserts that no subagent tool blocks leaked into
the coordinator's context.
Raises AssertionError with details if the check fails.
"""
for i, msg in enumerate(coordinator_messages):
content = msg.get("content", [])
if isinstance(content, list):
for block in content:
assert block.get("type") not in (
"tool_use", "tool_result"
), (
f"Subagent tool block found in coordinator "
f"at message index {i}: {block.get('type')}"
)
print("Isolation verified: bubbles stayed sealed.")
Run this assertion after every research session during development. It is a cheap, definitive check. If it fails, find where the raw tool output is being forwarded rather than summarized — that is the break in the architecture.
How to Apply This Pattern
The coordinator-subagent-synthesizer pattern generalizes beyond research. Here is a practical checklist for standing one up:
Step 1 — Partition by information type, not topic. Primary sources, recent developments, and counterarguments are natural partitions because they need different retrieval strategies and have different freshness requirements. Other valid axes: geographic region, stakeholder perspective, time period.
Step 2 — Write tight subagent system prompts. Each subagent needs: its specific objective, its required output format (the claim-source schema), guidance on which sources or domains to prioritize, and explicit scope limits (“do not cover counterarguments — that is a different subagent’s job”). Anthropic’s engineering notes stress that subagents need clear task boundaries to avoid redundant or conflicting retrieval (docs.anthropic.com/en/docs/claude-code/sub-agents).
Step 3 — Choose models by role. As of mid-2026, Claude Sonnet 4.6 is a strong default for subagents — fast, capable of structured output, good at constrained retrieval tasks. Reserve Claude Opus 4.8 (or Claude Opus 4.7 for cost-sensitive workloads) for the synthesizer, where the quality of final composition matters most.
Step 4 — Disable tools at the synthesizer level, not by prompt. Telling the synthesizer “do not search” in a system prompt is a soft constraint. Passing an empty tools array is a hard one. Use the hard one.
Step 5 — Assert the isolation. Run the bubble-seal assertion in your test suite, not just manually. If the architecture breaks under load or code changes, you want a failing test, not a degraded research report that is hard to diagnose.
Common Misconceptions
“A bigger context window solves this.” Raw capacity is not the same as reliable attention. Even Claude Opus 4.8’s 1M-token window does not fix the signal-to-noise problem that emerges when a single agent fills its context with raw research intermediaries. Structured delegation is a fundamentally different solution to a different problem. The window size matters when one agent genuinely needs to process a large coherent document; it does not help when the problem is messy multi-step retrieval.
“The synthesizer should be able to look things up if it needs to.” This collapses the provenance guarantee. The moment the synthesizer can fetch, it can introduce unverified claims into the final report — and you cannot tell from the output whether a citation came from a subagent or from the synthesizer freelancing. Keep it compose-only. If the synthesizer finds a gap, it should signal that the coordinator should dispatch another subagent, not fill the gap itself.
“Running three parallel subagents triples my token cost.” Parallel subagents cost roughly the same tokens as running them sequentially — you are doing the same research either way. They complete faster because they run concurrently, and each subagent works on a narrower, cleaner context, which tends to reduce hallucination risk and improve citation quality. The real cost driver is retrieval depth (how many sources each subagent fetches), not parallelism itself.
“Structured subagent outputs are unnecessary overhead.” Free-form prose between agents is where provenance dies. When a subagent returns “The paper introduced Constitutional AI in 2022” as prose and the synthesizer rephrases it, the source attribution has already begun to erode. The claim-to-source mapping is the data contract that makes the whole pipeline auditable. It is also what lets you render proper inline citations rather than footnotes that say “model output.”
Frequently Asked Questions
How do I pick what each subagent researches? Partition by information type, not by topic. The natural split — primary sources, recent developments, counterarguments — works because each angle needs different retrieval strategies and has different freshness requirements. Recent news needs date-filtered queries; primary sources need domain authority filtering; counterarguments need adversarial query framing. If your domain has other natural axes (geographic regions, stakeholder groups, regulatory jurisdictions), those can work too. The key is that each partition is internally coherent — a subagent should not need to context-switch between search strategies mid-run.
What happens when subagents return conflicting claims? The synthesizer receives all three structured payloads simultaneously and sees the conflict explicitly — two claims, each with its own source. It can note the disagreement in the final report, attributing each position to its source. This is actually a strength of the architecture: conflicts become explicit and citable rather than silently averaged away or dropped because one fact crowded out the other. A single-agent system would often pick one and discard the other; the multi-agent system preserves both with attribution.
Can I use more than three subagents? Yes, up to the point where the coordinator’s context fills with distilled outputs. In practice, three to five subagents covers most research tasks cleanly. Beyond five, you start needing hierarchical coordination — coordinators that coordinate other coordinators — which adds architectural complexity. Start with three, add a fourth for a specific dimension if the first three leave a consistent gap, and reach for hierarchical coordination only when a flat topology genuinely cannot cover the scope.
Does the synthesizer ever need any tools at all?
For pure research aggregation: no. If your synthesis step also needs to produce formatted artifacts — render a chart, call a formatting API, write to a database — you can add narrow, non-retrieval tools scoped to that output action. The hard constraint is: no search, no fetch. Those must stay with the researchers. Any tool that reads external content at synthesis time breaks the provenance contract.
How does this relate to the Claude Agent SDK? The Claude Agent SDK (launched 2025, documented at docs.anthropic.com) implements exactly this pattern natively. Each subagent runs in a fresh conversation with its own context. Only the final message returns to the parent agent. The SDK handles the spawning, parallelization, and result collection; you write the coordinator logic and the subagent system prompts. Anthropic’s own internal research system uses this architecture and published the design in June 2025.
What model should I use for each role? As of mid-2026: Claude Sonnet 4.6 is the practical default for subagents — good structured-output quality, fast, cost-efficient at scale. Claude Opus 4.8 for the synthesizer when final report quality is the priority; Claude Opus 4.7 if you need to optimize cost while keeping strong synthesis quality. The coordinator itself does minimal work (decompose, dispatch, assemble) and can run on Sonnet 4.6. Do not over-provision the coordinator — it is not doing the hard reasoning.
Where This Fits in the Series
This tutorial is the third capstone scenario in How Claude Actually Works, sitting at the top of the stack where token mechanics, context management, and tool architecture converge into a production pattern. The prerequisites are context window mechanics, how tool use works, and MCP fundamentals — these give you the building blocks that the coordinator-subagent pattern assembles. The Claude Agent SDK explained tutorial covers the SDK primitives this pattern runs on. If you are newer to the series, the Claude Stack mental model is the right starting point.
The next tutorial in the sequence — Structured Data Extraction Pipeline — picks up where this one leaves off: once you have a multi-agent system returning structured claims, the next question is how to extract precise, typed data from unstructured sources at scale.
Browse all tutorials to see the full sequence.
Found this useful? The deep version lives on YouTube — new breakdowns of how AI dev tools actually work, weekly.
Subscribe on YouTube →