lockstep
7 min readNaman Jain

Two AI agents, one codebase: why parallel work breaks without shared memory

Two coding agents can each produce a reasonable change and still leave the product inconsistent. The missing layer is shared decision memory: the settled calls every agent must know before it acts.

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.

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. It can show a strange validation rule. It cannot show the incident that made the rule non-negotiable.

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. In a multi-agent setup, the problem gets harder. 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 makes an API field optional for backwards compatibility. Another updates the client under the assumption that the field is now required. Tests scoped to each task pass. The contradiction only appears in production behavior.

The code does not collide. The decisions do.

This is decision drift at parallel speed: the product moves away from what the team agreed, not through one dramatic reversal, but through several locally defensible changes built on different assumptions.

And it affects more than the developers resolving the branches. Engineering leads inherit review as a context-reconstruction job. Product people see old scope return or current pricing leak into inconsistent places. Customer-facing teams get behavior nobody can explain cleanly. The faster the agents write, the faster these contradictions accumulate.

Task coordination is not decision coordination

The usual answer is to divide work more carefully.

Give each agent a bounded issue. Assign different directories. Add a planner agent. Make agents send status updates to one another. These are useful controls, but 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.

Even sophisticated multi-agent systems need explicit orchestration. 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.

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? Which paragraph matters to this change? 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. They rarely explain why a constraint exists, and they cannot catch every pair of individually valid changes that produce the wrong product together.

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. What did the team decide? "The trial starts after email verification," not three pages of conversation someone must interpret again.

The why. What constraint or goal made this the right call? 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, customers, 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. Decisions change. 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.

This structure matters to the whole team. A developer needs the active API contract. An engineering lead needs to know which decision a PR is violating. A product person needs to trace why the trial changed and whether the customer email reflects the same call. They are different questions over the same memory.

Brief before action, not after the mistake

Capturing decisions is only half the system. The read path decides whether the memory is useful.

Before an agent edits onboarding, it should receive the active decisions that affect onboarding: when the trial begins, what verification is required, which analytics event defines activation, 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.

That is the practical model:

  1. Capture a decision once, when the team makes it.
  2. Record its reason, owner, scope, and rejected alternatives.
  3. Rank it by what it can affect.
  4. Brief each agent on the relevant active decisions before it changes code.
  5. Preserve what replaced what, so old assumptions do not quietly return.

Now parallel agents can take different tasks without inventing different products.

Where Lockstep fits

Lockstep is the shared decision-memory layer for teams building with AI coding agents. It captures a call once, keeps the why and replacement history traceable, ranks the decision by blast radius, and briefs any MCP-compatible agent through get_product_context before it acts.

The goal is not to make every agent share one enormous context window. It is to give each agent the right slice of the team's memory at the moment it matters. Developers stop stitching context together by hand. Engineering leads review decisions instead of reconstructing them. Product people can see whether the product still matches the calls the team made.

Two agents can work on one codebase. They just cannot be allowed to work from two different versions of the truth.

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.
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.
Who benefits from shared memory for coding agents?
The whole team building with AI agents. Developers get fewer contradictory changes, engineering leads spend less time reconstructing context in review, and product people can trace why pricing, scope, and customer-facing behavior changed.

Keep reading