Section 11Ship faster — parallel execution

One agent is useful. The leap in throughput comes from running several at once — but only on top of everything so far, because parallelism multiplies output and needs review capacity to match.

Section 10 ended on a promise: agreed interfaces are what let several agents build at once without colliding. This chapter collects on it. Picture the salon owner's board on a good morning: three unblocked tickets — quiet hours for reminder messages (the notifications room), a refund flow (the payments room), and a help page that touches no other module at all. One agent works through them in sequence, an afternoon each. Three agents, set up the way this chapter describes, finish all three in the same afternoon — and nothing about the tickets had to change, only the way the work is run.

Notice what that speed-up did not require: a smarter model, a bigger context window, or a new prompting trick. Parallelism is a management discipline, not a technical one — which is why it sits this late in the guide. It presumes work already cut into small, independent tickets (Section 4), tests that judge each result without you (Section 5), a review habit that scales (Section 6), a pipeline that filters out the broken automatically (Section 8), and a floor plan whose rooms don't overlap (Section 10). Given those, running several agents adds exactly three new problems — keeping them physically apart, letting them run while you're away, and deciding how many is too many — and this chapter is those three problems in order.

For newcomers

Parallel agents are a kitchen with several cooks. One cook can only go so fast, no matter how good the knives get. A restaurant scales by adding cooks — but only because the kitchen is organised for it: each cook has their own station (nobody shares a chopping board), each works from a written docket rather than shouted instructions, and every plate crosses the pass, where the head chef inspects it before it leaves. Remove any of those and more cooks means more chaos, not more dinners. This chapter builds the same kitchen for agents: worktrees are the stations, your ticket board is the docket rail, and CI plus your review is the pass. And note who the head chef is in this picture — the one person who has stopped cooking.

What can actually run in parallel

The test for whether two tickets can run side by side is independence, and it has two halves. First: neither ticket needs the other's changes — each is an unblocked, self-contained tracer-bullet slice, exactly what Section 4's board was built to produce. Second: they live in different rooms of Section 10's floor plan, so their diffs touch different files. Quiet hours (notifications) next to refunds (payments) is a clean split; two tickets that both rework the bookings module is not — they will edit the same files, and the merge at the end hands you back all the coordination you thought you'd skipped. When in doubt, ask before you start: "for each of these tickets, list the modules and files it will likely touch, and flag overlaps" is a one-minute planning question that saves an evening of merge archaeology.

Two agents in one room

One agent adds waiting lists to bookings; another reworks buffer times in bookings. Both rewrite the same functions. The branches come back incompatible, and untangling them takes longer than doing the two tickets in sequence would have.

One agent per room

One agent in notifications, one in payments, one on the help page. Each talks to the rest of the system only through Section 10's agreed interfaces, so the three diffs share no files and merge without touching each other.

Give each agent its own workspace

Agents in the same folder trip over each other's changes. A git worktree gives each agent a separate copy of the repo on its own branch, so several run in parallel without collision. An orchestrator agent hands each one an unblocked ticket from your board (Section 4) and assembles the results.

For newcomers

A worktree is a second desk for the same project. Normally one repository folder means one desk: one checked-out copy of the code, sitting on one branch. git worktree adds extra folders that share the same underlying history but each sit on their own branch — so agent A works in ../salon-notifications, agent B in ../salon-payments, and neither ever sees the other's half-finished files. When a branch is done, it flows back into the shared history like any other branch, through the same pull-request-and-review door. The desks are separate; the filing cabinet is one.

The feature is much older than agents — worktrees shipped as a first-class Git command in version 2.5, back in July 2015 — but agent fleets are the workload it seems to have been waiting for. One command per agent does the setup: git worktree add ../salon-notifications -b quiet-hours creates the folder and its branch in one stroke, and git worktree remove cleans up after the merge. Two practicalities to know: each worktree usually needs its own dependency install before its agent can run tests, and if each agent starts a dev server, each needs its own port — small, one-time costs that a good orchestrator (or a project setup script, Section 13) pays automatically.

git worktree add ../salon-notifications -b quiet-hours   # one worktree + branch per agent

