
这年头做 Agent 的谁没被“上下文不够用”坑过我自己就吃过一个大亏去年给团队做客服机器人用户在对话框里聊了二十分钟报修流程中间切出去接了个电话回来问一句“那我那个订单到底怎么处理”Agent 直接回复“您好请提供一下订单号”。问题的根子不在模型能力而在 Agent 没有记忆——前一轮的有效信息全丢了。后来我把市面上能排上号的开源 Agent 记忆系统整体过了一遍包括 Mem0、Letta原 MemGPT、Zep 与 Graphiti、LangGraph 持久化方案、Cognee 这些代表从存储架构、检索方式、生命周期管理、部署成本、生态成熟度几个维度做了横向对比。这篇文章就是那份对比报告的完整版。想给 Agent 配记忆、准备做选型、或者单纯想搞清楚“记忆系统到底在解决什么问题”的同学这篇可以当个参考底稿我尽量把每家的底层逻辑和落地代价都说人话。1. 为什么非要在 Agent 里单独搞一套记忆系统1.1 没有记忆的 Agent连三件小事都做不好先说个基本判断模型本身的上下文窗口再大也撑不起真正可用的 Agent。原因很俗——上下文不是免费的。我自己实测过一个中型的 RAG 客服流程把知识库检索结果、历史对话、工具返回信息全塞进上下文一轮请求的 token 消耗比纯对话高出五到十倍长会话跑几十轮之后即便模型没“忘”成本也先崩了。更关键的是Agent 的任务形态决定了它必须记住三类东西事实性信息用户叫啥、住在哪、订单号、会员等级、上次投诉的诉求。事件性信息昨天聊到哪了、刚才工具返回了什么结果、用户对哪个方案明确拒绝过。偏好性信息用户习惯长话短说、讨厌被追问订单号、对价格敏感、希望回复里带表情。这三类信息混在一起如果全放在上下文里不仅贵还会互相干扰。用户一个月前说的“我打算搬家”跟今天聊“新家需要装宽带”其实是两条有关联但不同优先级的记忆。没有单独的存储与检索机制模型要么把它们当成同一批东西强行推理要么干脆把旧信息丢了。1.2 对比报告的评价维度我是这么定的市面上的开源方案看着多真正拿来对比的时候如果只看“谁 Star 多”就太草率了。我这次所有项目都用同一套维度去打量存储形态内存、向量库、关系数据库、图数据库还是分层混合结构。这个决定了它能承载的记忆规模和查询方式。写入方式是对话后自动异步提取还是同步强制写入还是靠 Agent 自己主动调用 API 写入。这个决定了系统对业务代码的侵入程度。检索召回语义相似度、关键词、图遍历、规则加权还是混合策略。生命周期记忆会不会过期、会不会自我修正、有没有重要性分层。这个决定了长期运行后系统会不会“被垃圾记忆淹死”。集成成本需不需要额外部署服务、有没有 SDK、跟 LangChain/LlamaIndex 这类框架的兼容性。运维代价依赖哪些中间件、是不是要配套向量库和图数据库、并发上来之后扛不扛得住。带着这六个维度去看项目很多宣传话术就骗不了人了。所谓“记忆系统”本质上就是存储系统加一套围绕 LLM 特化的读写策略没有银弹只有取舍。2. 六个代表性开源方案逐个拆2.1 Mem0把“记忆提取”做成开箱即用的服务Mem0 是目前开源 Agent 记忆领域名声最响的项目之一核心定位是“Add memory to your AI apps”。它的一大特点是独立于具体 Agent 框架运行你把对话历史丢给它它自己完成实体抽取、关系提炼、事实标准化然后分层存储。这套系统的记忆分成短期记忆和长期记忆短期记忆直接关联当前会话上下文长期记忆沉淀用户画像、事实偏好这类跨会话稳定的信息。我用下来最大的感受是——它确实把“从对话里挖记忆”这件事工业化、产品化了。你不用自己设计提取 prompt也不用自己写向量化脚本SDK 里add和search两个接口就能完成大部分需求。实际接入大概是这种感觉from mem0 import Memory memory Memory.from_config({ vector_store: {provider: qdrant} }) # 写入一条记忆绑定用户 memory.add( 用户在上海工作养了一只柯基平时工作日没空接电话, user_iduser_10001 ) # 后续 Agent 需要时检索 results memory.search(用户的宠物和可用时间, user_iduser_10001)如果你只想先跑通一个原型Mem0 是最容易出效果的一个。唯一要留意的是它的核心能力依赖 LLM 做信息抽取所以每次写入都会产生 token 开销量大了之后账要算清楚。2.2 Letta原 MemGPT让大模型像操作系统一样管理自己的记忆Letta 的前身 MemGPT 在圈内属于“概念级”项目论文标题就叫《MemGPT: Towards LLMs as Operating Systems》。它把大模型看成 CPU把上下文窗口看成物理内存把外部存储看成磁盘让 Agent 自己决定哪些东西留在“内存”里、哪些要被“换页”出去。这个思路解决了一个很本质的问题模型不知道哪些记忆重要只能靠外部规则硬塞而记忆的调换时机必须动态决策。Letta 的实现里有一整套自编辑记忆机制Agent 可以在对话过程中主动修改自己的记忆块比如把“用户现在用的手机是 iPhone 14”更新为“用户换成了 Pixel 8”而不是每次都追加一条新记录。这种自我管理的方式非常优雅但也带来了调试难度。我的经验是如果你做的是研究原型、或者产品逻辑里确实需要长期动态角色设定Letta 会给你很强的支撑但如果你只想要一个用于客服问答的“记忆插件”它的抽象层级反而偏高心智负担不小。2.3 Zep 与 Graphiti让记忆变成一张会过期的知识图谱Zep 的核心思路跟前面几家很不一样它不用传统向量库而是把记忆建模成时序知识图谱。什么意思呢它不只记住“甲和乙是朋友”还会记住“甲和乙是什么时候成为朋友的”“这段关系后来有没有变化”“哪条记忆已经过期了”。Graphiti 就是支撑这套能力的开源核心库负责完成事实的增量抽取和图的动态更新。时序知识图谱对一类场景特别有用需要跟踪状态变化的关系型记忆。比如用户上个月说“我在考虑退订”这个月说“还是留着吧”传统向量库会把它当两条语义相似但互相矛盾的记录放着靠模型猜时序图谱系统则会明确记录这条记忆发生了状态翻转重新检索时给最新状态更高权重。我用 Zep 体验到的最大价值是“记忆不太容易污染”。因为它把事实、关系、事件分开存检索时可以沿图谱链路走而不是一锅端做相似度召回。代价是部署复杂度上去了图数据库的运维要额外投入项目本身的抽象层级也偏高。2.4 LangGraph 持久化记忆框架原生的轻量方案LangGraph 是 LangChain 生态官方的 Agent 编排框架它内置了两层记忆能力Checkpointer负责保存图执行的完整状态快照支持断点续跑Store则用于跨线程、跨会话的长期记忆存储。如果你本来就在 LangChain 体系里做开发LangGraph 的记忆方案是接入成本最低的。以代码感官来说它非常轻from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import StateGraph checkpointer MemorySaver() graph StateGraph(...) app graph.compile(checkpointercheckpointer)你用invoke跑完一轮状态自动存了下一次带着相同线程 ID 进来它能把之前的状态恢复回来。它跟 Mem0 这类产品的最大区别在于LangGraph 的记忆基本上还是“状态保存与恢复”没有专门做信息抽取、知识提炼、生命周期分层这些事。如果你只需要断点续聊、会话恢复它完全够用如果你想做长期用户画像管理那还是得上专门的记忆服务。2.5 Cognee用认知图谱给 Agent 补全上下文Cognee 是这几个项目里相对小众、但思路非常有意思的一个。它主打的是“ECL”——实体Entity、认知Cognition、链接Link知识图谱。简单说系统不只是抽取实体和关系还会把 Agent 在不同时间对事物的看法、判断、推理过程也纳入记忆。我理解它的定位是“给 Agent 一个可解释的认知背景”。普通记忆系统告诉你“用户提到了 A 和 B 有关”Cognee 还能告诉你“用户为什么认为 A 和 B 有关”虽然这个判断也是模型给的不一定完全准确但至少在调试链路时你能看到推理依据。这个特性对追求可解释性的项目很有价值。接入方式也比较直接面向 Python 生态import cognee cognee.add(用户希望退款理由是对延迟发货不满) result cognee.search(用户与发货相关的诉求)它在隐私敏感、部署在本地的场景里比较吃香因为它默认不强依赖外部云服务图谱数据可以落在自己的环境里。2.6 绕不开的源头Generative Agents 的记忆流范式严格意义上 Generative Agents斯坦福小镇那个项目不算一个可部署的记忆系统但它提出的**记忆流Memory Stream**是几乎所有后续系统的思想源头。每条记忆按时间排序附带重要性评分、最近访问时间、相关度评分检索的时候按这三个维度的加权总分召回。公式大致是综合评分 α * 时间衰减因子 β * 重要性 γ * 相关度后续的 Mem0、Letta 多多少少都吸收了这套“分层 加权 动态老化”的思想。我强烈建议每个想深入记忆系统的人都读一读它的开源实现哪怕不用任何框架自己照着这个逻辑写一个最小实现都会对“记忆为什么需要老化”有更深的理解。3. 核心维度横向对比一张表看清打架的地方3.1 存储架构向量库、图库还是分层混合先说存储形态这个决定了系统的底座。我这次对比的项目大致分成三类纯向量库、图数据库、分层混合存储。项目核心思路存储形态检索方式上手难度最适合的场景Mem0独立记忆层向量库 图谱混合混合检索以语义为主低通用业务 Agent、快速接入Letta记忆即虚拟内存分层上下文 外部存储记忆自编辑 动态换页中高研究原型、长对话产品Zep / Graphiti时序知识图谱图数据库图遍历 矢量召回高长期客服、关系型记忆LangGraph框架原生状态内存 / 数据库快照状态恢复 Store 查询低LangChain 生态的会话恢复Cognee认知图谱图谱 向量实体链路搜索中可解释性要求高的场景这里面最需要展开的是 Mem0 的“混合”。它底层虽然有向量库但并不是只做相似度召回而是会先做实体提取再用实体关系过滤候选集最后才做语义排序。这种“图谱过滤 向量召回”的混合策略比单纯“把整段话向量化再搜相似”要精准得多代价是每次写入的提取步骤更重。3.2 写入与召回谁更智能谁更稳记忆系统的差距其实主要在写入环节就拉开了。Mem0 的提取策略是“最大化信息密度”它会把“用户今天下午三点要去机场接人”这种低价值信息直接丢掉只保留“用户近期有差旅安排”这种可复用事实。Zep 的写入则是“持续更新状态”它对同一实体的关系会做增删改而不是无限追加。Letta 的写入完全由 Agent 自主控制灵活但不可控。召回策略上的差异同样明显。向量库方案的通病是它只回答“哪些句子最接近”不回答“哪些事实最重要”。所以用了 Mem0 这类系统之后你还得自己调检索参数——比如限制 top-k 数量、做时间过滤、给不同记忆类型加权。Zep 因为是图结构检索时可以走“用户节点 → 关系边 → 相关事实节点”的路径天然能把不相干的信息挡住。有一点我非要提醒检索召回不等于翻历史。很多人以为记忆系统就是“把对话记录存下来搜索的时候把相关段落捞出来”这是 RAG 思路不是记忆思路。真正的记忆系统要做到“从对话中提炼可复用的、跨会话的、可更新的记忆单元”。你要是贪图省事直接拿 RAG 冒充记忆短期看不出问题跑一个月后记忆库里全是重复片段检索质量会断崖式下跌。3.3 部署难度、开源协议与社区活跃度开源协议的坑比很多人想象的大。某些项目是开源核心 商业闭源组件混着来社区版和云版本功能差距不小。我建议选型前一定去仓库里看一眼 LICENSE别看 README 里吹多少功能哪些功能在社区版要自己搭、哪些要付费走云都得列清楚。从部署难度看排序大概是LangGraph纯嵌入 Mem0单服务 向量库 Cognee需要中间件 Letta需要服务端和数据库 Zep/Graphiti需要图数据库运维。如果你的团队没有专门的中间件运维能力Zep 这条路线要谨慎图数据库本身就是一个需要调优的组件不是装完就能“稳了”的东西。活跃度方面Mem0 和 LangGraph 因为体量大、迭代快社区问答资料相对丰富Letta 社区很活跃但偏研究向文档里的“最佳实践”经常是论文味比较重的抽象描述Cognee 更新频率不低但这类垂直小众项目最大的风险是“哪天核心维护者不玩了你的记忆系统就没人管了”。4. 场景化选型建议不同目的别拿同一把尺子4.1 快速验证 MVP首选 Mem0 或 LangGraph如果你只是想把 Agent 的记忆能力跑通让产品在演示时不丢人我强烈建议先用 Mem0 或者 LangGraph 起步。Mem0 能在半天之内接入帮你把用户画像、会话记忆、偏好检索全搞定。LangGraph 更省事但它只解决“状态恢复”不解决“知识提炼”如果你的演示场景里需要 Agent 记住用户“上周问过哪些问题”那还是 Mem0 更合适。你的 MVP 如果跑了两三周记忆条数上千了这个时候再去评估“要不要换更重的方案”也不迟。一上来直接上时序图谱或者虚拟内存架构团队耗不起。4.2 生产级客服场景Zep/Graphiti 的价值会被长期放大客服、导购、售后这类的长期对话业务最需要的不是“记住用户说过的每句话”而是“记住用户状态的变化”。用户改地址、退货、升级会员这些是事件不是句子。事件之间还有因果和时序关系。我用 Zep 这类时序图谱的体验是它在处理状态翻转类记忆时的准确性是向量库体系很难追上的。比如用户一个月内两次投诉同一个问题第二次投诉时 Agent 必须知道“这是第二次之前处理结果是什么”图结构能让它沿着“用户→投诉事件→处理结果→复购行为”的路径把所有关联事实一次捞出来。这个场景的代价你也必须接受上线前要做好数据模型设计不能指望系统自动把图谱画完。4.3 多 Agent 协作与研究型场景看 Letta 和 Cognee多 Agent 系统里每个子 Agent 的记忆既要共享又要隔离Letta 的“记忆即虚拟内存”抽象在这里特别顺手——你可以把这个 Agent 的记忆块挂给另一个 Agent也可以单独复制一段。Cognee 的认知图谱则适合那些要求“每个记忆都有推理依据”的场景比如医疗问诊、金融投诉处理这类需要解释逻辑的领域。说实话这类场景目前还没有标准答案各家用得都很野。我的建议是别太早锁定一个框架先在记忆层之上做一层薄薄的接口封装将来换实现的时候不至于把所有业务代码重写一遍。4.4 已经在 LangChain 生态里的团队别为了记忆引入新架构这条是给“已经在 LangChain 体系里写好 Agent”的团队的建议。你如果只是想要断点续聊、会话合并、跨会话记住用户 ID 这类基础能力LangGraph 内置的 checkpointer 和 Store 完全够用不必再引入一个独立记忆服务。多一个服务就多一个故障点、多一类数据同步问题Agent 系统的运维复杂度已经够高了能少一事就少一事。当你真正遇到“基础记忆不够用”的痛点——比如用户画像无法跨会话自动沉淀、记忆条数上千之后检索质量下降——再考虑把 LangGraph 里的搜索逻辑替换成 Mem0 或者 ZepLangGraph 的模块化不至于把你绑死。5. 实操避坑这些坑我替你们踩过了5.1 记忆污染最隐蔽的杀手记忆系统跑久了八成会出一个很恶心的问题写入的“把关”不够严垃圾记忆反向污染了正常检索。比如用户说一句“我今天心情不好想投诉”系统可能提取成“用户对服务不满”下次用户问“这个套餐怎么续费”Agent 检索时反而捞到“服务不满”这条记忆语气变得小心翼翼甚至主动道歉。我自己处理记忆污染的常规手段有两个。一是给写入流程加“重要性门槛”低信息密度、纯情绪、纯寒暄的记忆直接丢弃二是给记忆打标签分事实、偏好、事件三类检索时按当前任务类型过滤标签。还有一条经验不要允许模型自由追加记忆要给它“更新”而不是“追加”的接口。用户的手机号从 138 换到 139应该更新原记忆而不是新增一条多出两条且互相矛盾的记忆就是灾难。5.2 记忆过期了Agent 仍然在喂过期数据记忆时效性比大多数人以为的严重得多。用户说“我这个月要搬家到下城区”下个月你再问“通勤建议”还拿“下城区”当新鲜事就露馅了。向量库没有“时间观念”你存进去一条、检索就召回一条过期多久全靠你外部维护时间戳。Zep 的时序图谱天生解决这个问题记忆自带生效时间窗口Mem0 和 LangGraph 这类方案则需要你手动维护生命周期。我的实践是给每条记忆加一个valid_until字段定时任务对所有长期记忆做一次“过期确认”该删的删该降权的降权。别偷懒这个定时任务不做三个月后记忆库里全是半年前的过时信息。5.3 并发与规模记忆层的瓶颈会反噬 Agent有人问“Agent 怎么扛并发”这是个好问题。记忆系统本身是有状态的比无状态 API 服务难扩展得多。你在前面无脑开十个 Agent 实例后面一个记忆服务分成十个写入并发打过去先崩的是向量库和图数据库而不是模型 API。我的经验原则是记忆服务的写入要走队列异步化对话响应不需要等记忆写入完成再返回。用户聊完一轮Agent 先回复记忆在后台异步入库。检索路径则要考虑缓存把高频记忆当前用户画像、最近会话摘要直接缓存在内存里别每次请求都打向量库。我实测过不缓存的情况下一次检索十来毫秒看起来不快不慢但并发上百之后全被数据库连接池拖死。5.4 隐形成本记忆不是免费的很多人在选型的时候只看安装部署难度忽略了运行成本。用 LLM 做信息抽取每条对话都产生额外的 embedding 调用和抽取 prompt 调用这个成本跟对话本身的成本差不多甚至更高。Zep 图数据库需要配套图谱计算资源Letta 的自编辑内存会周期性地触发模型调用“反思”现有记忆是否需要调整。成本控制上有两个直观的技巧。第一抽取用的模型可以降档用便宜的小模型做信息抽取对话才用主力模型我试过抽取质量下降不到百分之十成本降一半第二记忆检索要分级先试缓存、没有再打向量库、还不行才走 LLM 重排用推理链路换钱。5.5 安全与隔离记忆越强责任越大记忆系统存储的是用户隐私比日志的敏感度还高。至少要做到用户级隔离用户 A 的 Agent 永远检索不到用户 B 的记忆。这个在向量库里很容易漏因为 embedding 本身不区分用户检索时如果不带user_id过滤条件跨用户串记忆就是一个安全隐患。我坚持两条底线一是所有记忆按用户分库或者分 collection 存储二是记忆检索必须强制注入用户身份过滤并且这个过滤逻辑不要写死在下层存储接口里而是在应用层显式校验。别觉得多此一举等出了数据事故再后悔就来不及了。6. 几点选型心得当个结尾对比做完了说几个我在实操中总结的私人看法。没有哪家开源记忆系统是完美的Mem0 胜在接入快Zep 胜在关系表达强Letta 胜在理论深度LangGraph 胜在省心Cognee 胜在可解释。真正的分水岭往往不在技术本身而在你的团队有没有精力把一个方案跟到生产环境稳定运行。如果让我给一个最直接的入门路径我会说先用 LangGraph 把状态恢复做了让 Agent 不会断篇再用 Mem0 把用户画像和偏好沉淀下来当你的记忆图谱复杂到需要表达“状态翻转、关系演化”的时候才值得上 Zep 的时序图谱。别一上来就抱着最重的架构不放记忆系统的复杂度是逐步逼出来的不是一开始就需要的。最后再分享一个小技巧不管选哪一家一定要在项目早期就把记忆的“调试面板”做出来——能查看某条记忆如何被写入、为什么被检索、检索相关性打分是多少。没有这个面板记忆系统出了问题你只能靠猜那种调试体验会非常痛苦。有了可视化调试记忆系统才真正变得可控。