Behnam Analytics

Writing AI workflows & prompting

Subagents and parallel work in Claude Code

When to split work across Claude Code subagents, how to brief them, how to stop them racing each other, and how to check the result before anything ships.

Behnam Ebrahimi 8 min read

Parallel agents are not automatically faster or better. They’re faster when the work splits cleanly, and they produce a mess when it doesn’t. This article covers when to split, how to write the brief, how to keep agents from overwriting each other, and what the orchestrating session has to check afterwards.

What a subagent is

In Claude Code, a subagent is a worker the main session hands a task to. According to the subagents documentation, each one:

  • runs in its own context window, with its own system prompt, tool access and permissions;
  • starts fresh: it doesn’t see the main conversation’s history, only the task message written for it, plus the project’s CLAUDE.md files and a git status snapshot (the built-in Explore and Plan agents skip those two);
  • returns a summary to the main session when it finishes, so its file reads and command output never enter the main context;
  • sends its own requests, which count against the same usage limits as the main conversation.

A variant, the fork, inherits the whole conversation instead of starting fresh. You start one with /subtask. Forks are useful when a task needs too much background to re-explain. For a batch of independent tasks, fresh subagents working from a written brief fit better, because a brief is easier to audit than a long conversation history.

When splitting is worth it

The documentation’s guidance makes a good rule of thumb. Use subagents when:

  • the work is self-contained: each unit can be done without talking to the others mid-task and can come back as a summary;
  • a side task would flood the main context with verbose output you won’t look at again (test logs, search results, documentation);
  • you want a worker with restricted tools or permissions.

For parallel work, add one condition of my own: each unit touches its own files. When units would touch the same files, the docs point you to separate git worktrees.

Stay in one session when the task needs frequent back-and-forth, when the phases share a lot of context (plan, build, test the same module), when the change is small, or when latency matters. A fresh subagent has to gather its own context before it’s useful.

A content build is close to the ideal case. Say you need six project write-ups and twenty articles for a documentation or portfolio site. Each page is a folder. The pages cross-reference each other, but only by URL, and a URL can be agreed in advance.

A worked example: a content build in three phases

Phase 1: build the shared parts alone. Before any subagent starts, the main session builds everything the workers will share: the site generator and templates, any reusable components, and a style guide covering front matter, data formats and tone. Anything shared is finished before anyone else starts.

Phase 2: subagents in parallel. Each owns a disjoint set of folders, for example:

Agent Owns
1 One project and the two articles that explain its methods
2 A second project and its two articles
3 Four articles on one topic
4 Four articles on another topic, plus one reference page

Each task message points the agent at the shared brief and the style guide, names the folders it owns, and describes what should go in them.

Phase 3: the main session reviews, fact-checks, builds and commits. Building the published output and committing are reserved for it.

The shared brief

The brief is one Markdown file that every agent reads first. Its most important parts:

  1. The full map of outputs. Every planned URL slug or file path, with its owner. An agent writing about forecasting can link to /writing/prediction-intervals-for-planners/, owned by a different agent, before that page exists.
  2. Write boundaries. “Write only inside the paths your task assigns you. Other agents are writing other folders at the same time.” Followed by a list of shared paths nobody may touch: the generator, the templates, the generated output, lockfiles and the tests.
  3. One safe check command. Tell agents which command validates their work without writing anywhere shared, and name the command they must not run.
  4. Quality rules. Every number must come from running the agent’s own code. Claims about tools are checked against official documentation, and anything that can’t be verified is left out.
  5. A report format. Finish with the files created, the headline numbers, anything that couldn’t be verified, and anything the main session should check.
  6. No commits. The main session commits.

Here’s the shape of it as a template you can reuse:

# Shared brief: <project>

Goal and audience: <who reads the output and what they should get from it>
Read first: <style guide>, <example of finished work>

Rules
1. Write only inside the paths your task names. Others are working in parallel.
2. Never edit: <shared code>, <generated output>, <lockfiles>, <tests>.
3. Check your work with <safe command>. Never run <command that writes shared output>.
4. Every number must come from running your code. Rerun after any change.
5. Verify claims about tools against official docs; if you can't, leave it out.
6. Don't commit. Don't add dependencies; ask in your report instead.
7. Finish with a report: files created, key numbers, what you couldn't
   verify, what the main session should check.

Shared contract
<table of every planned output: slug or path, owner>

A check that can’t race

