Agent 到底该记住什么?读懂《What Must Generalist Agents Remember?》
TL;DR
- 场景:通用 Agent 在多目标、多隐藏环境下,仅靠当前观察无法区分状态,需依赖记忆
- 结论:记忆不是日志,而是消除隐藏状态不确定性的内部世界表征,必须包含三类控制相关信息
- 产出:四层 Agent 记忆分层框架(上下文引用 / 任务状态 / 环境区分 / 局部世界模型)
版本矩阵
| 功能/结论 | 状态 | 说明 |
|---|---|---|
| 记忆分离理论(Memory Separation) | ✅ 已验证 | 论文 Theorem 1,DQN/DRQN/ForkWorld 实验支撑 |
| 控制相关性筛选(Control Relevance) | ✅ 已验证 | 论文 Theorem 2 推论 |
| 价值预测→局部世界模型等价 | ✅ 已验证 | 论文 Theorem 3,probe 实验支撑 |
| DRQN hidden state 编码隐藏域 | ✅ 已验证 | 论文 probe 实验验证 |
| Oracle Agent 表现上限 | ✅ 已验证 | Oracle DQN / Oracle DRQN 在 ForkWorld 优于无记忆基线 |
| LLM Agent 直接评测 | ⚠️ 待验证 | 论文未在 GPT / Claude / Qwen 上实验 |
| 论文公开代码/复现脚本 | ⚠️ 待验证 | arXiv 2606.18746 编号未在公开搜索中匹配到 |
现在做 Agent,很多人一上来就会讨论"记忆系统"。
短期记忆、长期记忆、向量数据库、用户画像、历史对话、工具调用记录、任务状态、RAG、反思日志、episodic memory、semantic memory……
这些词都对,但容易把问题搞偏。
真正核心的问题不是"Agent 能不能存很多东西",而是:
一个真正能跨任务、跨环境工作的 Agent,最低限度必须记住什么?
arXiv 2606.18746 这篇论文《What Must Generalist Agents Remember?》就是围绕这个问题展开的。
它不是一篇工程教程,不是教你怎么搭建 Redis + Vector DB + Memory Manager。它更像是在给 Agent 记忆建立一套理论底座:如果一个 Agent 想在多个环境和多个目标中保持接近最优的行为,它的内部记忆必须包含哪些信息。
这件事非常重要。
因为现在很多 Agent 系统里的"记忆"其实只是外部存储:把历史对话、工具返回、网页内容塞进数据库,之后再检索出来。这样做当然有用,但它没有回答更深的问题:
哪些记忆对决策必要?
哪些只是日志?
哪些会让 Agent 更聪明?
哪些反而会制造噪声?
这篇论文给出的答案可以概括成一句话:
Agent 的记忆不是资料库,而是用来消除隐藏状态不确定性的内部世界表征。
为什么只看当前输入不够?
先用一个简单例子。
假设你走到一个岔路口,眼前画面完全一样:左边一条路,右边一条路。
但存在两个不同世界:
在世界 A 里,左边通向出口。
在世界 B 里,右边通向出口。
问题是,你现在看到的画面完全一样。只看当前观察,你无法判断自己在哪个世界。
如果你之前走过一段路,发现某些动作的结果和世界 A 更像,那么你就应该记住这个信息。到了岔路口时,你不能只看当前画面,还要结合之前经历判断:我现在大概率处于世界 A,所以应该走左边。
这就是记忆的必要性。
很多现实 Agent 场景也是这样:
同一句用户指令,在不同业务状态下含义不同。
同一个页面按钮,在不同系统版本下行为不同。
同一个 API 返回字段,在不同租户配置下解释不同。
同一个机器人动作,在不同地面材质、不同光照、不同设备状态下结果不同。
如果 Agent 只看当前输入,它会把这些状态混在一起。表面上看是"推理错误",本质上是"没有记住足够的上下文"。
论文把这种情况叫作隐藏域问题。Agent 面对的环境有一些隐藏变量,当前观测不直接告诉它,但这些隐藏变量会影响最佳动作。
所以 Agent 必须从历史轨迹中推断隐藏域,并把这个推断结果保存在记忆里。
通用 Agent 面对多个目标和多个环境
这篇论文讨论的是 generalist agent,也就是通用型 Agent。
它不是只解决一个固定任务,而是要在多个目标、多个环境中都表现良好。
这里有两个维度。
第一,目标不同。
比如机器人有时要去厨房,有时要去卧室;办公 Agent 有时要查订单,有时要改配置,有时要生成报表;代码 Agent 有时要修 bug,有时要重构,有时要写测试。
第二,环境不同。
比如机器人所处房间布局不同;业务系统的租户配置不同;API 版本不同;数据库状态不同;用户权限不同;外部工具的行为发生变化。
论文关心的是:当 Agent 不直接知道自己处于哪个环境时,它如何仍然做出正确动作?
更准确地说,Agent 只能看到自己的历史轨迹:之前看到了什么、做了什么、得到了什么反馈。它没有一个明确的"当前环境 ID"。
这就要求 Agent 的记忆承担一个任务:
把历史轨迹压缩成对当前决策有用的内部状态。
这不是简单地保存所有历史。保存所有历史太贵,也不一定有效。真正有价值的是保存那些会影响未来动作选择的信息。
第一层结论:记忆必须区分隐藏环境
论文的第一个关键结论可以翻译成:
如果两个隐藏环境在同一个观测状态下要求不同动作,那么一个足够成功的 Agent 必须在记忆中区分它们。
这句话很简单,但分量很重。
它说明记忆不是可选模块,而是某些任务里的必要条件。
继续用岔路口例子:
在世界 A,到了岔路口应该向上。
在世界 B,到了岔路口应该向下。
如果 Agent 到达岔路口时,内部记忆状态在 A 和 B 中完全一样,那么后面的策略头看到的输入也一样。既然输入一样,它就只能输出同一种动作分布。
但 A 和 B 需要相反动作。于是它不可能在两个环境里都表现好。
所以,只要 Agent 想同时处理 A 和 B,它在岔路口前必须已经把"我现在更像处于 A 还是 B"编码进记忆。
这就是论文说的 memory separation,记忆分离。
它不是说记忆里必须写一个明确字段:
{"domain":"A"}它可以是神经网络 hidden state 中的隐式表征,也可以是工程系统里的状态变量,也可以是历史窗口,也可以是显式 belief state。
形式不重要,关键是它必须让后续策略能区分这两种情况。
换成工程语言就是:
只要同一个输入在不同上下文下需要不同处理逻辑,那么上下文差异必须进入 Agent 的决策状态。
否则系统必然出现"同样输入下行为冲突"。
第二层结论:记住控制相关信息,而不是所有信息
这里要避免一个误解:Agent 不是为了记住环境标签而记住环境标签。
论文强调的是 control relevance,也就是"控制相关性"。
两个环境可能底层机制不同,但如果它们对当前任务的最优动作没有影响,那么 Agent 不一定需要区分它们。
比如两个服务器部署区域不同,但 API 行为完全一样;两个用户来自不同城市,但当前任务只是生成一段通用文本;两个机器人电池型号不同,但当前动作策略不受影响。
这种差异不一定需要进入记忆。
反过来,只要某个隐藏差异会改变最优动作,它就必须被记住。
这对工程设计很有启发。
很多 Agent 记忆系统喜欢什么都存:用户说过的话、工具返回、页面内容、历史任务、偏好、失败记录、日志摘要。问题是,存得多不等于记得好。
真正应该优先进入记忆的是:
会改变下一步动作选择的信息。
会改变工具调用参数的信息。
会改变任务分支的信息。
会改变风险判断的信息。
会改变权限、约束、目标解释的信息。
会改变环境动态预测的信息。
比如一个代码 Agent 在修项目时,真正关键的记忆不是"用户三分钟前说了某句话",而是:
当前项目使用什么技术栈。
哪些文件已经改过。
哪些测试失败过。
哪些接口存在兼容约束。
用户明确禁止改哪些模块。
当前 bug 的复现路径是什么。
某个工具调用失败的原因是什么。
某个依赖版本是否有坑。
这些才是控制相关记忆。
第三层结论:从价值预测到局部世界模型
论文第二个关键结果更深一层。
它说:如果 Agent 的记忆足以预测一类相关目标下的 action-value,也就是某个动作在当前状态下有多好,那么这份记忆就不仅仅是在帮 Agent 选动作,它还包含了足够信息,可以近似重建局部环境动态。
换句话说:
如果记忆能支持 Agent 判断"做这个动作会带来什么价值",那么它往往也隐含了"做这个动作会导致什么变化"。
这就是世界模型的味道。
一个真正强的 Agent,不只是知道"我该点哪个按钮",而是隐约知道:
点这个按钮之后系统会进入什么状态。
调用这个 API 后哪些字段会变化。
机器人向左转之后视角会怎么变。
执行这个 SQL 后数据会受到什么影响。
修改这个文件后哪些测试可能受影响。
论文把这叫作 local interventional dynamics,也就是局部干预动态。
"干预"这个词很关键。Agent 的动作不是旁观世界,而是在改变世界。它点按钮、调 API、移动机械臂、改代码、写数据库,本质都是对环境做干预。
所以 Agent 的记忆如果足够强,就应该支持一种预测:
在当前隐藏环境和当前状态下,如果我执行动作 a,下一步世界大概会怎么变化?
这比简单的历史检索高级很多。
历史检索回答的是:“以前发生过什么?”
世界模型回答的是:“如果我现在这么做,会发生什么?”
Agent 真正需要的是后者。
论文实验:ForkWorld 岔路口世界
为了验证理论,论文设计了一个很小但很干净的实验环境:ForkWorld。
它是一个 T 形岔路口网格世界。
Agent 从走廊出发,最后到达一个岔路口。目标可能是去上方终点,也可能是去下方终点。目标是可见的,但隐藏环境不可见。
关键在于,不同隐藏环境会改变"向上 / 向下"动作的含义。
在正常环境中,向上就是向上。
在交换环境中,向上和向下的效果可能被交换。
所以到了岔路口,Agent 不能只看当前位置和目标。它还必须知道当前处于哪种隐藏环境。
而这个隐藏环境只能通过之前的动作反馈推断出来。
论文比较了几类 Agent:
无记忆 DQN:只看当前状态和目标。
Stacked DQN:看一个有限历史窗口。
DRQN:用 GRU 处理轨迹,把 hidden state 当成隐式记忆。
Oracle DQN:直接给它隐藏环境标签。
Oracle DRQN:既有记忆,又有环境标签。
结果很符合直觉,也符合理论。
无记忆 Agent 做不好,因为同一个岔路口观测在不同隐藏环境下要求不同动作,它的 Q 函数会收到冲突训练信号。
带记忆的 Agent 能通过之前的轨迹推断隐藏环境,表现显著更好。
Oracle Agent 表现最好,因为它直接知道隐藏域,不需要从历史中猜。
更有意思的是,作者还做了 probe 实验:他们从 Agent 的内部表示中训练一个简单分类器,看能不能预测当前隐藏环境。
第一次到达岔路口时,大家都猜不出来,因为之前还没有足够信息。这个结果合理。
但当 Agent 探索过某条路再回到岔路口后,带记忆 Agent 的内部表示就能被用来识别隐藏环境,而无记忆 Agent 仍然不行。
这说明带记忆 Agent 的 hidden state 里真的编码了隐藏域信息。
对 LLM Agent 的启发
虽然论文使用的是强化学习和网格世界,但它对 LLM Agent 很有参考价值。
现在很多 LLM Agent 系统的问题,不是模型不会推理,而是状态管理混乱。
比如一个业务 Agent 负责处理订单。
用户说:“帮我把刚才那个订单取消。”
当前输入只有一句话。如果 Agent 不记得"刚才那个订单"是哪一个,就无法行动。
这是上下文引用记忆。
再比如用户说:“还是按上次那个规则处理。”
这要求 Agent 记得上次规则。这是任务偏好或工作流记忆。
再比如 Agent 调用一个内部 API,发现某个租户字段名和默认文档不一致。如果它不记住这个租户的特殊行为,后续还会反复失败。
这是环境动态记忆。
再比如代码 Agent 修 bug,第一次运行测试失败,发现原因是某个 mock 数据缺字段。它如果不记住这个失败原因,就可能在后续修改中重复踩坑。
这是轨迹经验记忆。
从论文角度看,这些记忆都不是"聊天记录",而是隐藏状态推断。
LLM 当前上下文窗口只是观测的一部分,不等于真正的记忆。真正的记忆应该把历史压缩成可行动的状态。
可以把 Agent 记忆分成四层
结合这篇论文,可以把工程上的 Agent 记忆分成四层。
第一层是上下文引用记忆。
它解决"这个、刚才、上次、那个文件、这个订单"指什么的问题。没有这一层,Agent 连用户当前指令都解析不完整。
第二层是任务状态记忆。
它解决"当前任务进展到哪一步"的问题。比如已经收集了哪些参数、调用了哪些工具、哪些步骤完成了、哪些步骤失败了、下一步应该做什么。
第三层是环境区分记忆。
它解决"我现在处于哪种隐藏环境"的问题。比如当前用户权限、租户配置、API 版本、系统状态、设备状态、网络状态、业务规则差异。
这正是论文第一条理论结果强调的部分:如果不同隐藏环境要求不同动作,记忆必须把它们分开。
第四层是局部世界模型记忆。
它解决"如果我执行这个动作,环境会怎么变化"的问题。比如调用接口后订单状态如何变更,修改代码后哪些测试会受影响,机器人移动后位置如何变化,生成内容后用户审核链路会怎么走。
这对应论文第二条理论结果:如果记忆足以支持价值预测,它就可能支持局部转移动态的解码。
这四层不是数据库表设计,而是认知功能划分。
工程实现可以很不同:短期上下文窗口、结构化 task state、向量检索、用户画像、工具调用日志、状态机、RNN hidden state、外部 memory service、world model module、反思总结、运行时 snapshot。
但不管怎么实现,都应该回答同一个问题:
这条记忆是否会改变 Agent 的下一步动作?
如果不会,它只是日志。
如果会,它才是决策记忆。
对 AI Agent 系统设计的直接建议
第一,不要把"长期记忆"理解成"永久保存所有历史"。
永久保存历史容易造成噪声污染。Agent 需要的是可压缩、可更新、可验证的状态。
第二,记忆应该围绕决策点组织,而不是围绕聊天轮次组织。
聊天轮次是交互格式,不是任务结构。真正重要的是:当前有哪些隐藏变量会影响动作。
第三,Agent 的 memory schema 应该显式区分几类信息:
用户目标。
任务阶段。
已知约束。
环境假设。
工具行为观察。
失败原因。
待验证假设。
下一步动作依据。
第四,记忆需要可失效。
很多环境信息会变:API 版本、用户权限、文件内容、业务状态、页面 DOM、数据库数据。过期记忆比没有记忆更危险。
第五,记忆需要服务于规划。
如果一条记忆不能帮助 Agent 预测动作后果,它对复杂任务的价值有限。真正强的 Agent 记忆应该能回答:
基于我记住的状态,下一步这么做会发生什么?
这篇论文的边界
这篇论文不是在解决 LLM Agent 的全部记忆工程问题。
它没有告诉你该用向量数据库还是关系数据库。
没有告诉你怎么做用户画像。
没有告诉你怎么做多轮对话摘要。
没有直接评测 GPT、Claude、Qwen 这类 LLM Agent。
实验环境也比较小,是一个受控的网格世界。
但它的价值在于把"记忆必要性"讲清楚了。
很多 Agent 记忆文章停留在经验层面:我们觉得 Agent 应该有记忆,因为人类有记忆,因为长任务需要上下文。
这篇论文更进一步:在某些条件下,记忆不是锦上添花,而是近似最优行为的必要条件。
只要存在隐藏环境,并且不同隐藏环境在同一观测下要求不同动作,那么 Agent 必须在内部状态中区分这些环境。
这对所有长程 Agent、业务 Agent、机器人 Agent、代码 Agent 都有意义。
总结
《What Must Generalist Agents Remember?》真正回答的是一个底层问题:
Agent 的记忆到底是什么?
它不是单纯的聊天历史。
不是越多越好的资料库。
不是把所有工具结果塞进向量库。
不是用户画像字段的堆砌。
Agent 的记忆,本质上是把过去的轨迹压缩成当前决策所需的隐藏状态表征。
它至少承担三件事:
第一,区分隐藏环境。
第二,支持价值判断。
第三,帮助重建局部世界动态。
用一句工程化的话概括:
Agent 应该记住那些会改变行动选择、行动参数和行动后果预测的信息。
这就是这篇论文对 Agent 记忆系统最重要的启发。
错误速查卡
| 症状 | 根因 | 定位 | 修复 |
|---|---|---|---|
| Agent 在多租户/多版本环境下反复调用错误接口 | 没有区分隐藏环境记忆 | 检查 memory schema 中是否包含 tenant/version/环境标签 | 在 memory schema 增加环境区分层 |
| LLM Agent 长任务中频繁重复犯错 | 失败经验未被压缩成决策状态 | 检查反思日志是否仅停留在文本记录 | 把失败原因升级为任务状态/环境假设条目 |
| 向量数据库存储量爆炸但命中率低 | 存了大量非控制相关信息 | 审查写入内容是否包含决策影响字段 | 按"是否改变下一步动作"过滤 |
| 长期记忆引用过期数据导致错误操作 | 记忆没有失效机制 | 检查是否有时间戳/版本校验 | 为每条记忆增加 source/timestamp,增加 staleness 检测 |
| 同一指令在不同上下文输出冲突策略 | 隐藏环境未进入决策状态 | probe 实验:在不同隐藏环境下模型输出是否一致 | 显式分离环境记忆,参考 memory separation 原理 |
作者:武子康的个人博客