Ch10: Letta/MemGPT——虚拟内存与 Agent 自管理
Part 3: 七大开源项目精读 前置章节:Ch09: mem0——极简事实提取与 25+ 后端生态 后续章节:Ch11: Graphiti——时序知识图谱与双时间轴
0. 一句话定位
源自 MemGPT 论文的有状态 Agent 框架,Agent 像操作系统一样自己管理”内存”——Core Memory 是 RAM(容量有限但读取零延迟),Archival Memory 是硬盘(容量无限但需要搜索),这是”Agent 自管理记忆”派的代表。
如果你只用一个关键词记住这个项目,那就是”自管理”——所有设计选择都围绕”让 Agent 自己决定记什么、怎么记、什么时候忘”展开。
1. 设计哲学——操作系统虚拟内存
1.1 从一个日常场景说起
你的电脑有 16GB 内存(RAM)和 512GB 硬盘(SSD)。你不可能同时把 512GB 的数据都放进 16GB 的内存——但你不需要这样做。操作系统会智能地决定哪些数据应该放在内存里(正在使用的),哪些应该留在硬盘上(暂时不用的),以及什么时候做内存和硬盘之间的数据交换(换页)。
关键设计点:
内存有限,硬盘无限:16GB vs 512GB。内存更快但更贵,硬盘更慢但更便宜。好钢用在刀刃上——最关键的数据放内存,其余放硬盘。
操作系统做调度:不是你手动决定哪些数据放内存——操作系统根据访问模式自动做调度。你打开一个 App,操作系统把它加载进内存;你关掉 App,操作系统回收内存。
换页是透明的:你不需要知道数据是在内存还是在硬盘——操作系统自动处理。当你要访问的数据恰好在硬盘上,操作系统把它换入内存,你只是感觉稍微慢了一点。
Letta(前身 MemGPT)把这套虚拟内存的设计直接搬到了 Agent 记忆系统上:
| 操作系统概念 | Letta 对应 | 特征 |
|---|---|---|
| RAM(内存) | Core Memory | 在 system prompt 中,读取零延迟,容量有限(受上下文窗口限制) |
| 硬盘(SSD) | Archival Memory | 在 PostgreSQL 中,容量无限但需要搜索 |
| 换页机制 | Agent 主动 tool call | Agent 决定何时在 Core 和 Archival 之间移动数据 |
| 进程的对话历史 | Recall Memory | 自动索引的对话记录,可搜索 |
1.2 Core Memory = RAM
Core Memory 是 Letta 最核心的概念——它是一段始终存在于 Agent system prompt 中的文本,Agent 在每次推理时都能看到它。
Core Memory 的结构:
=== Core Memory ===
[block: human]
姓名: 小明
技术栈: Python, FastAPI
偏好: 函数式风格
当前项目: 用户认证服务
[/block]
[block: persona]
我是用户的编程助手。我倾向于:
- 给出简洁直接的答案
- 优先推荐 Python 生态的方案
- 在给出代码前先解释思路
[/block]
Core Memory 的关键特征:
始终在线:Core Memory 的内容是 system prompt 的一部分,Agent 在每一次推理时都会”看到”它。这就像内存中的数据——CPU 在每个指令周期都能访问。
容量有限:Core Memory 受上下文窗口大小限制。即使模型支持 128K token,你也不能把所有 Core Memory 都塞满——还要留空间给对话历史、工具定义、Agent 输出等。实际可用空间通常只有几千 token。
Block 结构:Core Memory 被划分为多个 Block(如 human 和 persona),每个 Block 有独立的字符限制。Block 的划分让不同类型的信息有各自的空间,避免互相挤占。
可修改:Agent 可以通过 tool call 修改 Core Memory 的内容——添加、替换、删除 Block 中的文本。这是”Agent 自管理”的核心体现。
Core Memory 适合存储什么:
- 用户的长期偏好和画像(”用户偏好 Python”“用户是后端工程师”)
- Agent 自身的行为准则(”倾向于简洁回答”“优先推荐测试覆盖”)
- 当前任务的关键上下文(”正在开发用户认证服务,使用 FastAPI”)
Core Memory 不适合存储什么:
- 大量的历史对话(放不下)
- 需要精确检索的细节信息(Core Memory 是全文可见,无法做关键词或语义搜索)
- 频繁变化的临时状态(每次修改都需要 tool call,成本高)
1.3 Archival Memory = 硬盘
Archival Memory 是 Agent 的”外部存储”——一个基于 PostgreSQL 的持久化存储,容量几乎无限,但访问需要搜索。
Archival Memory 的关键特征:
容量无限:只要 PostgreSQL 能存下,Archival Memory 就能存。不像 Core Memory 受上下文窗口限制。
需要搜索:Agent 不能”看到” Archival Memory 的全部内容——它必须通过 archival_memory_search 工具来检索相关内容。这就像你不能同时看到硬盘上所有文件——你需要搜索或浏览才能找到你想要的。
搜索依赖 LLM 嵌入:Archival Memory 的搜索底层用的是向量语义搜索——先把内容转成 embedding 存入数据库,搜索时用 query 的 embedding 做最近邻查找。
Agent 主动写入:Agent 通过 archival_memory_insert 工具主动写入内容到 Archival Memory。系统不会自动把对话内容存入 Archival——存不存、存什么,完全由 Agent 决定。
Archival Memory 适合存储什么:
- 完整的对话历史(容量大,可回溯)
- 文档和知识库(需要时搜索)
- 项目代码的摘要(长期参考)
Archival Memory 不适合存储什么:
- 需要在每次推理时都可见的信息(应该放 Core Memory)
- 实时性要求高的信息(搜索有延迟)
1.4 Recall Memory = 被动回忆
Recall Memory 是对话历史的自动索引。每当 Agent 和用户进行一轮对话,系统自动把对话内容存入 Recall Memory,并建立索引。
Recall Memory 的关键特征:
自动索引:不需要 Agent 主动调用工具——系统自动记录对话并建立搜索索引。这和 Core/Archival 的”Agent 主动管理”不同——Recall 是被动积累的。
可搜索:Agent 可以通过 conversation_search 工具搜索历史对话。例如,Agent 可以搜索”上次讨论的数据库方案”,找到相关的对话记录。
粒度控制:搜索可以按消息级别或会话级别进行。消息级别返回具体的对话轮次,会话级别返回完整的对话。
Recall Memory 的定位比较微妙——它不像 Core Memory 那样是 Letta 的原创概念,也不像 Archival Memory 那样有明确的存储模型。它更像是一个”附带功能”——自动索引对话历史,方便 Agent 回溯。
在实际使用中,Recall Memory 的搜索能力经常和 Archival Memory 的搜索能力重叠——Agent 既可以搜 Archival 也可以搜 Recall,两者的区别在于 Archival 存的是 Agent 主动归档的内容,Recall 存的是系统自动记录的对话原文。
1.5 三种记忆的协作模式
Core、Archival、Recall 三种记忆不是孤立使用的——它们构成了一个完整的信息管理流程:
写入流程:
- 对话发生 → 系统自动存入 Recall Memory(被动)
- Agent 判断对话中有值得长期记住的信息 → 调用
core_memory_append写入 Core Memory(主动) - Agent 判断有些信息需要长期归档但不需要每次都看到 → 调用
archival_memory_insert写入 Archival Memory(主动)
读取流程:
- 每次推理时,Core Memory 的内容自动可见(零延迟)
- 如果当前问题需要历史上下文 → 调用
conversation_search搜索 Recall Memory - 如果需要更广泛的检索 → 调用
archival_memory_search搜索 Archival Memory
信息流动:
对话 → [自动] → Recall Memory
→ [Agent 判断] → Core Memory (关键信息)
→ [Agent 判断] → Archival Memory (归档信息)
Core Memory ←→ Archival Memory (Agent 主动搬移)
这个流程和操作系统的内存管理非常相似:
- 对话输入 → 相当于程序产生的新数据
- Recall Memory → 相当于操作系统的日志(自动记录)
- Core Memory → 相当于 RAM(快速访问,容量有限)
- Archival Memory → 相当于硬盘(大容量,需要显式加载)
- Agent 的 tool call → 相当于操作系统的换页操作
2. Agent 自管理记忆——核心创新也是核心争议
2.1 Agent 如何操作记忆
Letta 的 Agent 通过一组预定义的 tool call 来操作记忆。这些工具是 Agent 的”记忆操作接口”:
Core Memory 工具:
core_memory_append(block_name, content):向指定 Block 追加内容core_memory_replace(block_name, old_content, new_content):替换 Block 中的内容core_memory_insert(block_name, content, insert_after):在指定位置插入内容
Archival Memory 工具:
archival_memory_insert(content):插入内容到 Archival Memoryarchival_memory_search(query, limit):搜索 Archival Memoryarchival_memory_delete(memory_id):删除 Archival Memory 中的内容
Recall Memory 工具:
conversation_search(query, limit):搜索对话历史conversation_search_date(start_date, end_date):按日期范围搜索对话
一个典型的 Agent-用户交互流程:
用户: 我最近从 React 切换到了 Vue
Agent 内部推理:
思考: 用户说了技术栈的变化,我应该更新 Core Memory 中的技术栈信息
动作: core_memory_replace("human", "技术栈: React", "技术栈: Vue")
Agent 回复: 了解了,我会记住你现在是 Vue 用户。以后推荐方案时会优先考虑 Vue 生态。
这个例子展示了 Agent 自管理的精髓——Agent 自己判断”这个信息值得记”并主动更新记忆。系统没有规则说”提到技术栈变化就要更新 Core Memory”——是 Agent 的推理能力让它做出了这个判断。
2.2 优势:Agent 有最强的上下文判断
为什么让 Agent 自己管理记忆?最核心的论点是:Agent 拥有最完整的上下文来判断”什么值得记”。
考虑以下场景:
场景一:隐性偏好
用户: 帮我写一个排序函数
Agent: [提供冒泡排序实现]
用户: 这个太慢了,有没有更高效的?
Agent: [提供快速排序实现]
用户: 这个好多了
一个”系统自动管理”的记忆系统可能只提取了显性事实:”用户需要排序函数”。但 Agent 通过对话上下文可以理解更深层的偏好:”用户关注算法效率,不喜欢低效方案”——这是一个隐性偏好,只有理解了对话的语义才能推断出来。
Agent 自管理可以捕捉这种隐性偏好——当它观察到用户反复要求”更高效”时,可以主动在 Core Memory 中记录”用户偏好高效算法”。
场景二:上下文相关的重要性
用户: 我在做一个金融系统
用户: 帮我写一个金额计算函数
在这个上下文中,”金额计算需要精确”是一个关键信息——金融系统不能有浮点数精度问题。系统自动管理可能不会提取”精确计算”这个隐含要求,但 Agent 可以推理出”金融系统 → 金额计算 → 需要 Decimal 而非 float”,并主动记录这个约束。
场景三:遗忘时机的判断
用户: 我之前用 React,现在改用 Vue 了
Agent 可以理解”改用”意味着旧技术栈过时了,应该替换 Core Memory 中的旧信息。而系统自动管理的去重机制可能判断”用 React”和”用 Vue”是不同事实(技术栈不同),两条都保留。
2.3 风险:要求 Agent 有强元认知能力
Agent 自管理记忆的”风险面”同样不可忽视——它要求 Agent 有很强的元认知能力(metacognition),即”知道自己知道什么、不知道什么”的能力。
风险一:忘记保存
最常见的问题——Agent 在对话中获得了重要信息,但没有调用记忆工具保存它。
用户: 我对花生过敏
Agent: 好的,我记住了。[但没有调用 core_memory_append]
下一次对话:
用户: 推荐一道菜
Agent: [Core Memory 中没有过敏信息] 推荐宫保鸡丁(含花生)
这种”忘记保存”的错误在弱模型上频繁出现——模型”理解”了信息的重要性,但在生成 tool call 时遗漏了。就像你听了一句话心想”这很重要要记住”,但转脸就忘了——人类的记忆也需要”主动编码”才会持久。
风险二:保存错误的东西
Agent 可能保存了不重要的信息而遗漏了重要的:
用户: 我今天穿了蓝色衣服,顺便说一下我用 Python 写后端
Agent 内部推理: 用户提到了穿蓝色衣服,我应该记住
动作: core_memory_append("human", "用户穿了蓝色衣服")
[但没有记录 Python 后端信息]
这种错误源于 Agent 对”什么重要”的判断不准确——弱模型容易被表面的”新信息”吸引,忽略语义上的重要性。
风险三:保存格式错误
Agent 在使用 core_memory_replace 时可能出错:
Agent 想替换: "技术栈: React" → "技术栈: Vue"
Agent 实际调用: core_memory_replace("human", "React", "Vue")
结果: Core Memory 中的 "React Native" 也被替换成了 "Vue Native"
这是因为 core_memory_replace 的 old_content 参数需要精确匹配要替换的文本——如果 Agent 提供了太短的匹配字符串,可能误替换其他内容。
风险四:过度保存
Agent 可能对每条信息都”过度记忆”,导致 Core Memory 迅速被填满:
用户: 你好
Agent: core_memory_append("human", "用户打了招呼")
用户: 谢谢
Agent: core_memory_append("human", "用户说了谢谢")
用户: 天气不错
Agent: core_memory_append("human", "用户觉得天气不错")
Core Memory 很快被无用的寒暄信息填满,真正重要的信息反而没有空间了。
2.4 “自管理” vs “系统管理”的根本分歧
Letta 的 Agent 自管理和 DB-Agent-Memory/mem0 的系统自动管理,代表了记忆系统设计的根本分歧:
系统自动管理派(DB-Agent-Memory、mem0、Graphiti、cognee):
- 记忆的提取、存储、检索由系统自动处理
- Agent 不需要(也不应该)参与记忆决策
- 优势:Agent 专注于业务逻辑,不需要”元认知”能力
- 劣势:系统可能遗漏只有 Agent 才能理解的隐性信息
Agent 自管理派(Letta):
- Agent 通过 tool call 主动管理记忆
- Agent 自己决定记什么、怎么记、何时忘
- 优势:Agent 利用完整上下文做更精准的记忆判断
- 劣势:要求 Agent 有强元认知能力,弱模型容易犯错
这个分歧的本质是”信任谁”的问题:
- 信任系统 → 用规则和算法自动管理,牺牲灵活性换取可靠性
- 信任 Agent → 把决策权交给 Agent,牺牲可靠性换取灵活性
在实践中,两种路线正在趋同:
- Letta 最新版本增加了”自动记忆提取”的选项——系统可以自动从对话中提取记忆,不需要 Agent 每次都主动调用 tool call
- DB-Agent-Memory 竞赛贡献方向之一是”MCP Adapter 增强”——让 Agent 有能力在必要时主动参与记忆决策
理想的记忆系统可能是”混合模式”——系统自动处理大部分记忆操作,但在关键决策点(如”这条信息是否冲突”“这个偏好是否应该晋升为 Profile”)让 Agent 参与。这既保证了基础可靠性,又保留了 Agent 的上下文优势。
3. 框架耦合——Letta 不仅仅是记忆库
3.1 Letta 是什么
理解 Letta 的关键在于:Letta 不只是记忆库,而是围绕记忆设计的完整 Agent 框架。
这和 DB-Agent-Memory、mem0 有本质区别:
- DB-Agent-Memory:记忆引擎,可以嵌入任何 Agent 框架
- mem0:记忆服务,可以被任何 Agent 框架调用
- Letta:完整的 Agent 框架,记忆是框架的核心特性之一
Letta 的代码库约 1155 个文件,涵盖了:
- Agent 的生命周期管理(创建、配置、运行、停止)
- 记忆系统(Core/Archival/Recall Memory)
- 工具管理(工具注册、调用、错误处理)
- 消息路由(Agent 和用户之间的消息传递)
- 持久化(PostgreSQL 数据存储)
- API 服务(REST API 和 WebSocket)
- 多 Agent 协作
- Web UI(管理界面)
相比之下,DB-Agent-Memory 约 90 个文件,只做记忆。mem0 约 200+ 文件,只做记忆。Letta 的 1155 个文件中,记忆相关的代码可能只占 20-30%——其余都是 Agent 框架的基础设施。
3.2 框架耦合的表现
框架耦合意味着:你不能单独提取 Letta 的记忆模块,嵌入到你自己的 Agent 框架中。
具体表现:
表现一:记忆工具是 Agent 工具系统的一部分
Letta 的 core_memory_append、archival_memory_search 等工具,是通过 Letta 自己的工具注册系统定义的。它们不是独立的 Python 包或 API,而是深度嵌入 Agent 推理循环的一部分。
如果你想在自己的 Agent 框架中使用 Letta 的记忆能力,你有两个选择:
- 使用 Letta 的 REST API——但这意味着你的 Agent 变成了 Letta 的客户端,失去了独立性
- 自己实现 Letta 的记忆逻辑——但 Letta 的记忆和工具系统深度耦合,剥离出来工作量很大
表现二:记忆状态是 Agent 状态的一部分
Letta 的 Agent 状态(AgentState)包含记忆信息——Core Memory 的内容、Archival Memory 的引用、Recall Memory 的索引。这些状态和 Agent 的其他状态(如当前任务、工具列表、配置参数)紧密耦合,无法独立管理。
表现三:记忆操作依赖 Letta 的消息格式
Letta 的记忆工具调用结果以特定格式返回给 Agent——这个格式是 Letta 消息系统的一部分。如果使用不同的消息格式(如 LangChain 的消息格式),需要做格式转换。
3.3 框架耦合的利与弊
利:
- 一体化体验:记忆是 Agent 的一等公民——不需要额外配置,开箱即用
- 深度优化:记忆操作和 Agent 推理可以联合优化——例如,Agent 可以在推理过程中动态调整 Core Memory 的内容
- 一致性保证:记忆状态和 Agent 状态的一致性由框架保证,不会出现”Agent 状态更新了但记忆没更新”的情况
弊:
- 不可替换:如果你想用 Letta 的记忆但不想用 Letta 的 Agent 框架,做不到
- 迁移成本高:如果你已经在使用 LangChain 或其他框架,迁移到 Letta 意味着重写 Agent 逻辑
- 维护负担:Letta 需要同时维护 Agent 框架和记忆系统,代码量大、变更影响面广
3.4 和其他项目的对比
| 维度 | Letta | DB-Agent-Memory | mem0 |
|---|---|---|---|
| 定位 | 完整 Agent 框架 | 记忆引擎 | 记忆服务 |
| 可否独立使用记忆模块 | 否 | 是 | 是 |
| 可否嵌入其他框架 | 否(必须用 Letta 框架) | 是(通过 Adapter) | 是(通过 API) |
| 代码量 | ~1155 文件 | ~90 文件 | ~200+ 文件 |
| 记忆相关代码占比 | ~20-30% | ~100% | ~100% |
Letta 的框架耦合在学术研究中不是问题——论文只需要证明虚拟内存概念的有效性。但在工程实践中,框架耦合是采用 Letta 的最大障碍——大部分团队已经有自己的 Agent 框架,不会为了记忆功能而切换整个框架。
4. MemGPT 论文的核心思想
4.1 论文的核心论证
MemGPT 论文(2023 年发表)的核心观察:LLM 的上下文窗口就像操作系统的物理内存——容量有限,但需要处理的信息量可能远超这个容量。长期交互的 Agent 可能累积数千页对话、数百条偏好、大量文档——即使 128K token 也容纳不下。
论文指出传统 RAG 方案的局限:无状态(每次检索独立)、策略固定(不能动态调整)、只有读没有写。MemGPT 的解决方案:给 Agent 一个虚拟内存系统,让 Agent 自己决定什么放 Core Memory、什么放 Archival Memory、何时换页。
虚拟内存类比的有效性体现在:容量差异(RAM vs 硬盘)、主动调度(Agent 通过 tool call 换页)、透明访问(用户不需要手动操作)。
但类比有边界:操作系统调度目标是性能优化(有客观指标),Agent 调度目标是信息质量(无通用指标);操作系统换页策略是 LRU 等确定性算法,Agent 换页策略是 LLM 推理(不确定、可能犯错);操作系统要求严格一致性,Agent 允许一定程度不完美。
论文在文档问答和多会话聊天两个场景中验证了方法有效性,但实验规模较小,且没有和系统自动管理方案做直接对比。
5. Letta 的技术实现要点
推理循环:Agent 在每轮推理时,Core Memory 内容被注入 system prompt,保证始终可见——不会被对话历史”挤出”上下文窗口。但 Core Memory 占用 token 预算,容量管理是重要的工程问题。
Block 管理:Core Memory 划分为多个 Block(如 human 存用户信息、persona 存 Agent 行为准则),每个 Block 有独立的字符限制。好处:主题隔离、容量控制、操作粒度细——Agent 可以独立修改每个 Block。
工具调用:Agent 操作记忆通过 LLM 的 tool call——core_memory_append、core_memory_replace、archival_memory_insert、archival_memory_search 等。关键是 LLM 必须在推理时”想到”调用记忆工具,想不到则记忆不会更新。这和 DB-Agent-Memory(Adapter 自动流入)及 mem0(上层自动调用 add)形成鲜明对比。
持久化:Letta 使用 PostgreSQL + pgvector 做持久化和向量搜索,和 DB-Agent-Memory 的零依赖理念完全不同——Letta 认为 PostgreSQL 是 Agent 框架的必要基础设施。
6. 竞赛定位——Letta 对 DB-Agent-Memory 的启发
虽然犀牛鸟竞赛的贡献目标是 DB-Agent-Memory 而非 Letta,但 Letta 的设计思想对 DB-Agent-Memory 的改进有重要启发。
6.1 虚拟内存思想的应用
Letta 的 Core/Archival 概念可以被映射到 DB-Agent-Memory 的四层金字塔:
| Letta | DB-Agent-Memory 对应 | 区别 |
|---|---|---|
| Core Memory | L3 Profile + 部分 L2 Summary | Core Memory 由 Agent 管理,Profile 由系统自动晋升 |
| Archival Memory | L0 Observation + L1 Fact | Archival 由 Agent 主动写入,L0/L1 由系统自动采集 |
| Recall Memory | 无直接对应 | DB-Agent-Memory 没有对话历史的自动搜索 |
启发点:DB-Agent-Memory 可以引入”Core Memory”的概念——在四层金字塔之上,增加一个”始终注入”的精炼层,确保最关键的信息(Profile + 当前摘要)在每次推理时都可见,而不需要每次都做检索。
6.2 Agent 参与记忆管理决策
Letta 的核心论点是”Agent 有最强的上下文判断”。这个论点对 DB-Agent-Memory 的启发是:是否应该让 Agent 在关键决策点参与记忆管理?
具体的应用场景:
场景一:冲突解决时让 Agent 判断
当 DB-Agent-Memory 检测到事实冲突(”用户用 React” vs “用户用 Vue”),目前是系统用 LLM 做冲突判断。但如果这个判断交给 Agent(通过 tool call 询问 Agent:”检测到技术栈变化,是否更新?”),Agent 可以结合更完整的上下文做判断(如”用户说的是工作项目改用 Vue,但个人项目仍然用 React”)。
场景二:晋升决策时让 Agent 确认
当 L1 Fact 准备晋升为 L2 Summary 时,可以让 Agent 审阅晋升结果——”我总结了你最近的技术偏好是后端开发,这个总结准确吗?”Agent 的反馈可以用来改进晋升质量。
场景三:遗忘决策时让 Agent 参与
当系统判断某条记忆可能过时(长期未被引用),可以询问 Agent:”用户三个月前说用 React,但之后没再提过,是否需要更新?”Agent 可以结合最新的对话上下文做出判断。
这些场景的实现方式是通过 MCP tool call——系统在关键决策点生成一个 tool call 请求,Agent 在推理时处理。这既保留了系统自动管理的基础可靠性,又引入了 Agent 的上下文优势。
6.3 MemOS 是 Letta 的学术延伸
MemOS(第 14 章将详细介绍)可以被看作 Letta 虚拟内存思想的学术延伸——它保留了”记忆操作系统”的核心隐喻,但做了两个重要改进:
改进一:多层记忆架构
Letta 只有三层(Core/Archival/Recall),MemOS 扩展为更细粒度的多层架构——包括短期工作记忆、长期语义记忆、程序性记忆等。这更接近人类记忆系统的多模型理论。
改进二:Dream Pipeline
Letta 的记忆只在对话中更新——Agent 和用户交互时才有记忆操作。MemOS 引入了后台的”梦”管线——在 Agent 闲置时,系统自动对记忆做整合、压缩、推理。这解决了 Letta 的一个实际问题:Agent 只在”醒着”时管理记忆,”睡着”后记忆不做任何处理。
这些改进的思想源头都可以追溯到 Letta 的虚拟内存概念——只是把”Agent 管理”扩展为”系统 + Agent 联合管理”,把”在线管理”扩展为”在线 + 离线管理”。
7. Letta 在七项目版图中的位置
7.1 独特定位
Letta 是七个项目中唯一一个”Agent 自管理记忆”的框架——其他六个项目(DB-Agent-Memory/mem0/Graphiti/cognee/supermemory)都是系统自动管理,MemOS 是系统+Agent 联合管理。Letta 的选择假设 LLM 有足夠元认知能力做记忆决策,在强模型上部分成立,在弱模型上经常失败。
7.2 关键对比
和 DB-Agent-Memory 的分歧在”谁管理记忆”和”可嵌入性”:Letta Agent 自管理 + 框架耦合(~1155 文件,不可单独提取记忆模块);DB-Agent-Memory 系统自动管理 + 零依赖可嵌入(~90 文件)。
和 mem0 的分歧在”重量级”:Letta 是完整 Agent 框架(~8 个工具),mem0 是轻量记忆服务(4 个 API)。
适合用 Letta:从零构建有记忆的 Agent、使用强模型、需要精细记忆控制、学术研究。 不适合:已有 Agent 框架只想加记忆、使用弱模型、只需简单记忆功能。
8. 本章小结
Letta/MemGPT 的核心设计可以浓缩为三个关键词:
虚拟内存:Core Memory = RAM(容量有限但读取零延迟),Archival Memory = 硬盘(容量无限但需要搜索),Recall Memory = 日志(被动记录对话历史)。三层记忆的协作模式直接映射了操作系统的内存管理。
Agent 自管理:Agent 通过 tool call 主动操作记忆——core_memory_append、core_memory_replace、archival_memory_insert、archival_memory_search。这是 Letta 的核心创新,也是核心争议:强模型能做好的记忆判断,弱模型容易犯错(忘记保存、保存错误、过度保存)。
框架耦合:Letta 不只是记忆库,而是围绕记忆设计的完整 Agent 框架(约 1155 文件)。不能单独提取记忆模块嵌入其他框架——这是和 DB-Agent-Memory/mem0 的最大区别。
三个项目的对比揭示了记忆系统设计的三个根本分歧:
- 分层 vs 扁平:DB-Agent-Memory 四层金字塔 vs mem0 扁平事实列表——是否需要按重要性分层压缩
- 自管理 vs 系统管理:Letta Agent 自管理 vs DB-Agent-Memory/mem0 系统自动管理——记忆决策权在谁手里
- 可嵌入 vs 一体化:DB-Agent-Memory/mem0 可独立嵌入 vs Letta 框架耦合——记忆是独立服务还是框架特性
对 DB-Agent-Memory 竞赛贡献的启发:Letta 的虚拟内存思想可以指导 DB-Agent-Memory 的设计改进——在四层金字塔之上增加”始终注入”的精炼层,在关键决策点让 Agent 参与记忆管理,借鉴 MemOS 的 Dream Pipeline 实现后台记忆整合。
下一章我们将看到第四种记忆设计哲学——Graphiti 的时序知识图谱和双时间轴,它用图结构和时间维度提供了完全不同的记忆组织方式。
导读目录:README.md 上一章:Ch09: mem0——极简事实提取与 25+ 后端生态 下一章:Ch11: Graphiti——时序知识图谱与双时间轴