The subtle part is validation. Every agent needs to check that its pages render, its data files are valid and its links point somewhere real. The obvious command, the full build, rewrites the shared output folder, and several agents running it at once trample each other’s output.

The fix is a validate command that renders everything into a throwaway temporary directory, reports errors and broken links, and deletes it:

def validate() -> int:
    """Render everything into a throwaway directory; never touch the shared output."""
    with tempfile.TemporaryDirectory() as tmp:
        try:
            broken = build(Path(tmp), strict_links=False)
        except BuildError as exc:
            print(f"error: {exc}", file=sys.stderr)
            return 1
    for link in broken:
        print(f"broken link: {link}", file=sys.stderr)
    return 0

Broken links are reported but don’t fail validation, because a link to a page another agent hasn’t written yet is expected mid-build. Say so in the brief, so no agent “fixes” a link that isn’t broken. The full build, reserved for the main session, runs with strict link checking.

Avoiding shared-file races

The general rules:

  • Give every file exactly one owner. Disjoint folders are the simplest version. If two agents need the same file, it belongs to the main session, and agents request changes in their reports.
  • Build shared artefacts once, at the end. Generated output, indexes, sitemaps and lockfiles are written by the main session after everyone has finished.
  • Make checks side-effect free. Validate into a temporary directory, run tests against temporary paths, never write to a location another agent reads.
  • Use worktrees when ownership can’t be clean. A subagent defined with isolation: worktree in its front matter runs in its own git worktree, so its edits can’t collide with anyone’s; the /batch skill uses the same idea to split one large change across 5 to 30 worktree-isolated subagents. The cost is a merge step at the end.

If agents share one checkout, the boundaries are only instructions in a brief, and instructions are followed most of the time, not all of the time. Enforce them where you can: Claude Code’s PreToolUse hooks can block an Edit or Write whose path falls outside an allowed list, and a subagent’s front matter can carry hooks of its own. Claude Code hooks for analytics repos has a worked path-blocking hook, and the deny rule that should back it.

How the main session verifies

Parallel agents move the bottleneck from writing to reviewing. The main session’s job afterwards is the part you can’t delegate to the same agents that did the work:

  1. Read every report. The “couldn’t verify” and “should check” sections are the most useful lines in the whole process.
  2. Check the boundaries. git status --short shows every changed path, and any file outside an agent’s folders is a problem to explain before anything else.
  3. Rebuild and run the tests. One full build, then the test suite, including a check that fails if the generated output is stale or has broken links.
  4. Spot-check numbers against code. Rerun a project and compare its output with the numbers on its page.
  5. Fact-check tool claims. Especially anything about fast-moving products, including Claude Code itself.
  6. Review with fresh eyes. Claude Code’s docs recommend an adversarial review step: a subagent that sees only the diff and the criteria. They also warn that a reviewer told to find gaps will usually find some, so tell it to report only problems that affect correctness or the stated requirements.

Costs and failure modes

Tokens multiply. Every subagent sends its own requests, and the docs say plainly that running several at once multiplies token usage. The saving is wall-clock time and main-context space, not spend.

Reports fill the main context. Each finished subagent’s result lands in the main conversation. Several long reports are a lot of context, so ask for short ones with a fixed structure.

Limits exist. By default Claude Code stops spawning new subagents while 20 are running in a session, and subagents can nest up to three layers below the main conversation. Neither matters for a handful of agents, but both would for a large fan-out.

Permission prompts come back to you. A background subagent that needs approval surfaces the prompt in the main session. Pre-approve the commands the brief tells agents to run, or you’ll spend the build answering prompts.

The failure modes to watch for:

  • Drift outside ownership, usually a “helpful” fix to a shared file.
  • Style drift between agents. One style guide read by all of them is the fix; agents with their own taste produce their own house styles.
  • Confident claims without evidence. “All tests pass” is worth nothing without the output. Ask for the command and its result.
  • Invented facts filling gaps in a brief. The rule “if you can’t verify it, leave it out, and say so in your report” turns a silent invention into a visible gap.
  • Shared contracts changing mid-build. If a slug changes after agents have started linking to it, every agent’s links break. Freeze the contract before phase 2.

When not to bother

If the work fits in one context window and the pieces depend on each other, one session is simpler and cheaper. Subagents earn their overhead when the units are independent, the ownership is clean and a check exists that each agent can run without touching anyone else’s work. Get those three right and the rest is reading reports.

For the single-session workflow this builds on, see A Claude Code workflow for analysts and BI developers. For picking the model each agent runs on, see Choosing a Claude model and effort level.