Shared Tool Access: When Two Agents Touch the Same Resource
An agent holds a stale read for seconds, not microseconds — long enough that last-write-wins silently deletes another agent's work while both report success. Partition, append, or version.
Fan out five agents over five files and they work independently. Fan out five agents that all edit the same configuration, append to the same document, or update the same record, and you have a concurrency problem — one where the participants can't see each other and each will confidently report success.
The failures are the classic ones, with a twist: agents don't retry-and-reconcile the way well-written client code does. They read, reason at length about what they read, and write based on a state that may be several seconds stale.
The long read-modify-write window
Ordinary concurrent code holds a stale read for microseconds. An agent reads a document, spends four seconds reasoning, and then writes — a window thousands of times wider, during which another agent has certainly acted.
Last-write-wins under those conditions silently discards work. Agent A adds section 2, agent B — working from a copy without section 2 — writes its version, and section 2 is gone. Neither agent errors, and both report success.
Four ways out, in order of preference
1. Partition so sharing doesn't happen. By far the best option when available. Each agent gets its own file, its own section, its own record. Combine afterwards in code, which is deterministic and reviewable.
→ Most shared-resource problems in agent systems are fan-out-dimension problems. If the work was split by task and every task edits one shared document, splitting by document section instead removes the whole class of failure.
2. Append-only. Structure the resource so participants add rather than modify. Findings appended to a log, sections added to a document, rows inserted rather than updated. Appends commute — order varies, nothing is lost.
Then a single consolidation step, in code or by one designated agent, produces the final artifact from the accumulated entries.
3. Optimistic concurrency with a version. Every read returns a version; every write includes the version it was based on. A mismatch rejects the write:
write_doc(path, content, base_version=7)
-> {ok: false, current_version: 9,
error: "Modified since you read it. Re-read and reapply your change.
Changes since v7: sections added by agent-2."}
⚠️ The error message must tell the agent what to do, or it will retry with the same stale content. And it should summarize what changed, so the re-read is cheap.
4. Locks, reluctantly. A lock held across a model call is held for seconds, so throughput collapses and deadlock becomes plausible. If you must: short TTLs with automatic expiry, never a lock spanning more than one operation, and a defined behavior when acquisition fails. Locks are the last resort for agents, not the first tool.
Non-obvious shared resources
The document is the obvious case. Others cause more confusion because they're not visibly shared:
- Rate limit budget. Ten agents against a shared quota is a shared resource, and the convoy failure follows.
- The scratchpad or notes store, if agents share a run.
- External systems with their own state — a ticket that two agents both transition, a queue item two agents both claim.
- The token budget itself, if agents share a run-level cap. One verbose participant starves the others.
Each needs the same treatment: partition it, make it append-only, or version it.
🔍 Detecting lost updates
These failures are quiet, so instrument for them:
- Version conflicts per run. Should be low and non-zero. Zero on a genuinely shared resource means you aren't checking versions and are losing writes silently.
- Writes with no intervening read. An agent writing without having read the current version is operating on stale state by construction.
- Content diffs across the run. For an append-only resource, total content should only grow. A decrease means something overwrote.
✅ That last check is a few lines and catches the exact failure that's otherwise invisible.
The takeaway
Agent read-modify-write windows are seconds wide, which makes last-write-wins actively dangerous — work disappears and everyone reports success. Partition the resource so there's nothing to share; failing that, make it append-only and consolidate once; failing that, use versioned writes with errors that explain what changed. Keep locks as the last resort, and watch for content that shrinks when it should only grow.