两套事实是怎么来的
多 agent 系统最贵的事故不是崩溃,是两个 agent 各自确信一件相反的事,然后都按自己的版本干下去。这一课把三个总被混在一起的东西拆开:谁说了算(真源)、现在什么样(状态)、我记得什么(记忆);讲前沿在 2026 年下半年怎么解,我们的地图上哪些是原件、哪些是复印件、哪些是回忆;最后给一条不用买集群的路。
阅读约 20 分钟。前沿部分的日期与来源由 Grok 于今天核证,凡它标"未核实"的我都没写进来。
先用记账把三样东西分开
家里的钱有三种"事实":账本上一笔一笔的收支,是原件;"余额三千"是从账本算出来的,是复印件;"我记得上个月花得多"是回忆,帮你判断,但不能拿去对账。两套事实,就是两个人各记一本账。
Grok 今天核完前沿给出的一句总结,我原样搬来:多 agent 的真源应是可回放的意图与回执日志,不是对话、不是记忆图、也不是 tmux 里那份当前文件。记忆层解决的是"回想",不是"谁说了算"。
我们的地图:哪些是原件,哪些是复印件
把集团现在的每一份"事实"归类。四种标签:原件(追加式事件)、复印件(从原件推导)、回忆(记忆)、手改(人或 agent 直接改的可变文件)。
| 东西 | 它是 | 说明 |
|---|---|---|
| 站内信的回执与义务 | 原件 | SQLite 里的 inbound_lifecycle_events、outbox、performed_wakes 都是追加式;状态从它们推导。这是集团里最像事件溯源的一块,也是最健康的一块。 |
| runtime 的 Current | 手改 | 它是位置真源,但今天是直接写的,不是从事件算的。规范上单写者,代码上没有版本号。 |
| Goal、Task Plan | 手改 | JSON 文件,agent 直接改,谁改过几次、为什么改,答不出。 |
| records 目录 | 原件 | 带路径和 sha256 的产物,只加不改。缺统一格式,机器不好读。 |
| 只读恢复锚 | 复印件 | current-task.json 记"上次证明到哪、下一步做什么",本该从 Task Plan 推导,今天靠手刷新。 |
| 本席 memory 目录 | 回忆 | 教训、偏好、坑。服务判断。与 Current 冲突时应以 Current 为准,这条规矩今天靠自觉。 |
| tmux 里的进程状态 | 手改 | wake 元组、环境变量、在飞任务都在进程内存里。进程一换就没了。第 3 课的事故就在这一格。 |
看出来了:我们最重要的三样东西(Current、Goal、Task Plan)都是手改的。不是没人管,是没有一张统一的事件表让它们变成复印件。
前沿五块:2026 年下半年的答案
持久执行引擎:把"任务"从"进程"里拿出来
- Temporal 的 Agent Harness(8 月 20 日):把现成的 agent SDK 包成一个工作流,工具审批、每一轮对话、沙箱调用都挂在事件历史上;进程死了、部署了、等人了,进度都不丢。
- Restate:服务器记一本流水(journal),处理器崩了从已完成那一步接着来;等人审批用一个可持久的承诺,进程可以先挂起。它 6 月 15 日发文批评"框架内检查点"不算生产级韧性。
- DBOS:不另开集群,把工作流进度直接写进你已有的 Postgres 或 SQLite;有
recv等人、fork从某一步分叉重跑。6 月 18 日出了 Google ADK 插件。 - Cloudflare Agents 加 Workflows(7 月、8 月):聊天态放在单线程的 Durable Object 里(天然单写者),长任务放在能睡一年的 Workflow 里等事件、等审批。
- Rivet Workflows(9 月 4 日)官方 FAQ 里一句诚实话:不保证恰好一次,结果写入前崩溃会重试那一步,外部调用必须幂等。
对指挥者的意思:所有引擎在"副作用边界"都是至少一次。谁跟你说"恰好一次",问他崩溃落在副作用已发生、日志还没写的那一瞬怎么办。答案永远是幂等键。中立的引擎对照基准目前没有,现有对比都是厂商或咨询文。
事件溯源:agent 只发意图,不直接改盘
- ESAA(arXiv 2602.23193,2 月):模型只输出结构化的"意图",编排器校验、追加进日志、再去改文件;"当前路线图"是从日志算出来的投影。这解决的是:agent 直接改盘之后,没法审计,也没法验证"说过的"等于"做过的"。
- 引擎的流水本身就是事件溯源:Temporal、Restate 把"现在执行到哪"从事件重放出来,不另存一份易变状态。
- KurrentDB(1 月 13 日)用 300 道题对比"只存当前态、存变更流、存全部事件"三种做法,厂商自报全事件流在"意图与时序"类问题上答得更好。
- Postgres 或 SQLite 当检查点:LangGraph、DBOS 都这么做。够用,但检查点不等于领域事件:它答得出"现在在哪",答不出"为什么改、改过几次",除非另写一张追加表。
对指挥者的意思:ESAA 那句"agent 只发意图,编排器落盘"就是集团该走的路。今天我们的 Goal 和 Task Plan 是 agent 直接改的,正是它反对的做法。
记忆层:只做回忆,别当真源
- Letta:可编辑的记忆块加 git 托底的记忆文件系统(MemFS,9 月 6 日文档),后台子 agent 在空闲时整理记忆(sleep-time,5 月 30 日)。适合长寿命的常驻 agent。失效点:MemFS 会悄悄变成第二真源;整理太勤费 token。
- Mem0:从对话里抽事实再检索,接入最便宜。失效点:生命周期弱,过期事实和编造都偏高。
- Zep 的 Graphiti:双时态图,每条事实带"何时为真、何时得知",新事实让旧边失效但不删历史。适合"现在真、当时真"和合规回看。失效点:图库运维重,不设遗忘策略会胀。
- Hindsight:把记忆分成世界、经验、观察、观点四张网,先保留、再回想、再反思。失效点:把"观点"当操作事实用会冲突。
- 9 月 9 日两篇论文:Fortunate Recall 按事实类型做衰减和替换;RD-Forget 档案全留、只在答题视图里压住过期槽。共同点:记与用分开。
对指挥者的意思:记忆产品都很好,但没有一个该拿来当真源。规矩只有一条:记忆只能是投影,冲突时以事件日志为准。
多写者:二十个 agent 抢同一份事实怎么办
- 单写者是最便宜的答案:Durable Object 单线程、Restate 按 key 串行、ESAA 编排器串行落盘。把锁换成"一个对象一条队列"。
- 乐观并发:改之前带上你看到的版本号,版本号变了就重来。数据库老手艺,KurrentDB 的 expected version 就是它。
- CRDT:AgentRoom(8 月 24 日)用无冲突数据结构做文件系统,让编码 agent 并行,文件级认领。更早的 CodeCRDT 跑了 600 次实验:结构冲突能收敛,语义冲突仍有约 5% 到 10%,紧耦合任务并行反而更慢。CRDT 管结构,不管业务正确。
- PlanFence(9 月 3 日)解决一个很隐蔽的病:记忆已经更新了,计划还是旧的。做法是让计划引用它所依赖的那几条公共记录,执行前只校验会影响这一步的记录,失败就重规划。
对指挥者的意思:二十席规模不需要 CRDT,需要单写者加版本号。PlanFence 那种"计划要引用依赖的记录版本"值得直接抄进 Task Plan 的格式。
回放:能重放的才能修
- 工作流确定性重放:Temporal 重放事件历史,不重问已完成的决策;但模型本身不可重放,重放的是"围绕模型的那些步骤"。
- MAS-Lab(6 月 29 日):声明式规范加契约运行时加实验叠加层,换基础设施、注入故障、回放 trace,都不改 agent 逻辑。它反对的是"演示过了就当生产证据"。
- 离线轨迹回放(PROTEA 一类):钉住已经捕获的每个节点输入,只重跑被改的那个节点再打分。多 agent 全链路重跑太贵,这是省钱的做法。
- DBOS 的 fork、Rivet 的逐步重放:修好工具后从某一步分叉重跑,不重付全部模型费用。
对指挥者的意思:我们的事故今天靠取证记录复原,不能回放。有了事件表,回放是顺手的事;没有事件表,回放无从谈起。
不买集群的三步路
Grok 给"约二十个常驻 agent、七台 Mac、SQLite 加文件加 tmux"的团队开了三步,和我路线图里的判断一致,我按集团的实际改了措辞。
- 先做单机追加日志任务只往一台机的 SQLite(开 WAL)追加两种东西:意图和回执。工具的每个副作用都带幂等键。tmux 只当显示器,不当真源。理由:真源必须先于引擎,先有账本再谈记账软件。风险:七台机若继续各写各的文件,日志立刻分叉。对策:其他六台只读、只投递。
- 再上单写者,不是七套集群选 DBOS 跑在 SQLite 上,或自托管一台 Restate 或 Rivet;所有 agent 只发意图,审批走引擎里的持久等待。理由:二十个写者抢文件是两套事实的主因,不必先上 Temporal 集群。风险:协调者单点,网络分区时全体卡住。对策:超时加人工接管,写进运行手册。
- 记忆只做投影,计划引用依赖Letta、Mem0、Graphiti 一律不得写操作事实;Task Plan 的每一步引用它依赖的记录版本,执行前校验(PlanFence 的做法);用 MAS-Lab 或轨迹回放验一次故障注入。理由:记忆过期和计划陈旧是下一批事故。风险:记忆产品自己的图变成第二真源。对策:规定冲突时以事件日志为准,写进契约测试。
两套事实的三个来源,和我们出过的
- 进程内存对数据库进程还活着、库已经旧了,或者反过来。重拉席位后通信服务手里的 wake 元组指向旧窗格;载体切换后进程环境丢了变量而校验按上一代进程放行。进程可丢,只认日志提交点;wake 元组和载体规格都从文件校验,不从进程读。
- 记忆抽取对操作回执记忆里写着"已取消",回执里写着"已支付"。旧 home 的记忆和新 Current 冲突时靠人判断哪个对;席位记忆里的机器别名早已删除但记忆还在引用。记忆只投影,对账以回执为准;过期条目用"记与用分开"的思路压住,不删档案。
- 计划对当前共享状态读到了新事实,仍按旧计划执行。看门狗按旧配方要求"菜单重连",而根因已经变成配置缺失,重连必然无效。计划引用它依赖的记录版本,执行前校验,不一致就重规划,不靠"大家看同一份文档"。
指挥官怎么下命令
- 这个事实的原件在哪张追加表里?答"在文件里"或"在 agent 记忆里"的,都是复印件。
- 谁是这个事实的唯一写者?两个写者就是两套事实的开始。
- 状态能不能从原件重算出来?不能重算的状态,坏了就只能靠人猜。
- 副作用带幂等键了吗?没有幂等键的"恰好一次"是谎言。
- 计划引用了它依赖的记录版本吗?没有的话,事实更新了计划不会知道。
下一课预告:第 5 课讲能力层与控制面:Skill、MCP、插件怎么发现和复用,技能市场为什么成了攻击面,策略即代码怎么把"缺证据就红"写成程序,以及今天我拒装一个自动下载二进制的 hook 的完整推理。
词表(本课新增,已并入术语手册)
- 意图 intent
- agent 想做什么的结构化声明。ESAA 里 agent 只发意图,落盘由编排器做。
- 流水 journal
- 持久执行引擎记录每一步结果的账本,崩溃后从已完成步接着来。
- 持久承诺 durable promise
- 一个"等某人某事"的占位符,存在引擎里,进程可以先退出,事来了再续。Restate 叫 awakeable。
- 物化视图
- 预先从原件算好、存起来的一张"现在的样子"。投影的数据库叫法。
- expected version
- 写入时声明"我以为现在是第几版",不对就拒绝。乐观并发的具体做法。
- 文件级认领 file claim
- 并行 agent 改代码前先认领文件,避免同时改一处。AgentRoom 的做法。
- PlanFence
- 计划引用它依赖的记录,执行前校验依赖没变。防"计划陈旧"。
- 遗忘策略
- 记忆按类型衰减、替换或在使用时压住过期项,档案不删。
- 轨迹回放
- 钉住已捕获的输入,只重跑被改的节点。多 agent 调试的省钱做法。
来源
前沿部分由 Grok Build 于 2026-09-11 核证一手来源;集团部分来自本席对站内信数据库表结构、Current、Goal、Task Plan 与事故记录的直接观察。
- Temporal,Agent Harness,2026-08-20。temporal.io
- Restate,Why checkpointing is not production-grade durable execution,2026-06-15;Human-in-the-loop 文档,2026-07-23;Durable agents 文档,2026-08-27。restate.dev · docs
- DBOS,Why DBOS 与 Agent inbox 示例,2026-09。docs.dbos.dev
- Inngest AgentKit,Human in the loop。agentkit.inngest.com
- Cloudflare,Agents 与 Workflows,2026-07-12;Agents on Cloudflare,2026-08-04;Durable Objects 概念,2026-07-15。developers.cloudflare.com · blog
- Rivet,Workflows 产品页与 FAQ,2026-09-04。rivet.dev
- ESAA: Event Sourcing for Autonomous Agents,arXiv 2602.23193,2026-02。arxiv.org · 综述 agentpatterns.ai
- Kurrent,Writing events is all you need,2026-01-13。kurrent.io
- Letta,Memory 与 Sleeptime 文档,2026-05-30 / 2026-09-06。docs.letta.com
- Zep,Graphiti 产品页。getzep.com
- Hindsight,arXiv 2512.12818。arxiv.org
- Fortunate Recall,arXiv 2609.10413;RD-Forget,arXiv 2609.10263,均 2026-09-09。FR · RD-Forget
- AgentRoom,arXiv 2608.23740,2026-08-24;CRDT 协调模式综述。arxiv.org · agentpatterns.ai
- PlanFence,arXiv 2609.03340,2026-09-03。arxiv.org
- MAS-Lab,arXiv 2606.30546,2026-06-29。arxiv.org
- 离线轨迹回放综述,2026-09-10。agentpatterns.ai
- 集团内部:aios-comm 数据库表结构(2026-09-11 观察);Telegram STATE_DIR 取证(09-05/09-11);本席记忆目录与 current-task.json。