1. 为什么 Agent 会"失忆":长期记忆的技术原点
1.1 一次尴尬的对话让我开始研究 Agent 记忆
我做过一个客服 Agent,前几轮对话体验都很好,但用户第二天回来说"继续帮我处理昨天那个订单"时,Agent 直接愣住了——它完全不记得订单号、不记得协商结果,甚至不记得昨天聊过。这不是网络问题,也不是模型不够聪明,而是 Agent 缺乏长期记忆的根本性缺陷。
LLM 本质上是一个无状态的计算引擎。它的所有"知识"都来自训练数据,而对话过程中的所有信息,都只能临时存放在上下文窗口里。窗口内的内容模型能"看见",窗口之外的信息则完全不存在。就像一个人只有几秒的工作记忆,说完上一句话就忘了前面所有内容,这样的人没法处理任何复杂的连续任务。这个缺陷在短对话中不明显,但只要对话变长、跨天、或者需要积累历史信息,问题就会大面积爆发。
这个问题的普遍性远超想象。从 2023 年 AutoGPT 爆火开始,各家 Agent 项目在"怎么让 Agent 记住东西"这件事上走了完全不同的路线。有些把操作系统虚拟内存的概念搬了进来,有些把向量数据库当成了外置大脑,有些干脆把记忆做成了独立服务。本文要对比的就是其中最有代表性的六个项目,它们分别代表了 Agent 长期记忆设计的六种典型思路。
1.2 先把"记忆"这个词拆成四种类型
在对比项目之前,我们必须把"记忆"这个概念拆清楚,否则就是在拿苹果和橙子做比较。行业内默认的分法是四种记忆类型:
- 短期记忆(工作记忆):指当前上下文窗口里能直接看到的全部信息。它本质是窗口的内容,随对话推进不断被新内容挤掉,不需要额外存储。
- 长期记忆:指存储在外部系统中的信息,能在多次会话之间持久保留。这是所有项目都在解决的核心问题。
- 情景记忆:记的是"发生过什么事"。比如用户上周买过什么、Agent 上次执行任务的完整路径、某个项目的决策过程。
- 语义记忆:记的是"事实是什么"。比如公司知识库里的制度、FAQ 标准答案、用户的基础画像信息。
实际项目里,情景记忆和语义记忆经常共用一个存储引擎,但检索策略完全不同。情景记忆偏重时间线回放和按 ID 召回,语义记忆偏重向量相似度检索和标签过滤。如果你在设计记忆层时没有先分清这两种类型,后面的检索效果一定会别扭。
1.3 长期记忆的核心矛盾:写什么、存哪里、怎么取
任何长期记忆方案都逃不过三个核心问题,这也是我评价一个项目好坏的主要维度:
第一个问题,写什么。不是所有对话内容都值得记住。如果每轮对话都完整存进外部存储,三个月之后向量库里全是垃圾,检索出来只会污染新对话。所以主流项目基本都在做"记忆提炼"——让 LLM 定期做摘要、抽取关键实体和事件。
第二个问题,存哪里。存数据库、存文件、存向量库,各个项目给出的答案五花八门。存储介质的选择直接决定了查询方式、扩展成本和召回效果。这是本文对比的核心维度之一。
第三个问题,怎么取。这一步最容易被低估。很多人在实验环境觉得"只要把内容存进向量库就能用了",到生产环境才发现:检索到的信息不相关、相关但过期、多个记忆片段互相矛盾,这三种情况比"检索不到"更难处理。记忆系统设计得好不好,八成体现在检索环节,而不是存储环节。
这三个问题,是我们对比六个项目的一条暗线。每个项目在回答这些问题时的取舍不同,就形成了各自独特的设计风格。
2. 六个主流项目的长期记忆设计思路拆解
2.1 MemGPT / Letta:把操作系统搬进 Agent
MemGPT 是 UC Berkeley 的一个开源项目,后来改名为 Letta。它的核心创意相当大胆:把 LLM 的上下文窗口当作"物理内存",把外部存储当作"磁盘",然后用操作系统虚拟内存的分页技术来解决记忆容量问题。
具体工作逻辑是:Agent 有一个主上下文和一个外部存储。当主上下文快满时,系统通过"页面换出"把不重要的记忆写入外部存储,再把当前任务需要的信息换入上下文。这里的"重要"不由简单的过期时间决定,而是由一个记忆管理员来判定哪些信息值得留在主上下文、哪些可以被归档。
MemGPT 的独特价值在于把记忆管理从应用层下沉到了系统层。我们在数据库缓冲池、Redis 缓存淘汰里见过类似思想,但很少有人把它带到 Agent 领域。这个方案在长时间会话场景下表现很稳定,比如虚拟助手或角色扮演类的应用,因为你不需要自己操心上下文窗口什么时候会撑爆。
但它的缺点同样明显:系统复杂度偏高。你需要理解换页规则才能做精细调优,否则容易出现"该记住的被换出去了、该扔掉的却留下来了"的情况。我实测了一段时间后觉得,如果你只是想快速给 Agent 加一个长期记忆,MemGPT 不是那种开箱即用的方案,它更像一个值得学习的设计范本。
2.2 LangChain / LangGraph:图结构 + 检查点模式
LangChain 生态在记忆管理上的演进很值得关注。早期版本用 ConversationBufferMemory 和 ConversationSummaryMemory,思路简单粗暴:要么全量缓存,要么定期做摘要。这两个模块在真实项目里效果很一般,因为它们本质上只是给上下文窗口加了一层包装。
到了 LangGraph 时代,记忆系统升级成了基于图的检查点机制。检查点会把 Agent 每一步的状态持久化到一个线程里,下次继续这个线程时,可以从任一步骤恢复执行。这个设计对多步骤任务编排特别友好,你可以在一个多 Agent 协作系统中保存每个节点的状态,包括中间变量、消息历史、工具调用结果。
LangGraph 的长期记忆设计本质上是"流程状态保存",而非"内容记忆"。它的强项在于调试和回放:出问题时你可以完整看到每一步的状态迁移。它的弱点是:它保存的是状态,不是知识。如果想让 Agent 记住"这个老客户喜欢什么类型的产品",LangGraph 原生并不支持这种语义记忆,需要你自己叠加向量库或数据库。
我个人的判断是,LangGraph 更适合作为你构建 Agent 的编排底座,而不是专门的记忆系统。你要是业务里已经用了 LangGraph,记忆层另外找工具补上就行。
2.3 AutoGPT:向量数据库 + 自动摘要的"先锋路线"
AutoGPT 是让 AI Agent 概念普及化的项目之一。它在记忆设计上选择了一个大胆但朴素的路线:让 Agent 在运行过程中定期把重要对话内容保存到向量数据库(默认是 Pinecone,也支持 Weaviate 等),需要的时候通过语义搜索召回相关记忆。它不区分情景记忆和语义记忆,所有信息统一进向量库。
这套方案的优点是简单直接。你只需要定义好"什么该存"和"定期清理旧数据"两条规则,就能跑起来。对于数据探索、知识库问答、内容生成这几类场景,这个方案足够用,上手成本在六个项目里属于最低的一档。
但它的问题也很明显。检索质量完全取决于摘要质量和向量相似度,容易出现记忆混叠。比如用户上次讨论"想要一个蓝色沙发",你保存的摘要如果是"用户讨论家居装修偏好",下次检索时"蓝色"这个关键信息就丢了。AutoGPT 早期版本因为无限自我循环和记忆膨胀问题经常被吐槽,但它提出的"自动摘要 + 向量检索"组合,已经成为后来很多项目的记忆基础设施。
2.4 SuperAGI:微服务化的记忆架构
SuperAGI 是一个面向开发者的 Agent 管理平台,它的记忆模块给我印象最深刻的一点就是工程化。它不把所有记忆塞进一个存储引擎,而是把记忆拆分成多个租户级别的存储空间。每个 Agent 实例拥有自己的短期记忆存储、长期记忆存储和共享知识库,各租户之间数据隔离。
SuperAGI 在记忆上的核心优势在于可观测性。它提供了记忆管理面板,你可以直观看到每个 Agent 存了哪些信息,还能手动清理和编辑。这种能力在生产环境里非常重要,因为 AI 系统最怕的就是黑盒。出问题时你能直接检查记忆内容,而不是对着数据库猜测。
不过它的缺点是部署成本偏高。微服务架构需要跑多个容器,如果你想在一个轻量服务里快速做实验,它的上手成本会让你头疼。我见过一些小团队用 SuperAGI,结果光部署和调参就耗掉两周,业务还没跑起来。我的建议是:SuperAGI 更适合企业级多 Agent 管理场景,不适合个人项目起步。
2.5 BabyAGI:极致的任务迭代与上下文自刷新
BabyAGI 是早期的任务驱动型 Agent 项目,代码量很小,但它的记忆处理方式代表了一条独特的路线:不保存对话内容,而是保存"任务队列 + 任务结果"。Agent 每次循环会拉取新任务、执行任务、把结果添加到结果列表,同时根据结果再生成新任务。它的长期记忆本质上是一张持续增长的任务-结果表。
BabyAGI 的设计思路后来影响了大量自动化工作流项目。它证明了:只要任务生成和优先级排序做得足够好,Agent 可以在不维护复杂记忆的情况下完成多轮工作。对于批量数据生成、自动化任务链这类场景,它是最省心的方案。
但它的缺点也很显著:没有真正的语义记忆能力。如果下一个任务需要引用很久前的上下文,系统无法直接召回。对于需要深度推理的对话场景,这个方案不太够用。如果你要做的是聊天类 Agent,不要参考 BabyAGI,它适合的是任务型 Agent。
2.6 Zep:把记忆做成一个独立服务
Zep 是我个人比较欣赏的一个方向。它把长期记忆组件做成了独立的记忆服务,只需把消息发送给 Zep,它就会自动完成信息抽取、摘要、时间线构建和语义检索。Zep 的核心概念是时间感知的知识图谱。
它不是只存向量,而是维护每个实体和事件之间的关系、时间戳和置信度。举个例子:用户说"我三周前住在上海,今天搬到了北京",Zep 会生成一条时间线:上海-居住-三周前,北京-居住-今天。当你询问"用户现在在哪里",它能给出基于时间感知的正确答案,而不是把两条记忆平等地交给 LLM 去猜。
Zep 的底层支持 Postgres 和 Neo4j 这类图数据库,并用 Graphiti 框架构建时序知识图谱。它的缺点是需要额外的服务部署和数据建模成本,但如果你要做的是严肃的长期业务系统,这个成本是值得的。Zep 在六个项目里,是把记忆写入质量和时间感知逻辑做得最完整的一个。
3. 设计思路对比与场景选型建议
3.1 六个项目的记忆系统维度对比
为了直观呈现六个项目的差异,我把它们整理成一张对比表。这张表基于我实际使用体验整理,不是照抄官方文档,参数按默认配置估算。
| 项目 | 核心记忆载体 | 记忆类型侧重点 | 检索方式 | 上手成本 | 适用场景 |
|---|---|---|---|---|---|
| MemGPT/Letta | 虚拟内存分页,上下文窗口 + 外部存储 | 长期记忆(情景为主) | 系统换页式召回 | 中高 | 长时间会话、虚拟助手、角色扮演 |
| LangChain/LangGraph | 图结构检查点(线程状态) | 流程状态记忆、工作记忆 | 按线程恢复状态 | 中 | 多步骤任务编排、客服流程 |
| AutoGPT | 向量数据库(默认 Pinecone) | 情景+语义混合 | 向量相似度搜索 | 低 | 数据探索、知识库问答、内容生成 |
| SuperAGI | 微服务化多存储空间 | 长期记忆 + 共享知识库 | 面板管理 + 向量检索 | 高 | 企业级 Agent 管理、多 Agent 协作 |
| BabyAGI | 任务队列 + 结果列表 | 任务型记忆 | 任务 ID 遍历 + 顺序读取 | 最低 | 自动化任务链、批量数据生成 |
| Zep | 时序知识图谱 | 情景 + 语义混合,含时间感知 | 图查询 + 向量检索 | 中 | 对话记忆、个性化推荐、知识管理 |
这张表里最值得关注的是"检索方式"这一行。它决定了系统在不同场景下的表现风格。比如 MemGPT 的换页式召回适合对话连续性强的场景,因为它在上下文窗口内做管理;AutoGPT 的向量检索适合信息密度高、相关性分散的场景,因为它不在乎对话顺序。
3.2 按业务场景选择的三个判断标准
不要一上来就问"哪个项目最好",要先问"我的业务是哪个类型"。我用三个判断标准帮你做取舍。
判断标准一:会话形式是否长驻。
如果你的 Agent 主要处理长时间、多轮、跨天会话,比如陪伴型助手、深度咨询顾问,优先考虑 MemGPT/Letta。它把上下文窗口管理做到了系统级,长时间运行不会因为记忆膨胀而瘫痪。如果只是短问答型 Agent,比如 FAQ 机器人,LangChain 的检查点方案配合向量库就足够了,没必要引入 MemGPT 的高复杂度。
判断标准二:是否需要跨会话维持"世界状态"。
跨会话维持指的是:用户隔了两周回来,Agent 还能想起上次聊到哪、以前的决定是什么。如果业务需要这种能力,Zep 是最稳妥的方向,因为它的知识图谱能明确表达"什么时候发生了什么",而不是把所有记忆都熔成向量。如果只是需要"记笔记式"的记忆,AutoGPT 的向量摘要方案就够用。
判断标准三:团队是否有工程化维护能力。
如果你有运维和平台开发资源,SuperAGI 的微服务架构能让你对每个 Agent 的记忆做精细管理。如果你是一个人在做小项目,我建议别碰微服务,先用 BabyAGI 或 AutoGPT 这类轻量方案跑通业务闭环。很多团队在一开始就上了重架构,结果光部署和调参就耗尽精力,业务反而没跑起来。
3.3 一个容易被忽略的维度:记忆的"写入质量"
对比表里大家最容易忽略"记忆写入质量"这个横切维度。很多项目存储做得很好,但没处理好"什么值得写"。写入质量差的表现有三种:信息冗余导致检索噪声大、摘要过度压缩导致关键细节丢失、实体抽取不准导致图谱数据错误。
在六个项目中,Zep 和图谱方案在写入时做了实体关系抽取、时间戳标注和置信度记录,所以写入质量相对最高。MemGPT 通过系统级换页策略在写入时做了重要性排序,质量也不错。AutoGPT 和 BabyAGI 的写入质量完全取决于你的提示词设计——如果提示词没有要求 LLM 输出结构化摘要,写入结果会很乱。
所以选型时多问一句:这个项目有没有帮你做写入端的质量控制?如果没有,你需要自己写一个记忆提炼器,在写入前先用一个模型调用做摘要和实体抽取。
4. 动手实践:给 Agent 加一个可用的长期记忆层
4.1 一个最简但可扩展的记忆层设计
选型归选型,落地时你往往不能直接照搬某一个项目,而是要把多个项目的设计思想混搭。我给出一个经过生产验证、代码量不大但可扩展的记忆层设计方案,综合了 LangGraph 的状态管理和 Zep 的时间感知思想。
记忆层分三层设计:会话层负责短期记忆,保存当前会话的原始消息列表和摘要,使用 LangGraph 的检查点机制,在对话线程内按会话 ID 恢复;摘要层负责当会话消息数超过阈值(比如 30 条)或对话时长超过 10 分钟时,触发一次摘要任务,把当前会话的要点提炼成结构化事件,包括时间、参与者、主题、结论、待办;知识层负责把摘要中的事件写入带时间戳的存储,关键实体按关系拆表,用来支撑语义检索和时间线查询。
这个设计的核心价值在于把"对话记忆"和"事实记忆"分开:对话摘要负责让 Agent 能"回看",事实拆解负责让 Agent 能"回答"。这样既保证了对话连续性,又保证了知识可检索。
4.2 我用 Python 实现的一个轻量示例
这里我用 Python 写了一个最小可运行的示例,只为了看清记忆层与 Agent 的交互逻辑。它只依赖标准库 sqlite3 和一个摘要函数占位,实际使用时,你需要把摘要函数替换成真实的模型调用。
import sqlite3 import json from datetime import datetime MEMORY_DB = "agent_memory.db" def init_db(): conn = sqlite3.connect(MEMORY_DB) c = conn.cursor() # 事件表:保存带时间戳的结构化记忆 c.execute(""" CREATE TABLE IF NOT EXISTS events ( id INTEGER PRIMARY KEY AUTOINCREMENT, event_time TEXT NOT NULL, agent_id TEXT NOT NULL, content TEXT NOT NULL, entities TEXT ) """) conn.commit() conn.close() def save_event(agent_id, summary, entities=None): """保存一条时间感知的长期记忆""" conn = sqlite3.connect(MEMORY_DB) c = conn.cursor() c.execute( "INSERT INTO events (event_time, agent_id, content, entities) VALUES (?, ?, ?, ?)", (datetime.now().isoformat(), agent_id, summary, json.dumps(entities or [])) ) conn.commit() conn.close() def recall_recent(agent_id, limit=5): """按时间召回最近的记忆,模拟时间感知检索""" conn = sqlite3.connect(MEMORY_DB) c = conn.cursor() rows = c.execute( "SELECT event_time, content FROM events WHERE agent_id=? ORDER BY event_time DESC LIMIT ?", (agent_id, limit) ).fetchall() conn.close() return rows def summarize_conversation(messages): # 实际项目中替换成 LLM 调用 # 这里用简单的规则做演示,生产环境请用模型生成结构化摘要 return "用户询问了订单状态,并提到希望明天收到更新。" def run(): init_db() # 模拟对话结束后写入摘要 save_event("agent_001", summarize_conversation([]), ["订单", "更新"]) # 模拟新会话开始时召回 memory = recall_recent("agent_001") for item in memory: print(item) if __name__ == "__main__": run()这段代码的核心是 save_event 和 recall_recent 两个函数。save_event 负责把记忆连同时间戳写入事件表;recall_recent 负责按时间排序召回最近的记忆,然后把这些记忆拼接进新会话的 system prompt。entities 列是为了后续做图检索或过滤预留的,虽然我用 json 简单存了,但正式项目里建议拆成独立的实体表和关系表。
4.3 这个记忆层怎么接到现有 Agent 里
接入方式不复杂:每次新会话开始时,先从记忆系统拉取最近 N 条记忆,格式化成一段"记忆上下文"追加到系统提示词后面;每次会话结束时,对整个会话做一次摘要并写回记忆系统。这样读写分离。
这里有几个我在实测中总结的细节:
回写时机不要放在每轮对话之后,否则会产生大量冗余摘要和写入压力。正确做法是只在会话结束时写一次,或者对话长度超过阈值时触发一次增量摘要。
召回过滤不要只按时间排序,要加入相关性过滤,比如按实体匹配过滤一遍,能显著降低无关记忆对模型输出的干扰。
上下文放置顺序在 system prompt 里,记忆上下文应该放在任务指令之后、用户消息之前。顺序会影响大模型的注意力分配,实测放在最后容易被长指令淹没。
5. 实操中踩过的坑:记忆系统的三个典型故障
5.1 记忆膨胀:上下文被历史摘要塞爆
我见过最普遍的坑是"把记忆当存储,不设触发阈值"。有一次我做文档问答 Agent,为了追求记住所有历史细节,把每轮对话都存了摘要还全部塞进 system prompt,结果第三条会话开始,模型输出质量就开始下降——提示词里塞了太多无关摘要,模型核心注意力被稀释了。
排查思路:先检查实际进入上下文的记忆量。如果单次请求的 token 数超过模型窗口的 30%,基本可以断定是记忆膨胀。解决办法有两个:限制召回条数,比如只召回最近的 5 条;引入缓存机制,把不活跃的旧记忆换出系统。MemGPT 的换页逻辑在这里特别值得参考,别把所有记忆都平等对待。
5.2 语义漂移:向量检索召回了完全无关的内容
向量检索的默认行为是按向量距离排序,但"语义相近"不等于"业务相关"。我做过一个用户画像 Agent,把用户聊过的所有内容都存进向量库,结果一次检索"生日礼物推荐"时,召回的全是用户聊星座的旧内容,因为它们在某几个维度上向量距离很近。这就是语义漂移。
解决这个问题,建议在向量检索前面加一层业务过滤,也叫预过滤。先按标签、Agent ID、时间范围做 SQL 过滤,再对过滤后的少量候选做向量检索,这样既快又准。另一个技巧是混合检索:同时跑关键词匹配和向量检索,再用一个简单的打分策略合并结果。别指望单一向量模型能完全理解你的业务语义。
5.3 记忆冲突:旧记忆和新事实打架
当系统跨会话积累大量记忆片段,冲突是必然的。用户可能上周说"我喜欢极简风的设计",这周说"我最近在尝试复古风"。如果你把两段记忆都平等地交给 LLM,模型很容易混淆。
我的处理经验是给记忆加上时间权重和置信度字段。检索时优先召回最近时间窗口内的记忆,同时让 LLM 在输出时注明"根据近期偏好"。如果你用的是 Zep,它的时序知识图谱天生支持时间权重;如果你用自建 SQLite 方案,只需要在查询时按 event_time 排序,并给每个记忆条目增加一个"最后确认时间"字段,定期让模型确认一次是否仍然有效。
5.4 排查工具与调试思路
记忆系统是典型的"数据级 bug 大于代码级 bug"的系统,报错信息往往不会告诉你哪条记忆出了问题。我的调试心得是:先把记忆存储导出成 JSON,手工查看里面的内容是否结构化、是否有明显冗余。如果摘要内容混乱,先修写入端的提示词;如果摘要正常但召回不满意,再调检索端的过滤和排序规则。一定要先看数据,再改代码。
如果项目支持,强烈建议给记忆层加一个可视化面板,哪怕只是一张简单的终端表格,列出每个 Agent 最近写入的 20 条记忆。这个操作在调试时能省下至少一半的排查时间,我后来在 SuperAGI 上就主要靠这个面板做日常维护。
6. 选型之后的落地经验
6.1 一个不太常见的升级路径:从会话记忆走向知识图谱
六个项目的选择,本质上是从"会话级记忆"向"知识级记忆"演进。会话级记忆解决的是"记住上次聊了什么",知识级记忆解决的是"理解用户为什么要这么聊"以及"把不同时间发生的事实串联起来"。如果你的项目做到后期,一定会从 AutoGPT 那种纯向量存储迁移到 Zep 那种带时间感知的图谱存储,因为后期你需要的不只是搜索相似内容,而是推理。
迁移到知识图谱时,建议不要一步到位。先在现有存储上增加实体抽取和时间戳字段,验证一段时间;确认数据质量没问题后,再引入图数据库,把实体关系单独建模。这样迁移过程中老系统还能继续跑,业务不中断。
6.2 那些容易被遗忘的"元记忆"设计
最后想提醒一个关键点:元记忆,也就是"关于记忆的记忆"。很多 Agent 会记录用户的每条偏好,但从不记录"这个偏好是什么时候被确认过"、"哪条记忆在多次会话中被反复引用"、"哪里出现了矛盾记忆"。这些元信息是记忆系统自我修正的基础。
在实际产品里,我会在事件表旁边加一张 memory_meta 表,记录每条记忆的来源(用户明说还是模型推断)、置信度(模型置信度)、最后确认时间(最后一次被验证的时间)。每隔几天让 Agent 自动扫描低置信度或长期未验证的记忆,主动向用户确认或清理。这个功能花不了多少代码,但能显著提升长期运行时记忆系统的干净程度。
我自己在多个 Agent 项目里来回切换过这些方案,最后的体会是:没有绝对最好的记忆框架,只有当前阶段最适合你的记忆框架。早期用轻量方案快速迭代,中期引入结构化存储,后期才需要完整的时间感知和图谱能力。这不是技术攀比,而是一个系统逐渐长出自己骨架的过程。最后分享一个细节:无论你选哪个方案,先想清楚你要存的是"对话记录"还是"业务事实",这个决定会直接影响你整个记忆层的架构走向。