共享记忆与黑板模式 本节摘要:2026 多智能体系统里两种共享状态共存——消息池(所有人看到所有消息,如 AutoGen GroupChat/MetaGPT)与带订阅的黑板(Agent 订阅相关事件,如 CA-MCP/Matrix)。两者都是系统里唯一有状态的部分——所以两者都是有趣 bug 的住所。参考失败模式是记忆投毒(memory poisoning):一个 Agent 幻觉出一个「事实」,其他 Agent 当它已验证,准确率缓慢衰减,比立即崩溃难调试得多。本节用标准库搭出两种结构,注入一次投毒攻击,展示生产里真正有效的三条缓解:每次写附溯源、版本化追加写、保留至少一个不可写的验证者。我们还会回溯 Hayes-Roth 1985 的黑板先例,以及写竞争的三种模式。
本节摘要:2026 多智能体系统里两种共享状态共存——消息池(所有人看到所有消息,如 AutoGen GroupChat/MetaGPT)与带订阅的黑板(Agent 订阅相关事件,如 CA-MCP/Matrix)。两者都是系统里唯一有状态的部分——所以两者都是有趣 bug 的住所。参考失败模式是记忆投毒(memory poisoning):一个 Agent 幻觉出一个「事实」,其他 Agent 当它已验证,准确率缓慢衰减,比立即崩溃难调试得多。本节用标准库搭出两种结构,注入一次投毒攻击,展示生产里真正有效的三条缓解:每次写附溯源、版本化追加写、保留至少一个不可写的验证者。我们还会回溯 Hayes-Roth 1985 的黑板先例,以及写竞争的三种模式。读完本节,你能审计任何多智能体系统的共享记忆设计,在它投毒前堵住。
阅读完本节,你应当能够:
多智能体系统需要一处地方让 Agent 共享事实。字面的选项是「全用消息传」——但那是在重新发明共享状态还多了拷贝。另一个是「给所有人一份全局日志」——但全局日志无限增长且易被投毒。第三个是「每 Agent 投影视图」——可扩展但 schema 重。
当一个 Agent 幻觉并把幻觉写进共享状态,每个读该状态的下游 Agent 都把幻觉采纳为事实。等人类察觉时,推理链已深五层,根因是史上第三条消息。调试多智能体准确率衰减比调试崩溃难得多。
这就是记忆投毒。它是 MAST 分类(Cemri 等,arXiv:2503.13657)里第二多被记录的失败家族,且是结构性的:任何没有溯源、没有不可写验证者的共享记忆设计,最终都会出现它。
生产系统常混用:顶层小全量池(规划层),下层黑板(工人层)。
三 Agent 做研究:Agent A 检索,B 摘要,C 分析。
没有 Agent 崩溃,没有测试失败,系统「成功了」。幻觉从一个 Agent 的上下文,经共享状态,洗白进了每个下游 Agent 的推理。
⚠️ 这正是「协调难点在状态」的集中爆发——共享状态让一个 Agent 的幻觉变成所有人的事实。问题不在共享状态本身,而在没有溯源、没有独立验证者的共享状态。
无共享状态时,A 的幻觉留在 A 的上下文;下游会重新取数或重新推导,可能抓到错。天真的共享状态把 A 的上下文变成所有人的上下文,幻觉被洗白成事实。三条缓解:
黑板模式比 LLM Agent 早四十年。Hayes-Roth(1985, A Blackboard Architecture for Control)描述了专精的 Knowledge Source 观察全局黑板、贡献部分解、触发其他源。2026 的黑板(CA-MCP、Matrix)是同一模式,LLM Agent 当 Knowledge Source、JSON blob 当部分解。老文献里有写竞争、机会式控制、一致性的成文解法,现代系统在重新发现。
纯黑板给每个订阅者相同的投影(主题作用域)。更激进的是按 Agent 投影:每个 Agent 拿到按角色定制的视图。LangGraph 的 state reducer 是 2026 的典范实现——reducer 函数把全局状态折叠成角色专属切片。按 Agent 投影扩展更远但需要 schema;没有就在每个 Agent 提示里重建 ad-hoc 投影。
多 Agent 同时写是并发问题,不只是 LLM 问题。三种模式:
多数 2026 框架默认串行写者,因 LLM 调用够慢、竞争罕见、瓶颈不痛。
最承重的缓解是只读验证者。实现规则:
没有这种分离,验证者输出就成了池里的新条目——被投毒的池会投毒验证者,投毒其验证。
code/main.py 用标准库实现两种拓扑,加一个投毒攻击与三条缓解。
import threading class MessagePool: def __init__(self): self._lock = threading.Lock(); self.entries = [] def write(self, writer, content, provenance): with self._lock: self.entries.append({"writer": writer, "content": content, "ts": time.time(), **provenance, "superseded_by": None}) def view(self): return [e for e in self.entries if not e["superseded_by"]] class Blackboard: def __init__(self): self.topics = {}; self.subs = {} def subscribe(self, agent, topic): self.subs.setdefault(topic, []).append(agent) def publish(self, topic, entry): for agent in self.subs.get(topic, []): agent.receive(topic, entry)
def scenario_without_verifier(): pool = MessagePool() pool.write("retriever", "准确率提升 42%", {"source_uri": "page-X"}) # retriever 幻觉了;真实是 4.2% summarizer.write_summary(pool) # 「42% 大增」 analyst.write_rec(pool) # 「建议采纳,42% 变革性」 return final_report(pool) # 引用 42%,从未存在 def scenario_with_verifier(): pool = MessagePool() verifier = ReadOnlyVerifier(pool) # 读池,只写独立 channel verifier.re_fetch_all_sources() # 重取 page-X,发现真实 4.2% verifier.flag("retriever 条目与来源不符") # 池被标 flagged,最终报告含订正
设计要点:验证者的「只读 + 独立输出通道」是它不被投毒的关键——若它能写池,被投毒的池就投毒了它,进而投毒其验证。这条隔离边界是整个缓解的承重墙。
| 拓扑/机制 | 代表 | 共享状态 | 写竞争 | 验证者 |
|---|---|---|---|---|
| 全量消息池 | AutoGen GroupChat、MetaGPT | 全局日志 | 默认串行 | 调用者自加 |
| 带订阅黑板 | CA-MCP、Matrix | 主题 pub/sub | 主题分区 | 调用者自加 |
| 按 Agent 投影 | LangGraph reducer | 角色专属切片 | reducer 函数序列化 | 独立节点 |
| Hayes-Roth 经典黑板 | Hearsay-II | 全局黑板 | 机会式控制 | KS 互验 |
💡 心法:框架提供拓扑,但溯源/版本化/不可写验证者要你自己加。 不加这三条,任何框架都会被记忆投毒咬到——这是结构性问题,不是框架缺陷。
outputs/skill-memory-auditor.md:审计任何多智能体系统的共享记忆设计——查溯源、版本化、验证者分离。在进生产前对新架构跑一遍。
code/main.py,确认 run1 传播幻觉、run2 抓住它。下一节,我们进入分布式系统最经典的协调难题——共识与拜占庭容错,看当 Agent 可能出错甚至撒谎时,多智能体如何达成一致。