
最近我在调一个客服Agent对话轮次超过二十它就把关键信息忘得干干净净——用户刚说完的收货地址下一轮就开始“我这边暂时查不到”。这几乎是每个长期做Agent开发的人都绕不过的坎模型上下文窗口再大也包不住用户的全部历史。所谓“长期记忆”拼的不是谁的窗口长而是谁的工作台里多了一套能存、能找、能更新的记忆机制。为了把这件事彻底搞明白我把社区里讨论最多的六个项目翻了个底朝天LangChain、Dify、CrewAI、Mem0、LettaMemGPT和Zep。这篇文章不聊纸上理论只聊这六个项目各自的长期记忆设计思路以及什么样的应用场景适合用哪一套。如果你也在做Agent开发、或者正在给自己项目的Agent加记忆这篇文章应该能省不少弯路。1. 为什么Agent的记忆问题这么难1.1 模型本身是“金鱼”记忆得靠外部系统补先说一个最基础的认知大语言模型本身没有任何持久状态。每次调用接口模型看到的都是你这次传进去的提示词上一次聊过什么它完全不知道。即便你用的是支持超长上下文的模型那也只是把更长的对话历史“临时塞进”了这次请求关掉窗口之后一切归零。所以Agent的长期记忆本质上是一个外部系统问题。它要解决的不只是“把数据存下来”而是在每一次对话开始时从存下来的大量数据里找出对当前最有用的那部分再拼进Prompt里让模型表现得“像记得住一样”。这个思路很像人失忆之后的补救方案你不是真的想起来而是靠着日记、便签、数据库记录把自己伪装成一个有记忆的人。这也是为什么“记忆”这个问题这么容易翻车。它涉及三件相互矛盾的事存储的容量要大检索的准头要好注入的开销要小。三者在真实项目里几乎永远在互相妥协。1.2 长期记忆不是一种而是三种拆开看Agent的长期记忆其实可以分三类六个项目各自的侧重点完全不同。第一类是工作记忆也就是当前会话里正在发生的事情——用户刚才说了什么、现在进行到哪一步、待会要回什么。这类信息通常只对当前Thread有效会话结束就可以丢。对应到人身上就是“过脑就忘但当时一定得有”的状态。LangChain的对话缓冲、Dify的会话变量都在处理这类记忆。第二类是场景记忆也就是一个用户和Agent之间跨会话的历史经历。比如“上周张三咨询过退款流程”“他习惯用支付宝付款”。这类记忆需要持久化存储还需要在下次聊天时被准确召回。CrewAI的长期记忆、Mem0的实体偏好都在干这件事。第三类是长期知识更像是文档、产品手册、用户档案这些静态信息它不是对话过程中产生的而是预先塞给Agent的。很多项目把它叫知识库或者检索增强生成。严格来说这不算“记忆”但在落地时经常和记忆一起做容易混淆。一个真正成熟的Agent缺不了这三种记忆的配合。但六个项目在设计上多数只做好其中的一两层剩下的靠开发者自己拼装。这就是为什么我们做选型之前得先知道自己更缺哪一种记忆。2. 六项目选型与记忆架构全景图2.1 我为什么偏偏挑这六个市面上的Agent框架远不止这些但我刻意选了六种实现方式跨度足够大的项目而不是清一色的“LangChain系”。LangChain、Dify、CrewAI都是应用框架但它们把记忆嵌入到业务逻辑里的角度完全不同。LangChain是给程序员用的积木库Dify是给产品团队用的低代码平台CrewAI则是围绕“多Agent协作”设计的框架。Mem0、Zep、Letta是另一类。它们不把自己定位成让开发者快速搭Agent工作流的框架而是专门解决“记忆怎么管”这个子问题。Mem0把记忆做成一个独立服务Zep用图结构存关系记忆Letta干脆用操作系统管理内存的思路来设计Agent的大脑。六个项目刚好分成三条线应用框架、记忆服务和系统级记忆。对比起来看比单纯对比两个框架的API有信息量得多。2.2 核心差异一表看先放一张我整理了很久的对照表后面再逐个拆项目核心抽象记忆实现方式持久化层检索机制适合场景LangChainChain Memory类缓冲/摘要/向量/实体组合外接Redis、DB、向量库由开发者自行编排复杂多步编排、需要高度定制Dify应用 会话内置Thread对话历史开关、会话变量、知识库平台内置存储自动注入检索增强产品化部署、低代码搭建CrewAIAgent / Task / Crew短期、长期、实体三类记忆SQLite 向量存储任务执行的显式存取多Agent分工的复杂任务Mem0Memory服务 API自动抽取用户事实与偏好向量数据库 图数据库add/search语义检索自动冲突更新记忆作为独立基础设施LettaAgent 自编辑内存主上下文与外部内存分层持久化数据库模型自行决定读哪页内存超长对话、高连续性AgentZep会话时间线 图记忆图结构实体关系 时间序列图数据库Neo4j等按实体和时间检索关系密集的客服/CRM场景这张表别只看热闹重点看第三列和第五列。选手一套的“记忆实现方式”基本就决定了你以后要怎么跟它相处。是用封装好的记忆组件还是自己写存取逻辑还是把记忆当成一个黑盒服务这种差异比存储用什么数据库重要得多。3. 逐个拆解六个项目的记忆设计细节3.1 LangChain模块化记忆组件与链式抽象LangChain是典型的“拼装派”。它把记忆拆成了好几个Memory类ConversationBufferMemory直接把历史对话全部缓存ConversationBufferWindowMemory只保留最近N轮ConversationSummaryMemory用模型把旧对话压缩成摘要VectorStoreRetrieverMemory把历史片段向量化之后按相似度召回还有EntityMemory专门记录人名、地名、产品名这类实体信息。实际用的时候我通常把WindowMemory和SummaryMemory搭配着用。指令是近期两三轮对话用原文保持精准更早的内容走摘要节省Token。代码写出来大概是这样from langchain.memory import ConversationBufferWindowMemory, ConversationSummaryMemory from langchain.chains import LLMChain memory ConversationBufferWindowMemory(k2) summary_memory ConversationSummaryMemory(llmllm, memory_keysummary)但这里有个很容易踩的大坑LangChain的Memory只是“提示词拼接工具”它本身不做任何自动清理也不会判断哪些历史重要。如果你同时挂了好几个Memory类模型Prompt里可能同时出现原文、摘要和实体列表内容重复甚至矛盾——摘要说“用户喜欢微信支付”原文里用户刚刚又改成了支付宝模型就会精神分裂。所以我会建议所有模块化记忆组件最后都要自己写一个统一的Memory管理器至少控制好注入顺序和优先级别把记忆组件直接裸放到复杂链路上。3.2 Dify产品经理也能玩转的会话级记忆Dify跟LangChain不同它是一个完整的应用开发平台在界面上就能把Agent的长期记忆配置好。Dify的记忆机制有两套主要入口会话内记忆和知识库检索。会话内记忆就是普通的对话历史它把每个应用下的会话Thread独立存起来你可以在编排界面直接打开“记忆”开关还能设置上下文长度上限。它更特别的地方是“会话变量”你可以定义数组、字符串这类变量让Agent在对话中自行写入和读取。用第一个问题粗暴理解这就是“给状态一个持久化的坑位”。知识库检索才是Dify真正处理长期记忆的武器。你可以把用户档案、产品手册、历史工单塞进知识库再把记忆相关的对话也追加进去。每次对话时先做向量检索把最相关的片段拼进提示词以此实现“跨会话”的记忆召回。这套设计的好处是上手极快产品经理都能半小时内搭出一个带历史记忆的客服机器人。代价是定制能力有限。Dify的逻辑是给你几种足够通用的方案覆盖大多数场景就好。一旦你需要的记忆召回策略很特别比如“用户三个月前的订单信息要优先于最近聊天内容”就得自己写外部服务再通过API往会话里塞上下文。所以Dify适合先把业务跑起来的场景。先用它验证“Agent带长期记忆是不是真的能提升用户留存”验证通过之后再考虑切到更底层的东西。3.3 CrewAI让多Agent共享“团队记忆”CrewAI的核心心智模型是“团队”一群Agent各自有分工协作完成一个任务。它的记忆是围绕这个建模展开的有三种。短期记忆直接挂在任务执行过程中记录这个Agent这轮任务刚做过什么、发现了什么。长期记忆存在SQLite里跨任务保留“这类任务以前是怎么完成的”相当于团队的项目复盘记录。实体记忆存的是对象之间的关系比如“用户A和订单B的关联”。在多Agent协作场景里记忆不只是要给同一个Agent用的还要被团队成员共享。CrewAI在这方面做得相当直白每个Task允许开发者在内部写入特定的历史上下文运行完之后可以提取关键信息存入长期记忆下一个Task启动时又能把之前的经验拉出来参考。我在做一个跨部门工单流转Agent的时候深度用过CrewAI这套机制。客服组负责收集信息技术组负责排查两个角色之间需要的记忆完全不一样。客服组需要记住用户的语气和诉求技术组需要记住排查到哪一步。CrewAI的实体记忆刚好能把“用户”“工单”“系统环境”这类实体关系理清楚比把所有历史一股脑丢给每个Agent强太多。但也要注意CrewAI并不是一个低门槛的产品。它的多Agent编排和记忆存取逻辑需要你其实理解任务依赖关系。如果你只是单Agent对话机器人硬上CrewAI反而会让问题变复杂。3.4 Mem0把记忆当独立服务来管理Mem0是我见过“记忆模块化”做得最彻底的一个。它不关心你用什么框架而是提供一个REST API让任何Agent都能往一个独立的记忆数据库里写、改、查。Mem0的底层同时用了向量数据库和知识图谱。它能自动从对话里抽取出“这是一个事实”还是“这是一个偏好”“用户住在上海”是事实“用户喜欢言简风”是偏好然后分别存到不同索引下。调用时你只需要给一句查询它能同时从向量相似和实体关系两个维度找回相关记忆。最关键的是它的自动更新机制。如果用户在第二周改了需求说“我搬家到北京了”Mem0不是简单追加一条而是会找到旧的那条“住在上海”确认冲突后更新掉。这避免了一个长期记忆最典型的问题旧记忆和新记忆打架。如果你要我推荐“谁家的记忆像个人样”Mem0这套自动冲突处理机制是很接近的。不过引入Mem0也意味着你要多运维一套有状态服务而且它到底抽取了什么、更新了什么中间过程对开发者来说是半黑盒的。我一般会在系统里增加一个可视化调试界面定期去看它记住的东西是不是合理防止它抽到某些带有偏见的表述。3.5 LettaMemGPT用操作系统内存管理思路管理Agent记忆Letta的前身是MemGPT背后的核心思想是“把LLM上下文当作内存模型自己当操作系统”。它的设计是让LLM通过Function Call来管理自己的记忆而不是我们手工拼Prompt。它把记忆分成了两块主上下文in-context memory和外部内存external memory。主上下文就是模型当前能直接看到的信息外部内存则是大量归档在数据库中的历史数据。模型在对话过程中如果判断某个旧信息很重要会自己调用工具把相关内容从外部内存“翻”进主上下文如果主上下文太挤它会调用工具把不太重要的内容写回外部内存。这套思路最惊艳的地方在于“记忆自管理”。使用者不需要预估“最近几轮对话应该放进去”而是模型自己判断“这个话题现在需要哪段历史”。我用它做法律咨询顾问的时候效果非常明显对话从十几个小时前的合同条款自然过渡到今天的补充提问不需要开发者手动拼接任何长文档。但Letta的代价是模型依赖Function Call的稳定性如果函数调用失败记忆翻页就可能卡住。另外这套架构跟LangChain这类偏程序员找辅助工具的思路有些不同上手曲线陡峭适合有精力做深度定制的团队。3.6 Zep用图结构保存“实体关系网”Zep是这六个里最偏“企业系统”的项目。它不把记忆当文本片而是当一张图来处理。它会把每轮对话保存成时间线timeline同时从对话中提取实体用户、商品、地区、情绪和实体之间的关系比如“用户张三投诉了订单A”其中“张三”和“订单A”之间就有一条“投诉”的关系边。检索的时候既可以按时间线查“上一个会话说了什么”也可以按实体查“这个用户所有相关历史”。后者在客服场景尤其发挥优势同样问一句“上次出问题是什么情况”我不用把整个聊天记录交给模型只要把张三关联的节点和边抽取出来喂进去模型就能精准回答。Zep还有个细节设计做得很踏实它支持对记忆做临时性的“延迟决策”。本地提问一个事实时它可以把相关联但还没有被“确认”的关系一并返回让LLM自行判断是不是相关。这减少了误召回概率。它的硬伤是重。图数据库一旦做起来运维成本和数据建模就都是事。适合业务本身实体关系很紧密的场景比如CRM、供应链调度而不是那种“随便聊聊天”的轻量Agent。4. 设计思路对比两种根本路线的博弈4.1 路线A上下文拼装派LangChain、Dify、CrewAI把三个框架放在一起看它们的共同点是把记忆当成“给Prompt额外塞进去的上下文包”。每次用户提问系统从某个存储里把相关历史、摘要或实体信息捞出来拼接到系统提示词后面最后再交给LLM。这套路最直接的优点是透明、可控、容易调试。临时某一步出了问题你可以把真正的Prompt打出来看到底是哪一段历史在捣乱。同时它跟现有模型推理流程最匹配毕竟对LLM来说输入文字越长权重越大其他机制都得“转译”。缺点也很直观它把记忆质量寄托在“检索策略”上。检索策略不好召回的不是用户这次真正需要的旧信息模型就会被弱相关的内容干扰甚至产生幻觉。而且随着记忆越攒越多拼装出的上下文开销也越来越大成本随Token线性增长。几乎所有新手项目都会先选这条路线因为试错成本低。但当业务复杂到“Agent自己不知道需要哪段记忆”时拼装派就开始力不从心了。4.2 路线B记忆基础设施派Mem0、Zep、Letta另一派的共同点是尝试把记忆抽象成一个自主运行的系统而不是每次请求前由开发者手工决定“把哪几段文本塞进去”。Mem0像记忆管家自动抽取事实、维护冲突更新Zep像人际关系图谱把记忆变成实体和关系让LLM按图索骥Letta像操作系统让LLM自己决定把哪一页从磁盘搬进内存。三者都不需要你每次对话都去写“召回哪段历史”的调参逻辑而是设计了某种自动机制来管理。代价是系统复杂度大幅上升。你需要维护额外服务、理解内部抽取逻辑、处理黑盒更新带来的意外。模型对记忆的“自管理”行为并不稳定有时它会把重要的事写回外部内存留下不重要的在上下文里。这类问题一旦出现比拼装派那种可预期的“检索漏了”难排查得多。选这类方案的本质是信任“自动记忆机制”比“手工拼装”更能应对复杂场景。我个人的判断标准是如果你的Agent真的需要处理几万条协议级的历史记忆并且你愿意花时间调试蒸馏机制基础设施派是值得的如果你只是想让一个客服机器人别把昨天的订单号忘了那么次先拼装好也够了。4.3 四维对比持久化、检索、演化、更新策略维度拼装派代表基础设施派代表持久化外接数据库开发者自己决定存什么内置图/向量数据库自动建模检索向量相似度/规则过滤语义实体关系联合召回演化摘要压缩、窗口滑动图结构演化、实体冲突更新更新策略每次对话结束时人工触发写入Mem0类产物异步抽取、Zep类事件驱动这张表最值得关注的是最后一行更新策略。拼装派通常把“写入记忆”当成业务代码的一部分比如对话结束后把摘要存储到MySQL。基础设施派则更倾向于异步、自动的管道对话过程中就开始抽关系、写图谱。异步更新的好处是不阻断对话坏的方面是实时性差。如果你要做一个实时性要求特别高的Agent——比如用户上一秒刚修改了关键信息下一秒必须立刻生效——拼装派的同步写入更可靠。如果只是追忆历史状态异步自动抽取完全够用。5. 实战中的坑与判断什么情况选哪套方案5.1 我在落地时踩过的坑第一个坑是上下文污染。刚开始用LangChain组合记忆时我一股脑把VectorStore召回的前20条历史全塞进Prompt结果模型被大量无关内容干扰回复质量直线下降。后来我把召回条数压到5条再按时间倒序重排效果立刻好了很多。长期记忆不是越多越好是要刚好够用。第二个坑是记忆覆盖的冲突。用自建摘要记忆时如果用户中途更正了某个事实旧摘要在很长一段时间里仍然留在向量库里会被反复检索出来。我后来做了一层“记忆修正标记”处理检测到新矛盾信息时直接标记旧摘要失效而不是简单追加。这比让模型自己判断容易调试得多。第三个坑是成本爆炸。多Agent场景下每个Agent都塞一份长期记忆Token消耗按Agent数量倍增。CrewAI看起来每个Agent只塞自己的部分但团队协作时共享上下文依然会膨胀。后来我限制共享记忆只在Task边界传递流程内部的细节不跨Agent扩散成本才降下来。5.2 什么场景选什么方案如果你只有一个产品化的Agent想让电商客服、个人助理这种人机对话拥有基础记忆从Dify起手最稳。界面点几下就完成会话变量知识库已经覆盖80%的需求。如果你是开发者想动手搭一套可定制的多步链路LangChain仍然是首选。它的记忆组件虽然要自己拼装但胜在透明可控你完全知道自己喂了什么给模型。如果你的需求是多角色分工、需要多个Agent站在不同视角读取记忆CrewAI的团队级记忆设计是匹配的。它能让你把客服Agent和财务Agent的信息隔离得很干净。如果你希望“记忆”变成可复用的公司基础设施不绑定某个AgentMem0值得认真看。它自带API别的系统随时存取用户画像不用重头搭建。如果你要做一个角色很稳定、对话动辄上百轮的产品Letta的自我编辑机制是革命性的省心方案。它会主动管理上下文你基本上不需要手工调参。最后如果你做的是客服、CRM、客户成功这类实体关系密集的业务Zep的图记忆会让你比所有拼装派方案都省力。它能找到“用户、订单、售后工单”之间的内在联系调用历史时准确率明显高于纯文本向量检索。最后再分享一点实际体会不要一开始就追求完美记忆先跑出一版能“记住最近几轮”的然后逐步加摘要、加实体、加独立服务。记忆功能做得越“聪明”它带来的调试复杂度也越高。踩过几次坑之后我现在反而会刻意保留一套最朴素的“最近N轮原始对话长期外部摘要”的组合很多项目就这么简单的一套就已经够顺滑了。