Level 3 · Loop Engineering

Run Parallel Agents Without Corrupting Code or Context

Parallel agents only pay off when concurrency is treated as an isolation and verification problem, not as many chat windows pointed at the same repo.

Start With Isolation Boundaries

The central mistake in parallel agent work is assuming the conflict is mostly Git. Git conflicts are the visible failure. The deeper failures are shared filesystem state, shared database state, shared caches, shared task memory, and shared model bias. If ten agents inherit the same vague plan and mutate the same app surface, you have serial work with extra nondeterminism. Useful concurrency starts by giving each agent a bounded claim: a worktree, a database branch, a test namespace, a job contract, and an output format that can be compared without reading its whole conversation.

For code, default to one Git worktree per agent, one branch per hypothesis, and no agent writes outside its checkout except through declared artifacts. For application state, give each worktree its own database branch or schema. Neon-style branching, per-agent Postgres schemas, disposable SQLite files, and namespaced object storage all solve the same problem: tests must observe only that agent's changes. If your integration tests share Redis keys, S3 prefixes, Stripe webhook fixtures, or local ports, you have not isolated the run.

The job contract should be narrower than the project goal. Specify inputs, owned files or modules, forbidden areas, validation commands, retry limits, and escalation conditions. A good contract says what to do when an asset fails to generate, a migration conflicts, a flaky test appears, or a dependency install breaks. Without those rules, the agent spends expensive tokens inventing policy under pressure, often after it has already polluted the branch.

Route Work Before You Fan Out

Once isolation exists, the next constraint is context quality. Do not fan out a messy project prompt to a dozen workers. Run a classify-and-act pass first: one cheap or mid-tier model reads the goal, repo map, constraints, and recent failures, then emits typed jobs. Examples: implementation spike, security review, migration plan, UI variant, performance probe, test repair, documentation sweep. Each job gets a clean context and only the slice of repo knowledge it needs.

Use model routing aggressively. Expensive frontier models are most valuable when ambiguity is low and execution quality matters. Spend cheaper tokens on inventory, file discovery, task classification, rubric drafting, and candidate PRD refinement. Then hand the refined implementation packet to the stronger model in a fresh session. This avoids the common failure where the best model burns half its window exploring stale paths, then codes under compressed context with a half-remembered plan.

Keep long loops durable outside the chat. Store job state in a database or structured files: status, branch, worktree path, assigned model, token budget, validation commands, latest failure, retry count, and artifact links. The agent can reason, but the harness should remember. If a run dies at 3 a.m., the next invocation should resume from state, not from a pasted transcript. This also makes cost control tractable because you can see which job types consume tokens, which retry forever, and which models produce mergeable work per dollar.

Synthesize Outputs, Not Opinions

Fan-out is useful when outputs can be compared. It is weak when agents merely produce prose that inherits the same assumptions. For implementation, run multiple agents on the same bounded problem only when you can evaluate branches independently. The synthesis step should inspect diffs, run tests, compare behavior, and extract the strongest pieces. Avoid letting one agent read all prior rationales before choosing, because self-preference and anchoring will dominate. Give the synthesizer artifacts first: patch, test result, benchmark, screenshot, schema diff, and known risks.

For design or architecture choices, use tournament patterns instead of list scoring. Pair options in isolated comparisons, require a decision against a rubric, then advance winners. This reduces the bias that appears when a model sees every candidate at once and invents a global ranking from vibes. For code, tournaments can compare two branches on criteria like blast radius, migration safety, latency, test coverage, and rollback simplicity. The point is not to make the model objective. The point is to constrain its subjectivity into repeated, inspectable judgments.

Synthesis should be allowed to reject all candidates. In mature harnesses, the output of fan-out is often a better spec, not an immediate merge. If three agents fail differently, the correct result may be a new narrowed job: reproduce the failing test, isolate the missing abstraction, or generate a migration compatibility plan. Treat this as useful work. Parallelism is buying search over implementation space. Search includes learning that the current decomposition is wrong.

Verify Adversarially

After synthesis, verification must come from a context that did not author the solution. A self-checking agent will often validate the thing it meant to build, not the thing it actually changed. Spawn skeptic agents with the original requirements, the final diff, and a rubric. Ask them to find requirement misses, unsafe assumptions, hidden shared state, untested paths, and ways the patch could pass the declared tests while still being wrong. For security, authorization, migrations, billing, and data deletion, adversarial verification should be mandatory.

Make verification layered. Deterministic checks run first: format, typecheck, unit tests, integration tests, migration apply and rollback, lint, dependency audit, bundle size, benchmark thresholds. Agentic checks run after, focused on interpretation: Does the diff satisfy the goal? Did it touch forbidden areas? Are tests asserting behavior or just snapshots? Did the branch create new coupling? For frontend work, add browser automation with screenshots or GIFs so reviewers see actual behavior instead of trusting prose.

Loop-until-done belongs here, but only with hard exits. Good loops have a trigger, action, validation command, retry ceiling, and stop condition. Bad loops say “keep going until fixed” and let the model rewrite surrounding code until tests happen to pass. A disciplined loop can reproduce a flaky failure in fresh worktrees, try independent theories, and stop when a specific assertion is stable. An undisciplined loop converts uncertainty into churn.

Control Cost By Controlling Shape

High spend is not automatically waste. In advanced agent work, token burn often means you kept many workers productively occupied. The useful metric is accepted work per dollar, adjusted for human review time and regression risk. That said, most runaway cost comes from bad shape: huge contexts, broad mandates, repeated environment setup, agents debugging shared-state failures, and premium models doing clerical routing.

The harness should enforce budgets at the job level. Set model class, max attempts, max wall time, validation budget, and artifact requirements before launch. Batch dependent jobs so agents spawn only when prerequisites exist. Prefer short sessions with fresh context for research, planning, implementation, and review. Carry forward structured memory, not the whole conversation: decisions, constraints, file ownership, failed approaches, and mission objectives. Project rules and reusable skills should encode stable behavior such as test commands, commit conventions, local service startup, and review expectations.

The final architecture is a pipeline: classify, isolate, execute, synthesize, verify, merge. Worktrees prevent file corruption. Branched databases prevent state corruption. Fresh contexts prevent bias accumulation. Tournament and adversarial patterns prevent consensus theater. Durable state prevents overnight work from evaporating. Parallel agents become reliable when the harness makes every worker replaceable, every artifact inspectable, and every merge earned by independent evidence.

Key takeaways

  • Run each agent in its own worktree, branch, database namespace, cache namespace, and declared file ownership boundary.
  • Use cheaper models for discovery, classification, rubric drafting, and planning; reserve frontier models for narrowed execution and hard synthesis.
  • Fan out only when outputs are comparable through diffs, tests, benchmarks, screenshots, or structured findings.
  • Use tournament comparisons and independent skeptic agents to reduce shared-context bias and self-preference.
  • Persist loop state outside the conversation so overnight runs can resume, audit cost, and stop on explicit failure conditions.
  • Measure parallel agent systems by accepted work per dollar and review burden, not by lowest token usage.