You don't always have to run that command yourself. A subagent definition can carry isolation: worktree (the mechanics of those definitions are the next section), which puts that agent in a throwaway worktree branched from your default branch — and cleans it up automatically if the agent changed nothing. For orchestrated fan-out that is the least-effort version of this whole section: the isolation happens because the agent is configured for it, not because you remembered.

Long-running processes belong in the background

The dev-server problem above has a second half that trips people on their first parallel run: a dev server or a test watcher never exits, so an agent that starts one in the foreground blocks on it forever, and you come back to three agents all sitting on "server running on :5173". The mechanism for this is background tasks. Any long-lived command can be started detached — the agent passes run_in_background when it runs the command, or you press Ctrl-B to push a running command into the background — and it keeps running across turns while the agent gets on with the next thing. /tasks lists what's currently running and what has finished.

The rule for parallel work is simple: anything that doesn't terminate on its own goes in the background, on its own port per worktree. Anything that terminates — a test run, a type-check, a build — stays in the foreground, because the agent needs its exit code to know whether it passed. Getting this the wrong way round is the single most common reason a parallel run quietly stalls.

The orchestrator is a manager, not a better coder

The orchestrator earns its keep by not writing feature code. Its job is the head chef's: read the board, pick tickets that pass the independence test, spin up a subagent in each worktree with its ticket and nothing else, collect the results, and surface to you only what needs a decision. The moment the orchestrator starts implementing, you've lost the overview it exists to hold — its value is precisely that it stays above the work.

Define your subagents; don't re-describe them every time

A subagent is not only a thing you ask for in a sentence — it's a thing you configure once and then keep. A subagent definition is a markdown file in .claude/agents/ (committed, so the whole project inherits it) or in ~/.claude/agents/ (yours, everywhere — Section 13's Layer 1). Frontmatter at the top, the agent's system prompt in the body:

---
name: ticket-implementer
description: Implements one unblocked ticket on its own branch. Use for parallel dispatch.
tools: [Read, Edit, Write, Bash, Glob, Grep]
model: sonnet
permissionMode: acceptEdits
isolation: worktree
maxTurns: 60
---
You implement exactly one ticket and stop.
Write the test first, then the code. Run the test suite before committing.
If the ticket is ambiguous, do not guess — report back and stop.
Never touch files outside the modules named in the ticket.

Only name and description are required; everything else is a lever. description is load-bearing in a way that surprises people — it's what the orchestrator reads to decide which worker a task belongs to, so write it as routing instructions, not as a job title. tools is the least-privilege control Section 9 asked for: a reviewer or research agent that lists only Read, Glob and Grep holds no ability to write or run shell commands at all, so a prompt injection arriving in the material it reads has almost nothing to act with. permissionMode scopes the earlier permissions discussion per agent, so your implementer can accept edits while your deploy-adjacent agent still asks about everything. maxTurns is a per-agent version of the hard cap. To see what you currently have, or to add one, ask the agent directly — "create a subagent that reviews diffs and can only read" — or type /agents; either way the result is a file you can read, diff and commit, which is the point.

