Two AI agents, one codebase: keeping parallel work in sync
Parallel coding agents can each make a reasonable change and still leave the product inconsistent. Worktrees, handoffs, and shared decision memory fix it.
One issue says: rename POST /login to /session and remove the old route.
Another says: update the onboarding flow to call the auth endpoint after email verification.
Two engineers take one issue each. Both use an AI coding agent. Both agents move fast. The first changes the server, the SDK, and the tests. The second opens a separate branch, finds the client still calling /login, and keeps it because that is what the code in front of it says.
Each agent did reasonable work. Together, they produced a contradiction.
This is the uncomfortable part of multi-agent coding: parallel execution does not create shared understanding. It creates more places where understanding can split. (For the single-agent version of this problem, and the memory layers that address it, see the AI coding agent memory guide.)
Two agents do not see one codebase
People talk about multiple agents working on one repository as if the repository were the shared brain. It is not. It is the shared output.
Agent A sees its prompt, its branch, the files it opened, and the decisions someone happened to include. Agent B sees a different prompt, a different branch, and a different slice of the code. Even if both begin from the same commit, their context diverges as soon as they start.
The repository can tell them that two routes exist. It usually cannot tell them that the team deliberately killed one of them after a customer migration. It can show a false feature flag. It cannot show that product cut the feature because supporting it would break the new pricing model.
That missing why is where agents start making independent guesses.
Anthropic's guidance on context engineering makes the core point: effective agents depend on finding and maintaining the right context, not simply filling a larger window. With several agents, you are not maintaining one useful context. You are maintaining several, while each agent changes the ground beneath the others.
The conflict arrives before the merge conflict
Git is good at telling you when two branches changed the same line. Most multi-agent failures are less polite.
One agent changes the trial from 14 days to 7. Another rewrites the billing email and still promises 14. Different files, clean merge.
One agent removes an export because the feature was cut. Another adds a new settings screen for it. Different packages, clean merge.
One agent changes an API response shape. A second updates the frontend against the old shape. A third sees both branches, decides the mismatch is accidental, and adds a compatibility layer nobody wanted.
The code does not collide. The decisions do.
This is decision drift at parallel speed. And it affects more than the developers resolving branches: engineering leads inherit review as a context-reconstruction job, and product people see old scope return or pricing leak into inconsistent places.
How should you split work between agents?
A large task does not become parallel merely because you spawn more agents. Good parallel tasks have low overlap and clear outputs:
- investigate the current authentication flow
- implement backend token rotation in one worktree
- update mobile client handling after the backend contract is accepted
- write integration tests against the accepted response shape
"Improve auth" or "fix the API and UI" are not parallel tasks; they are invitations for two agents to make overlapping plans.
Claude Code's agent-team guidance says teams work best when tasks can proceed independently and coordination adds value. Each teammate has its own context window, and teams carry higher token and coordination cost than a subagent. Start with a few agents and add more only when the work actually separates. If one main agent just needs a bounded research or verification job done, a subagent is usually cheaper than an independent teammate.
Source: Claude Code agent teams
Give each implementation task its own worktree
A Git worktree gives each agent a separate working directory and branch while sharing repository history:
git worktree add ../repo-auth -b agent/auth
git worktree add ../repo-client -b agent/client
Claude Code can start an isolated session in a worktree, and Cursor's parallel-agent workflows use worktrees for the same reason: one agent's edits should not overwrite another's working directory.
Isolation prevents filesystem collisions. It does not prevent semantic conflicts. Worktrees solve where agents edit, not what the team has agreed.
Sources: Claude Code worktrees and Cursor worktrees
Make ownership and dependencies visible
| Task | Owner | Depends on | Done when |
|---|---|---|---|
| Define token contract | Lead | None | Owner approves fields and errors |
| Implement backend | Agent A | Contract | Unit and integration tests pass |
| Update mobile client | Agent B | Contract | Retry fixture passes |
| Cross-boundary test | Agent C | Backend + client | Full flow passes |
Dependencies matter more than simultaneous start time. Agent B can investigate the client before the contract is final, but should not hard-code a guessed response shape. Claude Code agent teams include a shared task list with dependency tracking; issues or any other task system work too, as long as every agent can see who owns what and what must finish first.
Task coordination is not decision coordination
Bounded issues, assigned directories, and a planner agent are useful controls. They solve ownership of work, not alignment on truth.
A task board can say who owns onboarding. It does not say why onboarding must wait for email verification. A planner can split a migration into five steps. It does not know that the old route must never be restored, unless the decision reaches its context. Agent-to-agent messages can keep one run coordinated. They disappear with the run, and the next agent starts from zero again.
Anthropic's account of its multi-agent research system describes the work of delegating scope, coordinating parallel paths, and bringing results back together. Coding adds another constraint: the result is not a report assembled once. It is a living product where today's agent inherits every decision yesterday's agents made.
The handoff cannot carry only code. It has to carry intent.
Treat interface changes as handoff events
When an agent discovers something that affects another workstream, it should update the shared task right away, not at merge time:
Auth contract update:
- refresh endpoint now returns `retry_after_ms`
- field is nullable only for permanent failures
- mobile client must not infer retry delay
- accepted in decision AUTH-12
- backend branch tests pass with `pnpm test auth`
A useful handoff names the change, the affected interface and consumers, its status (discovered, proposed, or accepted), the owner or decision reference, tests run, and remaining risk.
Separate exploration from decisions
Several agents may explore alternatives in parallel. That is useful. Their findings should return to an owner before implementation paths diverge:
- Agents investigate or propose.
- The lead summarizes options and tradeoffs.
- The responsible owner accepts one contract or architecture choice.
- The decision becomes current in the shared record.
- Implementation tasks unblock.
Without this gate, the first agent to commit code silently becomes the decision maker, and later agents normalize around an accidental choice.
Why the common fixes stop short
Give every agent the whole repository. Necessary, but the code is evidence of decisions, not a reliable record of them. Agents reverse-engineer intent from implementation and can reach different conclusions.
Put everything in AGENTS.md. Useful for stable instructions. Weak for a stream of changing product and engineering calls. The file grows, stale rules remain unmarked, and every agent pays the context cost whether a rule affects its work or not.
Make agents read the wiki. Which page? Which version? A document store is not a briefing system. The relevant decision has to reach the agent before the agent writes against it.
Add more tests. Tests are essential, but they only defend decisions someone encoded, and independent unit suites can pass while the combined contract fails.
Use one planning agent. A planner can reduce overlap in a run. It becomes another temporary memory boundary unless its decisions persist and future agents can retrieve them.
Microsoft's work on repository memory and repository-level planning points in the same direction: repository-scale work improves when agents can carry forward useful knowledge and reason across dependent changes. But a team needs more than a map of code. It needs a memory of the calls that code is supposed to honor.
What shared memory must contain
A shared transcript is not enough. Neither is a pile of summaries. Useful decision memory has a shape.
The verdict. "The trial starts after email verification," not three pages of conversation someone must interpret again.
The why. Without the reason, a future agent cannot tell whether the decision still applies when the code changes around it.
The rejected alternatives. If the team considered starting the trial at signup and rejected it because disposable accounts distorted activation, record that. Otherwise an agent will rediscover the idea and present it as new.
The scope. Which modules, flows, or product surfaces does the decision affect? Scope lets the system retrieve a small relevant briefing instead of dumping the entire company history into every context window.
The owner and status. Who made the call? Is it active, proposed, or replaced? Shared memory should align agents without turning every passing suggestion into policy.
The replacement chain. When seven days becomes fourteen again, the old entry should remain visible as superseded, linked to the new call and its reason. Silent rewrites create a memory nobody can audit.
One agent's local memory can't play this role: other agents cannot see it, and the team cannot review it. Accepted choices need to be promoted into the shared record.
Brief before action, not after the mistake
Capturing decisions is only half the system. Before an agent edits onboarding, it should receive the active decisions that affect onboarding: when the trial begins, what verification is required, and what was recently replaced. Before another agent edits billing email, it should receive the overlapping pricing and trial decisions.
They do not need identical prompts. They need a consistent set of truths where their work overlaps. If a new implementation conflicts with an accepted choice, the agent should stop and name the conflict rather than silently updating the architecture.
Who integrates the result?
A lead, human or agent, who integrates rather than merely merges:
- confirm the accepted interfaces and decisions
- merge the lowest-level dependency first and run its tests
- rebase dependent branches and run cross-boundary tests
- check that handoffs and decision pointers are current
- close temporary handoffs when the work is done
A clean Git merge is not proof of a consistent result. For high-risk work, have agents plan before implementing; Claude Code agent teams support plan approval, so the lead can review an approach before files change.
For the native ways to share what one engineer's agent learned with the rest of the team, see Claude Code team memory.
Where Lockstep fits
Lockstep is the shared decision-memory layer for teams building with AI coding agents. Owners approve decisions captured from Slack, docs, tickets, and PRs; Lockstep keeps the why and the replacement history, ranks each decision by blast radius, and briefs any MCP-compatible agent through get_product_context before it acts. A PR check flags changes that may conflict with an approved decision (it warns by default; blocking is opt-in).
Worktrees keep edits apart. Tasks keep ownership clear. Tests check the combined result. Lockstep keeps every agent working from the same version of the truth.
Related: how to share memory between Cursor and Claude Code and why Claude Code forgets architecture decisions.
Frequently asked questions
- Why do multiple AI coding agents conflict in the same codebase?
- Each agent sees a different prompt, branch, and slice of history. Without a shared record of settled decisions, two agents can make locally sensible changes that encode different assumptions about the same product or architecture. Git can merge text, but it cannot decide which assumption the team intended.
- Do Git worktrees stop agents from conflicting?
- They stop filesystem collisions: each agent edits its own working directory and branch. They do not stop semantic conflicts. Two agents can still implement incompatible interfaces in separate worktrees. Worktrees solve where agents edit, not what the team has agreed.
- Is a shared repository enough context for multiple coding agents?
- No. A repository shows what the code is now, but often not why it became that way, which alternatives were rejected, or which product constraint must survive the next change. Agents infer those missing decisions independently, and those inferences drift.
- How is shared decision memory different from agent-to-agent chat?
- Chat can coordinate agents during one run. Shared decision memory survives the run, records the verdict and its reason, marks what it affects, and briefs future agents before they act. It is durable team context rather than temporary coordination.
Keep reading