我让 Agent 的记忆系统“抄袭”了 CPU,结果它再也不失忆了
前两篇聊了 Agent 怎么编排调度(SA/PA/DA/CA/AA),以及为什么用 5W2H 和 PDCA 做认知框架。
今天进入一个更硬核的话题:记忆系统。
你有没有遇到过这种事:跟 AI 聊了 50 轮,它突然忘了第 3 轮说过什么?或者你让它分析一个复杂项目,结果它把两周前的需求忘得一干二净?
这不是 AI 笨,是它的记忆系统没设计好。今天聊聊我是怎么用 CPU 缓存架构的思路,给 Agent 打造了一套“永远不失忆”的记忆系统。
一、人脑是怎么记住东西的?
先来点脑科学。
人脑的记忆分好几种:
- 瞬时记忆:几秒钟,比如刚才那句话
- 短期记忆:几分钟到几小时,比如今天早饭吃了什么
- 长期记忆:几天到几十年,比如你的名字、你第一次写代码的经历
更重要的是,人脑有个海马体,专门负责把重要的短期记忆“巩固”成长久记忆。你睡觉的时候,海马体就在后台默默搬运。
AI Agent 的记忆系统完全可以照着这个模式设计。我把它分成了四层:
这套四层架构的灵感来自 CPU 的缓存体系:
- L1 Cache:极快极小,放 CPU 正在用的数据 →L1 上下文窗口,放 LLM 正在用的摘要
- L2 Cache:稍大稍慢,放近期热点数据 →L2 黑板,放当前任务的活跃数据
- L3 Cache:更大更慢,多核共享 →L3 投影引擎,按需从知识库调取
- 内存/磁盘:巨大但慢,存所有数据 →L0 持久图,永久保存一切
核心理念:越常用的数据,离 LLM 越近;越不常用的,甩得越远。
二、L1:给 LLM 上下文“截肢式减肥”
传统 Agent 是怎么处理上下文的?把每轮对话的完整内容全塞进去。聊了 50 轮,上下文里就塞满 50 轮完整对话。
Token 费用飞涨不说,LLM 还容易“迷失”——上下文太长,它就忘了哪些是重点。
我的做法:让 LLM 在回答时,除了给正式回复,还必须给我一个 Summary(摘要)。
每次 LLM 响应后,系统强制要求它输出三样东西:
{"thought":"详细推理过程……(存进 L0 图数据库,不占上下文)","content":"正式回答……(也存进 L0)","summary":"我们决定用 JWT 做认证,有效期 24 小时,用 256 位密钥"}关键操作来了:
thought和content→完整存进 L0 持久图,并分配唯一 IRI(比如memory:session-042/block-017)summary→追加到 L1 上下文窗口
效果:聊了 50 轮,上下文里只有 50 条摘要(每条十几个 Token),而完整的 50 轮对话细节全在 L0 图数据库里。
某天 LLM 突然想:“我们第三轮时那个 JWT 密钥长度是多少来着?”
它不需要在上下文里翻——直接用内置工具,沿着 IRI 查 Oxigraph:
SELECT ?content WHERE { <memory:session-042/block-003> mem:content ?content . }图数据库瞬间返回那轮的完整记录。
这就是 JSON-LD 作为“数据地址总线”和 Oxigraph 作为“高速查询引擎”结合后的威力:Token 消耗从 O(n) 变成 O(1),而记忆永不丢失。
三、L2 黑板:多 Agent 共享的“工作记忆”
单个 Agent 好办,但我的系统里 SA、PA、DA、CA、AA 五个角色要一起工作。
它们怎么共享信息?不能靠互相传话——那会乱套。
L2 是一个 Oxigraph 内存图数据库,所有 Agent 都能直接读写。
比如:
- DA 完成任务后,往 L2 写:
task:auth-refactor status "completed",同时附上产物的 IRI - CA 直接从 L2 读:
task:auth-refactor status "completed",然后去检查产物 - PA 能看到 L2 里所有节点的状态,随时调整计划
更骚的是,我给 L2 加了 MESI 协议(对,就是 CPU 缓存一致性那个):
- Agent A 修改了一个节点 → 状态标记为M(Modified,已修改)
- 系统自动通知其他 Agent:“这个数据过期了,赶紧重读”
- 其他 Agent 的缓存状态标记为I(Invalid,失效),下次访问时必须重新从 L2 或 L0 加载
这套机制保证了多 Agent 协作时绝不会出现“A 说做完了,B 说没做”的冲突。代价是四个状态位,收益是全局一致性。
四、L3 投影引擎:按需加载的“记忆提取器”
L0 存了所有历史数据,但 LLM 不需要一次性全看到。
L3 就是记忆的“检索系统”。当 Agent 说“我要查那个 JWT 的 Skill 定义”,L3 就自动从 L0 把相关子图提取出来,加载到 L2。
用 SQL 类比:
- L0 是完整的数据库
- L3 是查询优化器 + 结果集缓存
- L2 是应用层的工作内存
如果 L2 满了怎么办?L3 会根据 LRU(最近最少使用)自动淘汰不活跃的数据,丢回 L0。下次再需要时,重新加载。
Agent 完全感觉不到这个过程——它以为自己在操作无限大的工作记忆,实际上是 L3 在背后疯狂换页。
五、Skills 也是记忆:统一数据模型的威力
好多人问:Skills 不是工具吗,跟记忆有什么关系?
在我的系统里,Skills 也是记忆。它们和对话记忆、任务元数据、审计日志一样——全是 L0 图里的 JSON-LD 节点。
举个例子,一个 Skill 定义长这样:
{"@id":"skill:rust-jwt-auth","@type":"skill:AtomicSkill","skill:what":"Rust JWT 认证实现","skill:inputSchema":{...},"skill:links":[{"@type":"skill:PrerequisiteLink","skill:target":"skill:rust-basics"}],"wds:signature":{"wds:algorithm":"Ed25519","wds:value":"base64签名..."}}这带来的好处是碾压级的:
第一,Skills 之间能“互相发现”。因为都存成图节点,Skill A 能通过 SPARQL 查询发现 Skill B 是它的前置依赖,Skill C 是它的替代方案。就像网页之间有超链接一样。
第二,系统能自动转换普通 Skill。如果你手头有一堆 Markdown 写的 Skill,系统能自动解析并生成 JSON-LD 节点,兼容零成本。
第三,Agent 调用 Skill 时,Harness 会先校验 JSON Schema + 数字签名。Schema 校验确保参数类型正确、必填项不缺;签名验证确保 Skill 定义没被篡改。Markdown 做不到这种硬拦截。
第四,Skills、Agent 间通信、记忆系统,全部是同一套 JSON-LD 数据模型。这意味着任何组件都能用 SPARQL 查询任何数据——不管是历史对话、任务状态,还是 Skill 定义。统一的“数据地址总线”让整个系统变成了一个有机的整体,而不是一堆格式各异的散件。
六、L3 投影 + JSON-LD Framing:按需裁剪上下文
SA 在给下游 Agent 注入上下文时,不是一股脑把所有 Skill 定义全扔过去——那太浪费 Token。
L3 投影引擎能精确控制每个 Agent 看到的数据粒度:
- SA 做任务分析时:只需要 Skill 的
@id、skill:what、skill:triggerCondition,大概 200 Token - PA 做计划时:需要 Skill 的步骤概览,大概 500 Token
- DA 要执行某个步骤时:才需要那个步骤的完整代码和参数 Schema,大概 1500 Token
同一份底层数据,不同 Agent 看到不同的“分辨率”。这是 JSON-LD Framing 和图数据库结合后最骚的操作,Markdown 绝对做不到。
七、总结:记忆系统的三个核心收益
- Token 消耗从 O(n) 变成 O(1):多轮对话只记摘要,细节按需查图,Token 不再随历史膨胀
- 多 Agent 协作不出乱子:MESI 协议保证 L2 黑板的一致性
- Skills 从“文件”变成“知识网络”:可发现、可校验、可追溯、可安全调用
这套记忆系统的本质,是把 Agent 的记忆管理从“草稿纸”升级成了“企业级数据库”——而且是用 CPU 缓存架构的思路设计的,天生就是高并发、低延迟、海量容量的。
八、预告
下一篇聊 SA 调度器的核心能力:四个感知器官(态势感知、健康监控、模式识别、冲突检测)是怎么工作的。SA 不仅能调度 Agent,还能“看见”系统状态,做出智能决策。
我这套系统叫Gliding Horse(流马),所有代码都在 GitHub 上:https://github.com/doiito/gliding_horse
设计细节系列持续更新中。前面聊了编排调度和认知框架,这篇聊了记忆系统,下一篇聊 SA 的感知器官。想看什么在 Issue 里说,我优先安排。