1. 为什么 Agent 记忆系统会变成刚需
做 AI Agent 开发这一年多,我最大的感受是:记忆系统的好坏,直接决定了一个 Agent 项目是“demo 级玩具”还是“生产级工具”。很多刚接触 Agent 框架的开发者会问,大模型本身就有上下文窗口,为什么还要单独搞一套记忆系统?这个问题很关键,我建议所有入坑 AI Agent 的人先想清楚这一层,再去看具体方案。
1.1 我先讲一个自己踩过的坑
去年我做了一个开源 Agent 项目,用来帮团队做知识库问答和任务拆解。第一版代码很简单,把所有对话历史直接塞进 prompt,然后调大模型 API。单轮问答效果不错,但只要用户聊到第三轮,就明显感觉到模型开始“失忆”:前面刚说过喜欢简洁回答,后面它就开始长篇大论;上午确认过的项目截止时间,下午再问就变成了“我不确定您之前有没有提到过”。最离谱的一次,用户连续问了五个相关问题,Agent 把第三个问题的结论完全忘掉,给出了自相矛盾的答案。
这时候我才意识到,上下文窗口再大,也不等于记忆。大模型的上下文是“临时工作台”,每次请求结束就清空了。想要跨会话、跨天、跨用户地记住关键信息,必须在模型外面搭一套独立的记忆体系。这就是 Agent 记忆系统存在的意义。后来我去调研了社区里几乎所有叫得上名字的开源记忆方案,做了对比和落地测试,这篇报告就是我当时调研过程的完整复盘。
1.2 Agent 记忆到底在记什么
先说清楚概念。Agent 记忆通常分成三类:
- 工作记忆:就是当前任务上下文,比如正在进行的多轮对话、正在执行的子任务状态,对应到工程上就是会话窗口或者 LangGraph 里的 thread 状态。
- 长期记忆:跨会话保存的事实、偏好、知识,比如“用户是后端工程师”“用户偏好 Python”“项目截止时间是周五”。这部分是需要外部存储和检索的。
- 情景记忆:记住“发生过什么”,比如“上次讨论时用户否定了方案 A”“三天前已经发过版本 v1.2”。情景记忆往往带时间属性,像 Zep 这类时间感知图记忆就是专门做这个的。
还有一个容易被忽略的维度是程序性记忆,也就是 Agent 自身学会的技能和操作路径,严格来说这属于 Agent skill 的范畴。大部分开源记忆系统做的是长期记忆和情景记忆,工作记忆通常由 Agent 框架本身管理。理解了这个分类,再去读各项目的文档,就不会被“记忆”这个词搞得一头雾水。
1.3 这篇报告能帮你解决什么问题
如果你正在做以下事情,这篇报告应该对你有用:
- 你在选型一个 Agent 记忆组件,但面对 Mem0、Zep、Letta、LangGraph Checkpoint 等一堆开源项目不知道选哪个。
- 你已经把记忆系统接进项目了,但发现检索不准、写入重复、上下文膨胀这些问题不知道怎么排查。
- 你想搞清楚这些记忆系统的底层原理,避免被各种营销概念带偏。
我在报告里不做那种“人人都有优点缺点”的废话,直接给结论、给对比、给代码、给排坑经验。每个方案我都实际部署过,不是在 GitHub 上刷 star 就算了解的那种“云调研”。
2. 主流开源方案全景扫描
目前社区里讨论度最高的开源 Agent 记忆系统,我整理下来就五个代表:Mem0、Zep(Graphiti)、Letta(原 MemGPT)、LangGraph Checkpoint、Cognee。另外还有一些小众但很有特点的项目,比如 Memary、LangMem、SuperMemory,我也一并提几句。
2.1 Mem0:目前最像“记忆即服务”的开源组件
Mem0 是我最先测的方案。它的设计思路很明确:给 Agent 提供一层独立的“记忆存储与检索”能力。底层支持 Qdrant、pgvector、Milvus 等向量库,上层封装了记忆提取、检索、更新的完整流程。
Mem0 的亮点在于它对“记忆增量更新”做了专门处理。用户每次说了新内容,它不只是往里塞一段向量,而是先让 LLM 判断这段内容是否包含值得保存的记忆,再和历史记忆做对比,能合并的合并、该删除的删除。这个机制说实话很聪明,避免了我之前遇到的“记忆越存越乱”问题。
社区热度也很高,GitHub 上 star 涨得飞快,文档、示例代码都很齐全,官方还有托管版本可以白嫖额度。对大多数团队来说,Mem0 是最稳妥的“第一个记忆系统”。
2.2 Zep / Graphiti:知识图谱路线的时间感知记忆
Zep 这个项目的核心技术叫 Graphiti,是构建时间感知知识图谱的引擎。和向量检索路线完全不一样:Zep 会把对话、文档拆成实体和关系,节点带时间戳,边带时效权重。检索的时候不是做相似向量召回,而是从图谱里做“时态图遍历”,直接回答“用户三周前对这个问题是什么态度”。
这套设计的好处是可解释性强。你问它为什么召回这条记忆,它能给你看完整的实体关系路径。Zep 在做“情景回忆”方面几乎是吊打纯向量方案。代价就是部署有点重,依赖 Neo4j 或类似图数据库,维护成本比 Mem0 高一个量级。适合知识密集、关系复杂、对可解释性有要求的场景。
如果让选一个性能最强的,我可能会投 Zep;如果让我选最省心的,那我投 Mem0。这两条路线的差异,基本代表了当前 Agent 记忆系统的两个流派。
2.3 Letta(原 MemGPT):用操作系统的思路管记忆
Letta 这帮人把大语言模型比作操作系统:上下文窗口有限,相当于“内存”;外部记忆存储相当于“磁盘”;模型内部的自我反思机制相当于“页面置换”。系统会自动决定哪些信息留在上下文里、哪些信息换出到外部存储、什么时候从外部把旧记忆加载回来。
这个抽象很有意思,它解决的是“上下文爆炸”的问题。用 Letta 的时候,你不需要手动设计该把什么记忆塞进 prompt,它会通过记忆编辑工具自己管理。换句话说,它把记忆管理从“开发者的责任”变成了“Agent 的一种能力”。
实际用下来,Letta 更适合做那种长时间自主运行的 Agent,比如个人助理、自动研究员。但它因为定制了整套 runtime,所以如果你想把它嵌进已有的 LangGraph、LangChain 流程,会有点别扭。它更像一个完整的 Agent Server,而不是一个可插拔的组件。
2.4 LangGraph Checkpoint:不算记忆系统,但绕不开
LangGraph 是现在主流的 Agent 编排框架之一,它的 Checkpoint 机制在 dev 圈里经常被误归为记忆系统。严格来说,它管的是工作记忆持久化:把图的每个节点状态、消息列表、分支进度存到存储里,每次恢复时从 checkpoint 接着跑。这个很像给流程图加了“存档点”。
LangGraph 官方也有 long-term memory 的探索,比如 MemoryStore 接收器,能按用户维度存跨线程的 key-value,但整体还是偏基础,没有 Mem0 那种记忆提取、更新、遗忘的完整闭环。所以我的建议是:LangGraph Checkpoint 该用就用,它解决工作记忆;但长期记忆还是老老实实接一套独立的记忆系统。
2.5 Cognee:把记忆做成结构化知识管线
Cognee 的定位稍微不同,它更像是一个“记忆构建管线”:从原始文档、对话记录里抽取实体、概念、关系,然后构建成知识图谱和向量索引,最终给 Agent 提供结构化查询能力。
如果你的 Agent 需要的是“基于知识库的推理”,而不是“记住用户说了什么”,Cognee 会比普通 RAG 工具更合适。我在一个文档问答项目里用 Cognee 做过知识抽取,它的实体识别准确率还算能打,缺点是配置文件比较多,上手曲线比较陡。
2.6 其他值得记录的项目
- Memary:把记忆划分为短期、长期和反思层,用知识图谱组织,设计理念很清晰,适合做用户画像型 Agent。
- LangMem:LangChain/OpenAI 团队出的记忆工具包,通过“提取、修剪、固化”三条管道管理记忆,和 LangGraph 生态结合紧密。
- SuperMemory:更偏个人知识库记忆,当年号称“ChatGPT 记忆插件”,适合做私人笔记助手,不太适合做通用 Agent 组件。
3. 多维对比:五个关键维度给出结论
纸上谈兵没意思,我把五个方案真正部署了一遍,从五个维度做了对比。这里的结论都是基于我自己的测试环境,可能和官方宣传的数据有差异,但我尽量做到客观,把测试条件和限制说清楚。
3.1 存储与索引:向量库、图数据库、KV 的战场
存储层的选型决定了记忆系统的能力边界。
Mem0 默认走向量库,落地最简单。Qdrant 一个 docker 就能拉起来,pgvector 可以复用现有 PostgreSQL,基本没有额外学习成本。向量索引擅长做“语义相似”,但细粒度的关系查询就要靠 LLM 二次加工。
Zep 用图数据库,回忆逻辑强很多,比如“用户上周提到的技术栈和今天的话题有没有关联”,图遍历可以直接给出路径。但图数据库的运维门槛真的不低,如果团队里没人懂 Neo4j,我建议慎重。
Letta 的存储比较轻,主要靠自带的 SQLite/PostgreSQL 保存记忆块和指针文件,配合嵌入模型做检索。它不追求对复杂关系的建模,更看重“记忆块怎么调度到上下文”。
LangGraph Checkpoint 是 KV/文档型存储,按 thread_id 存状态快照,完全不涉及语义索引。它只负责“状态恢复”,不管“语义召回”。
Cognee 是混合型,图谱和向量都做,数据先入图再入向量,两边同步。这个方案在理论上最全面,但你得同时维护两套存储,资源消耗和复杂度都偏大。
3.2 检索策略:相似度搜索、图遍历、混合检索哪种好用
这一块直接影响用户体感。
Mem0 的检索采用“向量相似度 + LLM 相关度排序”的组合。第一次召回先拿 Top-20 候选,过 LLM 打分后保留 Top-3,准确率明显比单纯向量搜索高。缺点是引入 LLM 调用后,每次检索会有几百毫秒额外延迟,成本也上去了。
Zep / Graphiti 是图先行的检索,按实体邻域和时间窗口做遍历,时间复杂度低,结果稳定,不会出现“向量搜到八竿子打不着的内容”这种尴尬。它有一套基于时间衰减的边权重机制,近期记忆天然排前面。
Letta 的检索更像“虚拟内存分页”,Agent 自己决定加载哪块记忆块,从磁盘回到上下文。这套机制灵活,但对于那些依赖确定性检索的开发者来说,你没法预测它也下一次会换入什么。
LangGraph Checkpoint 的“检索”就是按 thread_id 取状态,没有语义检索。Cognee 则是图谱过滤加向量召回的混合,先在图谱里拿相关子图,再把子图内的文本向量化去配权重。
3.3 上下文压缩与遗忘机制:谁能主动“断舍离”
记忆系统最怕的就是无限膨胀。我到后期测试发现,如果只存不删,再强的检索也会被噪声淹没。
Mem0 有清理机制:每条记忆会有更新时间、访问次数,超过阈值或者被用户新信息覆盖,就会被标记为“已过期”并移出活跃集。这个机制是 LLM 驱动的,清理决策有语义判断,不会误删关键信息。
Zep 靠时间衰减实现软遗忘:旧关系的权重越来越低,检索时即便命中也不会排到前面,相当于“自然遗忘”。我觉得这个设计非常优雅,命中了一条旧记忆但权重很低,比直接删掉更符合人类记忆规律。
Letta 的上下文管理由 Agent 自己做,它通过自我反思决定“这个记忆块应该被丢弃还是归档”。效果好不好,很大程度取决于模型本身的判断力,实测中 GPT-4 级别的模型表现良好,换成开源小模型就有点不稳。
Cognee 有显式的“审计/清理”工具,算是半自动。LangGraph Checkpoint 不做语义清理,状态存了就存了,过期靠你自己删。
3.4 框架集成与工程成熟度
最简单的判断方式是看它怎么融入 LangGraph、LangChain、LlamaIndex 这些主流程。
Mem0 提供了现成的 LangChain/LlamaIndex 集成,还支持 OpenAI Agents SDK,基本就是“装包 + 写两行配置”的事。我自己从零接入到跑通只用了两个小时,这是它最吸引人的地方。
Zep 有官方 Python/TypeScript SDK,接口设计得也还可以,但因为底层是图数据库,接入前必须先把它管理的图谱 schema 设计好,否则后续查询会很别扭。
Letta 自成体系,你可以把它当成独立 Agent 运行时用,但想塞进 LangGraph 流程就基本不可能,生态封闭性较高。
Cognee 的集成是管线式 API,输入文档、输出记忆,适合用批处理任务去调。LangGraph Checkpoint 则只和 LangGraph 本身绑定,别无分店。
3.5 成本、自托管难度与社区健康度
如果我做项目评估,一般会看三件事:部署成本、维护成本、社区活跃度。
Mem0 自托管最轻量,一个向量库加一个 Python 服务就够,CPU 资源吃紧的小机器也能跑。社区非常活跃,Issue 响应快,遇到问题基本在 GitHub 上搜一圈就有答案。
Zep 默认依赖 Neo4j,如果你没有现成图数据库经验,起步会比较痛苦;一旦跑起来,日常维护主要还是图索引的优化,ES 级别的调优经验在这里同样适用。
Letta 有一体化 Docker 镜像,部署简单,但它需要相对强的算力跑记忆压缩任务,小内存机器跑起来比较吃力。Cognee 部署中等,文档繁杂,社区热度一般。LangGraph Checkpoint 部署零成本,但它的能力边界很窄,社区讨论基本都是围绕 LangGraph 本身展开的。
3.6 一个不算严谨但很直观的对比表
| 项目 | 记忆类型 | 存储索引 | 检索方式 | 遗忘机制 | 接入难度 | 适用场景 |
|---|---|---|---|---|---|---|
| Mem0 | 长期/情景 | 向量库 | 语义相似 + LLM 重排 | 增量合并/过期清理 | 低 | 通用 Agent 增强记忆 |
| Zep / Graphiti | 长期/情景 | 时间感知知识图谱 | 图遍历 + 时间权重 | 时间衰减 | 中高 | 知识密集、关系复杂场景 |
| Letta / MemGPT | 全类型 | SQLite/PostgreSQL | 记忆分页自动调度 | Agent 自我反思 | 中 | 自主长时间运行的 Agent |
| LangGraph Checkpoint | 工作记忆 | KV/文档存储 | 按 thread_id 恢复 | 手动清理 | 低 | LangGraph 流程状态持久化 |
| Cognee | 长期/知识库 | 图谱 + 向量 | 图过滤 + 向量混合 | 半自动 | 中高 | 文档知识抽取与推理 |
这个表我建议保存下来,做技术方案预选型的时候可以直接对照着划掉没必要的选项。
4. 一个可以直接复制的组合:LangGraph + Mem0 + Qdrant
光说不练假把式。我把自己跑通并且现在还在用的一个组合分享出来:Agent 编排走 LangGraph,长期记忆接 Mem0,向量库用 Qdrant。这套组合最稳,也是社区沉淀最多的搭配。
4.1 为什么选这个组合
LangGraph 负责把 Agent 的思考流程拆成节点,比如“意图识别 → 记忆检索 → 调用工具 → 生成回复”。Mem0 负责在“记忆检索”节点里提供长期记忆,让 Agent 能回忆起用户几天前说过的话。Qdrant 只是 Mem0 的底座,换 PostgreSQL 的 pgvector 也一样,我选 Qdrant 纯粹是因为它容器化部署最简单,监控面板也直观。
4.2 先把基础设施跑起来
Qdrant 用一行 docker 指令就能启动:
docker run -d --name qdrant -p 6333:6333 qdrant/qdrantMem0 我建议用 pip 安装官方 Python 包,它支持“独立服务模式”和“嵌入式模式”。嵌入部署最省事,同一个进程里直接调 API:
pip install mem0ai openai如果你要从零开始,还需要准备嵌入模型。Mem0 默认走 OpenAI 的 embedding,但国内团队用阿里、智谱、OpenAI 的都见过。我自己为了省钱换了本地开源的 bge-m3,用 sentence-transformers 加载,效果也没差太多。
4.3 核心代码:写记忆、读记忆、更新记忆
下面这段是我实际项目里摘出来的,去掉业务逻辑之后保留了核心调用链。
from mem0 import Memory # 初始化 Mem0,向量存储指向本地 Qdrant m = Memory.from_config({ "llm": { "provider": "openai", "config": { "model": "gpt-4o-mini", "temperature": 0 } }, "embedder": { "provider": "huggingface", "config": { "model": "BAAI/bge-m3" } }, "vector_store": { "provider": "qdrant", "config": { "host": "localhost", "port": 6333, "collection_name": "agent_memory" } } }) # ------------------- 记忆写入 ------------------- # 每次用户说话后,调用 add 提取值得保存的记忆 result = m.add( "用户偏好使用 Python 和 FastAPI,正在做一个开源 Agent 项目,计划两周后发布 v1.0", user_id="user_12345", metadata={"source": "chat", "session_id": "s_67890"} ) print(result) # 输出哪些记忆被新增、更新、删除 # ------------------- 记忆检索 ------------------- # 生成回答前,先检索和当前问题相关的历史记忆 related = m.search( "用户做的是什么技术栈的项目?", user_id="user_12345", limit=3 ) print(related)在 LangGraph 里接的时候,我把它设计成一个remember_node:
from langgraph.graph import StateGraph, END, START from langgraph.graph.message import add_messages from typing import Annotated, TypedDict class AgentState(TypedDict): messages: Annotated[list, add_messages] memory: dict async def remember_node(state: AgentState): query = state["messages"][-1].content related = m.search(query, user_id="user_12345", limit=3) # 把检索到的历史记忆拼到上下文中 memory_block = "\n".join([r["memory"] for r in related]) return {"memory": {"related": memory_block}}关键在于:不要每一次都把所有记忆往 prompt 里塞,只塞检索召回的最相关的 3 条,上下文干净,token 成本也低。
4.4 参数调优的几个心得
- limit 别贪多:我刚开始设置 limit=10,以为召回越多越好,结果模型被不相关的记忆干扰,回答质量反而下降。后来压到 3 条,效果好很多。
- user_id 一定要按业务隔离:多用户场景下,如果漏了 user_id,A 用户的记忆可能被 B 用户检索到,这是隐私事故级别的问题。
- metadata 里带上时间:给每条记忆打上一级时间戳,后续做时间衰减、做 Zep 那种“最近优先”的逻辑才有数据支撑。
- 温度设为 0:记忆提取和检索重排都是判断类任务,温度高了会导致提取结果不稳定,同样的话这次提取一条下次提取两条。
4.5 从 Demo 到生产还差三步
第一,加一层异步写入。对话过程中同步调用add()会拖慢首字响应,改成把对话日志先发消息队列,异步消费后再写进记忆系统。我用的 Redis Stream 比较简单,几百人在线没问题。
第二,做记忆审计。给记录维护每次写入的来源和置信度,来源分为“用户主动声明”“Agent 推断”“历史对话提取”。审计表能极大帮助纠错,用户说“我其实不是后端程序员”的时候,可以直接把错误记忆标记失效。
第三,定期做“记忆合并压缩”。Mem0 的 add 方法本身会触发增量更新,但每周最好跑一次离线批量任务,把分散的碎片记忆合并成大块记忆,性能会显著改善。
5. 常见问题与排查技巧实录
下面这些都是我真实遇到、并且在社区里也被反复讨论的问题。每个方案、每个组合都有各自的脾气,这块总结比原理部分更值得细看。
5.1 记忆写入太多、太碎,污染严重
刚开始用 Mem0 时,我提取到的记忆全是“用户今天说了句好的”“用户发了一个表情包”这种垃圾内容。问题出在提取阈值的设置上。
Mem0 有一个infer参数控制是否让 LLM 判断记忆重要性,默认在某些版本是开启的,但如果你用的模型能力不行,它没办法区分“闲聊”和“关键信息”。我后来做了一层硬性过滤:内容长度少于 10 个字的直接不保存;文本里没有实体词(技术栈、人名、时间、偏好动词)的不保存。
另外,短期高频出现的内容会不断触发更新,导致“同一件事存了 50 条”。我在生产环境加了“记忆合并窗口”,一小时内相同主题的对话,以最后一条为准,保存前先检索一遍是否已有近似记忆,有就直接更新,不新增。
5.2 检索不准,始终差一口气
如果你发现记忆系统总是唤不起真正有用的内容,先别急着怪系统。按这个顺序排查:
- 嵌入模型是否适配你的领域?通用 embedding 对专有名词不敏感,换成领域微调的 embedding,或者用 LLM 做二次重排,提升最明显。
- 检索的 query 是否完整?用户可能只说“那个项目怎么样了”,这种 query 直接去向量库搜基本搜不到有效记忆。正确做法是先让 Agent 把 query 做扩展,改写成包含实体和时间线索的完整句,再去检索。
- 是否做了时间衰减?纯向量检索没有时间概念,两周前的记忆和昨天的记忆权重一样,这对情景记忆是致命的。至少要手动加一个时间因子,对旧记忆降权。
5.3 多用户、多会话场景下的数据串线
这是所有记忆系统最危险的问题。我测试 Zep 的时候,因为 Session 和 User 的关系没有理清楚,出现过用户 B 在对话里“想起”了用户 A 的项目细节。后来我们强制规定:
user_id是业务用户的唯一标识,必须由业务方传入,禁止从消息内容里推断。session_id只是线程标识,默认不跨用户共享。- 所有检索入口,先按 user_id 做数据权限过滤,再进入语义检索,不能只依赖向量相似度做隔离。
这条规则适用于 Mem0、Zep、Letta,所有记忆方案都得遵守。
5.4 上下文窗口被历史记忆撑爆
有些开发者说“我加记忆系统之后,token 消耗反而上去了”,大概率是把记忆模块的输出全量拼到了 system prompt。正确做法是分两层:
- 短期会话内,只塞最近 2 轮对话,靠 LangGraph 的状态管理就够了。
- 长期记忆,只塞检索召回的 Top-3 到 Top-5,每条压缩成一句话摘要。
记忆系统应该是“外挂索引”,不是“全量搬运工”。把记忆当 prompt 的一部分无脑拼接,是很多 Agent 项目的通病。
5.5 记忆安全:我踩过的合规坑
最后必须聊一个很多人不注意的点:记忆系统是最容易泄露隐私的组件。你让 Agent 记住用户偏好,同时也意味着你要保存这些数据,而这些数据可能包含手机号、公司内部信息。
我现在的做法是:
- 敏感字段脱敏后再写入记忆,比如手机号中间四位打码。
- 记忆数据加密存储,至少要用 TLS 传输,存储端做静态加密。
- 提供“删除记忆”接口,用户可一键清空,这是很多主流产品的合规硬要求。
我之前在一个内部项目中把未脱敏的用户日志直接灌进了记忆系统,后来做安全巡检的时候差点出问题。从那时起,所有记忆写入前都要过一遍脱敏规则,宁可损失一些召回精度,也不能在合规上留下隐患。
6. 最后再分享一点个人体会
测试完这五个方案,我的一个强烈感受是:开源 Agent 记忆系统目前没有“银弹”。Mem0 均衡易用,Zep 推理更强,Letta 适合自主 Agent,LangGraph Checkpoint 是框架必备,Cognee 适合做知识管线。选型一定是从自己的场景出发,先确认要解决的是“跨会话记住偏好”还是“复杂关系情景推理”,再选方案,不要被 star 数量带着走。
如果让我给刚入坑的人一个最省心的建议:先用 LangGraph 做编排,用 Mem0 做长期记忆,向量库选 qdrant 或用已有的 pgvector。这套组合稳定性高、社区活跃、遇到问题有大量现成答案。等你的项目真的发展到需要关系推理、可解释召回的时候,再考虑上 Zep/Graphiti 也不迟。
记忆系统是 Agent 能力提升的关键一环,但它不是越复杂越好。先把基础链路跑通,让记忆闭环转起来,再慢慢沉淀属于你自己的最佳实践。