1
Consistency layer · RAG & shared memory
Apache-2.0 · single host · sequential lost-update guarantee · TLA+-checkedRetrieval and agent memory are shared mutable state. Two agents read the same record at version 1. One writes version 2. The other, still holding the version 1 it read minutes ago, writes its edit back and erases version 2. Last write wins, the update is silently gone, nothing errors, and every downstream answer builds on a version that no longer exists. agent-coherence turns that silent clobber into a typed refusal: a consistency layer that sits under your store, not another vector DB.
The first instinct is to reach for a stronger store: a transactional vector DB, an ACID memory backend. It doesn't help, because the stale copy isn't in the store. It's in the agent's view.
1
2
3
This is the exact shape CPUs faced in the 1980s and solved with cache coherence: every core can hold a shared line, but the instant one core writes, the others' copies are invalidated before they can read or write back a stale value. The backing memory was never the problem. Keeping the readers honest was.
So the missing layer isn't a better database. It's something that tracks which agent holds which record at which version, and invalidates a reader's view the instant a peer writes. The stale writer is stopped and made to re-read before it can act.
That's what agent-coherence is: a small MESI-derived protocol with single-writer / multiple-reader per record, monotonic versions, and a cheap (~12-token) invalidation signal instead of rebroadcasting the whole record every turn. In the lost-update case, concretely:
INVALID. B's next write is denied fail-closed. B must call reacquire(), which re-mints its identity and forces a fresh read, before it can write again. A bare retry doesn't clear the denial. That's deliberate, so a naive loop can't overwrite its way through. Both updates survive.The refusal is load-bearing. The deny is single-writer by invalidation, not a mutex you hold. The safety properties behind it (SingleWriter, MonotonicVersion, NoLostUpdate, NoStaleApply) are machine-checked in TLA+, with make tla-check running every spec in CI and every spec carrying a documented mutant that must fail. The guarantee is structural, not a prompt asking the model to be careful.
If you're on a LangGraph store, the layer your RAG and memory reads and writes flow through, CCSStore is a drop-in. store.get(), store.put(), and store.search() keep working unchanged. Reads now serve the current version, and a write from a stale view can't silently land.
# Before from langgraph.store.memory import InMemoryStore store = InMemoryStore() # After — one import change, no node code changes from ccs.adapters import CCSStore store = CCSStore(strategy="lazy")
If your shared memory is plain files across processes or sessions, say a memory.json, a LEARNINGS.md, or a scratchpad every run reads and writes, then CoherentVolume wraps them with the same protocol, no framework required.
from ccs.adapters.coherent_volume import CoherentVolume vol = CoherentVolume(workspace_root, managed=("memory/**",)) record = vol.read("memory/learnings.md") # tracked read — your view is registered vol.write("memory/learnings.md", revised) # stale view? denied fail-closed → vol.reacquire() and re-derive
Same protocol underneath either surface, and the same behavior regardless of which model provider (Anthropic, OpenAI, Google, Mistral, open-source) the agents talk to. Already on CrewAI, AutoGen, the OpenAI Agents SDK, or a custom loop? The library exposes the same coordinator through each of those seams.
Two runnable demos reproduce the failure and then prevent it. Both are offline and deterministic, with no API keys and no spend.
A
B
The conversation demo measured the providers first: a 100-trial OpenAI + 20-trial Mistral probe observed zero stale reads from the Conversations APIs, since both commit a write before returning the ACK. The APIs are not the bug. The client cache is. Agents cache state locally to avoid re-paying for the whole history, and that local copy goes stale the moment a peer writes, regardless of how consistent the server is. Coherence is about the readers. We don't claim those APIs serve stale reads, because in our trials they didn't.
pip install agent-coherence gets the adapters. The runnable demos live in the repo: github.com/hipvlady/agent-coherence/tree/main/examples.
agent-coherence is a consistency layer (does your view match the current version?), not a retrieval layer (which chunk is most relevant?). It partners underneath your memory and RAG vendors. It never tries to become one.
| Layer | Owns | Examples |
|---|---|---|
| Retrieval / memory | Embedding, ranking, storage, recall | Mem0, Letta, LlamaIndex, your vector DB, a LangGraph store |
| Coherence (this) | Whose cached view is current; denying a stale-view write before it lands | CCSStore, CoherentVolume, CoherenceAdapterCore |
| Orchestration | Who runs, in what order, with what tools | LangGraph, CrewAI, AutoGen, custom loops |
It doesn't embed, rank, or store vectors. It adds the one thing the retrieval layer doesn't give you: a guarantee that the version your agent is about to write over is the version it actually read.
Claiming less than the library does is the cheaper credibility trade. The honest scope is narrower than the headline, and worth stating plainly.
reacquire() re-mints identity and forces a fresh read, and a bare retry does not clear the denial. That's the whole mechanism: single-writer by invalidation.CCSStore or CoherentVolume) the stale view is caught. A user hand-editing the raw file, or an out-of-band re-index that never touches the coordinator, is the source-watcher case: on the roadmap, not shipped today.15-minute call. Walk me through your store and memory write-back loop, and I'll tell you where the lost-update surface is and whether the sequential single-host guarantee covers it, or whether you're in the cross-host case that's still on the roadmap.