NeurIPS 2026

STORM: Multi-agent Collaboration
with State Management

STate-ORiented Management for parallel coding agents

Mengyang Liu1,2 Taozhi Chen3 Zhenhua Xu4 Xue Jiang4 Yihong Dong1
1Shanghai Jiao Tong University 2Cortices AI 3Emory University 4Peking University
arXiv PDF Code BibTeX
TL;DR. Giving each coding agent its own git worktree only postpones conflicts to the merge. STORM puts all agents in one shared workspace and accepts a write only if every file the agent has read is still at the version it saw. Stale assumptions are rejected at write time, while the agent still has the context to fix them.
How STORM coordinates parallel engineers
An illustrative episode, step by step. Hover over any component for details.
Read Write Rejection (current content + diff + stale list)
The problem

Isolation defers conflicts. It doesn't remove them.

Most parallel coding-agent systems give each agent its own git worktree and merge at the end. That stops agents from overwriting each other while they work, but it also hides every agent's progress from every other agent. Agent A writes a helper that assumes a certain signature. Agent B changes that signature on its own branch. Each branch passes on its own, and the combined program breaks. The failure only shows up at merge time, when both agents have already built on the incompatible design.

Workspace isolation (git worktree)

Each agent works on a private copy. Coupling stays invisible until the manager merges, and by then the conflicting assumptions have spread into dependent edits. Git can merge two textually disjoint edits whose interfaces are semantically incompatible.

State management (STORM)

All agents share one live workspace. An agent sees other agents' latest code as soon as it reads a file. If a file the agent relied on has changed, its write is rejected on the spot, together with what changed, so it can re-plan while its context is still fresh.

Method

Method

An agent doesn't need a frozen snapshot of the whole repository to make a correct edit. It only needs the files it actually read to stay unchanged while it reasons. We call this local state consistency.

Let each file \(f\) carry a monotonically increasing version \(v_f\). As engineer \(a_i\) works, it accumulates a read snapshot \(S_i = \{(g, v_g^{\text{obs}})\}\) of every file it has read and the version it saw. A write by \(a_i\) is valid if and only if

\[\forall\,(g, v_g^{\text{obs}}) \in S_i:\quad v_g^{\text{obs}} = v_g^{\text{cur}}\]

A write can fail in two ways. In a direct conflict, another agent has updated the target file itself. In a stale dependency, some other file the agent read has changed, so its reasoning may rest on outdated context.

1

Write-time conflict control

An optimistic concurrency check, in the style of database OCC. Reads and writes go ahead without blocking, and the check runs only when a write lands. The host-side version comparison costs no extra LLM calls.

2

Reservation on rejection

After a rejection, the agent gets a short reservation on the target file (up to 30 s). This gives it a bounded window to refresh and retry, so two agents can't keep invalidating each other.

3

Intent annotations

Engineers leave short, attributed comments on the code they write. When another agent reads the file, it sees the purpose of the code as well as the code. The convention is injected into each engineer's system prompt automatically.

What a rejected write returns

# write_file(agent="engineer_2", path="src/core.py", ...)
{
  "success": false,
  "current_version": 9,
  "changed_by": "engineer_1",
  "diff": "--- core.py@v8\n+++ core.py@v9 ...",
  "current_content": "...",
  "stale_files": [
    { "path": "src/utils.py",
      "expected_version": 11, "current_version": 12,
      "changed_by": "engineer_3" }
  ],
  "has_reservation": true
}

Fields mirror WriteResponse in the multiagent_sync module. Values are illustrative.

An intent annotation

# engineer_1: validate numeric inputs before summing
def add(a, b):
    if not isinstance(a, (int, float)):
        raise TypeError("a must be numeric")
    return a + b

The manager is the only agent that commits. Engineers never message each other directly: they coordinate through the shared code and these annotations. STORM sits beneath the agents' file_editor tool, so it can be added to an existing manager–engineer system without changing the agents themselves.

