~/beer-and-code
▪ next event AI Engineering Lab 4ª Edição — Harness Engineering para Agentes Inteligentes · 14—15 Nov · 14 e 15 de novembro, das 09h às 13h — ao vivo via Google Meet save your seat ›
~ / tutorials / subagents-context-isolation $
Tutorials

Subagents: use them to isolate context, not to build an agent team

LS Lucas Souza · · 11 min read
Subagents: use them to isolate context, not to build an agent team

A subagent is a model call with its own context window, spawned by the main agent to solve a subtask and hand back only the result. The number one reason to use subagents in 2026 isn't building an "agent team". It's isolating context: keeping the search noise, logs and failed attempts out of the main agent's window.

The shift is subtle, but it changes the whole architecture.

In 2024 everybody was drawing org charts: a researcher agent, a writer agent, a reviewer agent, a manager agent, all talking to each other. Looks great on a diagram. Brittle in production.

What teams running agents for real have learned is different: start with a single agent. Add a subagent when the context window becomes the bottleneck. And choose carefully what the subagent sees when it's born.

In this post you'll see when a subagent pays for itself, the difference between isolated and fork modes, and how to implement both in a PHP harness calling the Claude API directly, no framework.

TL;DR

Why subagents became a context tool, not an org chart

In June 2025 Cognition, the team behind Devin, published a post with a blunt title: Don't Build Multi-Agents. The argument is simple and still holds. Subagents working in parallel, each with a partial view, make decisions that contradict each other. Two principles from the post:

  • "Share context, and share full agent traces, not just individual messages."
  • "Actions carry implicit decisions, and conflicting decisions carry bad results."

In other words: every action carries an implicit decision. The subagent that picked one naming pattern never told the other one, which picked another. When you merge, it breaks.

That same week Anthropic published how it built the multi-agent Research system. The numbers are good: Opus 4 orchestrating Sonnet 4 subagents beat a single Opus 4 by 90.2% on their internal research eval. But the same post explains where the gain comes from. On BrowseComp, token usage alone explains 80% of the performance variance. Subagents work because they give the system more context windows to spend in parallel.

And the bill comes with it: agents use about 4x more tokens than a chat, multi-agent systems about 15x. Anthropic itself warns that domains where every agent needs the same context aren't a good fit, and that "most coding tasks involve fewer truly parallelizable tasks than research".

Put both views together and you get the rule that's becoming consensus in 2026. The Modern Agent Harness Blueprint sums it up in one line: "Use subagents for context isolation, not because 'multi-agent' sounds advanced."

This is the kind of decision that separates a production-grade harness from a pretty demo, and it's exactly what we'll open up live at AI Engineering Lab 4th Edition, November 14 and 15, 9am to 1pm (Brasília time): where to cut the context, what the subagent receives and what comes back, with code running on screen.

When to use subagents (and when not to)

The blueprint lists four legitimate reasons. Outside of them, a single agent with good tools does the job:

  1. Parallel exploration. Searching five sources at once, scanning three large directories.
  2. Separate context window. The subtask generates a lot of noise (search, logs, file reads) and the main agent only needs the conclusion.
  3. Specialized prompt or tools. A reviewer that can only read, never write.
  4. Explicit ownership boundary. Who decides what is clear in the code.

And the signs that you don't need a subagent:

  • The task is sequential and each step depends on decisions from the previous one. Classic coding.
  • The "agents" would need to share almost all of the context.
  • You're splitting by job title ("the SQL agent", "the frontend agent") instead of by context volume.

The practical test: if the subagent hands back a 300-token summary after consuming 40k, it paid for itself. If it hands back almost everything it read, you just added latency.

Isolated vs fork: the two subagent context modes

In September 2026 LangChain formalized in Deep Agents a choice every harness makes, even without a name: what the subagent receives when it's born. There are two modes.

