长期 Agent 的记忆问题:过去什么时候还有资格影响现在
一个长期 Coding Agent 最容易出错的地方,往往不是不会写代码,而是把旧约束带进了新任务。
第一周,你告诉它:“支付模块风险太高,暂时不要重构。”第二周,你又把规则改成:“支付模块可以重构,但必须先补测试。”第三周,你让它“优化支付模块”。如果系统只是把历史对话存进向量库,它很可能召回第一条旧指令,因为“支付模块”“重构”“优化”在语义上非常接近。于是它不是忘了你,而是很认真地拿一个已经过期的版本来约束现在。
这才是长期记忆真正难的地方。问题不是历史有没有被存下来,而是每一段历史在今天还有没有资格影响回答。最近读到《MRMS: A Multi-Resolution Memory Substrate for Long-Lived AI Agents》这篇论文,我觉得它最有价值的地方,不是给 Agent Memory 起了一个新名字,而是把“记忆”从存储问题改成了影响控制问题。
一条旧记忆要真正进入当前回答,至少要走完这条路:
被记录下来→ 被写成可判断的记忆对象→ 被限定使用范围和有效状态→ 在新请求里被召回→ 和新旧证据一起被裁决→ 只以合格信息的形式进入上下文包要讲清这件事,不能从概念分类开始。更好的入口,是顺着那条“支付模块不要重构”的旧指令往下看:它最初怎样被记录,后来为什么需要降级,又怎样被新指令取代,最后为什么不该继续影响模型。
一问题不是旧指令被召回,而是系统不知道它已经失效
支付模块的旧指令被召回,本身并不奇怪。它和当前任务确实相关,甚至比很多历史记录都更相关。真正危险的是,系统只知道它“相关”,却不知道它“是否仍然有效”。
长上下文、向量检索、对话摘要和普通 RAG,都能让过去更容易被模型看见,但它们解决的是不同层级的问题。长期记忆一旦进入协作场景,真正棘手的不是找不到历史,而是找到了以后无法判断该不该用。
| 常见方案 | 能解决什么 | 解决不了什么 |
|---|---|---|
| 长上下文 | 让模型看到更多历史 | 哪些历史已经过期,哪些不该影响现在 |
| 向量检索 | 找到语义相近的历史 | 相似历史是否有效、越界、冲突、被取代 |
| 对话摘要 | 压缩一段历史的大意 | 摘要里的结论是否仍然成立 |
| 普通 RAG | 找到和问题相关的资料 | 资料和用户记忆之间是什么关系 |
所以,长期记忆系统不能只问“有没有召回到相关内容”。它还要继续追问:这条记忆是谁的,来自哪里,适用于哪个项目,现在是什么状态,后面有没有被新信息覆盖。没有这些判断,召回越准,旧信息误伤当前任务的概率反而越高。
二一条记忆写入时,就要留下以后能被裁决的证据
旧指令为什么会继续误导模型?根子通常埋在写入阶段。系统如果一开始只保存一句“支付模块不要重构”,后面就很难判断这句话是临时安全提醒、阶段性项目约束,还是长期偏好。它缺少可供系统裁决的信息。
MRMS 里很重要的一个思路,是把记忆当成memory object,而不是一段裸文本。这个对象不只保存一句话,还要保存来源、时间、范围、状态、置信度和修订历史。这样,当新任务到来时,系统才有材料判断它能不能继续影响回答。
| 记忆字段 | 它回答的问题 | 为什么重要 |
|---|---|---|
| 来源 | 谁说的,或来自哪份资料 | 区分用户指令、系统总结、外部文档、模型推断 |
| 时间 | 什么时候产生 | 判断新旧关系和是否过期 |
| 范围 | 适用于哪个用户、项目、任务 | 防止 A 项目的规则跑到 B 项目 |
| 状态 | 当前是否有效 | 区分原始记录、临时推断、有效记忆、已取代记忆 |
| 置信度 | 这条结论有多稳定 | 防止一次反馈被当成长期偏好 |
| 修订历史 | 后来有没有被改写 | 追踪旧指令为什么失效、新规则从哪里来 |
来源决定信任。用户明确说出的要求、从多次反馈里总结出的偏好、外部论文里的观点、模型自己临时推断的结论,不应该拥有同样的权重。没有来源的记忆,在短期对话里也许还能凑合;在长期系统里,它会变成审计黑洞。Agent 做了某个判断,但你不知道它为什么这么做,也不知道应该怎么纠正它。
范围决定边界。“日报要简洁”可能只适用于每日热点推送,“深度文章要讲透”适用于长文写作,“支付模块先别动”可能只适用于某个项目、某个阶段。没有范围,Agent 就会把局部反馈泛化成全局规则,最后表现得像一个记性很好但理解很差的助手。
状态决定影响力。一条记忆不能只有“存在”和“不存在”。它可能只是原始记录,可能是临时推断,可能当前有效,也可能已经被取代或退休。旧记忆可以保留,用于解释历史;但只要状态已经变了,它就不应该继续指导当前回答。
时间、置信度和修订历史,主要服务于同一件事:让状态变化有依据。时间告诉系统哪条信息更新,置信度告诉系统这是一句偶然反馈还是稳定规律,修订历史告诉系统旧规则是怎么被新规则覆盖的。比如“支付模块不要重构”如果只出现过一次,而且两周后被明确更新为“可以重构但要先补测试”,它就不应该继续保持高置信度的 active 状态,而应该被降级为一条已被取代的历史证据。
三旧指令变成长期规则之前,必须先经过时间和场景的筛选
有了记忆对象,还不能马上把所有内容都当成长期记忆。因为“写下来”和“长期生效”之间隔着一步判断:这条信息到底只是当前任务状态,还是已经足够稳定,可以变成未来也要遵守的规则。
支付模块的旧指令,在第一周可能是一个有效的项目约束;到了第二周,它更像一条被后续指令覆盖的历史证据。用户说“这篇写短点”,在当前文章里是有效要求,但不能直接推成“用户所有内容都喜欢短”。要避免这种误判,系统需要先把不同性质的过去分开看:
| 记忆类型 | 通俗理解 | 例子 | 最容易出的问题 |
|---|---|---|---|
| 工作记忆 | 当前任务正在用的信息 | 当前文件、这一轮需求、刚刚修改过的函数 | 过期很快,却被沉淀成长期规则 |
| 会话记忆 | 一次讨论的阶段性总结 | 今天确定日报要更清爽、更有重点 | 被误当成全局偏好 |
| 事件记忆 | 具体发生过的一件事 | 用户某天说不喜欢空泛、模板化的文章 | 从单次事件过度泛化 |
| 语义记忆 | 多次观察后形成的稳定认知 | 用户偏好干货、结构清楚、少铺垫 | 缺少证据和适用范围 |
| 外部知识 | 文档、网页、论文、API 资料 | 一篇 Agent Memory 论文的观点 | 被混成用户本人的要求 |
分清这些类型之后,系统才知道一条信息该被放在哪个速度层里。工作记忆和事件记忆可以快速写入,因为它们主要用于当前任务和事后追溯;语义记忆必须慢慢晋升,因为它会改变 Agent 以后怎么理解用户;外部知识则要单独放在证据通道里,不能混成用户自己的偏好。
这也带出一个很实用的规则:写入可以快,晋升必须慢。原始交互可以先记录下来,方便以后追溯;但只有当类似反馈多次出现,并且场景一致,系统才应该把它抽象成稳定偏好。越可能长期影响 Agent 行为的记忆,越需要更强证据、更清楚范围和更明确状态。
这也是 MRMS 里“两条轴”有用的地方。结构化记录、向量表示、关系图,讨论的是记忆以什么数据结构存在;短期轨迹、中期抽象、长期承诺,讨论的是记忆对未来行为有多大影响。很多系统把这两个问题混在一起:只要写入了向量库,就默认它可以长期生效;只要出现在最近上下文里,就默认它比旧信息更可信。这样做会让记忆系统越来越像一个没有判断力的历史堆栈。
四新请求到来时,检索应该先排除不合格记忆,再谈相似度
到了第三周,用户让 Agent 优化支付模块。这个时候,系统确实需要回看历史,但它不应该第一步就去向量库里找最相似的句子。更合理的顺序是:先用结构化信息排除不合格记忆,再用向量召回相关候选,最后处理这些候选之间的新旧关系。
换句话说,检索不是“找最像的历史”,而是“找当前有资格影响回答的证据”。
用户提出新请求→ 结构化过滤:用户、项目、任务、状态是否匹配→ 语义召回:找到可能相关的记忆→ 关系裁决:检查支持、矛盾、取代、来源关系→ 时间判断:它是短期痕迹、中期总结,还是长期承诺→ 上下文包:只把合格、有来源、有边界的记忆交给模型这条链路把“相似度”放回了合适的位置。相似度很重要,因为用户不会每次用同样的词表达同一个意思。今天说“支付模块”,明天可能说“结账流程”,后天可能说“订单扣款逻辑”。但相似度只能生成候选,不能决定最终使用。
真正进入上下文前,系统还要考虑置信度、新鲜度、任务效用和干扰成本。相似但已经过期的记忆,需要被降级;相关但会误导当前任务的记忆,需要被排除;已经被新指令取代的记忆,最好以“旧规则已失效”的方式出现,而不是继续作为当前约束出现。
五新旧记忆冲突时,系统必须说明谁取代了谁
长期协作里,最麻烦的不是单条记忆,而是多条记忆之间的关系。新的指令可能取代旧指令,多次事件可能共同支持一个偏好,一条外部资料可能和用户当前要求冲突。如果系统只能看到一堆孤立片段,就只能把裁决权交给模型自己猜。
一个可靠的记忆系统至少需要三套能力配合:结构化记录负责资格判断,向量召回负责找到相关候选,关系网络负责处理支持、冲突、取代和来源。
| 能力 | 它负责什么 | 没有它会怎样 |
|---|---|---|
| 结构化记录 | 按用户、项目、任务、来源、状态做精确过滤 | 私人记忆乱用、项目规则串场、过期信息继续生效 |
| 向量召回 | 找到语义上可能相关的历史 | 只靠关键词,很多相关历史找不到 |
| 关系网络 | 表达支持、矛盾、取代、来源、同一主题等关系 | 新旧冲突没人处理,模型只能自己猜 |
回到支付模块的例子。第一条旧指令不一定要删除,它可以保留为历史背景;但第二条新指令必须把它标记为 superseded,也就是“已取代”。这样下一次生成上下文时,系统不是把两条矛盾信息都丢给模型,而是告诉模型:过去曾有禁止重构的约束,但该约束已经被后续指令取代。
这里还有一个容易被忽视的工程细节:三套能力必须同步。结构化记录里一条记忆已经被标为“已取代”,向量索引不能因为它语义相似就继续把它当成可用答案;关系网络不能引用一个已经失效的记忆节点继续推理;最终上下文也不能因为模型“可能需要”就把退休记忆重新塞回去。很多 stale embedding 问题,本质就是文本向量还在,但结构状态已经变了,系统却没有把两边同步起来。
六模型最终看到的应该是裁决后的 Context Packet
前面这些步骤不是为了把系统做复杂,而是为了让模型在生成前拿到一份更干净的上下文包。这个上下文包不是聊天记录拼接,也不是向量库召回结果列表,而是一份已经区分来源、状态和关系的证据包。
一个合格的上下文包,至少要能通过这些检查:
| 上下文部分 | 放什么 | 为什么需要 |
|---|---|---|
| 当前任务状态 | 这一轮正在做什么、目标是什么 | 避免模型被远期历史带偏 |
| 事件证据 | 具体发生过的反馈和行为 | 让偏好有来源,不是凭空总结 |
| 稳定偏好 | 多次观察后形成的用户习惯 | 支持个性化和长期协作 |
| 关系说明 | 哪些记忆支持、冲突、取代 | 防止新旧信息打架 |
| 外部证据 | 文档、论文、网页、API 资料 | 和个人记忆分开,避免来源混淆 |
| 负上下文 | 已失效、不要再用的旧规则 | 主动阻断过期信息继续影响回答 |
负上下文尤其重要。很多系统只会告诉模型“现在应该用什么”,不会告诉它“不要再用什么”。但长期协作里,旧信息经常会以很强的语义相似度回来干扰当前任务。一个好的上下文包不应该只写“现在可以重构支付模块,但必须先补测试”,还应该明确写出“过去曾有过不要重构支付模块的约束,但该约束已被后续指令取代”。
所以,模型在回答“帮我优化支付模块”之前,看到的上下文不应该是一堆聊天原文,而应该更接近这样:
当前任务:- 优化支付模块,允许提出重构方案。当前有效约束:- 重构前必须补测试。- 风险较高的路径需要先给回滚方案。历史证据:- 用户早期曾要求暂时不要重构支付模块。- 后续用户明确更新为:可以重构,但必须先补测试。关系说明:- “不要重构支付模块”已被后续指令取代。负上下文:- 不要继续把“禁止重构”作为当前约束。再换一个更日常的写作场景看,会更容易理解 Context Packet 到底是什么。假设用户曾经说过三句话:“日报要短”“深度文章要讲透”“不要写空泛的总结”。如果普通 prompt 拼接只是把这三句话都塞进去,模型很可能只抓住“要短”,于是把所有内容都压薄。但上下文包会先把它们整理成不同槽位:当前任务是深度文章;稳定偏好是讲透、少空话;“日报要短”只适用于日报场景;负上下文是不要把日报规则套到长文里。这样模型拿到的不是三条散乱历史,而是一组已经处理好适用范围的写作约束。
这就是上下文包和普通 prompt 拼接的差别。普通拼接是把历史丢给模型自己理解;上下文包是提前把历史的状态、关系和边界整理好,让模型少猜一点。
七向量检索能找回旧记忆,但拦不住旧记忆
长期记忆系统不是只会犯一种错。它可能根本想不起旧信息,也可能想起了不该用的信息;可能把 A 项目的规则带到 B 项目,也可能把已经过期的指令继续当成当前约束。把这些错误混在一起看,只能得到一个很粗的“记忆好不好”;拆开看,才能知道到底是哪一层没有拦住。
MRMS 的实验没有先问“模型最后答得好不好”,而是先问一个更靠前的问题:生成答案之前,系统交给模型的记忆包选对了吗?这个切法很有用。因为最终答案错了,原因可能是模型推理错,也可能是提示词错,还可能是记忆选错;如果先看记忆包,就能更直接地评估记忆系统本身。
实验覆盖 800 个合成任务,场景包括延迟回忆、边界控制、来源区分、记忆修订、旧记忆抑制、证据归因、冲突处理、时间承诺等。消融结果大致如下:
| 方案 | 总体表现 | 暴露出来的问题 |
|---|---|---|
| 只看最近上下文 | 3.9% | 稍远一点的历史基本不可用 |
| 只用向量检索 | 21.2% | 能找相关内容,但容易召回过期、越界、冲突记忆 |
| 结构化记录 + 向量 | 37.6% | 边界问题明显改善,但修订和冲突仍处理不好 |
| 再加时间层级 | 75.0% | 旧记忆抑制、修订、是否该弃用有明显改善 |
| 完整架构 | 98.8% | 主要剩余问题集中在证据归因 |
只看最近上下文,稍远一点的历史基本用不上;只用向量检索,召回能力变强,但过期、越界、冲突的旧信息也会一起回来。结构化记录把“这条记忆属于谁、能不能用在哪个范围”先挡了一层,所以边界控制明显变好;时间层级继续处理“这条记忆是不是已经过期、该不该继续生效”;完整架构再加入关系网络,才真正能处理“谁支持谁、谁反驳谁、谁取代谁”。
这也解释了为什么很多 Agent 产品在 demo 里看起来不错,长期使用却越来越别扭。短期演示主要考察模型能不能根据眼前上下文完成任务,长期协作考察的是历史能不能被正确管理。你把向量召回做得更强,可能只是更稳定地召回错误历史;你把摘要做得更好,也可能只是更流畅地总结已经过期的结论。真正的改进不是“更会想起过去”,而是“更会决定过去还能不能用”。
八产品不必一步到位,但必须先让记忆能失效
论文里的 800 个任务,是人为构造出来的测试题,用来精确检查记忆系统有没有选对证据;它们不是来自真实用户长期使用 Agent 的完整产品环境。也就是说,这些结果能说明“这套记忆架构在受控测试里拦住了哪些错误”,但还不能直接证明它放进真实产品后一定好用。
真正接入 LLM 后,还会多出几层问题:模型会不会正确使用上下文包,工具调用会不会改变记忆状态,用户能不能方便地查看、纠正或删除记忆,团队环境里谁有权让一条记忆失效。这些都不是一个离线测试能完全回答的。
工程成本也不能忽略。结构化记录、向量索引、关系网络、时间策略、上下文包生成、审计日志,都会增加系统复杂度。小型工具可能不需要全套能力,但只要一个 Agent 会跨天、跨项目、跨任务工作,它就迟早会遇到同一个问题:旧规则怎么失效,新规则怎么接管,用户怎么知道系统为什么这么记。
因此,产品落地不一定要一开始就做完整 MRMS。更现实的顺序,是先补三件最小治理能力:记忆别串场,旧规则能失效,模型别自己猜历史重点。
| 最小治理能力 | 解决什么问题 | 可以先怎么做 |
|---|---|---|
| 给记忆加范围和状态 | 防止规则串场、旧记忆继续生效 | 每条记忆至少记录 user、project、task、status |
| 记录新旧记忆的取代关系 | 防止新旧指令一起进入上下文 | 支持 supersedes / contradicts / supports 这类关系 |
| 生成上下文包而不是拼历史 | 防止模型自己在历史里猜重点 | 把当前约束、证据、负上下文分槽输出 |
做到这三件事,很多“旧信息继续生效”“项目规则串场”“用户偏好被误读”的问题,就已经会少很多。向量库当然仍然有用,但它应该服务这套治理链路,而不是替代这套治理链路。产品真正要交付的不是“我记住了你”,而是“我知道哪些记忆现在仍然算数,哪些已经不能再用”。
九长期协作的门槛,是让记忆有边界、状态和生命周期
Agent Memory 最重要的问题不是“能不能记住更多”,而是“这段过去,今天还有没有资格影响现在”。当一个系统只能保存历史,它最多是一个更大的笔记本;当它能管理历史的来源、范围、状态、关系和影响力,它才开始接近长期协作系统。
未来的 Agent 不会只靠更长上下文变可靠,也不会只靠更大的向量库变聪明。它需要一套记忆治理能力:知道什么是临时反馈,什么是稳定偏好;什么来自用户,什么来自外部资料;什么已经被取代,什么仍然有效;什么应该交给模型,什么必须挡在模型之外。
一个真正可靠的长期 Agent,不是把你说过的话都记下来,而是知道哪些话在今天仍然算数。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~
