Agent Coherence — Stale Write Guard (FS)
OfficialThe stale-write-guard-fs server provides coherence-tracked, stale-write-protected file access for shared workspaces, preventing agents from silently overwriting each other's changes. It exposes five tools:
swg_read(path): Reads a workspace text file and returns its content plus a version token used as a comparand for subsequent writes.swg_write(path, content): Writes a file with automatic stale-view detection. If the file changed since your last read — via a peer agent commit or an out-of-band edit — the write is denied with a typed reason (stale_vieworcommit_preempted) rather than silently overwriting the newer version.swg_reacquire(path): Recovers from astale_viewdenial by re-minting your agent identity and returning the file's current content. You must re-derive your edits from these fresh bytes before attempting to write again.swg_write_cas(path, expected_version, new_content): Performs an optimistic compare-and-set write. If a peer committed a newer version since your read, you receive a typed conflict (reason=version_mismatch) with thecurrent_version— never a silent overwrite. Re-read, re-merge, and retry.swg_status(): Reports the coherence state of the coordinator (on/off/unknown) and per-path enforcement status (enforced/not_registered). Useful for diagnostics.
Key constraints:
Single-host only — multi-host or network-mount writers are outside the v1 guarantee.
Does not perform auto-merge or semantic reconciliation.
swg_reacquiredoes not return a version comparand forswg_write_cas— useswg_readfor that.
Adapter for CrewAI to coordinate shared state and prevent lost updates or stale reads across agents.
Provides a drop-in CCSStore adapter for LangGraph that adds read-side coherence and stale-write prevention via MESI protocol.
Integration with the OpenAI Agents SDK to enforce coherence and avoid silent clobbering of shared artifacts.
agent-coherence
agent-coherence stops one agent from silently clobbering another's work on a shared plan.md, store key, or memory.json — a vendor-neutral MESI + optimistic-concurrency coordinator for agent state on a single host, with the safety invariants machine-checked in TLA+.
Two agents share an artifact — a plan.md, a store key, a memory.json. One reads it and works; meanwhile a peer commits a newer version; the first writes back anyway. Last write wins, the peer's work is silently gone, nothing errors, and every downstream decision builds on the wrong version.
Why it goes unnoticed. An agent system keeps two records of what happened: the one your infrastructure can verify — which version each agent held, what actually committed, what was refused — and the one the model narrates, "task complete", "the plan is updated". They agree until an agent acts on a version that moved underneath it, and the narrated record is the one you read. That is why a lost update looks like a clean run and gets debugged as a model problem. agent-coherence is the verified record for the state your agents share. (It does not verify what an agent did in the outside world — a sent email, a fired webhook — that stays your outbox and idempotency layer's job.) agent-coherence turns that silent clobber into a loud, typed refusal: MESI-style ownership and invalidation over shared artifacts, optimistic commit-CAS for concurrent writers, and a read-generation fence for crash-reclaimed ones — a stale write is denied or returned as a retryable conflict, never silently applied. Same library, same protocol, across LangGraph, CrewAI, AutoGen, the OpenAI Agents SDK, plain files shared across processes (CoherentVolume), any MCP client (the stale-write-guard-fs server, via the mcp extra), and any custom orchestrator. Same behavior regardless of which model provider (Anthropic, OpenAI, Google, Mistral, open-source) the agents talk to.
mcp-name: io.github.Cohexa-ai/stale-write-guard-fs
# Requires Python 3.11+
pip install "agent-coherence[langgraph]" # LangGraph drop-in
pip install "agent-coherence[crewai]" # CrewAI adapter
pip install "agent-coherence[openai-agents]" # OpenAI Agents SDK adapter (experimental)
pip install "agent-coherence[diagnose]" # ccs-diagnose CLI
pip install "agent-coherence[mcp]" # stale-write-guard-fs MCP server
pip install "agent-coherence[conformance]" # substrate conformance corpus (for foreign implementations)
pip install "agent-coherence[all]" # everything# 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")store.get(), store.put(), store.search() keep working unchanged. CCSStore adds read-side coherence: a peer's commit invalidates your cached view, so your next read is a fresh miss. It does not deny a stale write-back — put is not version-CAS; for write-side lost-update prevention, route writes through CoherentVolume or write_cas (below).
The one-import swap assumes your store namespaces carry the agent identity in
namespace[0]— a(user_id, "memories")shape would merge users onto one shared artifact. See the namespace convention.
# Plain files shared across processes / sessions — no framework required
from ccs.adapters.coherent_volume import CoherentVolume
vol = CoherentVolume(workspace_root, managed=("plans/**",))
plan = vol.read("plans/plan.md") # tracked read — your view is registered
vol.write("plans/plan.md", revised_plan) # stale view? denied fail-closed → vol.reacquire() and re-deriveagent-coherence-replay — invariant-replay for any CoherenceAdapterCore-mediated agent system. LangGraph capture verified in v1 via CCSStore.record_to(path); CrewAI / AutoGen wired through the same seam but unverified — file an issue if it breaks.
What it guarantees
Each row is a safety invariant model-checked with TLA+/TLC. make tla-check runs all eight specs in CI on every push, and every spec carries a documented mutant that must fail — the invariants are load-bearing, not decorative.
The silent failure | What happens instead | Mechanism | Invariant |
Stale-read overwrite — an agent acts on an old snapshot and writes over a newer version (two sessions, one | the write is denied fail-closed; the writer must | MESI single-writer ownership + invalidation |
|
Concurrent lost update — two writers hit the same key and both "succeed" | exactly one wins; the loser gets a typed conflict + bounded retry, never a silent drop | optimistic commit-CAS ( |
|
Reclaim-zombie write — a stalled writer is reclaimed by crash recovery, wakes later, and lands its stale commit; the version never moved, so a version check passes | the commit is rejected with a typed | read-generation fence — reclamation bumps the artifact's ownership epoch, checked atomically at commit |
|
Reclaim-zombie effect — the same reclaimed writer's escaping effect (a webhook, a deploy, an opened PR) fires on a decision made under the revoked grant; the version never moved, so a version-only re-check passes | the effect is held ( |
|
|
Torn multi-artifact read (read-skew) — an agent reads several artifacts one by one while a peer commits in between; each read was individually current, but the combination never coexisted | session reads serve from a pinned consistent cut; commits validate against the pinned base; a lapsed session fails closed with a typed rejection, never a silent fall-through to live state |
| |
Dead owner blocks the fleet — a crashed agent holds EXCLUSIVE forever | the heartbeat/TTL sweep reclaims the grant (on by default; best-effort, rate-limited) | crash-recovery sweep | sweep invariants I3–I6 |
Scope, honestly: the guarantees hold for writers that go through the coordinator, under a single coordinator (one host). Concurrent same-key writers on one host are covered; cross-host fencing is on the roadmap, demand-gated — if you need it, open an issue. Edits that bypass the coordinator entirely (a human in an editor, a formatter, a regenerating script) are caught at the read()/write() boundary by content-hash checks — the foreign-edit guards below, enforced by tests rather than TLA+; the batch CAS path has a narrower boundary, spelled out in Atomic multi-file publish. Specs, the invariant ↔ implementation map, and the mutant recipes live in formal/tla/.
Correctness is the wedge; the token savings come with it. Writes publish ~12-token invalidation signals instead of rebroadcasting full artifacts, so read-heavy fleets stop re-paying for state they already hold:
Workload | Agents | Reads:Writes | Hit rate | Savings |
Planning (read-heavy) | 4 | 12:1 | 75% | 69% |
Code review (moderate) | 3 | 8:3 | 60% | 47% |
High-churn (write-heavy) | 4 | 8:4 | 50% | 29% |
Measured on real LangGraph graphs; see docs/reproduce.md and the user guide.
Those are the spatial savings (more agents sharing one artifact). The temporal dimension — a single agent whose source drifts between its turns — has its own pre-registered benchmark, TC-1 (#116): a reproducible savings-regime map of how many re-fetches coherence-gating avoids as the change-rate rises. The metric is re-fetches-avoided — a proxy, a regime map, not a token/dollar invoice. Reproduce with python tools/run_cost_sweep.py; the locked verdict + numbers (PASS at n=50, crossover r≈0.31) live in benchmarks/cost_preregistration.md. Shipped in v0.9.3.
Related MCP server: agnt-lock
RAG & shared agent memory
RAG corpora and agent memory are shared mutable state, so the stale-read→write lost update lands there too — and a consistent store doesn't save you: the staleness is in the agent's cached view of a record, not the store. Two agents read a record at v1; one writes v2; the other, still on its v1, writes an edit computed from v1 and clobbers v2. agent-coherence keeps the readers current — CCSStore is a drop-in for langgraph.store (composing with Mem0, Letta, LlamaIndex, a vector store, or a plain file underneath whatever you already use; it stores no vectors and does no ranking), so a peer's commit invalidates the stale cached view (read-side coherence). Preventing the stale write-back itself is the write side — route those writes through CoherentVolume or write_cas.
Runnable, deterministic demo (offline, no keys):
python -m examples.coherent_volume.mainreproduces the documented lost update, then prevents it.Honest scope: writes that go through the coordinator are caught. Auto-watching an unmanaged external source that changes with no coordinator write (a hand-edited file, an out-of-band re-index) is the source-watcher case — on the roadmap, demand-gated, not shipped today.
Positioning + FAQ: agent-coherence.dev/rag.
📖 User guide — installation, namespace convention, strategies, observability, telemetry, examples, full API reference
🔎 RAG & shared memory — coherence for retrieval corpora and agent memory stores, with the runnable lost-update demo
🗂️ Coherent workspace —
CoherentVolume, the data-plane appliance for plain files shared across processes🧱 BYO substrate —
CoherentRow/CoherentObject, the same coherence over a Postgres row or an S3 object you already run⏪ Workspace versioning & restore —
WorkspaceVersioner, checkpoint a mixed file + S3 workspace and bring it back with per-member honesty🛡️ Foreign-edit guards — catch out-of-band edits (a human, a formatter, a script) at the read/write boundary
🔌 MCP server —
stale-write-guard-fs, the same guarantee for any MCP client, no Python integration required🚦 Effect-ordering gate —
gate(), fire an agent's effect only on the input state — value and grant — it decided from📸 Multi-artifact snapshot sessions — read several artifacts as one consistent cut; no torn reads
📦 Atomic multi-file publish —
atomic_publish, land a set of files all-or-nothing; never a torn pair🧮 Formal verification — the TLA+ specs, invariant ↔ implementation map, mutant recipes
🩺
ccs-diagnoseCLI — find divergent reads in your existing LangGraph graph without changing any code🧩 Claude Code plugin — cross-session coherence for the prose rules (CLAUDE.md, plan.md) parallel Claude Code sessions share
🔍 Why coherence matters — the gap across LangGraph, CrewAI, AutoGen, and Claude Agent SDK
🧭 The MESI-derived approach — how the protocol maps each documented gap to a shipped surface, with boundaries
🔐 Security & supply chain — kill switches, hash-pinned install, attestation verification, threat model
📜 Changelog — version history
📄 Paper on arXiv (2603.15183) — formal protocol, TLA+ verification, simulation results
How it works
Each shared artifact is cached locally per agent and reads serve from the local cache when that copy is fresh. Writes commit to a coordinator, which sends lightweight invalidation signals (~12 tokens) to peers so the next read fetches the new version instead of rebroadcasting the full artifact. Consistency is single-writer-multiple-reader per artifact with bounded staleness — peers re-fetch on next read.
Two write disciplines share the same guarantee. Pessimistic: acquire EXCLUSIVE, commit; a writer whose view went stale is denied and must reacquire(). Optimistic: write_cas — read, compute, commit-CAS; the loser of a race gets a typed conflict and bounded retry. Crash recovery composes with both: reclaiming a stalled grant bumps the artifact's ownership epoch, so a reclaimed writer that completes later is rejected at commit even when the version is unchanged (the read-generation fence). On the read side, a snapshot session pins a consistent cut across several artifacts, so a multi-artifact read never sees a torn mix of versions.
Five synchronization strategies ship out of the box: lazy (default), eager, lease (TTL-based), access_count, and broadcast. Pick the one that matches your workload's read/write ratio and how aggressively cached reads should refresh.
Architecture
Protocol (
ccs.core,ccs.strategies) — coherence state machine and synchronization strategies; no framework dependencies.Coordinator (
ccs.coordinator) — authority service tracking directory state, publishing invalidations, arbitrating commit-CAS, and reclaiming stale grants (crash recovery + read-generation fence).Adapters (
ccs.adapters) — framework integrations for LangGraph, CrewAI, and AutoGen (~100 lines each), plus an experimental OpenAI Agents SDK adapter (Session-cache coherence +RunHooks).Coherent workspace (
ccs.adapters.coherent_volume) — the data-plane appliance: an out-of-process coordinator client that brings the same guarantee to plain files on disk, no framework required. See Coherent workspace.MCP server (
ccs.mcp) — thestale-write-guard-fsstdio server that exposes the coherent-workspace guarantee to any Model Context Protocol client over sixswg_*tools. See MCP server.Simulation (
ccs.simulation) — deterministic tick-driven engine for scenario benchmarks with failure injection.Event bus (
ccs.bus) — the transport for invalidation signals; in-memory / in-process today (InMemoryEventBus). Networked transports (Redis, Kafka, NATS, gRPC) for a multi-host deployment are on the roadmap, demand-gated.
Protocol safety properties — single-writer, monotonic versioning, the crash-recovery sweep invariants, the OCC no-lost-update, the reclamation fence's no-stale-apply, the effect gate's no-stale-admit, version retention's no-collected-read, the snapshot session's no-read-skew-within-cut, and workspace restore's no-partial-restore-registered — are model-checked with TLA+/TLC. The tla-check CI job runs all eight specs on every push and PR.
Coherent workspace: the data plane for shared files
The framework adapters wrap a store. CoherentVolume is the other half — the data-plane appliance, the building block that makes a shared workspace coherent for plain files on disk, with no framework in the loop. Architecturally it's an out-of-process coordinator client, not an in-process wrapper: it writes the policy, spawns (or attaches to) a local coordinator over SQLite-WAL, and routes reads and writes through it. Your content stays on the real filesystem; the coordinator holds only MESI state, a content hash, and a version per managed file. Point a sibling volume in another process at the same workspace and it attaches to the same coordinator, so a single-host fleet shares one coherent view.
from ccs.adapters.coherent_volume import CoherentVolume
vol = CoherentVolume(workspace_root, managed=("plans/**", "memory/**"))
data = vol.read("plans/plan.md") # bytes — registers a SHARED view
vol.write("plans/plan.md", revise(data)) # stale view? denied fail-closed
data = vol.reacquire("plans/plan.md") # recover: re-mint identity + mandatory fresh readThe explicit read / write / reacquire / write_cas API is the supported primitive (write_cas(path, make_content) is the optimistic counterpart for same-key contention — the loser gets a typed conflict, never a silent drop). For code you'd rather not rewrite, an opt-in, demo-grade open() shim routes managed-path opens through the volume so existing open() / pathlib calls get coherence unchanged:
from ccs.adapters.coherent_volume import coherent_workspace
with coherent_workspace(workspace_root, managed=("plans/**",)):
text = open("plans/plan.md").read() # registers a SHARED view
open("plans/plan.md", "w").write(edit) # stale view? raises out of close()Scope, honestly. Plain write() prevents the sequential stale-read→write lost update for a single-host fleet sharing one workspace (A reads v1, B reads v1, A commits v2, B's stale write is denied → B re-reads); concurrent same-key racers go through write_cas — one winner, the loser gets a typed conflict and re-derives, never a silent drop. Edits that bypass the volume entirely are caught at the boundary by the foreign-edit guards. It does not catch an agent that re-reads fresh bytes and then writes a buffer computed from older ones. The open() shim is convenience, not the contract: it covers open()/pathlib text+binary read/write, but not raw os.open, subprocess redirection, mmap, or append/update modes — those delegate to the original open() unchanged. Run it yourself: python -m examples.coherent_volume.main (offline, deterministic, no keys), or read the positioning + FAQ.
Foreign-edit guards: writes that bypass the coordinator
Coordination covers writers that opt in — but real workspaces also get edited from outside: a human fixes a file in an editor, a formatter rewrites it, a CI script regenerates it. Without a guard, the next agent write silently buries that edit, and the next agent read silently builds on bytes the coordinator never saw. CoherentVolume guards both boundaries with a content-hash check:
Write boundary — on by default. Before writing, the volume checks whether the managed file's on-disk bytes changed out-of-band since it last read or wrote them. If they did, the write raises
StaleViewinstead of clobbering the foreign edit — recover withreacquire()(fresh read → re-derive → re-write). Opt out withCoherentVolume(on_stale_write="allow")to restore last-writer-wins.Read boundary — opt-in. With
CoherentVolume(on_stale_read="raise"), re-reading a managed file whose bytes changed out-of-band raisesStaleViewinstead of returning bytes your other state wasn't computed from; in strict mode the coordinator enforces the same check server-side. A volume never denies its own just-written bytes — the benign commit→disk-write lag window is recognized and suppressed.
vol = CoherentVolume(workspace_root, managed=("plans/**",), on_stale_read="raise")
# a formatter rewrites plans/plan.md out-of-band …
vol.write("plans/plan.md", revised) # StaleView — the foreign edit survives
fresh = vol.reacquire("plans/plan.md") # recover: fresh read, re-derive, re-writeScope, honestly. These are content-hash checks at the volume's read/write boundary — best-effort point-in-time detection, not filesystem interception. A write that never goes through the volume is caught at the next volume read/write of that file, not blocked as it happens; watching unmanaged external sources is on the roadmap, demand-gated. These guards are enforced by tests, not TLA+ — the model-checked invariants cover the protocol state machine, not disk bytes. They cover read()/write() (and the MCP tools that wrap them); the CAS paths check versions instead — write_cas/write_cas_at still fail closed on a foreign edit (the content-checked comparand read wedges rather than clobbering), but a multi-file atomic_publish does not check disk content at all — see its scope note.
MCP server: stale-write-guard-fs
The same guarantee for agents that speak Model Context Protocol — Claude Code, Cursor, or a custom runtime — with no Python integration at all. stale-write-guard-fs is a stdio MCP server that wraps CoherentVolume and exposes coordinated file access as six tools:
pip install "agent-coherence[mcp]"{
"mcpServers": {
"stale-write-guard-fs": {
"command": "stale-write-guard-fs",
"env": { "SWG_ROOT": "/path/to/shared/workspace" }
}
}
}Tool | What it does |
| Tracked read — registers the agent's view of the file |
| Guarded write — a stale view or a foreign edit gets a typed |
| Recovery — fresh identity + mandatory fresh read after a deny |
| Single-shot version-checked write for concurrent same-key contention |
| Effect fence — re-checks the |
| Three-state coordination health: |
The server binds one workspace per session (SWG_ROOT, defaulting to its working directory; the whole workspace is guarded unless SWG_MANAGED — a comma-separated glob list — narrows it), rejects path traversal and any access to the coordinator's own state directory, and fails closed on IO errors. Denials come back as typed, machine-readable payloads — an agent can parse recover: reacquire and self-heal instead of retrying blindly. Run the red→green demo: python -m examples.mcp_stale_write_guard.main (offline, deterministic, no keys).
Scope, honestly. Same contract as the volume it wraps: single-host, managed paths, cooperative — it guards agents that route file access through the tools; it cannot see edits made around them (those are caught at the next tool call on that file by the foreign-edit guards).
Effect-ordering gate
Agents don't only overwrite files — they fire effects (a deploy, a PR, a shell command) computed from inputs they read earlier. If the input moved in between, the effect fires on stale state. gate() narrows that window: it captures the input's (version, ownership generation) pair at decision time, re-reads the pair at the effect boundary, and fires only if both are unchanged at that re-read — otherwise it holds the effect before it runs. The two comparands catch different failures: the version catches a peer that changed the input; the generation catches a coordinator sweep that reclaimed the grant the input was read under while the bytes never moved — a stalled agent whose lease lapsed mid-decision would otherwise fire its effect on revoked authority, with the version check none the wiser.
from ccs.adapters import CoherentVolume, gate
vol = CoherentVolume(workspace_root, managed=("deploy/**",))
# fires run_deploy(plan) only if deploy/config.txt is unchanged since decide() read it;
# else raises StaleView before the deploy runs — reacquire() and re-decide.
gate(vol, "deploy/config.txt", decide=plan_deploy, effect=run_deploy)It's plain Python, so the same call drops into a LangGraph node, a CrewAI task, or a raw script unchanged.
Scope, honestly. The gate orders effects, it does not roll them back: it fires pre-effect and never undoes one, so for an escaping effect there's a residual re-read→fire window it narrows but can't close. It's single-host and cooperative — the agent opts in. Both comparands are fail-closed: an unconfirmed version (degraded read) or an unconfirmed generation (a strict-mode deny, or an older coordinator daemon from before this release's generation reporting) HOLDs rather than firing. For a pure write effect, use vol.write_cas_at(path, expected_version, content) directly, which is the atomic, no-window path. Gating several mutually-consistent inputs at once is a snapshot-session operation on the coordinator, not this single-input wrapper. Run it: python -m examples.effect_gate.main (offline, deterministic, no keys), or add --baseline to see the stale fire it catches; python -m examples.gate_effect_ordering.main adds the reclaimed-lease act (version unchanged, authority revoked, deploy held).
Multi-artifact snapshot sessions
gate() protects one input. But an agent that reads several artifacts one by one — a plan, a config, a memory file — can see a torn combination: plan.md from before a peer's commit and config.json from after it. Every individual read was current; the set never coexisted (read-skew). A snapshot session closes that window: it pins a consistent cut of the artifacts you name, captured at a single point, and serves every session read from that cut while peers keep writing.
Against a running coordinator (the same one CoherentVolume spawns), over HTTP:
POST /session/begin {session_id, read_set: ["plans/plan.md", "config/app.json"]}
→ {session_token, cut: {path: version}, …}
POST /session/read {session_id, session_token, path}
→ the artifact at its PINNED version — never a newer one
POST /session/commit {session_id, session_token, path, content}
→ wins only if no peer moved the artifact since the cut
POST /session/heartbeat {session_id, session_token} — keep the session's lease aliveOr in-process: CoordinatorService.begin_session(read_set=…, owner=…) → session_read(…) / session_commit(…). The cut is an inspectable {artifact: version} map, not an opaque handle — you can read exactly which versions your session is pinned to.
Fail-closed by construction: reading an artifact that was not in the pinned read-set is refused with a typed rejection — never silently served from live state. Sessions have a bounded lifetime backed by a heartbeat lease: a session whose heartbeat lapses, or that is lost to a coordinator restart, is invalidated — later reads get a typed "session invalidated" rejection telling the agent to re-establish, never a quiet fall-through to whatever is current. Model-checked: NoReadSkewWithinCut and PinAlwaysRetained (formal/tla/Snapshot.tla).
Scope, honestly. This prevents read-skew — torn reads across artifacts. It does not add write-skew prevention: commits validate per-artifact against the pinned base through the same optimistic CAS as write_cas, so two sessions that read one cut and write different artifacts can still interleave. Single coordinator, single host. When the coordinator retains version bodies it serves the pinned bytes directly; otherwise it returns the pinned version and content hash as a typed signal and the caller fetches the bytes from its own data plane.
Atomic multi-file publish
write_cas_at lands one file if it hasn't moved. But an agent often edits a set of files that must stay consistent — a plan and its manifest, a config split across files — and must land them together or not at all, never a torn pair where one file references another that already changed. atomic_publish is that all-or-nothing batch:
from ccs.adapters import CoherentVolume
vol = CoherentVolume(workspace_root, managed=("proj/**",))
# lands BOTH files iff each is still at the version the agent read; otherwise the
# WHOLE publish is held (StaleView / CasVersionConflict) with NO file written.
versions = vol.atomic_publish([
("proj/plan.md", plan_version, new_plan_bytes),
("proj/manifest.md", manifest_version, new_manifest_bytes),
]) # -> {"proj/plan.md": 2, "proj/manifest.md": 3}Either every member's version advances or none does, and a moved member holds the whole batch — a torn commit is never a reachable state, formally specified as the NoPartialPublish invariant in formal/tla/AtomicPublish.tla. A single-file publish takes the direct CAS path; a multi-file publish opens a snapshot session so the versions it checks are captured at one point (no member read across a peer commit). Run it: python -m examples.atomic_publish.main (offline, deterministic, no keys), or add --baseline to see the file-by-file torn pair it prevents.
Scope, honestly. The all-or-nothing guarantee is at the coordinator commit — that is what NoPartialPublish covers. Disk materialization happens after the commit and is best-effort: every file is staged to a temp then renamed into place, so a disk fault fails before any rename (disk stays uniformly old) and a rename failing partway raises a typed PublishMaterializationError naming exactly which files landed — never a bare error implying nothing published. This shrinks, but a crash between renames can't fully eliminate, the multi-file disk window (there is no POSIX multi-file atomic rename); on that error the coordinator is ahead of disk and you re-read + re-materialize. It is single-host and cooperative. The multi-file path also adds a small capture→commit window (the session open); a peer winning it holds the publish rather than tearing it. This is all-or-nothing publish of a file set — not rollback of effects that already escaped, and not write-skew prevention across sessions. And the staleness it detects is version drift: only writes routed through a volume advance versions, so an edit that bypasses the volume entirely (a human in an editor, a formatter, a script writing a member directly) is invisible to a multi-file publish — the batch commits and overwrites it. A single-file publish and plain write() fail closed on that same edit via the foreign-edit guards; use atomic_publish only for file sets whose every contending writer goes through a volume.
BYO substrate: coherence over the store you already run
CoherentVolume puts coherence over files on disk. But shared agent state often lives in a store you already run — a Postgres row, an S3 object. BYO-substrate bindings bring the same coherence over that store, with the coordinator holding only metadata (a version, per-agent MESI, a fixed-width content_hash, an opaque substrate token) — never the bytes:
from ccs.adapters.coherent_row import CoherentRow # pip install "agent-coherence[coherent-row]"
from ccs.adapters.coherent_object import CoherentObject # pip install "agent-coherence[coherent-object]"
# agent A reads a row it will edit over several steps
row = CoherentRow(dsn=..., table="workspaces", artifact_id="ws-42")
data, token = row.read("ws-42")
# ... meanwhile agent B commits a new version through the binding ...
# A's next binding-mediated read/act is DENIED before A writes:
row.commit("ws-42", expected_token=token, new_bytes=revised) # -> StaleView; reacquire() and re-decideThe value over the substrate's own conditional write (UPDATE … WHERE version=?, S3 If-Match): a bare CAS rejects A's write at write time; the binding tells A its cached view went stale before it acts, in the same typed vocabulary a file (CoherentVolume) or a store key (CCSStore) uses — one coherence surface over a row, an object, or a file. A declarative Coherence Manifest wires each artifact to a substrate and an honest guarantee tier, with credentials as references (secret-file: / aws-default, never literals) and SSRF-constrained connection targets.
Scope, honestly. v1 ships two native-CAS bindings (Postgres + S3) and a forward-only tier for action backends (a Slack post, a Gmail send — decision-input freshness only, no CAS). The value is invalidation-before-act + cross-substrate uniformity; the read-generation fence over a substrate is a documented roadmap item, not claimed — v1 OCC writers ride admit-on-absent + the version-CAS. Single-host and cooperative; when the substrate is itself distributed (S3, managed Postgres) the no-lost-update guarantee is the substrate's and identical with or without this layer. Run it: python -m examples.coherent_row.main / examples.coherent_object.main (offline, deterministic, no keys — an in-memory substrate stand-in; production points the same binding at real Postgres / S3). Full API, per-binding least-privilege, and the honest tier table: BYO substrate bindings.
Workspace versioning & restore
Everything above keeps shared state safe while agents write it. Workspace versioning answers the after-the-fact question: an agent mutated a workspace spread across backends — files on disk, objects in S3 — the attempt failed, and you want it back, with per-member honesty about what can and cannot come back:
from ccs.adapters.workspace import WorkspaceVersioner
wv = WorkspaceVersioner(service=service, owner=owner, file_resolver=resolver)
wv.add_file_member(source, "ws/notes.md")
wv.add_object_member(binding, "reports/summary.txt") # a CoherentObject (S3)
wv.add_forward_only_member("actions/deploy-step") # named, not captured
checkpoint = wv.checkpoint("before-migration") # pins on by default
report = wv.restore(checkpoint.record.checkpoint_id) # per-member terminal truthA checkpoint is a named manifest of native version pointers (an S3 versionId, a file's coordinator version) and content fingerprints — never a second copy of your bytes — captured as a skew-declared cut: the capture window is recorded rather than hidden, and a member that moved inside it is flagged, not silently torn. A member missing at capture is recorded as absent, so restore includes delete legs. Restore drives one conditional write per member under a termination contract, so it always concludes with a frozen per-member report — restored, converged (live state already matched), conflict (a live foreign writer won: bounded re-drive, never a livelock, never a clobber), target_lost (the captured version is gone — reported, never substituted), held_unconfirmed, or forward_only_skipped.
Every member carries an honest restore tier: restorable (versioned S3, backed by a legal hold in your bucket), restorable-unpinned (history exists now and may expire), or forward_only (described, not restorable — stated at capture, not discovered at restore). The durable truth is the pair (restore_tier, pin_state): (restorable, unpinned) is rendered claimed-but-not-yet-backed, never as a plain promise. Scriptable from the shell, where exit code 3 means the restore concluded — read the report:
agent-coherence-workspace checkpoint before-migration --file notes.md --file plan.md
agent-coherence-workspace status <checkpoint-id> # (restore_tier, pin_state) per member
agent-coherence-workspace restore <checkpoint-id> # 0 clean · 3 concluded with absorbed outcomesScope, honestly. Single-host coordinator — checkpoints, pins, and restore progress live in local coordinator state and make no cross-host claims. Restore is over artifacts, never effects: a file or an object comes back, a sent message does not. File members are detection-only (no-arbiter) — only a backend with a native conditional write arbitrates a racing foreign writer — and they ride coordinator retention, which offers no per-version hold: their tier stays restorable-unpinned, and a version that ages out surfaces as target_lost rather than restoring different content. Restore is a forward commit carrying old bytes: versions strictly increase, history is never rewritten. S3 members are captured and restored through the Python API, because their bindings carry credentials the CLI never holds. Run it: python -m examples.workspace_versioning.main (offline, deterministic, no keys), or add --baseline to see the loss first. Full honesty model — tiers, pin states, the retention caveat, the exit-code contract: guide § Workspace versioning & restore.
Status
v0.14.0 released — workspace versioning & restore, the authority-axis effect fence, and compaction-aware re-grounding for Claude Code. WorkspaceVersioner checkpoints a workspace whose members live in different backends — files, S3 objects, declared forward-only action surfaces — as a named manifest of native version pointers and fingerprints (never a second copy of your bytes), and brings it back with per-member honesty: restore tiers (restorable / restorable-unpinned / forward_only), fail-closed pins with loud downgrades (S3 legal holds), and a convergent restore engine under a termination contract — driven from the agent-coherence-workspace CLI or the Python API. The packaged conformance corpus (ccs.testing.substrate_conformance, [conformance] extra) lets foreign substrate implementations run the same scenarios, and WorkspaceVersion.tla joins the CI model-checking sweep. gate() — and the MCP server's new sixth tool, swg_gate — now re-checks the grant an input was read under, not only its version, so a sweep-reclaimed (zombie) holder's escaping effect HOLDs instead of firing on revoked authority. And when Claude Code compacts a session, the adapter re-grounds it: the grants it held at compaction and each touched artifact's current version, with stale flags, delivered at the next user message or tool admit. Single-host scope unchanged. See CHANGELOG.md.
See CHANGELOG.md for the full version history and releases for tagged artifacts. Alpha — APIs may change before v1.0.
Paper
Token Coherence: Adapting MESI Cache Protocols to Minimize Synchronization Overhead in Multi-Agent LLM Systems arXiv:2603.15183
@article{parakhin2026token,
title = {Token Coherence: Adapting MESI Cache Protocols to Minimize
Synchronization Overhead in Multi-Agent LLM Systems},
author = {Parakhin, Vladyslav},
journal = {arXiv preprint arXiv:2603.15183},
year = {2026}
}Community
Questions, war stories, and ideas welcome in Discussions. If you've hit a stale-read bug in a multi-agent workflow, open an issue — I'd like to hear about it.
License
Apache-2.0. See LICENSE.
Available Tools
6 toolsswg_gateA
Verify a file is STILL unchanged and still under the same grant. Pass BOTH comparands from your earlier swg_read — expected_version AND expected_generation (its owner_generation). Call this immediately BEFORE any irreversible external action you decided from that read (sending a webhook, opening a PR, running a deploy, posting a message). Returns decision=proceed, or DENIES with reason=stale_view if the file moved OR the grant you read it under was reclaimed (the version alone cannot see a reclaim) OR either comparand is unconfirmed. On a deny: do NOT take the action — swg_reacquire, re-read, re-decide. SINGLE-HOST only. Out of guarantee and NOT detected in v1: writers on different hosts or across a synced/network mount, divergent-history reconciliation, semantic correctness, server-enforced auto-merge.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| expected_version | Yes | ||
| expected_generation | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the sparse readOnlyHint=false annotation, the description discloses important behavioral traits: it explains why version alone cannot detect a grant reclaim, lists precise deny reasons, and explicitly states the SINGLE-HOST limitation and out-of-scope guarantees. This is substantial transparency for a concurrency-sensitive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: purpose, required inputs, invocation timing, return/deny behavior, recovery path, and limitations. Front-loading the core purpose helps an agent quickly identify the tool, and the limitation details are essential for correct use.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and only a single annotation, the description fully compensates: it states what the tool returns (decision=proceed or deny with reason=stale_view), why a deny occurs, how to respond, and the boundary of its guarantees. This is complete enough for an agent to call and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameter semantics. It does well for expected_version and expected_generation by tying them to an earlier swg_read call and clarifying that expected_generation is the owner_generation. Path is not elaborated, but it is self-evident as the file being verified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Verify a file is STILL unchanged and still under the same grant.' It clearly identifies the tool as a pre-action gate and distinguishes it from siblings by specifying it must be called before irreversible external actions, unlike swg_read or swg_write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'immediately BEFORE any irreversible external action' and lists concrete examples such as webhooks, PRs, deploys, and messages. It also provides the on-deny workflow: do NOT take the action, then swg_reacquire, re-read, re-decide, which clearly routes to the correct sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
swg_reacquireA
Recover from a stale_view deny: re-mint identity and return the CURRENT bytes. You MUST write FROM these exact bytes — the server enforces version lineage, NOT that your content was derived from what you read. SINGLE-HOST only. Out of guarantee and NOT detected in v1: writers on different hosts or across a synced/network mount, divergent-history reconciliation, semantic correctness, server-enforced auto-merge.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint=false annotation, the description explains re-minting identity, version lineage enforcement, and lists out-of-guarantee scenarios. This adds significant behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense sentence with additional clarifications. It conveys essentials without excess, though it could be slightly more structured for readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's niche purpose, the description covers recovery action, behavioral rules, and reliability caveats. It is sufficient for an AI agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has one required parameter 'path' with no description. The tool description does not explain what 'path' represents, leaving ambiguity. With 0% schema coverage, the description should compensate but fails to.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool recovers from stale_view deny by re-minting identity and returning current bytes. It distinguishes itself from siblings like swg_read and swg_write by specifying the recovery context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use ('recover from stale_view deny') and when-not-to-use (SINGLE-HOST only, not for divergent history). Also gives instructions to write FROM exact bytes returned, with warnings about limitations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
swg_readA
Read a workspace text file under coherence tracking. Returns {content, version, owner_generation}. The version is the comparand you pass to swg_write_cas; KEEP BOTH version and owner_generation and pass them to swg_gate before any irreversible external action you decide from this read (owner_generation=null means this coordinator does not report generations, so swg_gate will hold). A sticky-INVALID view returns fresh bytes but stays INVALID — use swg_reacquire to recover before writing. SINGLE-HOST only. Out of guarantee and NOT detected in v1: writers on different hosts or across a synced/network mount, divergent-history reconciliation, semantic correctness, server-enforced auto-merge.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description provides substantial behavioral detail beyond annotations: it specifies the exact return contract, the meaning of null owner_generation, the sticky-INVALID semantics, the SINGLE-HOST limitation, and the list of out-of-guarantee scenarios. It also implicitly discloses that reads can leave the view in a non-writable INVALID state, which is non-obvious behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence carries necessary information: purpose, return contract, downstream workflow, failure mode, host constraint, and explicit non-guarantees. The most important usage guidance is front-loaded early, and the limitations are compactly listed at the end. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and only a minimal readOnly annotation, the description carries heavy responsibility. It provides return values, usage protocol, error/recovery behavior, operational constraints, and explicit non-guarantees. This is complete enough for an agent to call the tool correctly and understand the consequences.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, path, is a required string in the schema with 0% description coverage. The description adds the context that the path refers to a workspace text file under coherence tracking, which orients the agent about the kind of path to provide. It doesn't describe path syntax, existence requirements, or valid forms, but the single parameter is self-evident enough to make this adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('workspace text file under coherence tracking'), and clearly differentiates from siblings by describing the read/cas/gate/adquire workflow. An agent can see this is the read entry point and not confuse it with write, status, gate, or reacquire.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly guides when to use this tool and what to do with its output: pass version and owner_generation to swg_gate before irreversible actions, pass version to swg_write_cas, and use swg_recquire to recover from a sticky-INVALID view. It effectively contrasts with siblings by naming them in the appropriate workflow context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
swg_statusARead-only
Report coherence state: coordinator on|off|unknown (unknown is NOT off), per-path enforced|not_registered, is_attached/is_degraded/session_id, and heterogeneous_scope_detectable=false (a multi-host or differently-scoped setup is NOT distinguishable in v1). SINGLE-HOST only. Out of guarantee and NOT detected in v1: writers on different hosts or across a synced/network mount, divergent-history reconciliation, semantic correctness, server-enforced auto-merge.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the readOnlyHint annotation by detailing the specific states reported (coordinator on/off/unknown, per-path enforced/not_registered, etc.) and explicitly lists limitations (e.g., 'Out of guarantee and NOT detected in v1: ...'). No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and contains many technical details (fields, limitations). While front-loaded with 'Report coherence state', it could be more concise. The structure is somewhat fragmented with commas and semicolons.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully explains the return values (coordination state, per-path status, attachment/degradation, session ID, etc.) and covers limitations. It is sufficiently complete for the tool's purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, and schema coverage is 100%. Baseline for no parameters is 4. The description does not add parameter semantics but explains the output, which is not directly relevant to this dimension.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with 'Report coherence state', a clear verb+resource combination. It lists specific fields and constraints, and it is distinct from sibling tools like swg_read, swg_write, etc., which have different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives. It mentions 'SINGLE-HOST only' as a constraint but does not provide when-to-use or when-not-to-use guidance relative to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
swg_writeA
Write a workspace text file (acquire -> write -> commit). DENIED with reason=stale_view if the file changed since you read it — a peer commit OR an out-of-band edit (another tool/editor): recover with swg_reacquire, then write FROM its bytes. A mid-write preempt returns reason=commit_preempted (disk may hold un-versioned bytes; reacquire_and_reconcile). SINGLE-HOST only. Out of guarantee and NOT detected in v1: writers on different hosts or across a synced/network mount, divergent-history reconciliation, semantic correctness, server-enforced auto-merge.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, so no contradiction. Description details stale view detection, preemption, single-host limitation, and v1 limitations. Adds significant behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Lengthy but efficient; every sentence adds value. Front-loaded with core action, then details. Not overly verbose given complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Fully explains error conditions, recovery procedures, limitations (single-host, no auto-merge). No output schema, but return values are implicitly clear from context. No gaps for agent invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, requiring description to compensate. Description implies 'path' and 'content' via 'file' and 'bytes', but does not explicitly describe them. Since parameters are simple and purpose is clear, minimal but adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Write a workspace text file' with specific workflow (acquire->write->commit). Distinguishes from siblings like swg_write_cas and mentions recovery tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use (after acquire, before commit), when not (stale view, preempted), and recovery steps with alternative tools (swg_reacquire, reacquire_and_reconcile).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
swg_write_casA
Concurrent same-key write via compare-and-set. You read (swg_read returns the version comparand; swg_reacquire does NOT — it is for swg_write recovery), MERGE, then call swg_write_cas(path, expected_version, new_content). Stale-write-rejected: if a peer committed since your read, the CAS is a TYPED CONFLICT (reason=version_mismatch, current_version returned) — NOT an auto-merge; re-read at current_version, re-merge, and retry. The per-session conflict counter bounds only a COOPERATING agent (one session, stops on retryable=false); it is NOT livelock-proof against a fresh session or one that ignores retryable=false. SINGLE-HOST only. Out of guarantee and NOT detected in v1: writers on different hosts or across a synced/network mount, divergent-history reconciliation, semantic correctness, server-enforced auto-merge.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| new_content | Yes | ||
| expected_version | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description transparently discloses the tool's behavior: it rejects stale writes with a typed conflict (version_mismatch) and returns current_version, it does not auto-merge, and it has retry logic bounded by a per-session counter but not livelock-proof. It also documents critical limitations: single-host only, undetected issues for multi-host or network mounts. Annotations only indicate non-read-only (readOnlyHint=false), so the description provides extensive additional behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively long but well-structured: it starts with the core purpose, then explains the usage flow, conflict handling, and limitations. Every sentence provides useful information, but could be slightly condensed without losing clarity. The front-loading is effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (CAS, conflict resolution, single-host constraint), the description covers most essential aspects: how to use, conflict response, retry guidance, and limitations. It lacks explicit return value documentation (no output schema), but implies the conflict response includes current_version. The distinction from siblings is clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must compensate. It explains that 'expected_version' comes from swg_read (not swg_reacquire) and 'new_content' is the merged result. 'path' is not elaborated, but its purpose is clear from the schema. The description adds meaningful context for two of three parameters, enhancing understanding beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a compare-and-set write operation for concurrent same-key updates. It explains the CAS pattern (read, merge, write with expected_version) and distinguishes from swg_write (non-CAS) and swg_reacquire (recovery only). The verb 'write' and resource 'shared file' with CAS semantics are specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool (after reading and merging) and how to handle conflicts (re-read, re-merge, retry). It warns that swg_reacquire should not be used to get the version for CAS. It also notes the single-host limitation and the cooperative agent assumption. However, it does not explicitly list alternative tools for different scenarios, though siblings are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
1 tool update
v0.14.0- Added
swg_gate
5 tool updates
v0.12.0- First observed
swg_reacquire - First observed
swg_read - First observed
swg_status - First observed
swg_write - First observed
swg_write_cas
TDQS
Each tool has a clear role in the workflow, but swg_write and swg_write_cas are both write entry points and could be misselected by an agent. The detailed descriptions distinguish normal write from CAS merge write, while the other tools are cleanly separated.
All tools use the swg_ prefix and lowercase snake_case, so the set is immediately recognizable and predictable. However, swg_status and swg_gate are noun-style command names rather than verb_noun action names, a minor deviation from the otherwise verb-oriented pattern.
Six tools is well-scoped for a stale-write guard: read, write, CAS write, reacquire, gate, and status each serve a distinct purpose. No tool feels redundant, and the count matches the focused domain.
The core stale-write lifecycle is covered end-to-end: read, write, recover, verify before external action, and inspect status. Minor gaps remain around explicit path registration and the referenced reconcile step, which is not surfaced as a named tool, but agents can work around these with existing tools.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Coordinate multiple AI agents over MCP: atomic claims, leases, shared ledger, handoffs, tasks.
Durable agent-to-agent handoffs and shared scratchpad for multi-agent workflows.
Tamper-evident audit log service for agent-to-agent transactions
Coordination board for AI agents: atomic claims, no self-verification, independent verify-gate.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenancePrevents AI coding agents from conflicting by coordinating file claims and resolving conflicts in real-time across multiple sessions.3361MIT
- AlicenseAqualityDmaintenancePrevents AI agents from overwriting each other's work by providing file locking and coordination via MCP tools.41MIT
- AlicenseAqualityDmaintenanceProvides file-level exclusive locking across multiple Claude Code instances to prevent edit conflicts when multiple agents edit the same project simultaneously.4MIT
- AlicenseAqualityAmaintenanceCoordination for parallel coding agents: TTL file claims stored in the git common dir (visible across all worktrees), enforcement hooks that block colliding edits, agent presence, handoff notes, and a git-committed lessons knowledge base with BM25 search. Single static Go binary — no server, no database.81MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Cohexa-ai/agent-coherence'
If you have feedback or need assistance with the MCP directory API, please join our Discord server