Three more things worth knowing before you run wide:

  • Subagents nest. A subagent that has the Agent tool can spawn its own subagents — a reviewer that dispatches one verifier per finding, say — and only the top-level summary comes back to you. Depth is capped at five levels below your main conversation, and the cap is fixed rather than configurable. To stop a particular agent delegating further, leave Agent out of its tools.
  • There is a runaway guard. A session can spawn at most 200 subagents by default (raise it with CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION; it can't be switched off). You will not meet this ceiling dispatching four tickets — you meet it when an orchestrator misreads a loop and starts spawning workers to fix the workers. That is exactly the failure it exists to stop, and it's the fleet-level equivalent of the AFK loop's iteration cap below.
  • You can see what each agent cost. /usage breaks recent consumption down by subagent, skill, plugin and MCP server. That turns the 15× token figure below from a rumour into a number you can attribute — which of your workers is expensive, and whether it was worth it.
The orchestrator, instantiated

Nothing exotic hides behind the name. In practice the orchestrator is your ordinary main agent session, handed a saved orchestrator prompt — kept as a skill or a reusable prompt file, so you never retype it. The prompt below is the dispatch loop, spelled out — it's what you send to configured workers like the one above, not a way of avoiding configuring them. The difference matters: a definition carries the tool restrictions, the permission mode and the isolation, and a prompt carries none of those, however carefully worded.

You are the orchestrator. You never write feature code.
1. Read the ticket board; list the unblocked tickets.
2. Check independence: flag any two tickets likely to touch
   the same modules or files — those run in sequence, not parallel.
3. For each independent ticket: spawn one ticket-implementer
   subagent with the ticket text and nothing else. It isolates
   itself in its own worktree and branch.
4. Collect each subagent's result summary and branch name.
5. Run the gates on each branch: tests, types, lint.
6. Green: queue the branch for the one-at-a-time merge.
   Red, or wandered off-ticket: bounce it back once with the failure.
7. Report to me only what needs a decision: merged, bounced, blocked.

This division of labour is measured, not just tidy. Anthropic built its research feature as exactly this pattern — a lead agent that plans and delegates to parallel subagents — and reports that the multi-agent version outperformed a single agent using the same top-tier model by 90.2% on their internal research evals. The same report carries the bill: multi-agent runs burned around 15× the tokens of a normal chat. That is the honest shape of parallelism — you are buying throughput with compute and with your own review load, not getting it free — which is why the width question at the end of this chapter matters more than any of the setup.

One asymmetry to hold onto for Section 12: every worker starts with a fresh, empty context window, but every summary and status report flows back into the orchestrator's — so the orchestrator's window fills fastest of all. The working rule: workers do the reading and the typing in their disposable windows; the orchestrator keeps only decisions, and when its own window nears the limit, it gets a handoff to a fresh session like anything else. Section 12 turns that into numbers.

There is also a much smaller move worth having in your hands, for the side quest that doesn't justify a worktree at all: /branch. It copies the conversation you're in — full history, same context — and continues in the copy, leaving the original untouched. Where a fresh subagent starts empty and has to be told everything, a branch already knows the situation, which makes it the right tool for the tangent that would take five minutes to re-explain: "go write the migration for what we just designed," explored in the copy while the design conversation stays clean behind it. This is not parallelism — it is one conversation splitting into two paths you walk one at a time. It belongs here because it removes the most common reason people reach for a second agent: not needing two things done at once, just not wanting to contaminate a good context with a detour.

Running unattended — the AFK loop

You can let agents run while you sleep: pull a ticket, implement, commit, repeat. That is the whole of the Ralph loop, and it is worth knowing that the mechanism is genuinely this small — a shell for loop around a headless agent invocation. Tools that package it exist and come and go (Pocock's Sand Castle is the one most often named in this corner of the community, and his talk on the pattern is on the resources page); nothing in this section depends on you finding a particular one, because the loop is a dozen lines you can write yourself:

#!/usr/bin/env bash
# ralph.sh — run N passes, each a brand-new agent session
set -euo pipefail
MAX=${1:-20}                       # hard cap: the first guardrail
for i in $(seq 1 "$MAX"); do
  echo "--- pass $i/$MAX ---"
  claude -p "Read prd.json. Pick the next unfinished story.
Implement it, run the tests, commit only if they pass.
When every story passes, print exactly: PROMISE COMPLETE"
  git log -1 --oneline
  claude -p "Print DONE if prd.json has no unfinished stories, else NOT_DONE" \
    | grep -q '^DONE' && { echo "all stories complete"; break; }
done

Written out, the three guardrails it needs — no exceptions — are visible in the shape of the script itself:

A sandbox

Run inside a sandbox, never loose on your machine — an unsupervised agent can run destructive commands. Section 2's built-in sandbox is the floor; for a run nobody will look at until morning, a container is the ceiling. Changes come back as clean git patches either way.

A hard cap

The loop takes a max-iteration limit (./ralph.sh 100) so a stuck agent can't spin forever.

A done signal

State lives on disk: prd.json tracks which stories pass; the agent emits a token like "promise complete" to exit and ping you.

For newcomers

"AFK" is old chat slang — away from keyboard. In this guide it names a whole working mode: the agent keeps pulling work while nobody is watching, whether that's an overnight loop on your own machine or the repository-hosted version described next. The "Ralph loop" is the affectionately silly nickname for the simplest possible implementation: a script that does nothing cleverer than starting the agent, letting it do one unit of work, and starting it again — as many times as the cap allows.

The loop's real trick hides in that third card. Because state lives on disk, every pass through the loop can be a brand-new session: each iteration starts an agent with an empty window that reads prd.json, picks the next unfinished story, implements it, commits, and exits — and the script starts the next pass fresh. The agent's memory is the repository itself: the code, the tests, the commit history, the state file. That is Section 12's fresh-session hygiene turned into a mechanism — no iteration lives long enough to reach the dumb zone, because the loop throws the window away on every lap and keeps only what was written down.

How an unattended agent gets permission to act

Here is the question every one of those loops raises on its first night, and the one most write-ups skip: an agent that stops to ask "may I run the tests?" at 2am is an agent that achieved nothing by 7am. So how does it get to act without you? There is a wrong reflex and a right answer, and the gap between them is most of this chapter's risk.

The wrong reflex is --dangerously-skip-permissions. It is discoverable in about thirty seconds of frustration, it makes the prompts stop, and it does so by removing every check at once — file reads, shell commands, network calls, all of it, on your actual machine with your actual credentials. The flag is named the way it is on purpose. It has exactly one defensible use: inside a disposable container that holds nothing you'd miss, where "unrestricted" is bounded by the container walls rather than by trust. Outside a container it is not a configuration choice, it's the absence of one.

The right answer is the two layers you already built in Section 2, turned up for the night shift:

  • The sandbox does the quieting. With sandbox.enabled and autoAllowBashIfSandboxed on, commands that run inside the OS-enforced fence don't need a prompt at all — because they physically cannot reach outside the project or call a host you didn't list. That is the mechanism the bypass flag pretends to be: prompts disappear because the risk is gone, not because the checks were switched off.
  • The permissions block does the scoping. Write down, before you walk away, exactly what the night shift may do. allow the loop's real verbs — the test runner, the type-checker, git commit. deny the things no unattended run should ever touch: production credentials, git push to main, deploy commands, Read(./.env*). Set defaultMode to acceptEdits so file edits flow (git records them; you review the diff at breakfast), and leave anything you didn't think of falling through to a prompt — which, unattended, simply means that run stalls and waits for you. A stalled run is a cheap failure. An unbounded one is not.
  • Prefer stalling to guessing. The ask list is not wasted on an unattended run, it's the tripwire: if the agent hits it, the loop pauses and you find out in the morning that a ticket wanted something you hadn't sanctioned. That is information, and it is the whole reason not to blanket-approve.

Two smaller controls finish the picture. --permission-mode sets the mode for a single invocation from the command line, so an overnight script can run in acceptEdits without changing what your interactive sessions do. And where the OS sandbox isn't available — Windows without WSL2, or simply a run you want walled off completely — the container route is the substitute: a Docker image with the repo mounted and nothing else, credentials scoped to that container, results collected as git patches. That is the one context where the bypass flag stops being reckless, because the container has become the fence.

Never the bypass flag on your own machine

If you take one line from this section: unattended does not mean unrestricted. The correct setup for an overnight run is more written-down policy than a supervised session, not less — because nobody is there to be the policy. Reaching for --dangerously-skip-permissions because the prompts were annoying skips the ten minutes of configuration that make the annoyance go away safely, and it does it on the machine with your SSH keys on it.

What to hand an unattended agent

An overnight run is only as good as the tickets you feed it, because there is no midnight conversation to rescue a vague one. Everything from the daytime chapters compounds here: a well-grilled spec, tickets cut as small tracer-bullet slices, each with tests that define done. For the salon app, "add a per-salon quiet-hours setting; reminders scheduled inside quiet hours move to the next morning; tests cover the boundary times" is a good overnight ticket — small, testable, no judgment calls left in it. "Improve the reminder system" is not; an unattended agent resolves every ambiguity in it by guessing, and you read the guesses at breakfast.

Keep one-way doors out of the night shift

Never queue a one-way door for an unattended run — no schema migrations, no auth changes, no published-API changes. Section 10's triage applies with extra force at night: the whole point of the AFK loop is that nobody is watching, and hard-to-reverse decisions are precisely the ones that need someone watching. A second, quieter caveat: an unattended agent is judged only by your gates. If the test suite is thin, the loop will happily commit plausible-looking wrong code all night — it amplifies whatever your gates are, including their gaps.

The autonomous implementation loop — approve, walk away, decide

The AFK loop above runs on your machine. The same idea also runs entirely in your repository's own infrastructure, and it changes the shape of your day: once planning is done and a ticket is explicitly approved, the implementation no longer needs you watching. You mark work as ready; machinery picks it up, builds it in isolation, proves it against the tests, and comes back with a finished pull request. Your involvement collapses to the two points where judgment actually matters — approving the plan at the start, and reviewing the result at the end.

1

A human marks the work approved

Nothing starts on its own. The trigger is an explicit signal on an issue — a mention, an assignment, a label — applied by a person after the plan is agreed (Section 4's tracer-bullet issues are exactly the right unit: small, self-contained, testable).

2

An agent implements on a branch, never on main

The agent spins up in a clean, disposable environment, creates a feature branch, implements the issue, and runs the test suite as it works — the same discipline as Section 5, just unattended.

3

The pipeline judges the work

The agent opens a pull request, and CI runs the full gauntlet from Section 8 — types, tests, security scans — exactly as it would for a human's branch. Machinery filters out the broken; only work that survives reaches you.

4

You get notified and make the decision

What lands in front of you is a reviewable pull request with green checks — not a request for help. You review (Section 6's demo-reel approach works unchanged) and merge, request changes, or close. The decision stays yours; only the typing moved.

This is not speculative tooling — it's how Anthropic's own GitHub integration works today. The official action (anthropics/claude-code-action@v1) triggers on an @claude mention or an issue being opened or assigned, then creates the branch, implements, and opens the pull request from inside a standard GitHub Actions runner, following the repo's AGENTS.md/CLAUDE.md. Equivalent setups exist for GitLab and self-hosted runners; the pattern matters more than the vendor.

Two other places an agent can run that isn't your laptop

CI is the most disciplined way to host an unattended agent, because the gates are already there. Two lighter-weight options round out the picture, and both matter more the wider you run.

Hosted cloud sessions. Claude Code on the web runs sessions on Anthropic-managed infrastructure rather than your machine: you point it at a repository, describe the work, and it runs in its own isolated environment and comes back with a pull request. The session survives closing the browser, and you can check on it from a phone. For parallel work the appeal is obvious — width stops being bounded by your laptop's CPU, its ports, or whether the lid is open — and the discipline is unchanged: the same gates, the same one-at-a-time merge, the same review capacity limit. It is a different place to run the agent, not a different set of rules.

The Claude Agent SDK. Everything this chapter describes — spawning agents, giving them tools, capping their turns, collecting results — is also available as a library (@anthropic-ai/claude-agent-sdk for TypeScript, claude-agent-sdk for Python) rather than a CLI you script around. Reach for it when the loop stops being a shell script: an eval runner that scores fifty prompt variants (Section 12), a custom orchestrator with your own dispatch logic, or the agent-shaped internal tooling that Section 13's system-building tends to grow into. The shell loop earlier in this chapter is the right first version; the SDK is where it goes when it earns real structure.

The guardrails are the same deterministic machinery as everywhere else (Section 12), applied without exception:

  • The agent never merges its own work. Branch protection on main means required checks plus a human approval stand between any agent branch and production — a runaway agent physically cannot ship.
  • One issue per run. Scope stays reviewable; a run that wanders gets closed, not debugged.
  • Hard caps. A turn limit (the action's --max-turns), a workflow timeout, and a concurrency cap bound what a stuck or misfiring loop can cost — the CI-side version of the AFK loop's iteration cap.
  • Least privilege. The agent's credentials reach the repo, not production; deploy stays a separate, gated step (Section 8).
The interrupt protocol

An unattended agent should interrupt you for exactly three reasons: it's blocked, it's done, or it failed — and stay silent otherwise. Human attention is the scarcest resource in this whole setup; a loop that pings you with progress updates has quietly reinvented you watching it work. Configure notifications accordingly: a finished PR, a red pipeline, or a question — nothing else.

Merging without mayhem

Parallel branches eventually have to become one main branch again, and the discipline is: land them one at a time. Merge the first green pull request; have the remaining branches update onto the new main and re-run their tests; then take the next. It feels slower than merging everything at once, and is dramatically faster in practice, because every branch is always judged against the main it will actually join — CI's verdict stays meaningful. An agent (or the orchestrator) can do the updating and re-running; you only reappear if a branch stops being green after the update.

Conflicts themselves carry information. If tickets were cut along the floor plan, merges are boring — the diffs share no files. A conflict that shows up anyway means two rooms are sharing a wall you didn't draw; a conflict that keeps showing up in the same place is an entropy reading in the Section 10 sense, and the fix is architectural — extract the shared piece behind its own interface — not better merge tooling. Treat recurring conflicts as tickets for the refactoring backlog, not as weather.

What your day looks like now

Put the pieces together and the salon owner's day changes shape. Morning: read the night's output — a few finished pull requests with green checks — with Section 6's demo-reel review; merge what's good, close what wandered. Then ten minutes at the board: approve the next few independent tickets, watch the agents start, and leave — there are haircuts to give. Midday, maybe one interrupt: a blocked agent with a genuine question. Evening: one more review pass, and a couple of tickets queued for the night shift. The craft has moved entirely to the two ends of the pipeline — deciding what's worth building, and judging what came back. The middle, which used to be the whole job, runs while you're standing at a chair.

That reshaped day is also the honest limit of it. Every hour of agent output costs minutes of your review time, and review is the one part of this that never parallelises — which is why the last word of this chapter is a warning, not a victory lap.

Match width to your review capacity

Verification is the bottleneck, not generation. Pocock runs about four parallel agents — as many as one person can meaningfully review. Ten agents you can't review isn't ten times the output; it's ten times the unreviewed risk. Scale width only as fast as your gates and demo-reel review can keep up.

The practical ramp: start with two agents, not ten. Two parallel worktrees on genuinely independent tickets, until the rhythm — cut, dispatch, merge one at a time, review — feels routine and your gates have caught their first few bad runs. Then three, then four. Width is something you earn as your review muscle and your pipeline's strictness grow; it is never something you get by opening more terminals.

And notice what running wide multiplies besides output: context windows. Several workers, one rapidly filling orchestrator, handoffs between sessions — everything in this chapter leans on managing the agent's working memory well, and that is exactly where the guide goes next. Section 12 is about the window itself: how big it really is, when it goes bad, and how deterministic machinery keeps quality up when no human is in the loop.

Quick check: six tickets are ready and you have the evening free. Do you spin up six agents?

No — run the two tests first. Independence: which tickets touch different rooms of the floor plan? Perhaps four qualify; the two that both touch bookings run in sequence, not in parallel. Capacity: how many results can you actually review tomorrow morning? Pocock's answer is about four for a full-time practitioner — for a salon owner with customers booked, two or three is honest. Dispatch those in their own worktrees, queue the rest, and let CI plus the one-at-a-time merge discipline handle the landing.

The wider chapter in one breath: parallelism multiplies output only when the work is cut so it can't collide — independent tickets in different rooms of Section 10's floor plan. Each agent gets its own worktree, long-running processes go in the background, and workers are configured, not just prompted — a file in .claude/agents/ carrying its tool list, permission mode and turn cap — while an orchestrator manages instead of coding. Unattended modes — the AFK loop on your machine, a hosted cloud session, or the approve-walk-away-decide loop in your repository's own CI — run on non-negotiable guardrails: a sandbox plus a written permissions block rather than the bypass flag, hard caps, a done signal, and an agent that never merges its own work. It interrupts you only when blocked, done, or failed. Branches land one at a time, re-tested against the main they'll actually join, and recurring merge conflicts are architecture feedback, not bad luck. Above all: verification is the bottleneck — scale width to your review capacity, starting with two.