Parallel coding agents are useful only when they can make independent progress without corrupting each other’s work. Launching sixteen agents at the same repository does not automatically produce a sixteen-fold speedup. If every agent sees the same failing test, edits the same files, and merges without coordination, the system spends its budget on duplicated effort and conflict repair.
A verifier-guided agent team treats the harness as the real product. The harness creates isolated workspaces, assigns or lets agents claim distinct tasks, runs strong tests, summarizes failures in model-readable form, and uses known-good oracles to split giant failures into smaller work packets. The agents still write code, but the environment determines what counts as progress.
Anthropic’s C compiler experiment is a concrete stress test of this pattern. The project used nearly 2,000 Claude Code sessions over two weeks to build a clean-room Rust C compiler that could compile large real programs and a bootable Linux kernel on multiple architectures. The transferable lesson is not that every team should build compilers with agents. It is that autonomous software teams need external verifiers, file-based coordination, fresh execution sandboxes, and decomposition strategies that make parallelism possible.
An autonomous agent will optimize whatever signal the harness exposes. If the tests are weak, slow, noisy, or easy to bypass, the agent team will drift toward local patches that look successful while breaking untested behavior. The first design task is therefore not prompt writing; it is constructing a verifier that catches regressions and reports failures clearly.
For code projects, the verifier usually combines unit tests, integration tests, compiler or type checks, linters, benchmark thresholds, and project-specific acceptance tests. For agent teams, these checks should run outside the model’s discretion. The agent may invoke fast subsets while iterating, but the final gate must be enforced by the harness.
Long-running conversations accumulate stale assumptions and irrelevant logs. A parallel-agent harness can instead run each work cycle in a fresh container or workspace, with durable state stored in files, commits, task lists, and progress logs. This lets each agent orient from the current repository state rather than from a sprawling transcript.
Git is a useful coordination substrate because it already provides commits, branches, merge conflicts, diffs, and rollback. A simple team can use one bare upstream repository, per-agent clones, and push/pull cycles. More advanced systems can use worktrees, branch-per-task execution, or explicit state commit/revert operations for multi-agent trajectories.
Parallel work needs a claim mechanism. Anthropic’s prototype used text-file locks in a task directory: an agent wrote a file for the task it claimed, worked on it, merged changes, pushed, and then removed the lock. The important property is not the exact file format. The important property is that agents can discover current work, avoid duplicated effort, and leave behind compact notes about failed approaches.
Agent intelligence is not enough when one huge failure hides many smaller bugs. The harness should expose independent slices, deterministic subsets, and known-good comparisons so different agents can work on different causes at the same time.
A basic parallel harness creates an upstream repository, starts each agent in a fresh container, gives it a local clone, and asks it to claim one task. The agent edits locally, runs verifier commands, pulls from upstream, resolves conflicts if needed, pushes its changes, and releases the task lock.
type AgentRun = {
id: string;
image: string;
upstreamRepo: string;
taskDir: string;
verifier: string[];
};
async function runAgent(spec: AgentRun) {
const container = await docker.run(spec.image, {
mounts: [{ source: spec.upstreamRepo, target: "/upstream" }],
workdir: "/workspace",
});
await container.exec("git clone /upstream repo");
await container.exec("cd repo && ./claim-task.sh current_tasks/");
await container.exec("cd repo && agent-code-loop prompt.md");
await container.exec(`cd repo && ${spec.verifier.join(" && ")}`);
await container.exec("cd repo && git pull --rebase origin main");
await container.exec("cd repo && git push origin HEAD:main");
await container.exec("cd repo && ./release-task.sh current_tasks/");
}
This sketch omits production details such as admission control, branch protection, artifact collection, timeouts, credential scoping, and merge queues. The core invariant is that every agent has an independent workspace and an external proof obligation before its work enters the shared state.
Agents need concise, searchable feedback. A harness that prints megabytes of irrelevant logs pollutes context and hides the real failure. Prefer short terminal summaries, structured log files, stable error prefixes, and precomputed aggregate statistics. If a failure detail is verbose, write it to a file and print the path.
#!/usr/bin/env bash
set -euo pipefail
mkdir -p .agent-logs
if cargo test --workspace >.agent-logs/tests.log 2>&1; then
echo "OK tests workspace"
else
reason=$(grep -m1 -E "^(error|fail|thread|ERROR)" .agent-logs/tests.log || true)
echo "ERROR tests ${reason:-see .agent-logs/tests.log}"
exit 1
fi
if ./compile-linux-subset --fast --seed "$AGENT_ID" >.agent-logs/kernel.log 2>&1; then
echo "OK kernel_subset seed=$AGENT_ID"
else
grep -m5 "ERROR" .agent-logs/kernel.log || true
exit 1
fi
Some failures do not parallelize naturally. If compiling a kernel fails, every agent may hit the same first bug. Anthropic’s workaround was to use GCC as a known-good compiler oracle: compile most files with GCC and only a subset with the experimental compiler. If the mixed build works, the bug is outside the experimental subset. If it fails, refine the subset until the failing files are isolated. That turns one giant task into many independent debugging targets.
Compilers, interpreters, and runtimes have unusually strong oracles: conformance suites, differential tests against known-good implementations, fuzzers, corpus builds, and generated programs. A parallel agent team can assign different failing tests, source files, architectures, or optimization passes to separate agents while the harness enforces semantic equivalence.
Migration projects often contain hundreds of similar but not identical failures: API changes, type errors, deprecations, dependency upgrades, and test fixes. File-based locks and deterministic task lists let agents claim separate modules. A final verifier prevents the team from accepting local fixes that break global behavior.
A bug-hunting loop can keep a queue of suspected issues, require each agent to write a failing test before fixing code, and reject work that lacks proof. Separate agents can explore different modules while shared negative-knowledge files record dead ends, flaky tests, and false positives.
Parallelism also supports specialization. One agent can focus on implementation, another on duplicate-code cleanup, another on performance, another on documentation, and another on review. Role specialization works best when each role has a separate verifier or acceptance rubric rather than a generic “improve the project” prompt.
File-based task queues are crude but robust. A task file can include the target failure, reproduction command, expected verifier, owner, status, and notes. Atomic file creation or git conflict behavior can prevent two agents from claiming the same item. The task list remains inspectable by humans and future agents.
# current_tasks/compile_sqlite.md
status: claimed
owner: agent-07
repro: ./harness compile-package sqlite --fast
gate: ./harness compile-package sqlite --full
Goal:
Fix the first compiler bug that prevents SQLite from compiling.
Notes:
- Do not edit the package source.
- Record failed approaches below before releasing the task.
Agents need quick feedback while iterating, but the system needs stronger final checks. Provide deterministic fast subsets per agent so work cycles are not dominated by long runs. Then enforce full suites, cross-architecture builds, or corpus checks before shared-state integration.
Merge conflicts are not exceptional in parallel agent teams; they are part of the workflow. The harness should expose conflicts clearly, allow agents to resolve them in their workspace, rerun affected tests, and reject pushes that skip verification. For high-risk repositories, use a merge queue or integration agent rather than pushing directly to the main branch.
Resetting a branch removes bad code, but the team still needs memory of what failed. Keep append-only notes for failed hypotheses, flaky checks, expensive dead ends, and verifier improvements. This prevents fresh agents from rediscovering the same attractive but wrong fix.