Twenty agents, one workspace, nothing lost.
Fan a job out across a fleet and they all reach for the same place to write. Every write in Markbase says which version it's changing — so the loser of a race gets told and retries, instead of quietly winning.
Silent loss is the failure mode you don't catch.
Fan-out is the reason multi-agent workflows are worth running at all. Twelve agents auditing twelve subsystems finish in the time one takes to do a third of the job. The pattern works — right up to the point where they all need to record what they found.
Send them at a shared file and the arithmetic is unforgiving. Each one reads the file, appends its section, writes the whole thing back. The reads all happen before the writes, so every write is built on a copy that's already stale, and the last one to finish silently erases eleven colleagues' work.
The dangerous part isn't the loss. It's that the file looks fine afterwards. It's well-formed, it has content, and it names a plausible set of findings. You'll notice in a week, when someone asks about the subsystem nobody apparently audited.
The write has to say what it's changing
Markbase gives every document version an ETag, and every
read hands it back. When an agent writes, it asserts the
ETag it expects to be replacing. If the document still
matches, the write lands. If anything changed in between, the write is
refused — cleanly, with a stable etag_mismatch
code and the current ETag attached.
The refusal is the feature. The agent re-reads the document as it now stands, re-applies its change to the current text, and writes again. That loop is a couple of tool calls and it's the normal path, not an error path — agents handle it without asking anyone.
What the server deliberately never does is merge on the agent's behalf. Rebasing someone's edit onto text they haven't read is how you get a document that's syntactically fine and semantically wrong. The agent gets the current text and decides — with the full contents in front of it — what its change means now.
Better still: don't have the race
Retrying a contended write is a safety net. The stronger move is to design the contention out, and for fan-out that's usually easy: give each agent its own document instead of a shared one.
Make the destination a typed collection — a folder with a
_schema.md defining what a finding looks like — and each
agent appends a record. Every record is its own file at its own path, so
twenty concurrent writers never touch the same bytes and nothing can be
lost by construction.
You don't give up the single view to get that. Because the records are typed, the collection queries like a table: every confirmed finding above medium severity, newest first. The summary is something you ask for at the end rather than something twenty agents fight over while they work.
Then the shared document is one writer's job
The pattern that falls out: the fleet appends records, and a single agent reads the collection afterwards and writes the one summary document a human will actually read. Fan out to collect, fan in to conclude. Exactly one writer touches the shared doc, and the race is gone rather than survived.
Where a shared document genuinely is the right shape — a running plan several agents update as they go — anchored writes hold the line, and the version history means an end state you didn't expect is something you can read backwards rather than guess at.
In practice
A race, resolved by the agent that lost it.
Two agents in a fan-out finish within a second of each other and reach for the same running document. The second write is refused with the current version — so it re-reads, re-applies, and lands both changes.
What makes it work
Three primitives, doing the work.
Anchored writes
Every read returns an ETag; every write asserts the one it expects. If something landed in between, the write is refused with the current ETag rather than applied on top of a stale read.
Append instead of racing
In a typed collection each agent's finding is its own record at its own path. Twenty writers, zero contention — and the result is still queryable as one table.
The whole sequence is kept
Nothing is destructively overwritten: every successful write becomes a version. When a fan-out produces a surprising end state, the order it got there in is still readable.
More use cases
Other jobs a shared workspace does.
- Decisions & precedent An agent that can't see why you chose Postgres over Redis will cheerfully propose Redis again. A decision log it can query turns settled questions into constraints.
- Session handoff Context windows end; the work doesn't. Write a handoff into the workspace and resume it in a fresh session — on another machine, or with another agent.
- Agents from different vendors Different models are genuinely better at different jobs. The one thing they have in common is MCP — so make the memory the thing they share.
- Onboarding an agent The first thing a fresh agent does is read the workspace — what the system is, what's settled, how to work here — instead of asking you or guessing.
- Background & scheduled agents A nightly run has nowhere to put what it found. Give it a folder and the report is waiting in the morning — for you, and for the next run.
- Research & deliverables Agents produce spreadsheets, PDFs and rendered charts. Keeping them at the same paths as the notes that cite them is what makes the analysis reproducible later.
Free plan, no card
If you've ever lost a subagent's findings and not noticed.
If you're running fan-outs today and quietly wondering whether every agent's work is actually landing, that suspicion is usually right. Point one fleet at a workspace and see what the anchored writes catch — starting costs nothing.