Skip to content

Parallel Coding Agents for Large Refactors

A coding agent can often complete a focused change: fix one bug, update one component, or repair one failing test.

A repository-wide refactor is different. It may touch hundreds of files, cross several ownership boundaries, and require intermediate states that must continue to build. One agent can run out of useful context, repeat an early mistake across the codebase, or stop after completing only part of the migration.

Parallel-agent orchestration addresses that problem by treating the refactor as a coordinated program of smaller changes.

In beginner terms:

  1. map the large change
  2. divide it into reviewable batches
  3. identify which batches depend on others
  4. give ready batches to isolated coding agents
  5. verify every result
  6. merge accepted batches in a controlled order
  7. run whole-system checks before completing the migration

The important idea is not “use more agents.” It is make the work divisible, independently verifiable, and safe to integrate.

How This Differs From One Long-Running Agent

Section titled “How This Differs From One Long-Running Agent”

A single long-running agent owns one conversation and one evolving context. It can inspect, plan, edit, test, and recover over many steps.

Parallel orchestration creates several bounded workers. A coordinator, usually application code plus human oversight, decides what each worker receives and when its result can be accepted.

One long-running agentParallel coding agents
One task trajectorySeveral bounded task trajectories
One working copySeparate branches, worktrees, or sandboxes
Context accumulates in one conversationEach worker receives task-specific context
Fewer merge conflictsFaster independent work, but integration is harder
Best when steps are tightly connectedBest when meaningful batches can run independently

Use Prompting Long-Horizon Coding Agents when one agent can reasonably own the complete change. Use parallel editing only when the work can be partitioned without several agents modifying the same state at the same time.

The phrase “parallel agents” is used for several different designs.

LevelWhat runs concurrentlyExample
Parallel toolsOne agent requests several independent tool callsRead three files or call three read-only APIs
Parallel subagentsA parent delegates independent investigationsOne checks tests while another checks documentation
Parallel coding workersSeparate agents edit isolated copies of a repositoryMigrate independent components on separate branches
Repository fleetAn orchestrator dispatches work across many repositoriesApply one dependency or security change across an organization

This page focuses on the third level and the architecture that can later scale to the fourth.

Parallel reads are comparatively easy. Parallel writes are where dependency planning, isolation, verification, and integration become mandatory.

flowchart TD
    A["Migration goal and acceptance criteria"] --> B["Discovery<br/>Map files, interfaces, and dependencies"]
    B --> C["Human-approved batch plan"]
    C --> D["Dependency-aware scheduler"]
    D --> E1["Agent A<br/>isolated workspace"]
    D --> E2["Agent B<br/>isolated workspace"]
    D --> E3["Agent C<br/>isolated workspace"]
    E1 --> F1["Batch verification"]
    E2 --> F2["Batch verification"]
    E3 --> F3["Batch verification"]
    F1 --> G["Review and integration queue"]
    F2 --> G
    F3 --> G
    G --> H["Repository-level verification"]
    H -->|Pass| I["Merge migration stage"]
    H -->|Fail| J["Diagnose integration failure"]
    J --> C

The coordinator should own:

  • the migration goal and non-goals
  • the batch graph
  • workspace creation and cleanup
  • concurrency limits
  • verification policy
  • retries, timeouts, and cancellation
  • integration order
  • human approval gates
  • the final repository-wide result

An individual coding agent should own only its assigned batch.

Choose Tasks That Are Actually Parallelizable

Section titled “Choose Tasks That Are Actually Parallelizable”

Good candidates usually have four properties.

Examples include:

  • upgrading a dependency across many packages
  • migrating components from one library to another
  • adding type information across a codebase
  • replacing a deprecated API
  • applying a well-defined security remediation
  • removing a known code smell
  • updating generated or repetitive configuration

The individual changes may require judgment, but the target pattern remains recognizable.

One completed batch should be reviewable and, ideally, mergeable without waiting for every other batch.

