关于 Agent Coherence
Agent Coherence 在单主机上协调 Agent 共享状态,防止基于过期视图或并发写入静默覆盖新内容。它面向多 Agent 系统,提供适配器、文件协调及经 TLA+ 检查的安全不变量。
主要功能
- 01MESI 式所有权与失效通知
- 02用于并发写入的乐观提交 CAS
- 03多资源一致性读取会话
- 04崩溃恢复时回收授权
- 05用于共享文件的 CoherentVolume
- 06经 TLA+ 检查的安全不变量
适用场景
- 01防止 Agent 覆盖共享计划
- 02协调共享状态的并发写入
- 03保持 Agent 记忆与 RAG 记录一致
- 04回收崩溃 Agent 持有的授权
MCP 相关
`stale-write-guard-fs` MCP 服务向 MCP 客户端提供一致性协调功能,可通过 `mcp` extra 安装。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
agent-coherence
agent-coherence 可防止一个 Agent 在共享的 plan.md、存储键或 memory.json 上悄悄覆盖另一个 Agent 的工作——它是一个与供应商无关的 MESI + 乐观并发协调器,用于管理单台主机上的 Agent 状态,并通过 TLA+ 对安全不变量进行机器验证。
两个 Agent 共享一个工件——plan.md、存储键或 memory.json。一个 Agent 读取工件并开始工作;与此同时,另一个 Agent 提交了更新版本;第一个 Agent 却仍然写回。后写入的内容覆盖先前内容,另一个 Agent 的工作悄无声息地消失,没有报错,后续的每个决策都建立在错误版本之上。
为何难以察觉。 Agent 系统会保留两份事件记录:一份是基础设施能够验证的——每个 Agent 持有哪个版本、实际提交了什么、哪些操作被拒绝;另一份是模型叙述的——“任务已完成”、“计划已更新”。在某个 Agent 基于已被更新的版本采取行动之前,两份记录看起来一致,而你读取的是模型叙述的那份。这就是为何丢失更新看起来像一次顺利运行,问题却会被当作模型问题来排查。agent-coherence 为 Agent 共享的状态提供经过验证的记录。(它不会验证 Agent 在外部世界中做了什么——例如发送邮件或触发 webhook;这些仍由你的发件箱和幂等层负责。)agent-coherence 会将悄无声息的覆盖转变为明确、带类型的拒绝:对共享工件采用 MESI 式所有权和失效机制,使用乐观提交 CAS 处理并发写入者,并通过读取代次栅栏处理崩溃后回收的实例——过期写入会被拒绝或作为可重试冲突返回,绝不会悄悄应用。同一个库、同一套协议,可用于 LangGraph、CrewAI、AutoGen、OpenAI Agents SDK、跨进程共享的普通文件(CoherentVolume)、任何 MCP 客户端(通过 mcp extra 使用 stale-write-guard-fs 服务),以及任何自定义编排器。无论 Agent 使用哪家模型提供商(Anthropic、OpenAI、Google、Mistral、开源模型),行为都一致。
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() 均可保持原样使用。CCSStore 增加了读取端的一致性:同伴提交会使你的缓存视图失效,因此你下一次读取会重新从缓存未命中开始。它不会拒绝过期的写回——put 不是版本 CAS;如需防止写入端丢失更新,请通过 CoherentVolume 或 write_cas(见下文)路由写入。
只需替换一个导入的前提是,存储命名空间通过
namespace[0]携带 Agent 身份——(user_id, "memories")这样的结构会把多个用户合并到同一个共享工件中。请参阅命名空间约定。
# 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-derive
agent-coherence-replay——用于任何由 CoherenceAdapterCore 协调的 Agent 系统的不变量重放。v1 中已通过 CCSStore.record_to(path) 验证 LangGraph 捕获;CrewAI / AutoGen 已通过同一接入点接通,但尚未验证——如果出现问题,请提交 issue。
它能保证什么
每一项都是通过 TLA+/TLC 模型检查的安全不变量。make tla-check 会运行全部九个规约。对于每个会更改 TLA+ 输入(规约及其配置、Makefile、工作流,以及决定并评判运行结果的脚本)的拉取请求,CI 都会通过三个并行作业运行这些检查;在拉取请求之外的每次运行中也会执行。每个规约都附有一个必须导致失败的已记录变异体——这些不变量是承载安全性的关键,不是装饰。
| 静默失败 | 实际发生的情况 | 机制 | 不变量 |
|---|---|---|---|
覆盖陈旧读取——Agent 基于旧快照采取行动,并覆盖了较新版本(两个会话,共用一个 plan.md) | 写入会失败关闭并被拒绝;写入方必须调用 reacquire() 并读取当前版本 | MESI 单写入方所有权 + 失效处理 | SingleWriter、MonotonicVersion |
| 并发更新丢失——两个写入方针对同一个键操作,且都“成功” | 恰有一个写入方成功;另一个会收到带类型的冲突 + 有界重试,绝不会被静默丢弃 | 乐观提交 CAS(write_cas) | NoLostUpdate |
| 回收后的僵尸写入——停滞的写入方被崩溃恢复机制回收,随后恢复运行并提交陈旧内容;由于版本从未变化,版本检查会通过 | 提交会被拒绝:在悲观路径(CoherentVolume.write() 和 Claude Code 钩子 /hooks/post-edit)上,返回 commit_not_allowed,并指出回收者(reclaimed_by=reclaim_heartbeat);在提交 CAS 路径(write_cas、write_cas_at、/hooks/post-edit-cas)上,返回带类型的 stale_read_generation 冲突 | 在悲观路径上,授权检查会拒绝授权已被回收的持有方;读取代际栅栏会在回收时递增资源的所有权纪元,并在提交时以原子方式检查,从而在提交 CAS 路径上拒绝该提交;如果回收发生在提交过程中,也会在悲观路径上拒绝该提交 | NoStaleApply |
| 僵尸撤销——生成了一条失效信号,但在应用时,信号指向的 Agent 已被回收、重新获取授权并重新读取;此时应用该信号会撤销在信号之后发放的授权,而目标版本从未变化,因此版本检查无法发现问题 | 该失效信号会被作为过时信号丢弃——目标版本并不落后于信号所指版本,因此授权仍然有效 | 对等方发起的撤销会固定到目标最后观察到的版本;每一种会结束写入声明的撤销操作——清扫回收或释放——都会变更所有权纪元(对等方的写入获取不会变更两个比较项;效果门则通过授权状态来进行防护) | NoZombieRevoke、NoSilentRevoke |
| 回收后的僵尸效果——同一个被回收的写入方,其逃逸效果(webhook、部署、已打开的 PR)基于被撤销授权下的决策触发;由于版本从未变化,仅检查版本会通过 | 效果会在边界处被拦截(StaleView)——版本相同,所有权代际却不同 | gate() 会在触发效果前,重新验证成对原子的 (version, ownership generation) 快照 | NoStaleAdmit |
| 撕裂式多资源读取(读取偏斜)——Agent 逐个读取多个资源,而对等方在读取过程中提交了更改;每次读取单独来看都是最新的,但这些内容的组合从未同时存在过 | 会话读取从固定的一致性切面提供;提交会根据固定的基准状态进行验证;会话过期时会失败关闭并返回带类型的拒绝,绝不会静默退回实时状态 | 多资源快照会话 | NoReadSkewWithinCut、PinAlwaysRetained |
| 所有者宕机导致整个集群阻塞——崩溃的 Agent 永远持有 EXCLUSIVE | 心跳/TTL 清扫会回收该授权(默认开启;尽力而为,并受速率限制) | 崩溃恢复清扫;操作员可在清扫即将回收每个写入授权时从 /status?detail=full 读取(方法),并查看已回收的授权(方法) | 清扫不变量 I3–I6 |
该表还会通过测试套件进行机器校验:已打包的声明阶梯(ccs.testing.claim_ladder)将上述每条声明短语与缺少它便会失败的测试绑定起来——在收集测试时解析,并由 tests/conformance/test_claim_ladder.py 进行双向漂移防护,因此声明不能超出其证明的有效范围(跨主机阶梯也不能在没有证明的情况下出现)。 |
**如实说明范围:**这些保证适用于通过协调器进行写入的场景,且仅限单个协调器(一个主机)。两个注册表都会在每个检查并执行的序列中持有一把锁——持久化的 SQLite 注册表和内存注册表遵循相同的并发约定,因此嵌入方可以从多个线程驱动任一注册表。单个主机上的同键并发写入已覆盖,但仍有一个未解决的问题(#248):某个对等方的 write_cas_at 已提交、但其字节尚未写入磁盘时,若写入卷没有该文件的实时视图,此时发起的普通 write() 会丢失——它从未读取过该文件、只在那个时间窗口内读取过(即使 read() 在默认 on_stale_read="allow" 下返回旧字节,协调器也会拒绝此类读取),或者它执行的 write_cas / write_cas_at 以 ViewWedged 结束。两次调用都会报告成功;磁盘保留对等方的字节,而协调器将丢失的写入记录为最新版本。此后,对该文件执行的所有 write_cas / write_cas_at 都会抛出 ViewWedged,直到普通 write() 替换该文件。如果某个卷在对等方提交前读取过该文件,则会被拒绝。跨主机防护已列入路线图,按需求推进——如果你需要此功能,请提交问题。完全绕过协调器的编辑(人在编辑器中修改、格式化工具修改、重新生成脚本修改)会在 read() / write() 边界通过内容哈希检查捕获——下文的外部编辑防护:绕过协调器的写入,由测试而非 TLA+ 强制执行;批量 CAS 路径的边界更窄,详见原子多文件发布。规范、不变量 ↔ 实现映射以及变异体配方位于 formal/tla/。
**正确性是切入点;节省令牌也随之而来。**写入会发布约 12 个令牌的失效信号,而不是重新广播完整产物,因此读取密集型集群不必反复为已有状态付费:
| 工作负载 | Agent 数量 | 读取:写入 | 命中率 | 节省 |
|---|---|---|---|---|
| 规划(读取密集型) | 4 | 12:1 | 75% | 69% |
| 代码审查(中等) | 3 | 8:3 | 60% | 47% |
| 高变动(写入密集型) | 4 | 8:4 | 50% | 29% |
在真实 LangGraph 图上测得;参见 docs/reproduce.md 和用户指南。
这些是空间节省(更多 Agent 共享一个产物)。时间维度——单个 Agent 在不同轮次之间,其来源发生变化——有自己的预注册基准 TC-1(#116):一张可复现的节省区间图,展示随着变化率上升,一致性门控能避免多少次重新获取。该指标是 re-fetches-avoided——一种代理指标、一张区间图,不是令牌或美元账单。使用 python tools/run_cost_sweep.py 复现;锁定的判定结果和数字(n=50 时 PASS,交叉点 r≈0.31)位于 benchmarks/cost_preregistration.md。已随 v0.9.3 发布。
RAG 与共享 Agent 记忆
RAG 语料库和 Agent 记忆是共享的可变状态,因此过时读取→写入导致的更新丢失也会出现在这里——而且一致性存储也无法解决问题:过时的是 Agent 缓存的记录视图,而不是存储。两个 Agent 读取了 v1 版本的记录;一个写入 v2;另一个仍基于 v1,用根据 v1 计算出的编辑内容写入,覆盖了 v2。agent-coherence 让读取者保持最新——CCSStore 可直接替代 langgraph.store(可与 Mem0、Letta、LlamaIndex、向量存储或普通文件组合,作为你现有方案的底层;它不存储向量,也不进行排序),因此某个对等方提交更改后,会使过时的缓存视图失效(读取侧一致性)。要防止过时的写回本身,则需要通过 CoherentVolume 或 write_cas 路由这些写入。
- 可运行的确定性演示(离线,无需密钥):运行
python -m examples.coherent_volume.main,即可重现文档所述的更新丢失问题,然后防止它。 - **明确的适用范围:**通过协调器进行的写入会被捕获。自动监视非托管外部源在没有协调器写入时发生的更改(例如手动编辑的文件、在协调器之外重新索引)属于源监视器的范畴——已列入路线图,按需求推进,目前尚未发布。
- 定位与常见问题:agent-coherence.dev/rag。
- 📖 用户指南 — 安装、命名空间约定、策略、可观测性、遥测、示例、完整 API 参考
- 🔎 RAG 与共享内存 — 为检索语料库和 Agent 内存存储提供一致性,并附带可运行的丢失更新演示
- 🗂️ 一致性工作区 —
CoherentVolume,用于在进程间共享普通文件的数据平面设备 - 🧱 自选底层存储 —
CoherentRow/CoherentObject,在你已运行的 Postgres 行或 S3 对象上提供相同的一致性保障 - ⏪ 工作区版本控制与恢复 —
WorkspaceVersioner,为混合文件与 S3 的工作区创建检查点,指定可恢复工作区的人员,并按成员如实恢复 - 🛡️ 外部编辑防护 — 在读写边界捕获绕过协调器的编辑(来自人员、格式化程序或脚本),并统计离线期间发生的编辑(外部写入检测)
- 🔌 MCP 服务 —
stale-write-guard-fs,为任何 MCP 客户端提供相同保障,无需 Python 集成 - 🚦 效果顺序闸门 —
gate(),仅当 Agent 的效果所依据的输入状态(值和授权)未变时才触发;通过 MCP(swg_gate)和 HTTP(POST /hooks/effect-fence)提供相同判定 - 📸 多工件快照会话 — 将多个工件作为一个一致的快照读取;不会出现撕裂读取
- 📦 多文件原子发布 —
atomic_publish,一次性发布一组文件;绝不会出现撕裂的文件对 - 🤝 定向授权移交 — 将文件移交给一个指定会话;版本变更、后继者拒绝或移交者撤回之前,移交者后续的写入都会被拒绝,并返回
handed_off。可通过 Claude Code、CoherentVolume、MCP 或 HTTP 使用;仅由 Python 协调器提供 - 🔒 在
pre-edit上获取或失败 — 当另一个 Agent 持有文件时,发送"if_unheld": true的pre-edit会被拒绝并返回other_holder,同时指出持有者;授权不会被移交。该机制仅在选择启用的调用方之间生效:普通pre-edit仍会取代选择启用的持有者。仅适用于已跟踪路径,因此请在严格模式路径上选择启用;目前还没有任何代码发送此标志。由 Python 协调器提供(请求中包含调用方主体);从 0.6.0 之后的版本起,也由 Claude Code 插件的 Node 协调器提供,后者不需要主体,并允许请求收回其他 Agent 已持有 30 分钟或更久的授权 - 🧮 形式化验证 — TLA+ 规范、不变量 ↔ 实现映射、变异体配方
- 🩺
ccs-diagnoseCLI — 找出你现有 LangGraph 图中的分歧读取,无需更改任何代码 - 📊 冲突结果计数器 — 统计每种类型的拒绝实际发生的次数,并从已关闭的
state.db离线读取 - 🧩 Claude Code 插件 — 为 Claude Code 并行会话共享的规则文档(CLAUDE.md、plan.md)提供跨会话一致性
- 🔍 为什么一致性很重要 — LangGraph、CrewAI、AutoGen 和 Claude Agent SDK 之间存在的差距
- 🧭 基于 MESI 的方法 — 协议如何将每个已记录的差距映射到已交付的功能面,并明确其边界
- 🪪 调用方主体 — 写入方声明主体后,未携带该主体、却以其会话名义发出的请求将无法释放其授权或以其名义提交;从未声明主体的客户端仍可正常工作
- 🔐 安全与供应链 — 紧急关闭开关、哈希固定安装、证明验证、威胁模型
- 📜 变更日志 — 版本历史
- 📄 arXiv 论文(2603.15183) — 形式化协议、TLA+ 验证、模拟结果
工作原理
每个共享工件都会按 Agent 缓存在本地;如果本地副本仍然是最新版本,读取就会从本地缓存提供。写入会提交到协调器,协调器会向对等方发送轻量级失效信号(约 12 个令牌),这样下一次读取就会获取新版本,而不是重新广播整个工件。每个工件采用单写多读的一致性模型,并允许有限的陈旧状态——对等方会在下次读取时重新获取。
两种写入方式都能提供相同保证。**悲观模式:**获取 EXCLUSIVE 后提交;如果写入方看到的视图已过期,写入就会被拒绝,必须调用 reacquire()。**乐观模式:**使用 write_cas——读取、计算、执行提交 CAS;竞争失败的一方会收到带类型的冲突,并进行有限次数的重试。两种模式都支持崩溃恢复:即使版本未变,已回收的写入方稍后完成写入时,也会在提交阶段被拒绝。悲观模式的提交会被拒绝,因为写入方不再持有授权;提交 CAS 会被读取代次栅栏拒绝,因为回收停滞的授权会递增工件的所有权纪元。在读取侧,快照会话会固定多个工件的一致性切面,因此多工件读取不会看到版本不一致的混合结果。
开箱即用地提供五种同步策略:lazy(默认)、eager、lease(基于 TTL)、access_count 和 broadcast。请根据工作负载的读写比例,以及缓存读取需要多积极地刷新,选择合适的策略。
架构
- 协议(
ccs.core、ccs.strategies)——一致性状态机和同步策略;不依赖任何框架。 - 协调器(
ccs.coordinator)——权威服务,用于跟踪目录状态、发布失效通知、仲裁提交 CAS,以及回收过期授权(崩溃恢复 + 读取代次栅栏)。 - 适配器(
ccs.adapters)——为 LangGraph、CrewAI 和 AutoGen 提供框架集成(每个约 100 行),另提供实验性的 OpenAI Agents SDK 适配器(Session缓存一致性 +RunHooks)。 - 一致性工作区(
ccs.adapters.coherent_volume)——数据平面设备:进程外的协调器客户端,无需框架,即可为磁盘上的普通文件提供相同保证。请参阅一致性工作区。 - MCP 服务(
ccs.mcp)——stale-write-guard-fsstdio 服务,通过十个swg_*工具向任何 Model Context Protocol 客户端提供一致性工作区的保证。请参阅 MCP 服务。 - 模拟器(
ccs.simulation)——由确定性时钟驱动的引擎,用于带故障注入的场景基准测试。 - 事件总线(
ccs.bus)——用于传输失效信号;目前采用内存内/进程内实现(InMemoryEventBus)。面向多主机部署的网络传输方式(Redis、Kafka、NATS、gRPC)已列入路线图,是否实现取决于需求。
协议安全属性——单写入方、版本单调递增、崩溃恢复扫描不变量、OCC 不丢失更新、回收栅栏不应用陈旧写入、效果门控不接受陈旧操作、版本保留不读取已回收版本、快照会话在一致性切面内不发生读取偏斜,以及工作区恢复不会注册部分恢复结果——均使用 TLA+/TLC 进行模型检查。CI 会在每个更改 TLA+ 输入(规范及其配置、Makefile、工作流,以及用于决定和判定运行结果的脚本)的拉取请求中运行全部九个规范,并分为三个并行任务;在所有非拉取请求的运行中也会运行。
Coherent 工作区:共享文件的数据平面
框架适配器会包装一个存储。CoherentVolume 则是另一半——数据平面设备,它是一个构建模块,能让普通磁盘文件组成的共享工作区保持一致,无需框架参与。从架构上看,它是一个进程外的协调器客户端,而非进程内包装器:它会写入策略,通过 SQLite-WAL 启动(或连接到)本地协调器,并通过协调器路由读写操作。你的内容仍保存在真实文件系统中;协调器仅保存每个受管理文件的 MESI 状态、内容哈希和版本。让另一个进程中的同级卷指向同一工作区,它就会连接到同一个协调器,因此单主机集群共享同一个一致视图。该集群中的每个卷都必须声明相同的 managed glob:连接中的卷不会向运行中的协调器策略添加任何内容,因此连接时,每个卷都会将自己声明的 glob 与协调器严格执行、跟踪和忽略的集合进行核对;如果有任何 glob 未被执行,卷就会拒绝连接并指出具体内容。混合 glob 的集群不受支持;它会安全失败,而不会悄悄放行。
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: clear the stale view + mandatory fresh read
显式的 read / write / reacquire / write_cas API 是受支持的基本操作(write_cas(path, make_content) 是用于处理同键争用的乐观并发版本——失败方会收到有类型的冲突,绝不会静默丢弃)。对于不想重写的代码,可选择启用仅供演示级别的 open() 垫片,将针对受管理路径的打开操作路由到卷,使现有的 open() / pathlib 调用无需更改即可获得一致性:
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()
如实说明适用范围。 对于共享同一工作区的单主机集群,普通 write() 可防止单个主机上顺序发生的“读取旧数据→写入”导致的更新丢失(A 读取 v1,B 读取 v1,A 提交 v2,B 的旧数据写入被拒绝 → B 重新读取);并发的同键竞争者会通过 write_cas 处理——一方胜出,失败方收到有类型的冲突并重新推导,绝不会静默丢弃。完全绕过卷的编辑会在边界处由外部编辑防护捕获。它无法捕获这样的 Agent:重新读取最新字节后,却写入根据旧字节计算出的缓冲区。open() 垫片只是为了方便,并非契约:它支持 open() / pathlib 的文本和二进制读写,但不支持原始 os.open、子进程重定向、mmap 或追加/更新模式;这些操作会原样交给原始 open()。亲自运行:python -m examples.coherent_volume.main(离线、确定性、无需密钥),或阅读定位说明 + 常见问题。
外部编辑防护:绕过协调器的写入
协调机制涵盖主动接入的写入方,但实际工作区也会从外部被编辑:有人在编辑器中修复文件,格式化工具重写文件,CI 脚本重新生成文件。如果没有防护,下一个 Agent 写入会悄无声息地覆盖这项编辑,而下一个 Agent 读取则会悄无声息地基于协调器从未见过的字节继续工作。CoherentVolume 通过内容哈希检查防护这两个边界:
-
写入边界 — 默认启用。 写入前,卷会检查受管理文件在磁盘上的字节自上次读取或写入后是否发生了卷外更改。如果发生了更改,写入会抛出
StaleView,而不是覆盖外部编辑 — 可通过reacquire()恢复(重新读取 → 重新推导 → 重新写入)。使用CoherentVolume(on_stale_write="allow")可选择退出,恢复最后写入者胜出的行为。 -
读取边界 — 可选启用。 使用
CoherentVolume(on_stale_read="raise")时,如果受管理文件的字节发生了卷外更改,重新读取该文件会抛出StaleView,而不是返回其他状态并非基于其计算得出的字节;在严格模式下,协调器会在服务端执行相同检查。卷不会拒绝自己刚写入的字节 — 它会识别并抑制无害的提交→磁盘写入延迟窗口。on_stale_read仅适用于read()。无论该设置为何,版本化读取 —read_with_version()、read_with_version_generation()和 MCPswg_read— 都会拒绝读取字节并非协调器在所报告版本下对应内容的受管理文件,但卷自身刚提交后、上述同一延迟窗口内的情况除外:这些读取会抛出reason为split_pair的StaleView,以便与其他陈旧视图区分(swg_read会以stale_view拒绝,并且不返回版本),而不是提供一个随后会被用于比较并交换的版本。
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-write
适用范围,如实说明。 这些是在卷的读写边界进行的内容哈希检查 — 属于尽力而为的瞬时检测,并非文件系统拦截。未经过卷的写入会在下次通过卷读取/写入该文件时被发现,而不会在写入发生时被阻止;监视未受管理的外部来源已列入路线图,是否实现取决于需求。现在,下次读取或写入前发生的情况也可以观测:Python 协调器的扫描会询问 git 哪些协调文件在磁盘上发生了更改,并将所有无法归因的更改记录为 foreign — 只计数,绝不拒绝;ccs.diagnose.foreign_writes.read_foreign_write_report 则可以在离线状态下从已关闭的 state.db 读取统计结果(外部写入检测 — 谁在我背后写了东西?)。它只监视 git 跟踪的文件,而且只有在协调器的根目录位于其 git 工作树顶层时才会生效(#241)。这些防护由测试确保,而非 TLA+ — 经模型检查的不变量覆盖协议状态机,不覆盖磁盘字节。它们适用于 read()/write()(以及封装这些方法的 MCP 工具);CAS 路径检查的是版本 — write_cas/write_cas_at 遇到外部编辑仍会失败关闭(经过内容检查的比较值读取会卡住,而不会覆盖内容),但多文件 atomic_publish 完全不检查磁盘内容 — 请参阅其适用范围说明。
MCP 服务:stale-write-guard-fs
为使用 Model Context Protocol 的 Agent 提供相同保障 — Claude Code、Cursor 或自定义运行时均适用,完全无需集成 Python。stale-write-guard-fs 是一个基于 stdio 的 MCP 服务,它封装了 CoherentVolume,并将协调文件访问作为十个工具提供:
pip install "agent-coherence[mcp]"
{
"mcpServers": {
"stale-write-guard-fs": {
"command": "stale-write-guard-fs",
"env": { "SWG_ROOT": "/path/to/shared/workspace" }
}
}
}
| 工具 | 功能 |
|---|---|
swg_read | 受跟踪的读取——记录 Agent 对文件的视图。如果磁盘上的字节与协调器记录的不一致,读取会返回带有 stale_view 的拒绝结果,且不包含版本号。请先重试几秒钟 swg_reacquire + swg_read,因为对等方的提交可能仍在写入磁盘;如果仍被拒绝,说明文件是在协调器之外被修改的(外部编辑,或磁盘写入失败的提交),因此请将重新获取的内容写入 swg_write,以便记录下来 |
swg_write | 受保护的写入——视图过期或存在外部编辑时,会返回带有 recover: reacquire 的类型化 stale_view 拒绝结果,绝不会静默覆盖 |
swg_reacquire | 恢复——清除过期视图;收到拒绝结果后必须重新读取 |
swg_write_cas | 针对同键并发争用的单次版本校验写入 |
swg_gate | 效果围栏——在执行不可逆的外部操作(webhook、部署、创建 PR)之前,重新检查 swg_read 返回的 (version, owner_generation) 对;如果值已变更、读取时所依据的授权已被收回,或对等方的写入声明抢先取得优先权(这不会改变两个比较值——围栏也会重新检查授权是否仍然有效),则拒绝操作 |
swg_status | 三态协调健康状态:on / off / unknown,并返回此会话的 session_agent_id,以及其他会话用于将路径移交给此会话的 ID |
swg_transfer | 将此会话对一个或多个路径的声明移交给其 session_agent_id 与之匹配的会话;移交结束前,此会话对这些路径调用 swg_write / swg_write_cas 都会收到类型化的 handed_off 拒绝结果(定向授权移交) |
swg_accept | 作为接任方,接受移交,但不写入路径 |
swg_decline | 作为接任方,拒绝移交;移交方随后可以再次写入该路径 |
swg_withdraw | 作为移交方,仅在用户或宿主明确指示时撤回移交 |
POST /hooks/effect-fence | 不是工具——而是 swg_gate 的 HTTP 对应接口。 协调器会向任何能够发出 HTTP 请求的客户端返回相同的围栏判定,无需 MCP,也无需 Python;它也是唯一能够处理无内容声明分支的接口。参见 通过 HTTP 使用效果围栏 |
每个会话绑定一个工作区(SWG_ROOT,默认为其工作目录;除非 SWG_MANAGED——以逗号分隔的 glob 列表——缩小保护范围,否则整个工作区都会受到保护)。服务器会拒绝路径遍历和对协调器自身状态目录的任何访问,并在 IO 出错时采取失败关闭策略。拒绝结果会以类型化、机器可读的负载返回——Agent 可以解析 recover: reacquire 并自行恢复,而不是盲目重试。如果协调器停止响应,每次工具调用都会返回 coordinator_unavailable 和 recover: stop_and_report:Agent 会停止,不会通过其他途径写入任何内容,并报告必须重启服务器(详情)。如果协调器在响应读取请求时出错,或在释放先前 swg_write 留下的写入授权时出错,调用会返回 coordinator_failed:Agent 会再尝试一次,然后停止并报告;提交得到此响应的写入,或收到 HTTP 5xx 的写入,可能已经生效,因此会返回 commit_unconfirmed(详情)。运行红→绿演示:python -m examples.mcp_stale_write_guard.main(离线、确定性运行,无需密钥)。
诚实说明适用范围。 与其包装的存储卷具有相同约束:单主机、受管理路径、协作式——它保护通过这些工具访问文件的 Agent;无法检测绕过这些工具进行的编辑(这些编辑会在下次通过工具调用访问该文件时被外部编辑防护机制捕获)。
效果顺序门控
Agent 不只会覆盖文件,还会触发根据先前读取的输入计算出的效果(部署、PR、shell 命令)。如果输入在此期间发生变化,效果就会基于过时状态触发。gate() 缩短了这个时间窗口:它会在做出决策时捕获输入的 (version, ownership generation) 对,在效果执行边界处重新读取该对,并且只有在重新读取时两者都未变化才触发效果;否则会在效果运行前将其拦截。两个比较值分别捕获不同的故障:version 能发现同伴更改了输入;generation 能发现协调器扫描回收了读取该输入时所依赖的授权,而字节内容始终未变——如果 Agent 停滞不前,租约在决策过程中到期,它就会在权限已撤销的情况下触发效果,而 version 检查对此毫无察觉。一次撤销不会改变任何一个比较值:同伴的悲观写入获取会拿走持有者的授权,但此时尚无提交操作,因此 version 未变;也不会触发 epoch 递增(该触发条件被特意排除在递增集合之外)。gate 还要求重新读取本身必须由有效授权提供,从而封堵这条路径——被抢占的持有者重新读取时会得到过期结果,效果便会被拦截。协调器不会为这次重新读取验证而重新授予授权,因此拦截是电平触发的:直接重试仍会再次被拦截,直到调用方重新获取授权。第三条路径由测试强制执行(claim 梯级将其固定),而非 TLA+;经模型检查的 NoStaleAdmit 覆盖的是这对比较值。
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)
这是纯 Python,因此同一个调用可以原样用于 LangGraph 节点、CrewAI 任务或原始脚本。
三种接入方式,一条规则。 gate() 是 fence 的 Python 写法。swg_gate 是 MCP 写法,而 POST /hooks/effect-fence 会向任何不使用前两者的客户端返回相同的判定——问题相同、分类相同、拦截原因也相同。这些原因构成线上的词汇表,并在effect-fence contract中公布每种原因的触发条件和对应恢复方式。不同接入方式支持的路径并不完全相同:只有 HTTP 路由能报告 content_claim_absent,即协调器根本没有为该产物记录内容声明的情况——Python 和 MCP 接入方式读取的是哈希比对结果,而非协调器自己的记录,因此“声明匹配”和“没有声明”对它们来说会得到同一个值。
如实说明适用范围。 gate 对效果进行排序,而不回滚效果:它会在效果发生前触发,但绝不会撤销效果,因此对于外部效果,它能缩短但无法消除重新读取到触发之间的剩余窗口。它仅支持单主机且依赖调用方配合——Agent 必须主动使用。两个比较值都采用失败即关闭策略:version 未确认(降级读取)或 generation 未确认(严格模式拒绝,或协调器未报告 generation,例如版本早于 v0.14.0)时,都会拦截,而不是触发。对于纯写入效果,请直接使用 vol.write_cas_at(path, expected_version, content),这是原子且无窗口的路径。要同时门控多个彼此一致的输入,应在协调器上使用 snapshot-session 操作,而不是这个单输入封装。运行方式:python -m examples.effect_gate.main(离线、确定性、无需密钥),或添加 --baseline 查看它能捕获的过期触发;python -m examples.gate_effect_ordering.main 会增加租约被回收的场景(version 不变、权限已撤销、部署被拦截)。
多制品快照会话
gate() 会保护一个输入。但 Agent 如果逐一读取多个制品——计划、配置、记忆文件——就可能看到一个不一致的组合:plan.md 来自某个同伴提交之前,而 config.json 来自该提交之后。每次读取都获取了最新内容,但这些内容从未同时存在过(读取偏斜)。快照会话可以消除这种情况:它会为你指定的制品固定一个一致性切面,该切面在同一时刻捕获,并在同伴继续写入期间,让会话中的每次读取都基于该切面。
通过运行中的协调器(即 CoherentVolume 启动的同一个协调器)使用 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 alive
也可以在进程内使用:CoordinatorService.begin_session(read_set=…, owner=…) → session_read(…) / session_commit(…)。该切面是一个可检查的 {artifact: version} 映射,而不是不透明句柄——你可以准确查看会话固定了哪些版本。
从设计上确保失败关闭:如果读取的制品不在固定的读取集内,系统会通过类型化拒绝予以拦截,绝不会静默地从实时状态提供数据。会话的有效期有限,并由心跳租约支持:如果会话心跳超时,或会话因协调器重启而丢失,该会话就会失效;后续读取会收到类型化的“会话已失效”拒绝,提示 Agent 重新建立会话,绝不会悄然回退到当前状态。已进行模型检查:NoReadSkewWithinCut 和 PinAlwaysRetained(formal/tla/Snapshot.tla)。
范围说明。 这可以防止读取偏斜——跨制品的不一致读取,但不提供写入偏斜防护:提交会通过与 write_cas 相同的乐观 CAS,基于固定的基准版本逐个验证制品,因此,读取同一切面的两个会话仍可能交错写入不同的制品。仅支持单协调器、单主机。如果协调器保留了版本内容,就会直接提供固定版本的字节;否则,它会将固定版本及内容哈希作为类型化信号返回,由调用方从自己的数据平面获取字节。
原子化多文件发布
如果文件尚未变动,write_cas_at 就会写入一个文件。但 Agent 往往会编辑一组必须保持一致的文件——例如一份计划及其清单,或拆分到多个文件中的配置——并且必须一并写入,或者都不写入,绝不能出现撕裂的一对文件,即一个文件引用了另一个已经变动的文件。atomic_publish 就是这种全有或全无的批量操作:
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}
要么所有成员的版本都前进,要么一个也不前进;只要有成员变动,整个批次就会被阻止——撕裂的提交绝不会成为可达状态。该保证在 formal/tla/AtomicPublish.tla 中被正式规范为 NoPartialPublish 不变量。AtomicPublish.tla 已完成规范并通过语义验证,但未纳入 CI 扫描——它暂不纳入,等待一种能在 CI 时间预算内收敛的有界编码,因此 NoPartialPublish 不属于每次推送时都会进行模型检查的九项不变量之一。单文件发布会走直接的 CAS 路径;多文件发布会打开一个快照会话,确保所检查的版本是在同一时刻捕获的(不会在另一个文件已提交后才读取某个成员)。运行方式:python -m examples.atomic_publish.main(离线、确定性、无需密钥);或者添加 --baseline,查看它所防止的逐文件写入撕裂状态。
如实说明范围。 全有或全无的保证仅适用于协调器提交——这正是 NoPartialPublish 所覆盖的范围。磁盘物化发生在提交之后,尽力而为:每个文件都会先写入临时文件,再重命名到目标位置,因此磁盘故障会在任何重命名发生前失败(磁盘上的文件仍全部保持旧状态);如果重命名中途失败,则会引发带类型的 PublishMaterializationError,准确指出哪些文件已写入,而不会抛出暗示什么都没发布的普通错误。这缩短了多文件磁盘操作的时间窗口,但无法彻底消除重命名之间发生崩溃的可能(POSIX 不支持多个文件的原子重命名);发生此错误时,协调器会领先于磁盘:使用已发布的字节,通过 write() 重写每个尚未写入的文件(在此之前,不允许对这类文件进行带版本读取)。该机制仅适用于单主机环境,并且要求各方协作。多文件路径还会增加一个较小的捕获→提交窗口(会话开启期间);若其他参与者在此期间抢先提交,发布会被阻止,而不会造成撕裂。这是针对一组文件的全有或全无发布,并非回滚已经产生的影响,也不防止会话间的写入偏差。它检测的是版本变化:只有通过卷路由的写入才会推进版本,因此绕过卷直接进行的编辑(例如用户在编辑器中修改、格式化程序操作、脚本直接写入某个成员)对多文件发布不可见——批次仍会提交并覆盖这些修改。针对同样的修改,单文件发布和普通 write() 会通过外部编辑防护(绕过协调器的写入)安全失败;只有当所有可能竞争写入的参与者都通过卷操作时,才应使用 atomic_publish。
BYO 基础设施:在现有存储之上实现一致性
CoherentVolume 为磁盘上的文件提供一致性。但共享的 Agent 状态通常存放在你已经运行的存储中——例如 Postgres 行或 S3 对象。BYO 基础设施绑定在这些存储之上提供同样的一致性,协调器只保存元数据(版本、每个 Agent 的 MESI、固定宽度的 content_hash、不透明的基础设施令牌)——绝不保存字节:
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-decide
相较于基础设施自身的条件写入(UPDATE … WHERE version=?、S3 If-Match),其价值在于:单纯的 CAS 会在写入时拒绝 A 的写入;而绑定会在 A 执行操作前告知它,缓存视图已过时。它使用与文件(CoherentVolume)或存储键(CCSStore)相同的类型化术语——在行、对象或文件之上提供统一的一致性界面。声明式的 Coherence Manifest 会将每个构件关联到一个基础设施和明确的保证等级;凭据以引用形式提供(secret-file: / aws-default,绝不用字面量),连接目标则受 SSRF 限制。
如实说明范围。 v1 提供两个 native-CAS 绑定(Postgres + S3),以及一个用于操作后端的 forward-only 等级(例如发布 Slack 帖子、发送 Gmail 邮件——仅保证决策输入的新鲜度,不提供 CAS)。其价值在于操作前失效通知 + 跨基础设施统一性;基础设施之上的读取代际栅栏是文档记录的路线图项目,目前不作此承诺——v1 的 OCC 写入方依赖仅在不存在时准入 + 版本 CAS。单主机且要求协作;当基础设施本身是分布式的(S3、托管 Postgres)时,不丢失更新的保证由基础设施自身提供,无论是否使用这一层都相同。运行方式:python -m examples.coherent_row.main / examples.coherent_object.main(离线、确定性、无需密钥——使用内存基础设施替代实现;生产环境可将同一绑定指向真实的 Postgres / S3)。完整 API、每个绑定的最小权限要求,以及如实说明的等级表:BYO substrate bindings。
工作区版本控制与恢复
以上功能会在 Agent 写入共享状态时保护它。工作区版本控制则解答事后问题:Agent 修改了跨后端分布的工作区——磁盘上的文件、S3 中的对象——尝试失败后,你希望将其恢复,并如实说明每个成员可以和不可以恢复的内容:
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 truth
检查点是一个具名清单,其中包含原生版本指针(S3 的 versionId、文件的协调器版本)和内容指纹——绝不另存一份字节数据——它以声明偏斜的切面形式捕获:记录捕获时间窗口,而非将其隐藏;窗口内发生变化的成员会被标记,而不会被静默撕裂。捕获时缺失的成员会记录为不存在,因此恢复操作也包含删除步骤。恢复会在终止契约下对每个成员执行一次条件写入,因此始终会结束并生成冻结的逐成员报告——restored(捕获的字节覆盖当前活动内容,报告会逐成员说明该写入丢弃了什么)、converged(当前活动状态已匹配)、conflict(实时的外部写入方胜出:有限次重试,不会活锁——该成员的实时状态得以保留)、target_lost(捕获的版本已消失——会报告,绝不替换)、held_unconfirmed 或 forward_only_skipped。
每个成员都有明确的恢复等级:restorable(版本化 S3,在你自己的存储桶中通过合法保留策略保护)、restorable-unpinned(目前存在历史版本,但可能过期),或 forward_only(已说明,但不可恢复——捕获时就会说明,而非等到恢复时才发现)。持久化的真实状态是 (restore_tier, pin_state) 这一对值:(restorable, unpinned) 会显示为已声明但尚未获得保障,绝不会显示为普通承诺。可通过 shell 编写脚本;退出代码 3 表示恢复已结束——请读取报告:
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 no absorbed outcome · 3 concluded with absorbed outcomes
谁可以恢复检查点,以及如何释放其固定保留。 检查点会记录由谁创建,但恢复时不会检查这一点:很多时候,让其他人来恢复正是预期行为。若要限制恢复权限,请在创建检查点时指定接收方——使用 wv.checkpoint(name, receiver=<their owner id>),或在 POST /workspace/checkpoint 中指定 receiver_session_id——其他控制器将收到拒绝结果 not_the_receiver。无论是否指定接收方,第一个注册恢复操作的控制器都会认领该检查点:之后其他控制器都会收到拒绝结果 already_registered,认领者自己的重试仍具有幂等性,而且认领永远不会释放。因此,如果该控制器停止运行,请继续使用它,或者创建一个新检查点(其中会捕获工作区当前状态)。注册还会根据检查点本身进行检查:不在检查点描述范围内的路径(not_a_checkpoint_member)或与捕获内容不同的字节(fingerprint_mismatch),都会在任何更改发生前被拒绝。在进程内,restore() 会在写入任何内容前检查接收方和认领状态,并抛出 CheckpointRegistrationRefused;CLI 则以 2 退出。wv.release_checkpoint(checkpoint_id) 会释放检查点持有的固定保留——但如果同一注册表中的其他检查点仍依赖某个 S3 固定保留,该保留会继续存在——并保留其清单。此操作不可逆,且仅支持 Python;每个 S3 成员都必须先通过最初创建其固定保留的绑定和密钥,在该版本管理器上重新声明。详情请参阅指南:谁可以恢复检查点和释放固定保留。
如实说明范围。 协调器仅运行于单台主机——检查点、固定保留和恢复进度都保存在本地协调器状态中,不对跨主机行为作任何保证。恢复作用于制品,而非效果:文件或对象可以恢复,已发送的消息则不能。文件成员仅用于检测(no-arbiter)——只有支持原生条件写入的后端才能仲裁与之竞争的外部写入;文件成员依赖协调器保留策略,该策略不提供逐版本固定保留,因此其层级始终为 restorable-unpinned,版本过期时会显示为 target_lost,而不会恢复为不同内容。恢复是携带旧字节的正向提交:版本严格递增,历史记录永不改写。恢复也不是合并:捕获后内容发生变化的成员会被覆盖,较新的内容将丢失,而且此流程不会拒绝该写入。你能获得的是相关记录——对每个成员,记录被丢弃的版本和摘要(只要执行该步骤时能够读取它们),以及用于在事后使此类运行以非零状态退出的 restore --exit-nonzero-on-discarded-content。退出码 0 表示没有成员以被吸收状态结束;它从不表示没有内容被覆盖。S3 成员通过 Python API 捕获和恢复,因为其绑定携带 CLI 无法获取的凭据。运行 python -m examples.workspace_versioning.main(离线、确定性运行,无需密钥),或添加 --baseline 先查看损失;运行 python -m examples.session_handoff.main 会将两个会话作为独立进程运行,并通过检查点和恢复交接工作,其中也包括在第一个会话仍在写入时出现的有界 conflict。完整的如实说明模型——层级、固定保留状态、保留策略注意事项和退出码约定:见指南 § 工作区版本管理与恢复。
状态
v0.15.0 已发布——定向交接写入权、调用方主体、HTTP 上的 effect fence,以及注明谁有权恢复的检查点。 会话现在可以将文件交给一个指定会话:在版本变更、接收方拒绝或交出方撤回之前,交出方对该文件的写入都会被拒绝,并返回 handed_off。Claude Code、CoherentVolume、MCP 服务(新增 4 个工具,总计 10 个工具)和 HTTP 均支持交接。Claude Code 钩子客户端、CoherentVolume、MCP 服务,以及 BYO 基底绑定背后的协调器会话,现在都会自动为自己的会话声明调用方主体;声明后,协调器会对未提供该主体、却在可更改其他写入方工作成果的路由上指定该会话的请求返回 HTTP 400。这能将遵循协议的客户端彼此区分开来,但并非安全边界。POST /hooks/effect-fence 会向任何 HTTP 客户端返回 effect fence 判定;新增的第八种暂缓原因 content_claim_absent,适用于协调器从未记录其内容的制品。现在,恢复注册会根据检查点的成员和已捕获的指纹进行校验;检查点可以指定唯一有权恢复它的控制器,且首个注册恢复操作的控制器会永久取得该权限;恢复操作会报告其覆盖的内容;WorkspaceVersioner.release_checkpoint 会释放检查点的固定项。运维人员可以通过 /status?detail=full 查看清理任务何时会回收每项写入授权、回收了哪些授权,以及最后写入各制品的是谁;现在所有 /status 视图都会报告 registry_schema_version。Claude Code 插件的 Node 协调器不提供任何新接口:它对交接、调用方主体和 effect fence 路由返回 404,对 /status?detail=full 返回 501,且其 /status 不包含 registry_schema_version。
从 0.14.1 升级。 注册表架构从 7 升至 10,且不支持降级迁移:此版本打开某工作区的 state.db 或工作区 CLI 的 workspace.db 后,0.14.1 将无法使用它们。部分响应和返回类型也会改变——例如,低于运维层级时,/status 会将 agent_name 报告为 null,而 write_cas() / write_cas_at() 会返回 CasCommitResult。请同时升级协调器、客户端和 Claude Code 插件,并搭配 0.6.0 或更高版本的插件使用。本指南的从 0.14.1 升级列出了不兼容变更。
完整版本历史请参阅 CHANGELOG.md,带标签的构建产物请参阅 releases。目前为 Alpha 版——v1.0 前 API 可能会变更。
论文
Token Coherence:调整 MESI 缓存协议,以最大限度降低多 Agent 大模型系统中的同步开销 arXiv:2603.15183
BibTeX
@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}
}
社区
欢迎在 Discussions 中提出问题、分享实战经验和交流想法。如果你在多 Agent 工作流中遇到过陈旧读取问题,请提交 issue——我很想听听你的经历。
许可证
Apache-2.0。请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。