agent-coherence. Book a call

Consistency layer · RAG & shared memory

Apache-2.0 · single host · sequential lost-update guarantee · TLA+-checked

Your agents' shared memory has a lost-update bug. RAG didn't introduce it. It widened the surface.

Retrieval 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.

A consistent store doesn't save you.

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

Two agents read the same record.

A retrieval result, a memory.json entry, a plan.md, a store key. Agent A and agent B both read it at version 1 and start working from that snapshot.

2

A writes. B is now holding the past.

A finishes, writes version 2, and releases. The store is perfectly consistent. It has v2. But B is still operating on the v1 it read minutes ago. There was no real concurrency. B's world simply moved on without it.

3

B writes its v1-derived edit. v2 is gone.

B computes its change from v1 and writes it back, overwriting v2. The filesystem did nothing wrong. No exception fired. A's work is simply erased, and the next retrieval returns B's version as if A's had never existed. This is the lost update.

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.

The fix is on the readers, not the store.

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:

Why "denied," not "warned."

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.

One import, on the store you already use.

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.

See it run: deterministic, no keys.

Two runnable demos reproduce the failure and then prevent it. Both are offline and deterministic, with no API keys and no spend.

A

Conversation memory goes stale across turns.

Two agents share one conversation. One caches it, the other revises it, and the first acts on a stale copy. CoherenceAdapterCore invalidates the stale cache so the reader re-fetches before it acts.
python -m examples.conversations_stale_read.main

B

The shared-file lost update, reproduced and prevented.

A faithful offline reproduction of a documented data-loss event (one shared file, sequential runs, earlier content destroyed on overwrite) paired with the coherence layer that catches the stale write before it lands.
python -m examples.coherent_volume.main

The honest framing the demos ship with.

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.

Where it sits: under your memory stack, not in front of it.

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.

What this doesn't claim.

Claiming less than the library does is the cheaper credibility trade. The honest scope is narrower than the headline, and worth stating plainly.

Running multi-agent RAG or shared agent memory?

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.

Book a call →