This matters because some workers will fail, stall, or discover blocked cases. A workflow that produces 80 safe pull requests and 20 explicit blockers is often more useful than one giant run that returns nothing until every case succeeds.

Useful verification signals include:

  • unit and integration tests
  • compiler or type-checker output
  • lint and formatting checks
  • API compatibility tests
  • schema validation
  • security scanners
  • snapshot or visual regression checks
  • a precise search proving that a deprecated construct is gone

If nobody can state how to verify a batch, dispatching more agents only creates more unverified code.

The safest batches own different files, modules, packages, services, or repositories.

Parallel agents are a poor fit when:

  • every batch must edit the same central file
  • one worker’s output constantly changes another worker’s assumptions
  • the target architecture is still undecided
  • tests are missing and behavior is poorly understood
  • a migration requires one indivisible transaction
  • merge conflicts would dominate the work
  • the change affects safety-critical behavior without strong review controls

Do not ask ten agents to begin editing from a one-sentence migration request.

First build a current map of the repository:

  1. locate every use of the old interface
  2. identify entry points and public contracts
  3. map build, test, and deployment boundaries
  4. find generated code and files that must not be edited
  5. identify owners and high-risk modules
  6. establish characterization tests for behavior that must remain unchanged
  7. record known exceptions and unsupported cases

The discovery output is not merely a list of files. It should explain relationships that affect execution order.

For an unfamiliar repository, begin with Codebase Onboarding with Coding Agents and Finding Unknowns Before Agentic Work.

A useful batch is small enough for one agent to finish and one person to understand, but large enough to represent a coherent change.

Good boundaries include:

  • one package and its tests
  • one service
  • one UI component family
  • one database access layer
  • one group of files that share an internal interface
  • one repository in a cross-repository campaign

Avoid assuming that one file equals one task. A file may be meaningless without its tests, generated types, fixtures, or closely coupled dependencies.

Every batch should have an explicit contract:

