一个多 Agent 工作环境运行久了,常会出现一种很隐蔽的分叉:每个 Agent 都有自己的长期记忆,里面保存着模型、通道、服务和工具状态。它们写入时都是真的,但环境改变后,只有执行变更的那一个知道新状态。
于是同一时刻可能出现几份互相冲突的“事实”:
- 一个 Agent 认为某个通道仍然开启;
- 另一个记得它已经停用;
- 第三个根据配置残留判断它仍可使用;
- 实际服务早已走了另一条链路。
这不是简单的记忆质量问题。持续变化的运行状态,本来就不应该由多个独立记忆副本承载。
🧠 记忆回答“我学到了什么”,状态回答“现在是什么”
Agent 的长期记忆适合保存稳定知识:用户偏好、协作规则、踩坑经验、项目背景。它的目标是跨会话延续认知。
环境状态则不同:
- 当前模型链是什么;
- 某个通道是否开启;
- 某项服务是否存活;
- 某份凭据由谁使用;
- 某个工具是否已经卸载。
这些事实会频繁变化,并且需要被多个 Agent 同时消费。把它们复制进每份记忆,等于手工维护多个缓存,却没有失效机制。
真正的问题不是“哪份记忆写错了”,而是系统缺少唯一权威来源。
📚 共享账本不能只是另一份文档
最容易想到的修复,是建一份公共 Markdown,要求所有 Agent 开工前阅读。但如果它只能由人手动更新,它很快也会变成新的过期副本。
一个可用的共享事实层至少需要四样东西:
- 唯一标识:每条事实有稳定 ID,而不是散落在自然语言段落里。
- 登记值与验证条件:既写“应该是什么”,也写“怎样证明它仍然如此”。
- 状态分级:已验证、过期待复测、验证失败、人工确认、明确搁置要能区分。
- 变更闭环:修改环境后,必须同步登记、重新验证并留下变更记录。
例如,“服务正在运行”不能只是一句文字。它还应该绑定一个最小探针:端口监听、进程状态、一次真实请求,或者更接近业务目标的端到端验收。
共享层的价值不在于集中保存更多文字,而在于把“事实”变成可验证的契约。
🔗 私有记忆只存指针,不存易变值
接入共享事实层后,Agent 的私有记忆仍然有用,但边界要改变。
不再写:
消息通道 X 已开启,模型链是 A → B → C。
而是写:
消息通道状态见共享事实 channel.agent.x。
模型链状态见共享事实 model.agent.chain。
这样做看似少记了一些,实际上减少了最危险的一类信息:看起来具体、读起来可信、但已经失效的旧值。
开工时同步一次公共层;准备依赖某项能力时,查看对应事实;如果状态过期或异常,先实测再使用。私有记忆负责告诉 Agent“去哪里查”,共享层负责回答“现在是什么”。
🧪 探针结果必须高于登记值
即使有统一账本,也不能把登记值当成现实本身。配置可能被其他程序改写,服务可能崩溃,账号权限也可能在外部发生变化。
因此需要明确优先级:
当前实测 > 共享账本登记值 > 私有记忆 > 对话中的旧说法
如果实测与登记值冲突,只有两种处理:
- 环境被改了但账本没更新:修正账本;
- 环境坏了:修复环境,再重新验证。
不能为了让探针变绿而降低验证标准,也不能因为文档写着“正常”就忽略失败的真实调用。
对无法自动验证的事实,也要明确标为人工声明,而不是伪装成机器已确认。对已经决定搁置的事项,则应该禁止 Agent 反复重测,避免浪费资源和重新引入风险。
🧱 方法、状态和秘密还要继续分层
共享并不意味着把所有东西都塞进同一份账本。
- 方法进入 skill:描述如何诊断、如何操作、如何验收。
- 状态进入事实层:描述当前启用什么、谁在使用、最近何时验证。
- 秘密留在凭据系统:事实层只保存引用位置和不可逆指纹,不保存明文。
- 项目进度留在项目状态文档:事实层只记录跨项目、跨 Agent 都需要依赖的环境事实。
这个分层能避免另一种常见污染:把实时持仓、运行数据或账号状态写进“可复用方法”,导致 skill 每次分发都产生冲突;或者把秘密为了共享方便写进公共文档。
✅ 结论
多 Agent 系统里的记忆同步,不该靠所有参与者反复复制同一批运行状态。复制得越多,失效点越多。
更可靠的结构是:稳定经验进入记忆和 skill,易变事实进入可验证的共享账本,私有记忆只保存指针,真实探针永远高于文档。
当每个 Agent 都知道从哪里取得当前事实、怎样验证它、变更后怎样回写,协作才不再依赖“谁最后记得更新自己的那一份”。
马启航Marvis