isolated fork
What the subagent receives Fresh window, only the task description The supervisor's entire state, history included
What comes back The final message, as the tool call result The final message, as the tool call result
Prompt caching New prefix, cold cache Reuses the supervisor's prefix
Good for Research, independent review Continuing already-diagnosed work

isolated is the default and the historical behavior: the subagent gets "a fresh context window, receiving only the task description specified by the supervisor". fork propagates the supervisor's state, and the post says it can be "faster and cheaper than isolated subagents" precisely because the prefix is already cached.

The Deep Agents config looks like this (excerpt from the LangChain post):

subagents = [
    {
        "name": "fixer",
        "description": "Use when a problem has already been diagnosed and the remaining work is to implement and test the fix",
        "mode": "fork",
    },
    {
        "name": "reviewer",
        "description": "Use after an implementation is complete and needs an independent review",
        "mode": "isolated",
    },
]

The selection rule from the post is the part worth gold: whoever continues the work uses fork, whoever verifies uses isolated. For the reviewer, inheriting the supervisor's reasoning "can be counterproductive". Makes sense. If the reviewer read every justification behind the code, it'll agree with it.

▪ Clã Beer and Code

A tutorial shows you the way — in the Clã you build alongside us. A live class every week, real AI Engineering projects, next to people already in production.

Join the Clã

Hands-on: isolated and fork subagents in a PHP harness

Let's implement the pattern with no framework, straight on the Messages API. The idea: the main agent has a delegate tool, and the harness decides, per subagent type, whether the context starts empty or inherited.

Step 1: declare the delegation tool

The model doesn't call another agent. It calls a tool. Your code is what creates the subagent.

$delegateTool = [
    'name' => 'delegate',
    'description' => 'Delegates a subtask to a subagent. Use "researcher" for searches '
        . 'that generate a lot of noise and "reviewer" for an independent review of finished work. '
        . 'You only receive the final result, not the intermediate reasoning.',
    'input_schema' => [
        'type' => 'object',
        'properties' => [
            'agent' => ['type' => 'string', 'enum' => ['researcher', 'reviewer', 'fixer']],
            'task'  => ['type' => 'string', 'description' => 'Complete, self-contained task.'],
        ],
        'required' => ['agent', 'task'],
    ],
];

Look at the tool description. It says when to delegate. That's where you stop the agent from delegating everything on reflex.

Step 2: run the subagent with the right context mode

Each subagent type has its own mode, prompt and tools. The reviewer is isolated and read-only. The fixer is fork.

use Illuminate\Support\Facades\Http;

class SubagentRunner
{
    private array $profiles = [
        'researcher' => ['mode' => 'isolated', 'tools' => ['web_search', 'read_file']],
        'reviewer'   => ['mode' => 'isolated', 'tools' => ['read_file']],
        'fixer'      => ['mode' => 'fork',     'tools' => ['read_file', 'write_file', 'run_tests']],
    ];

    public function run(string $agent, string $task, array $parentMessages): string
    {
        $profile = $this->profiles[$agent];

        $messages = $profile['mode'] === 'fork'
            // fork: inherits the supervisor's history (same prefix = warm cache)
            ? [...$this->withoutPendingToolCall($parentMessages),
               ['role' => 'user', 'content' => "You are a subagent. Task: {$task}"]]
            // isolated: fresh window, task only
            : [['role' => 'user', 'content' => $task]];

        return $this->loop($agent, $messages, $profile['tools'], maxTurns: 15);
    }

    private function loop(string $agent, array $messages, array $tools, int $maxTurns): string
    {
        for ($turn = 0; $turn < $maxTurns; $turn++) {
            $response = Http::withHeaders([
                'x-api-key' => config('services.anthropic.key'),
                'anthropic-version' => '2023-06-01',
            ])->post('https://api.anthropic.com/v1/messages', [
                'model' => config('services.anthropic.model'),
                'max_tokens' => 4096,
                'system' => $this->systemPrompt($agent),
                'tools' => ToolRegistry::only($tools),
                'messages' => $messages,
            ])->throw()->json();

            if ($response['stop_reason'] !== 'tool_use') {
                return $this->finalText($response); // only this goes back to the supervisor
            }

            $messages[] = ['role' => 'assistant', 'content' => $response['content']];
            $messages[] = ['role' => 'user', 'content' => ToolRegistry::execute($response['content'], $tools)];
        }

        return "Subagent {$agent} hit the {$maxTurns}-turn limit without finishing.";
    }
}