Batch: migrate account-settings state management
Owns:
- src/account-settings/**
- tests/account-settings/**
Goal:
- replace the old state API with the approved adapter
- preserve current user-visible behavior
May read but not edit:
- src/shared/state/**
Must not change:
- public component properties
- persistence format
Prerequisites:
- compatibility adapter merged
Verification:
- account-settings unit tests
- type check
- production build
- no imports from the deprecated package inside owned paths
Output:
- focused commit or pull request
- verification evidence
- discoveries that affect other batches
- unresolved blockers

The ownership list prevents two workers from silently editing the same files. The prerequisite and verification fields let the scheduler decide when the batch is ready and whether it is complete.

A file-level dependency graph may be too detailed to schedule directly. Convert it into a smaller batch graph:

  • each node represents one reviewable batch
  • each edge means one batch must be completed before another can safely begin or merge
flowchart LR
    A["Compatibility adapter"] --> B["Account settings"]
    A --> C["Checkout"]
    A --> D["Notifications"]
    B --> E["Remove old dependency"]
    C --> E
    D --> E
    E --> F["Delete migration scaffolding"]

In this example, Account settings, Checkout, and Notifications can run concurrently after the compatibility adapter is ready. Removing the old dependency must wait for all three.

Possible strategies include:

StrategyUseful whenRisk
Directory or package boundariesRepository structure matches ownership and behaviorRelated code may live elsewhere
Dependency graph communitiesImports reveal meaningful clustersGenerated or dynamic dependencies may be missed
Domain or service boundariesArchitecture has clear business modulesShared infrastructure still creates coupling
Search-result groupsTransformation is syntactically regularSimilar syntax may hide different semantics
Ownership boundariesTeams review and deploy independentlyOwnership may not match runtime dependencies

Use repository structure as evidence, not as proof. Confirm the proposed batches against tests, interfaces, and human knowledge.

If batch A depends on B and B also depends on A, they are not independently schedulable in their current form.

Options include:

  • combine them into one batch
  • introduce a temporary compatibility interface
  • split out their shared contract first
  • complete the cycle serially under one worker

Pretending a dependency cycle does not exist creates repeated integration failures later.

A batch is ready when:

  • its prerequisites are merged into its starting point
  • its owned files are not assigned to another active worker
  • its required context and verification commands are available
  • no unresolved design decision blocks it
flowchart TD
    P["Pending batch"] --> R{"Prerequisites satisfied?"}
    R -->|No| P
    R -->|Yes| W["Create isolated workspace"]
    W --> A["Agent implements batch"]
    A --> V["Run batch verification"]
    V -->|Fail| X["Return focused failure evidence"]
    X --> A
    V -->|Pass| H["Human or policy review"]
    H -->|Changes requested| A
    H -->|Accepted| M["Merge batch"]
    M --> U["Unlock dependent batches"]

The scheduler should not rely on agents remembering the entire graph. It should represent batch state explicitly in code, a database, a workflow engine, or at minimum a versioned task file.

Useful states include:

  • pending
  • ready
  • running
  • verification_failed
  • awaiting_review
  • accepted
  • merged
  • blocked
  • cancelled

This state model makes partial progress and failure visible.

Do not run multiple editing agents in the same working directory. They can overwrite files, invalidate each other’s tests, stage unrelated changes, or interpret temporary state as committed architecture.

Isolation methodStrengthMain limitation
Git branch in a separate cloneFamiliar and strongly separatedMore disk and setup work
Git worktree with its own branchLightweight and shares repository objectsStill shares host credentials and resources
Container workspaceIsolates dependencies and filesystem stateContainer security and resource policy still matter
Remote sandbox or VMStronger execution and scaling boundaryHigher operational cost and credential complexity

The Git worktree documentation explains how several working trees can share one repository while keeping separate checked-out branches. The existing Claude Code guide covers the basic worktree workflow.

Isolation is not complete security by itself. Each worker also needs:

  • least-privilege credentials
  • restricted network and filesystem access
  • resource, time, token, and cost limits
  • explicit rules for external side effects
  • secret redaction in logs and prompts
  • cleanup after completion or cancellation

A container that receives an unrestricted production token is still dangerous.

Verification should be designed before workers start.

Run the cheapest and most deterministic checks first:

  1. changed-file and ownership checks
  2. format and syntax checks
  3. compiler, type checker, or linter
  4. focused unit tests
  5. package or service integration tests
  6. repository build
  7. broader end-to-end or visual checks
  8. semantic review where code cannot decide correctness
flowchart LR
    A["Agent patch"] --> B["Scope check"]
    B --> C["Static checks"]
    C --> D["Focused tests"]
    D --> E["Package integration"]
    E --> F["Human or semantic review"]
    F --> G["Accepted batch"]

The worker that wrote a patch should run tests, but its declaration of success is not sufficient evidence.

Use an independent verifier to:

  • execute checks in a clean environment
  • confirm the diff stayed inside the ownership boundary
  • detect missing tests or changed public contracts
  • record exact commands, versions, and results
  • reject a patch without trying to explain it away

If verification fails, pass focused evidence back to the fixer:

Failed check: package type check
Command: npm run typecheck --workspace checkout
Error: CheckoutStore no longer satisfies PersistedStore at src/checkout/store.ts:84
Allowed scope: src/checkout/** and tests/checkout/**
Do not modify the shared PersistedStore interface.

This is more useful than “the tests failed, fix it.”

An LLM can review semantic concerns such as whether a refactor preserved intent or whether a new abstraction violates documented architecture.

Do not use an LLM judge as a substitute for a compiler, test suite, or security scanner. Model-based verification is nondeterministic and can share the same mistaken assumptions as the coding agent.

Use it after deterministic checks, with a narrow rubric and access to the actual diff and evidence.

Add Temporary Migration Scaffolding When Needed

Section titled “Add Temporary Migration Scaffolding When Needed”

Some migrations cannot move each component directly from old to new while keeping the application runnable.

A temporary compatibility layer can create an intermediate state:

flowchart TD
    A["Current system<br/>old interface only"] --> B["Add compatibility layer"]
    B --> C["Old and new implementations can coexist"]
    C --> D1["Migrate batch A"]
    C --> D2["Migrate batch B"]
    C --> D3["Migrate batch C"]
    D1 --> E["All consumers use new interface"]
    D2 --> E
    D3 --> E
    E --> F["Remove compatibility layer and old dependency"]

Examples include:

  • an adapter that presents one interface over old and new libraries
  • dual readers during a storage-format migration
  • a compatibility API while callers move incrementally
  • a feature flag that selects old or new behavior
  • temporary shims for renamed types or methods

Scaffolding must have:

  • an owner
  • a removal condition
  • tests for both temporary paths
  • a tracked final cleanup batch
  • a limit on how long the dual state may remain

Without a removal plan, temporary migration code becomes permanent complexity.

Share Context Without Sharing Every Transcript

Section titled “Share Context Without Sharing Every Transcript”

Giving every worker every other worker’s conversation recreates one oversized context window. It also spreads irrelevant details, stale guesses, and accidental instructions.

Use layered context instead.

Every worker may need:

  • migration goal and non-goals
  • approved architecture decisions
  • repository conventions
  • verification policy
  • prohibited changes
  • security boundaries

Keep this small, versioned, and human-reviewed.

Each worker receives:

  • owned files and allowed dependencies
  • prerequisite commit or artifact versions
  • relevant interfaces and tests
  • batch-specific acceptance criteria
  • known risks and exceptions

A worker may learn something that affects other batches. It should propose a structured discovery rather than broadcast its transcript:

Discovery: persistence middleware assumes store keys remain stable
Evidence: src/shared/persistence.ts and tests/persistence/restore.test.ts
Affected batches: account-settings, checkout
Proposed action: preserve existing keys during migration
Confidence: confirmed by tests

A human or coordinator reviews the discovery before promoting it into shared campaign context.

This prevents one worker’s hallucination from becoming a fleet-wide instruction.

A passing batch is not proof that several accepted batches work together.

Use an integration branch or equivalent staging environment:

  1. update the branch from the approved base
  2. merge ready batches in dependency order
  3. resolve conflicts with ownership and design context available
  4. run affected package checks after each merge
  5. run repository-wide verification at defined checkpoints
  6. stop and diagnose when a regression first appears
  7. tag or record known-good integration points

Avoid merging dozens of branches and testing only at the end. When the combined build fails, the search space is much larger.

Shared interfaces, schemas, generated clients, build configuration, and dependency lockfiles are conflict hotspots.

Prefer one of these strategies:

  • merge the shared interface change first, then rebase workers onto it
  • assign the shared file to one integration owner
  • generate shared artifacts centrally after batch merges
  • serialize batches that must modify the same contract

Parallel execution does not require parallel merging.

Human review is most valuable where the system cannot cheaply recover from a wrong decision.

Useful gates include:

GateHuman decision
Before dispatchAre the architecture and batch boundaries correct?
After a new discoveryDoes this change the campaign plan?
Before accepting a batchIs the patch understandable, scoped, and supported by evidence?
Before shared-interface changesAre downstream effects understood?
Before removing scaffoldingHave all consumers migrated and rollback needs expired?
Before final mergeDoes the integrated system meet the original acceptance criteria?

The goal is not necessarily complete automation. It is to automate repetitive execution while keeping architectural judgment, risk acceptance, and final accountability visible.

At scale, some workers will fail. Plan for it.

  • enforce a maximum runtime and model-call budget
  • capture its current diff and verification state
  • retry only if the failure is transient
  • split the batch when the task was too broad
  • escalate a real design ambiguity to a human
  • fail the ownership check
  • discard or manually isolate the out-of-scope changes
  • clarify the contract before retrying
  • do not automatically expand permissions to make the patch pass
  • inspect whether the original decomposition was wrong
  • serialize the affected work or introduce a shared prerequisite
  • assign one owner to the contested interface
  • update the dependency graph

Verification passes locally but integration fails

Section titled “Verification passes locally but integration fails”
  • identify the first combined checkpoint that fails
  • add the missing cross-batch test
  • update future batch contracts with the discovered invariant
  • avoid patching the integration branch without feeding the learning back into the plan
  • merge independently safe batches when policy allows
  • record blocked cases and reasons
  • retain compatibility scaffolding only with explicit ownership
  • decide whether remaining exceptions justify a different design

Partial progress is useful only when it remains supportable.

Measure The Workflow, Not Just Agent Output

Section titled “Measure The Workflow, Not Just Agent Output”

Track whether orchestration improves delivery rather than merely increasing activity.

Useful measures include:

  • batches accepted without rework
  • first-pass verification rate
  • human review time per batch
  • merge-conflict rate
  • integration failures caused by cross-batch assumptions
  • elapsed time from ready to merged
  • model and infrastructure cost per accepted batch
  • stalled and cancelled batches
  • regression rate after integration
  • percentage of the migration completed without permanent exceptions

Compare those with a baseline such as one human team, one agent, or a smaller pilot. A large number of simultaneous workers is not success if reviewers become the bottleneck or integration quality falls.

Adopt the pattern incrementally.

  1. choose a reversible, repetitive migration
  2. define five to ten coherent batches
  3. run only a few editing workers concurrently
  4. keep deterministic verification mandatory
  5. review every batch and measure rework
  1. automate workspace creation and cleanup
  2. persist explicit batch states and dependencies
  3. standardize batch contracts and evidence
  4. add integration checkpoints
  5. promote only reviewed discoveries into shared context
  1. route pull requests to code owners
  2. enforce organization-wide permission and cost limits
  3. isolate credentials per repository or campaign
  4. add durable scheduling, retries, and cancellation
  5. monitor quality by repository, transformation, and agent configuration

When runs must survive process failures, long waits, or approval delays, combine this pattern with Durable AI Agents with Temporal or another durable workflow runtime.

The source workshop demonstrates these durable ideas:

  • repository-wide changes should be decomposed before editing
  • dependency-aware batches are safer than arbitrary parallel tasks
  • each batch needs a verifier and a bounded fixer
  • isolated agents can work concurrently on ready batches
  • temporary scaffolding can make incremental migration testable
  • humans should review intermediate outputs and integration decisions
  • context should be curated instead of copied everywhere

The workshop also contains OpenHands installation steps, a live vulnerability-remediation exercise, product-specific APIs, and productivity claims. Those details are not the basis of this guide.

Current OpenHands documentation still describes its Software Agent SDK as supporting major multi-agent tasks such as refactors and rewrites. It also supports local, Docker, and remote workspaces. However, its parallel tool-execution feature is currently marked experimental and warns about shared-state races. That reinforces the conservative rule used here: parallelize only independent operations and keep write isolation explicit.

Before dispatch:

  • The target behavior and non-goals are explicit.
  • Current repository behavior has been mapped.
  • Batches are coherent and reviewable.
  • Dependencies and cycles are represented.
  • File ownership does not overlap between active workers.
  • Every batch has deterministic verification where possible.
  • Credentials and execution environments are isolated.
  • Human approval gates are defined.

Before completing the migration:

  • Every accepted batch includes verification evidence.
  • Shared discoveries were reviewed and recorded.
  • Batches were integrated in a controlled order.
  • Repository-wide tests and builds pass.
  • Temporary scaffolding has been removed or explicitly retained.
  • Deprecated dependencies and interfaces are actually gone.
  • Known exceptions, costs, and residual risks are documented.
  • Rollback or recovery remains possible.

Diagram viewer