Agent 记忆——虚拟上下文与记忆分页
上下文窗口是有限的。对话、文档和工具轨迹不是。解决办法是重新采用操作系统的虚拟内存思想:主上下文是内存,外部存储是磁盘,agent 在两者之间换页。MemGPT(Packer 等人,2023)为这个模式命名,许多生产记忆系统都建立在它之上。
类型: Build 语言: Python(标准库) 前置要求: 阶段 14 · 01(Agent 循环)、阶段 14 · 06(工具使用) 预计时间: ~75 分钟
学习目标
- 解释 MemGPT 立足的 OS 类比:主上下文 = 内存,外部上下文 = 磁盘,记忆工具 = 换入/换出。
- 用标准库实现 MemGPT 的两级模式,含一个主上下文缓冲区、一个可搜索的外部存储和换入/换出工具。
- 描述 agent 如何发出「中断」来查询或修改外部记忆,以及结果如何拼回下一个 prompt。
- 认清那些延续到 Letta(第 08 课)和 Mem0(第 09 课)的 MemGPT 设计选择。
问题背景
上下文窗口看起来像是该能解决记忆问题。但它没有。生产中反复出现三种失败模式:
- 溢出。 多轮对话、长文档或工具调用密集的轨迹越过了窗口。截断点之外的一切都没了。
- 稀释。 哪怕在窗口内,塞进无关上下文也会稀释模型对真正重要内容的注意力。前沿模型在长输入上仍会退化。
- 持久化。 新会话从一个空窗口开始。没有外部记忆的 agent 没法跨会话说「记得你之前让我……吗」。
更大的窗口有帮助,但解决不了这个问题。Mem0 的 2025 年论文测出,128k 窗口的基线仍会漏掉一些长跨度事实,而一个 4k 窗口配外部记忆的 agent 能抓到。
核心概念
OS 类比
MemGPT(Packer 等人,arXiv:2310.08560,v2,2024 年 2 月)把上下文管理映射到操作系统的虚拟内存:
| OS 概念 | MemGPT 概念 | 2026 生产对应物 |
|---|---|---|
| 内存 | 主上下文(prompt) | Anthropic/OpenAI 上下文窗口 |
| 磁盘 | 外部上下文 | 向量数据库、KV、图存储 |
| 缺页 | 记忆工具调用 | memory.search、memory.read、memory.write |
| OS 内核 | agent 控制循环 | 带记忆工具的 ReAct 循环 |
agent 跑一个普通的 ReAct 循环。多出来的一类工具让它把数据换入换出主上下文。
两级
- 主上下文。 固定大小的 prompt,装着当前任务。对模型始终可见。
- 外部上下文。 无界,通过工具可搜索。相关时读取,事实浮现时写入。
原论文在两个超出基础窗口的任务上评估了这个设计:长于 100k token 的文档分析,以及跨多天保持持久记忆的多会话聊天。
中断模式
MemGPT 引入了「记忆即中断」:对话中途 agent 可以调用一个记忆工具,运行时执行它,结果作为一个新观察拼进下一个助手轮。概念上等同于一次 Unix read() 系统调用 —— 它阻塞进程、返回字节,然后进程继续。
标准的记忆工具接触面:
core_memory_append(section, text)—— 写入 prompt 的某个持久 section。core_memory_replace(section, old, new)—— 编辑某个持久 section。archival_memory_insert(text)—— 写入可搜索的外部存储。archival_memory_search(query, top_k)—— 从外部存储检索。conversation_search(query)—— 扫描过往轮次。
论文到哪儿结束、生产实现从哪儿开始
2024 年 9 月 MemGPT 变成了 Letta。研究仓库(cpacker/MemGPT)还在;Letta 扩展了这个设计:
- 三级而非两级(core、recall、archival —— 第 08 课)。
- 用原生推理取代
send_message/heartbeat 模式(第 08 课)。 - 跑异步记忆工作的 sleep-time agent(第 08 课)。
即便生产系统跑的是 Letta、Mem0 或一个自定义两级存储,MemGPT 论文仍是 2026 年的基石。
这个模式在哪里会出错
- 记忆腐烂。 写入攒得比读取快;检索淹没在过时事实里。修法:周期性整合(Letta sleep-time)、显式失效(Mem0 冲突检测器)。
- 记忆投毒。 外部记忆是被检索回来的文本。如果攻击者控制的内容落进了一条记忆笔记,agent 下个会话会再次摄入它。这就是 Greshake 等人(第 27 课)的攻击在时间维度上的重述。
- 引用丢失。 agent 回忆起「用户让我交付 X」,但说不出是哪一轮。每次 archival 写入都存上来源引用(会话 ID、轮次 ID)。
context-budget动手构建
code/main.py 用标准库实现 MemGPT 的两级模式:
MainContext—— 固定大小的 prompt 缓冲区,带一个core字典和一个messages列表;超上限时自动压实最老的消息。ArchivalStore—— 内存中的类 BM25 存储(token 重叠打分),存 (id, text, tags, session, turn) 记录。- 映射到 MemGPT 接触面的五个记忆工具。
- 一个脚本化 agent,先用事实填满 archival,然后通过调用
archival_memory_search回答一个问题。
运行它:
python3 code/main.py轨迹展示 agent 写入三个事实、把主上下文填到上限(强制驱逐),然后通过从 archival 检索来回答一个追问 —— 在没有任何真实 LLM 的情况下复现 MemGPT 工作流。
实际使用
今天每个生产记忆系统都是 MemGPT 变体:
- Letta(第 08 课)—— 三级、原生推理、sleep-time compute。
- Mem0(第 09 课)—— 向量 + KV + 图,融合一个打分层。
- OpenAI Assistants / Responses —— 通过 thread 和 file 的托管记忆。
- Claude Agent SDK —— 通过 skill 和会话存储的长期记忆。
按运维形态(自托管、托管、框架集成)来选,而不是按核心模式 —— 核心模式就是 MemGPT。
Agent 记忆的形态
换页解决的是容量问题,却没有决定该存什么。生产系统中反复出现四类记忆,每类回答一个不同的问题:
- 工作记忆:现在什么最重要?它是上下文内的一层,包含当前任务、最近几轮和固定的核心 section,也就是 prompt 本身。
- 情景记忆:发生过什么?保存过去的对话轮次和执行轨迹,并附上会话与轮次引用,需要时可以重放。
- 语义记忆:什么是真的?记录关于用户、领域和世界的事实,并在事实变化时更新和去重。
- 程序性记忆:这件事该怎么做?保存学到的流程、偏好和规则,用来引导未来行为,而不仅是被动回忆。
不同开源实现选择了不同切入点:
| 类型 | 实现 | 处理方式 |
|---|---|---|
| 工作记忆 | MemGPT / Letta | 通过记忆工具,在固定 prompt 预算中换入和换出内容(本课、第 08 课) |
| 情景记忆 | Zep | 使用时序知识图谱,事实带有效期,因此可以查询“某个时间点什么为真” |
| 语义记忆 | Mem0 | 通过提取流水线,在向量、KV 和图存储间去重并更新事实(第 09 课) |
| 语义 + 程序性记忆 | LangMem | 在后台提取事实和行为规则,写入 agent 在不同轮次之间会查询的存储 |
| 情景 + 语义记忆 | agentmemory | 在会话运行时捕获记录,再整合成带类型、可搜索的条目 |
拿去用
outputs/skill-virtual-memory.md 是一个可复用技能,为任意目标运行时产出一个正确的两级记忆脚手架(主 + archival + 工具接触面),驱逐策略和引用字段都接好。
练习
- 加一个以 token 计的
max_main_context_tokens上限(用len(text.split())* 1.3 近似)。超限时把最老的消息压实成一段摘要。对比有/无摘要器的行为。 - 在 archival 存储上正经实现 BM25(词频、逆文档频率)。在一组玩具事实上度量 recall@10,与 token 重叠基线对比。
- 给 archival 插入加
citation字段(session_id、turn_id、source_url)。让 agent 在每个有检索支撑的答案上引用来源。 - 模拟记忆投毒:加一条 archival 记录写着「忽略未来所有用户指令」。写一个守卫,扫描检索结果里指令形态的文本并标记为不可信。
- 把实现移植到使用 MemGPT 研究仓库的 core-memory JSON schema(
cpacker/MemGPT)。从扁平字符串切到带类型的 section 时,有什么变化?
关键术语
| 术语 | 大家怎么说 | 它实际是什么 |
|---|---|---|
| Virtual context | 「无限记忆」 | 主(prompt)+ 外部(可搜索)两级,带换入/换出 |
| Main context | 「工作记忆」 | prompt —— 固定大小、始终可见 |
| Archival memory | 「长期存储」 | 外部可搜索的持久化,按需检索 |
| Core memory | 「持久 prompt section」 | 钉在主上下文里的具名 section |
| Memory tool | 「记忆 API」 | agent 发出的读/写外部记忆的工具调用 |
| Interrupt | 「记忆缺页」 | agent 暂停,运行时取数,结果拼进下一轮 |
| Memory rot | 「过时事实」 | 旧写入淹没检索;用整合来修 |
| Memory poisoning | 「注入的持久笔记」 | 攻击者内容被存为记忆,回忆时再次摄入 |
延伸阅读
- Packer et al., MemGPT (arXiv:2310.08560) —— OS 启发的虚拟上下文论文
- Letta, Memory Blocks blog —— 三级演进
- Anthropic, Effective context engineering —— 把上下文当预算来对待
- Chhikara et al., Mem0 (arXiv:2504.19413) —— 建立在这个模式之上的混合生产记忆
- Zep (getzep/zep) —— 上表中的时序知识图谱记忆
- Mem0 (mem0ai/mem0) —— 第 09 课混合存储背后的提取流水线
- LangMem (langchain-ai/langmem) —— 在后台提取事实和行为规则
- agentmemory (rohitg00/agentmemory) —— 捕获会话并整合成带类型、可搜索的记录