Results

Results

Commit0-Lite: 16 Python repositories whose implementations have been stubbed out, scored by their own test suites. Multi-agent runs use one manager and four engineers.

STORM weighted pass rate (Scorew)
46.4
vs 25.1 GitWorktree · 21.7 single agent
STORM macro pass rate (Score)
82.3
vs 66.3 GitWorktree · 69.9 single agent
Gain over GitWorktree (Scorew)
+21.3
points, mean of 3 full evaluations
Commit0-Lite, Claude Sonnet 4.6: mean of 3 full evaluations
Error bars show ±1 sample standard deviation. Higher is better.
Single-Agent GitWorktree STORM
Commit0-Lite, Sonnet 4.6 (3 runs)Scorew (mean ± std)Score (mean ± std)
Single-Agent21.70 ± 1.4169.90 ± 4.95
GitWorktree25.11 ± 0.7166.30 ± 3.53
STORM46.40 ± 0.2882.29 ± 0.30

PaperBench Code-Dev

Sonnet 4.6 agents on the 20 PaperBench Code-Dev papers, scored by a GPT-5.5 judge (mean ± std over 3 evaluations; multi-agent methods use 2 engineers).

GPT-5.5 judge, 3 runsScore (mean ± std)
Single-Agent65.71 ± 2.74
GitWorktree67.74 ± 0.95
STORM72.27 ± 2.28

Across models

Single-run results for three agent models (PaperBench judged by Sonnet 4.6). STORM has the best weighted Commit0-Lite score and the best PaperBench score among standalone methods for every model. Tick + Single to add runs that pair the single agent with a multi-agent system and keep the better codebase per task.

Click a column header to sort. Bold marks the best standalone method in each column.

Costeff = total USD / score (lower is better), at OpenRouter list prices.

Per-task results

Every repository and paper

Each row is one Commit0-Lite repository or PaperBench paper (single run each, from the paper's appendix). Rows are listed alphabetically by default. Hover over a row to see the score, cost, and wall-clock time for each method. In Table view, click any column header to sort.

Single-Agent GitWorktree STORM
Baselines

Other coordination mechanisms

STORM against shared-memory (MARBLE-based) and CRDT (CodeCRDT-based) coordination, all with the same model, four engineers, and the same budgets (Commit0-Lite, Sonnet 4.6).

Analysis

Analysis

Case study: the same coupling, caught at opposite ends

Assignment Coupling-aware assignment Engineer work Focus task Accepted review Rejected review

Paired runs on jinja. Under GitWorktree, the utils.py coupling stays invisible until merge review: the manager rejects the focus diff with a merge-conflict reason, and the same engineer redoes it in the shaded window. Under STORM (restricted to the coupled task set), the manager spots the coupling when it decomposes the task. It puts utils.py and async_utils.py in one assignment and schedules the downstream tasks after it. The focus task passes on its first review.

Scaling engineers

Score, %
WeightedMacro
Average cost, $ per repository
 
Average time, minutes per repository
 

Sonnet 4.6 on Commit0-Lite; the x-axis is the maximum number of engineers, and 1 is the single agent (blue). The small number under each score column is the average number of engineers the manager actually deployed. Hovering over a column highlights the same setting in all three panels. Going from 2 to 8 engineers lifts the weighted score from 38.2% to 69.7%. Cost grows roughly linearly, while wall-clock time per repository stays flat because engineers run in parallel. The manager deploys fewer engineers than allowed on simple repositories.

Cite

BibTeX

@misc{liu2026multiagentcollaborationstatemanagement,
      title={Multi-agent Collaboration with State Management},
      author={Mengyang Liu and Taozhi Chen and Zhenhua Xu and Xue Jiang and Yihong Dong},
      year={2026},
      eprint={2605.20563},
      archivePrefix={arXiv},
      primaryClass={cs.MA},
      url={https://arxiv.org/abs/2605.20563},
}