Ch04: 记忆的四种类型——从工作记忆到外部记忆
Part 2: 记忆基础概念 前置章节:Ch03: 前置知识检查清单 后续章节:Ch05: Profile vs User Memory——写给 Agent 的 vs Agent 自己学的
1. 从一张书桌说起
想象你是一个学生,书桌就是你的工作空间。你每天在这张桌子上学习、做题、写笔记。仔细观察这张桌子,上面有四种不同的”记忆载体”。
第一种,你正在翻的那本教材——它打开在你面前,内容一目了然,不需要额外查找。但桌面空间有限,同时只能摊开两三本书。你合上书或者离开书桌,翻到的那一页就不再”可见”了。这是工作记忆——当前上下文窗口里的信息。
第二种,贴在书桌右上角的那张黄色便签纸——上面写着”下午 3 点有组会”“这周交读书报告”。这些不是书上的内容,是你自己写上去的行为提醒。它不会因为你看完一本书就消失,只要你不去撕掉,它就一直贴在那里。这是画像记忆(Profile Memory)——开发者或用户主动写给 Agent 的行为规范。
第三种,你抽屉里的那个笔记本——上面记着老师上课时提到的重点、你做错的题目类型、你发现的有效解题方法。这些不是你刻意写的便签,而是在学习过程中逐渐积累的理解。你需要翻开笔记本才能回忆起来,有时候笔记写得太早、方法已经改进了,但你忘了更新。这是用户记忆(User Memory)——Agent 从交互中自动学到的关于用户的知识。
第四种,楼下的图书馆——你不可能把所有书都堆在书桌上,但需要的时候可以下楼去借。图书馆的书有独立的编目系统,其他同学也能借到同一本书。去图书馆需要花时间(走路、检索、借阅),但你获得的信息量远超桌面能容纳的范围。这是外部记忆(External Memory)——通过 MCP 等协议连接的外部记忆服务。
这四种载体对应着 Agent 记忆系统的四种类型。它们不是谁替代谁的关系,而是各有分工、互相配合。下面逐一深入。
2. Working Memory(工作记忆)
2.1 定义
工作记忆是当前上下文窗口中的全部信息。它包括 system prompt、对话历史、已注入的记忆条目——所有 LLM 在生成下一条回复时能”直接看到”的内容。
用技术语言说:工作记忆 = 当前 inference 请求中发送给 LLM 的全部 token。它在 API 调用结束后不存在——没有持久化,没有跨会话。下次对话重新开始,工作记忆从零构建。
2.2 类比与特征
回到书桌类比:工作记忆就是你面前摊开的那几页纸。核心特征有三个。
容量有限。128K token 的窗口看似不小,但 system prompt、对话历史、Agent 回复各占一部分,留给记忆注入的空间可能只有几万 token。这是记忆系统设计的核心驱动力——正因为容量有限,才需要精心设计”哪些记忆值得占这个位置”。
会话内有效。对话结束后上下文窗口清空。这决定了工作记忆不能承担”跨会话持久化”的任务——它只解决”当前对话中需要什么信息”。
速度最快。在上下文窗口中的信息,LLM 可以零延迟地”看到”并使用,不需要检索、不需要网络请求。这使得工作记忆成为最”可靠”的记忆类型——放进上下文窗口的信息,LLM 一定会看到。
2.3 所有 LLM 天然拥有
这一点容易被忽略:工作记忆是所有 LLM 天然拥有的——不需要任何额外的系统设计。只要你在和 LLM 对话,它就自动拥有工作记忆。区别只在于容量大小(4K 还是 1M token)和利用效率(是否通过 prompt engineering 充分利用窗口空间)。
但”天然拥有”不等于”够用”。恰恰因为工作记忆容量有限且不持久,才需要其他三种记忆类型来补充。所有记忆系统的核心设计问题都可以归结为一句话:怎么把外部存储中的信息,在恰当的时候注入工作记忆,同时不超过容量上限。
3. Profile Memory(画像/配置记忆)
3.1 定义
Profile Memory 是开发者或用户主动写给 Agent 的行为规范和背景知识。它不是 Agent 自己学来的,而是人类显式编写的。其载体通常是 Markdown 文件或配置文件,在会话开始时被注入 system prompt。
用技术语言说:Profile Memory 是通过文件系统持久化、在会话初始化时被确定性注入 system prompt 的静态配置。它的内容是声明式的——描述”Agent 应该怎样”,而不是”发生了什么事”。
3.2 类比与特征
回到书桌类比:Profile Memory 是贴在桌角的便签纸。核心特征有三个。
人工维护。便签纸是你自己写上去的——你决定写什么、怎么写、什么时候更新。同样,CLAUDE.md、AGENTS.md、Cursor Rules 都是人工编写的文件。Agent 不会自动修改它们(除非你明确允许)。这带来了一个重要的特性:内容是确定的、可审计的——你打开文件就能看到 Agent 会收到什么指令,没有”Agent 自动加了一条你看不到的规则”这种不可控情况。
稳定性高。便签纸贴上之后一般不会频繁更换。Profile Memory 同理——一个项目的代码规范、技术栈偏好、行为准则等,通常在项目周期内是稳定的。这使得它适合存放”长期有效”的规则,而不适合存放”可能随时变化”的动态信息。
容量可控。便签纸的大小有限,你自然会精简内容,只写最关键的提醒。Profile Memory 同样有容量意识——CLAUDE.md 的最佳实践是”控制在几千 token 以内”,因为太长的 system prompt 会挤压上下文窗口中留给对话和记忆的空间。
3.3 具体实例与边界
Profile Memory 在生产系统中有多种形态:CLAUDE.md 沿路径逐级加载(最复杂),AGENTS.md 支持 override 做本地覆盖(最精巧),Cursor Rules 有四种 Apply 模式从 Always 到 Manual(最精细)。这些在 Ch05 中详细对比。
这里先说一个关键的边界问题:什么该放进去,什么不该放。
应该放:稳定的、声明式的规则——代码规范、技术栈声明、行为约束。这些信息在相当长的时间内不会变,且 Agent 需要每次都遵守。
不应该放:动态的、事实性的信息——项目当前进度、用户最近的偏好变化。这些信息可能很快过时,写进 Profile Memory 后过时的内容不会自动消失,Agent 会一直按旧信息行事。这个边界问题在 Ch05 中深入讨论。
4. User Memory(用户记忆)
4.1 定义
User Memory 是 Agent 从与用户的交互中自动学到的关于用户的知识。它不是人类写的,而是系统自动从对话中提取并存储的。其载体通常是结构化的记忆条目(JSON 对象或文本片段),存储在文件系统或数据库中,在需要时被检索并注入上下文窗口。
用技术语言说:User Memory 是通过自动化机制(LLM 提取、规则匹配等)从交互数据中提取的关于用户偏好、历史事件、行为模式的持久化记录。它需要显式的检索机制才能进入工作记忆——不像 Profile Memory 自动注入 system prompt,User Memory 通常需要语义搜索、LLM 筛选或图遍历才能被找到。
4.2 类比与特征
回到书桌类比:User Memory 是抽屉里的笔记本。核心特征有四个。
自动提取。笔记本上的内容不是你刻意写上去的便签,而是你在学习过程中逐渐积累的理解。同样,User Memory 不需要用户显式输入——mem0 从对话中用 LLM 提取独立事实,Claude Code 的 extractMemories 用 forked agent 从对话中抽取值得记住的信息。用户只需要正常对话,记忆系统在后台自动工作。
需要检索。笔记本合上放在抽屉里,你需要翻开它才能看到内容。同样,User Memory 存储在外部(文件系统或数据库),不在上下文窗口中。Agent 需要通过某种检索机制——语义搜索、LLM 筛选、图遍历——才能找到相关的记忆并注入工作记忆。这意味着检索质量直接影响 User Memory 的有效性:存了但找不到,等于没存。
可能过时。笔记本上高一的笔记到了高三可能不再适用——学习方法变了、知识点覆盖范围变了。User Memory 同理——用户半年前说”我喜欢 React”,现在可能已经转用 Vue 了;用户三个月前说”我在做项目 A”,现在可能已经换到项目 B。过时的记忆不仅没有帮助,还会误导 Agent。
需要遗忘机制。这是上一点的推论——既然记忆可能过时,就需要某种机制来处理过时信息。可能是显式的(用户说”我不再用 React 了”,系统更新旧记忆),也可能是隐式的(长期未被引用的记忆权重降低)。遗忘机制的设计是 User Memory 最核心也最困难的挑战之一。
4.3 十个系统的核心关注点
在我们研究的十个系统中,User Memory 是最核心的关注点。七个开源项目的核心差异几乎都体现在 User Memory 的处理方式上——mem0 关注事实提取和向量检索,DB-Agent-Memory 关注分层存储和逐级提炼,Letta 关注 Agent 自管理,Graphiti 关注时间轴区分,cognee 关注本体论定义,supermemory 关注多流融合检索,MemOS 关注认知科学框架。三个生产系统的差异同样集中在 User Memory——Claude Code 关注 LLM 筛选相关记忆,Codex 关注两阶段蒸馏管线,OpenClaw 关注 Pre-Compaction Flush。
为什么 User Memory 成为焦点?因为它是”最有问题”的类型——Profile Memory 人工维护所以可控,Working Memory 天然存在所以不需要设计,External Memory 是外部服务所以不操心实现。只有 User Memory 同时涉及”提取准确性”“检索精确性”“遗忘及时性”三大难题,每个都没有完美解法,自然成为差异化主战场。
4.4 User Memory 的生命周期
User Memory 的完整生命周期包含五个阶段:提取(从对话中识别值得记住的信息)→存储(选择格式和后端)→检索(在需要时找到相关记忆)→注入(放进上下文窗口)→遗忘/更新(处理过时或矛盾的记忆)。
每个阶段都有设计选择空间。提取:LLM 提取(mem0)vs Agent 自管理(Letta)vs 分层提炼(DB-Agent-Memory)。存储:扁平文本(mem0)vs 分层结构(DB-Agent-Memory)vs 图结构(Graphiti)vs 文件系统(Claude Code/Codex)。检索:语义搜索(mem0)vs LLM 筛选(Claude Code)vs 全量注入(Codex)vs 图遍历(Graphiti)。注入位置影响 LLM 的”注意力”程度。遗忘是最不成熟的阶段——十个系统中只有三个有明确机制。
5. External Memory(外部记忆)
5.1 定义
External Memory 是通过 MCP 等协议连接的外部记忆服务。它不由 Agent 自身管理,而是由独立的外部系统提供。Agent 通过标准化的接口(如 MCP 的 Tools/Resource 原语)来读写外部记忆。
用技术语言说:External Memory 是生命周期独立于 Agent 进程的记忆服务,通过标准化协议暴露读写接口,支持跨应用、跨 Agent 共享。它不在 Agent 的上下文窗口中,也不在 Agent 的本地文件系统中——它在”网络上的某个地方”。
5.2 类比与特征
回到书桌类比:External Memory 是楼下的图书馆。核心特征有三个。
独立生命周期。图书馆的开放时间、书籍的采买淘汰,都不受你控制。同样,External Memory 的存在和更新不依赖于某个 Agent 进程是否在运行。supermemory 的 MCP Server 在你关掉 Claude Code 之后仍然在线,其他 AI 工具也可以连接同一个记忆库。这意味着 Agent 必须处理”外部记忆可能不可用”的情况——网络延迟、服务宕机、数据格式变更。
跨应用共享。图书馆的书所有读者都能借。同样,External Memory 可以被多个 Agent、多个应用共享。你在 Claude Code 中积累的记忆,通过 MCP Server 可以被 Cursor 读取;你在浏览器扩展中保存的网页阅读笔记,可以被任何支持 MCP 的 AI 工具检索。这种跨应用共享是 External Memory 独有的优势——其他三种记忆类型都局限于单个 Agent 或单个应用。
网络延迟。去图书馆借书比从桌上拿书慢得多。同样,访问 External Memory 需要网络请求(MCP 调用),延迟远高于读取本地文件或上下文窗口中的信息。supermemory 把检索延迟控制在 300ms 以内,但 300ms 相比上下文窗口中的零延迟仍然是数量级的差距。这意味着 External Memory 不适合存放”每轮对话都需要”的信息——那些应该放在 Profile Memory 或工作记忆中。
5.3 MCP 与外部记忆
MCP 是当前 External Memory 最主流的集成协议:记忆服务实现 MCP Server 暴露工具,AI 工具作为 MCP Client 调用这些工具,LLM 通过 tool call 间接访问外部记忆。好处是解耦(记忆服务独立演进),坏处是间接(链条比直接注入长)。
适用场景:跨 Agent/跨应用共享记忆(多个 AI 工具访问同一份用户记忆)、海量历史数据检索(记忆量远超上下文窗口容量)、第三方知识服务集成(浏览器阅读历史、邮件等外部数据源)。
不适用场景:实时性要求高(10ms 以内)、单应用内部使用(Profile + User Memory 足够)、对延迟敏感的交互场景。
6. 四种类型的系统对比
把四种记忆类型放在一起对比,差异更清晰。
| 维度 | Working Memory | Profile Memory | User Memory | External Memory |
|---|---|---|---|---|
| 写入方式 | 自动(每轮对话追加到上下文) | 人工编写文件 | 自动提取(LLM/规则/Agent 自管理) | 通过协议(MCP Tools)写入 |
| 读取方式 | 直接可见(在上下文窗口中) | 确定性注入(加载到 system prompt) | 需要检索(语义搜索/LLM 筛选/图遍历) | 需要网络请求(MCP 调用) |
| 容量 | 受上下文窗口限制(4K-1M token) | 人工控制(通常几千 token) | 受存储后端限制(通常很大) | 受外部服务限制(通常很大) |
| 生命周期 | 单次会话 | 文件存在即有效 | 跨会话持久化,可能过时 | 独立于 Agent,跨应用共享 |
| 是否需要遗忘 | 不需要(会话结束自动清空) | 不需要(人工更新) | 必须考虑(信息可能过时) | 取决于外部服务设计 |
| 一致性 | 会话内一致 | 确定性(同文件同内容) | 可能矛盾(新旧记忆冲突) | 取决于外部服务一致性保证 |
| 延迟 | 零(已经在上下文中) | 极低(文件读取 + 注入) | 中等(检索需要时间) | 较高(网络请求 + 检索) |
| 代表系统 | 所有 LLM | CLAUDE.md / AGENTS.md / Cursor Rules | mem0 / DB-Agent-Memory / Letta | supermemory MCP Server |
对比表的解读
这张对比表有三个要点值得展开。
要点一:遗忘需求随”动态性”递增。Working Memory 不需要遗忘——会话结束自动清空。Profile Memory 不需要遗忘——人工维护,内容更新由人类决定。User Memory 必须考虑遗忘——自动提取的信息可能过时,而用户不会每次都主动说”之前那个已经不对了”。External Memory 的遗忘取决于外部服务——有些服务提供了 TTL(Time-To-Live)机制,有些则完全不处理。
要点二:延迟和容量的权衡。速度快的容量小(Working Memory),容量大的速度慢(External Memory)。这是一个经典的存储层次结构——和计算机的 L1/L2/L3 Cache → RAM → SSD → 网络存储的层次完全同构。记忆系统的设计本质上是在这个层次结构中做信息放置决策——什么信息值得放在快但小的层级,什么信息应该放在慢但大的层级。
要点三:写入方式的自动化程度。从人工到全自动:Profile Memory 完全人工,User Memory 自动提取,Working Memory 自动(对话本身),External Memory 半自动(需要 Agent 主动调用 MCP 工具写入)。自动化程度越高,检索和遗忘的难度越大——Profile Memory 人工写所以确定性强,User Memory 自动提取所以可能提取错、可能过时、可能矛盾。
7. 四种类型不是互斥的
一个常见的误解是”我选一种记忆类型就够了”。实际上,一个完整的记忆系统通常需要多种类型的组合——就像一个学生不可能只靠摊开的书(Working Memory)学习,也不可能只靠便签纸(Profile Memory)或只靠笔记本(User Memory)。
7.1 组合的必要性
为什么单一类型不够?因为每种类型都有其无法弥补的短板:
- 只有 Working Memory:没有跨会话持久化,每次对话从零开始
- 只有 Profile Memory:只能覆盖人工预知的规则,无法从交互中学习
- 只有 User Memory:没有确定性的行为约束,Agent 可能”学到”错误偏好并坚持执行
- 只有 External Memory:延迟高、依赖网络,且记忆内容不受 Agent 控制
所以任何实用的记忆系统都需要至少两种类型的组合。而成熟的生产系统通常三种甚至四种都用到了。
7.2 十个系统的类型组合
十个系统各自用了哪些类型?快速扫描:
- DB-Agent-Memory:Profile Memory(宿主 Rules 文件)+ User Memory(四层金字塔)
- mem0:User Memory(事实条目 + 向量检索)+ External Memory(MCP Server)
- Letta:Working Memory(Core Memory)+ User Memory(Archival Memory)
- Graphiti / cognee / supermemory:User Memory + External Memory(MCP Server)
- MemOS:Working + User + External Memory(三种 MemCube + MemScheduler)
- Claude Code / Codex / OpenClaw:Working + Profile + User Memory
没有一个系统只使用单一类型。最轻量的组合是 Profile + User Memory,最重的是 Working + Profile + User + External Memory 全覆盖。
7.3 组合设计的核心挑战
当多种记忆类型组合在一起时,会出现新的设计挑战。
挑战一:记忆冲突。Profile Memory 说”用 Python 写代码”,User Memory 从对话中学到”用户喜欢 TypeScript”。哪个优先?答案通常是 Profile Memory 优先——因为它是人工维护的、确定性更高的信息。但如果 Profile Memory 写的是”根据用户偏好选择语言”,那 User Memory 的提取结果就变成了决策依据。
挑战二:冗余注入。同一条信息可能同时出现在 Profile Memory 和 User Memory 中。比如 CLAUDE.md 写了”这个项目用 React”,extractMemories 又从对话中提取到”用户在用 React”。如果两条都被注入上下文窗口,浪费了宝贵的 token 空间。Claude Code 的做法是:extractMemories 明确排除 CLAUDE.md 中已经包含的内容——这不仅是优化,更是防止信息不一致的安全机制。
挑战三:更新同步。Profile Memory 人工更新后,User Memory 中的旧信息可能没有同步更新。比如你在 CLAUDE.md 中把”用 React”改成了”用 Vue”,但 Agent 从之前对话中学到的”用户喜欢 React”这条 User Memory 还在。需要某种机制来检测和更新这种矛盾。
这些挑战在 Ch05(Profile vs User Memory)和 Ch19(技术挑战)中会更深入讨论。
8. DB-Agent-Memory 四层金字塔与四种类型的映射
DB-Agent-Memory 的四层金字塔是本导读的重点关注对象(尤其是竞赛路径的同学)。理解它和四种记忆类型的映射关系,有助于定位”你要贡献的代码在哪一层、属于哪种记忆类型”。
8.1 四层金字塔回顾
DB-Agent-Memory 把记忆按重要性分为四层,从下到上:
- Observation 层(观测层):最原始的交互记录——用户说了什么、Agent 做了什么。信息量大但未经提炼。
- Fact 层(事实层):从观测中提取的独立事实——”用户偏好 Python”“项目使用 FastAPI”。经过一次提炼,信息量减少但质量提升。
- Summary 层(摘要层):对事实的阶段性归纳——”用户是一个全栈开发者,偏好 Python 后端 + React 前端”。经过二次提炼,更精炼但丢失了部分细节。
- Profile 层(画像层):最精炼的用户画像——”Python 全栈,偏好简洁风格”。经过三次提炼,只保留最核心的特征。
这四层构成一个金字塔——越往上越精炼、容量越小、重要性越高、注入上下文窗口的优先级越高。
8.2 映射关系
四层金字塔和四种记忆类型的对应关系如下:
| 金字塔层级 | 对应的记忆类型 | 说明 |
|---|---|---|
| Observation | User Memory(原始阶段) | 自动记录的交互数据,未经提炼 |
| Fact | User Memory(提炼阶段) | 从原始数据中提取的独立事实 |
| Summary | User Memory(归纳阶段) | 对事实的阶段性归纳 |
| Profile | User Memory(画像阶段) | 从交互中自动提炼的用户画像 |
注意一个容易混淆的点:DB-Agent-Memory 的 Profile 层(金字塔顶层)和 Profile Memory(四种类型之一)不是同一个概念。
Profile Memory 指的是人工编写的、确定性注入 system prompt 的配置文件——如 CLAUDE.md、AGENTS.md。它是人写的,内容是”Agent 应该怎样”。
DB-Agent-Memory 的 Profile 层指的是从交互中自动提炼出的用户画像——它是系统自动生成的,内容是”用户是什么样的人”。
两者都属于”画像”概念,但来源和确定性完全不同。Profile Memory 的来源是人工编写,确定性高,不需要遗忘机制。Profile 层的来源是自动提炼,可能出错、可能过时,需要遗忘和更新机制。
8.3 为什么这个映射重要
理解四层金字塔和四种类型的映射关系有三个实际意义。
定位贡献方向。竞赛路径的同学需要知道”我要改的代码属于哪种记忆类型”——不同类型的设计约束不同。DB-Agent-Memory 主要覆盖 User Memory(四层金字塔)+ Profile Memory(宿主 Rules 文件),主要设计空间在 User Memory 侧。
理解设计哲学。”四层金字塔”背后的哲学是”不同重要性的信息应该有不同的存储和检索优先级”——与四种类型中”不同类型有不同延迟和容量特征”是同一思路的两种体现。
横向对比基础。读其他项目时可以问”这个项目的 User Memory 对应金字塔的哪一层”——mem0 的独立事实对应 Fact 层,Letta 的 Core Memory 对应 Profile 层。这种映射把不同术语统一到同一框架中理解。
9. 从类型到设计
四种记忆类型的分类是分析框架,不是为了贴标签。面对任何 Agent 记忆系统时,问三个问题:1. 它用了哪些类型?2. 每种类型怎么存、怎么找、怎么忘?3. 不同类型之间怎么协调?
还有一个隐含价值:避免”用同一个标准评判不同类型”。Profile Memory 的标准是”是否清晰、稳定、可审计”,User Memory 的标准是”是否准确、可检索、可遗忘”,External Memory 的标准是”是否可靠、低延迟、可共享”。用错标准评判会导致错误结论。
10. 本章小结
回顾本章的核心要点:
- 用”学生的书桌”类比理解四种记忆类型:摊开的书(Working Memory)、桌角便签(Profile Memory)、抽屉笔记本(User Memory)、楼下图书馆(External Memory)
- Working Memory = 当前上下文窗口,容量有限、会话内有效、速度最快,所有 LLM 天然拥有
- Profile Memory = 人工编写的行为规范,确定性注入 system prompt、稳定性高、容量可控
- User Memory = Agent 自动学到的用户知识,需要检索、可能过时、必须考虑遗忘——十个系统的核心关注点
- External Memory = 通过 MCP 等协议连接的外部服务,独立生命周期、跨应用共享、有网络延迟
- 四种类型在写入方式、读取方式、容量、生命周期、遗忘需求、延迟等维度各有差异
- 四种类型不是互斥的——完整的记忆系统需要多种类型的组合,组合带来记忆冲突、冗余注入、更新同步等新挑战
- DB-Agent-Memory 的四层金字塔主要覆盖 User Memory(四层都是自动提炼的),Profile 层 ≠ Profile Memory
- 四种类型的分类是分析框架,帮你定位、分析设计选择、理解组合策略,也避免用错标准评判不同类型
下一章我们聚焦两种最容易被混淆的类型——Profile Memory 和 User Memory,深入对比它们的设计哲学、具体实现和常见误区。
导读目录:README.md 上一章:Ch03: 前置知识检查清单 下一章:Ch05: Profile vs User Memory——写给 Agent 的 vs Agent 自己学的