Three details that matter:

  • Only the final text comes back. The 15 rounds of search die with the subagent. That's where the context gain lives.
  • In fork mode, strip the pending tool call from the history before passing it on. LangChain does the same: "The trailing tool call is excised". Without it, the inherited conversation is invalid.
  • Always cap the turns. A subagent with no ceiling is a cost with no ceiling.

Step 3: force the subagent to return a summary, not a transcript

The most common mistake is the subagent returning everything it read. Then you paid 15x in tokens and isolated nothing. Put the output contract in the system prompt:

You are a research subagent. When you finish, reply ONLY with:
1. Conclusion in up to 5 lines.
2. Sources used (path or URL), one per line.
3. What you could NOT verify.
Do not include long file excerpts or logs. The main agent doesn't need them.

Item 3 matters most. The supervisor needs to know what was left out, otherwise it assumes the subagent covered everything.

Step 4: verifier always isolated, with restricted tools

The reviewer only has read_file. It can't fix, only point out. And it's born isolated, without reading the supervisor's justification. Same logic as human code review: whoever reviews shouldn't have written it.

Limitations and gotchas

  • Cost. Multi-agent burns about 15x the tokens of a chat. Measure before and after. If quality didn't go up, go back to a single agent.
  • Lost implicit decisions. In isolated mode the subagent doesn't know what the supervisor already decided. If the task depends on that, either write it into the task description or use fork.
  • Fork inherits biases. Fork carries the supervisor's reasoning, wrong parts included. Never use fork to review.
  • Parallel writes. Two subagents writing to the same files is the recipe for the conflict Cognition described. Parallel for reading, sequential for writing.
  • Security. A subagent with write or network tools is as much attack surface as the main agent. Restrict tools per profile, as in Step 2.

Quick FAQ

Is a subagent the same as a multi-agent system?

Not necessarily. Multi-agent usually means agents with fixed roles talking to each other. A subagent, in the sense used here, is an ephemeral call spawned by the main agent through a tool, with context controlled by the harness. It's born, solves, returns the result and dies.

When should I use fork and when isolated?

Fork when the subagent continues work that depends on what the supervisor already found, like implementing an already-diagnosed fix. Isolated when you want an independent view or the subtask is self-contained, like research or review. When in doubt, isolated is the safer default.

Do subagents save tokens?

They save tokens in the main agent's window, not in total. The total goes up, sometimes a lot. The gain is quality: the main agent reasons over summaries instead of drowning in noise. Fork cuts part of the cost because it reuses the prefix cache.

Does Claude Code have subagents?

Yes. You define subagents in .claude/agents/, each with its own prompt, allowed tools and context window. The researcher, executor and validator pattern is broken down in Subagentes na prática (Portuguese).

Conclusion

A subagent isn't a job title. It's a context window.

The right question isn't "how many agents does my system have", it's "what goes in and what comes out of each window". Start with one agent. Add a subagent when the noise from a subtask is polluting the main reasoning. Use isolated to research and review, fork to continue work. And demand a summary, not a transcript.

The next step of this trend is already showing up: better models deciding on their own when to delegate, with the harness just offering the modes. It ties directly into what we discussed in Harness minimalista (Portuguese): the smarter the model, the less the harness should decide for it.

Lucas Souza
Written by
Lucas Souza

{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.

▪ Clã Beer and Code

There is no shortage of content. What is missing is someone to untangle it: what matters now is how to implement it the right way. In the Clã you get that live, every week, with people who have already filtered out the noise.

Join the Clã
Meet the Clã Beer and Code
playing