经验不是记忆,也不是 Skill:Agent 记忆的第五层
上个月写记忆架构那篇文章的时候,我把 Agent 的记忆分成四层:工作记忆(上下文窗口)、程序性记忆(skills)、情景记忆(会话历史)、语义记忆(事实和约定)。写完挺满意的,觉得该覆盖的都覆盖了。
然后最近看了阿里云 AgentLoop 的一篇产品介绍,讲他们怎么从 Agent 的真实运行轨迹里自动挖掘「经验」,再注入回 Agent 的运行时上下文。看完之后我坐在那儿想了很久,脑子里一直转着一个问题:他们说的这个「经验」,到底该放进我那个四层模型里的哪一层?
答案是:哪一层都放不进去。
先说为什么四层不够
回顾一下那四层各自管什么。
程序性记忆是 skills——「怎么做事」。排查 OOM 的标准步骤、发布流程、数据订正操作。这些东西是人写的,稳定的,跟具体会话无关。写一次,用很久。
情景记忆是原始会话历史。上周三那次排查的完整记录,原样存、不加工。它的价值在于原始,需要的时候全文搜。
语义记忆是提炼过的事实。「测试库只读,用 mock」「提交信息用中文」。一份人工可审的 Markdown 小文件,常驻上下文。
现在想想 AgentLoop 说的「经验」是什么:「排查 ECS SSH 连接超时时,先查安全组再查 iptables,不要反过来,因为 80% 的情况是安全组规则问题」「调用这个查询接口时,时间范围不要超过 7 天,超过会超时返回空结果,Agent 会误以为没有数据然后反复重试」。
乍一看最像 skill。但仔细想,skill 是完整的操作流程——「第一步做什么,第二步做什么」。上面那两条不是流程,是判断。是在某个具体节点上告诉你应该选 A 不要选 B,以及为什么。Skill 像菜谱,经验更像老师傅站在你旁边说的那句「火别开太大,这个锅薄」。
跟情景记忆的区别更明显。情景记忆是「上周三发生了什么」,是一次具体执行的原始记录。经验不属于任何一次会话,它是从几十次、几百次类似执行里长出来的。
最容易混的是语义记忆。毕竟都是提炼过的、可以写成一句话的东西。但语义记忆存的是静态事实——「测试库只读」不管你在干什么任务都是真的。经验不是。经验有适用范围,跟当前情境强相关。「时间范围不要超过 7 天」这条,只有在你调用那个特定接口的时候才需要看见,写前端代码的时候它出现在上下文里就是噪音。
想来想去,经验是另一种东西。它回答的问题跟前面四层都不一样——不是「怎么做」,不是「发生过什么」,不是「什么是真的」,而是「在这种情境下,以前怎么走通的、怎么栽的」。
Trace 不是经验,中间差着一步
AgentLoop 那篇文章里有一个我觉得很重要的区分:Trace 不等于 Trajectory,Trajectory 不等于经验。
原始 Trace 是 Agent 跑一次任务留下的全部日志——模型调用、工具调用、中间推理、基础设施 span、重复消息,什么都有。他们给了一个数字:清洗后的高价值轨迹大概只有原始 Trace 的 4% 到 6%。
这个数字让我停下来想了想。我们现在的做法是把会话历史原样存 JSONL 进 SQLite,当时觉得「原样存、不加工」是对的,因为加工会丢信息。但如果 95% 的内容是噪音,那「原样存」的代价就是:你以后每次检索都要在 95% 的垃圾里翻找那 5% 有用的东西。我们第一版记忆系统检索命中率不到一成,现在回头看,问题不只是「存了不该存的」,还有「该提炼的没提炼」。
从 Trajectory 到经验还有一步:跨轨迹比较。不是对单条 Trace 做摘要,而是把几十条同类任务的轨迹放在一起看——哪些动作反复出现在成功轨迹里,哪些反复出现在失败轨迹里,失败之后什么恢复策略有效。这一步才是真正产生「经验」的地方。
我们现在的 skills 是人写的。人写 skill 的过程其实就是手动做这件事——一个资深工程师踩了十次坑,总结出「以后遇到这种情况先查 A 再查 B」,写成文档。AgentLoop 试图让这个过程自动化。能不能做到、做到什么程度,后面再说。但方向上,它填的确实是一个真实的空档。
一个更实际的指标:每个成功任务花多少钱
文章里有一个观点我觉得比产品本身更有价值:衡量 Agent 成本不应该看单次调用用了多少 Token,应该看每完成一个成功任务花了多少 Token、时间、工具调用和人工介入。
这个说法戳中了一个我之前的盲区。我们之前优化 Agent 成本的时候,盯着的是「这次调用能不能少用点 Token」「prompt 能不能再压缩一点」。但真正烧钱的地方往往不是单次调用贵,而是 Agent 走错了方向之后反复重试。选错了信息入口,推理了三轮才发现不对;工具参数填错了,原样重试五次;查询范围太大超时了,换个范围再来。这些无效循环消耗的 Token 远超正常执行。
如果经验能帮 Agent 在关键节点上少走弯路——一开始就选对入口、第一次就把参数填对、失败后直接用有效的恢复策略——那 Token 总量下降是自然结果,不需要专门去「省 Token」。
他们给的 benchmark 数据里,PawBench 通过率从 24.53% 到 30.67%,Token 降了 58%。这个组合说明的就是这件事:做对的次数多了,浪费在错误路径上的 Token 就少了。不是刻意省,是不走弯路自然就省了。
当然,这些数据是阿里云自己跑的,bench 也是他们选的,得打个折扣看。SWE-bench Verified 那组数据就诚实一些:成功率从 67.2% 到 74.4%,但 Token 从 362M 涨到了 536M。质量和成本之间确实存在权衡,不是所有场景都能「又准又省」。他们自己也承认了这一点,我觉得这个态度还行。
如果重新画那张表
回到我的四层模型。如果现在重新画,我会加一行:
| 层 | 存什么 | 怎么来的 | 什么时候用 |
|---|---|---|---|
| Working | 当前会话 | 实时 | 始终在窗口里 |
| Procedural | 怎么做事 | 人写 | 按需加载 |
| Episodic | 发生过什么 | 原样存 | 全文搜索 |
| Semantic | 什么是真的 | 人工提炼 | 常驻上下文 |
| Experiential | 什么有效什么会失败 | 自动挖掘+人工审 | 按情境召回 |
第五层和前面四层的关键区别在于它的产生方式和召回方式。Skills 是人写的,写一次用很久,更新慢。经验是从真实执行里自动提炼的,理论上可以随着 Agent 跑得越多而持续更新。Skills 是完整流程,按需加载整个 skill 文件。经验是碎片化的判断,按当前任务的具体情境——目标、工具、进度、错误状态——召回少量相关的几条。
这个「按情境召回」很关键。不是把所有经验一股脑塞进上下文,而是在 Agent 准备调用某个工具的时候,只拉出跟那个工具相关的参数约束;在 Agent 遇到空结果准备重试的时候,只拉出有效的恢复策略。这跟上下文工程里说的「选取」操作是一回事——信噪比永远比召回率重要。
跟微调和 RL 的边界
文章里有一张对比表,把经验自进化和 Memory、RAG、Skill、微调、RL 放在一起比较。这张表本身比产品更有参考价值,因为它回答了一个很多人混淆的问题:这些东西到底是不是在干同一件事?
不是。
微调改的是模型权重,是「让模型本身变得更倾向于做对的事」。经验不改模型,改的是模型做决策时看到的上下文,是「在模型已经具备能力的前提下,告诉它当前情境下哪条路更靠谱」。
这个区分在工程上非常重要。微调需要数据、算力、验证周期,改一次模型要重新评估所有下游任务。经验是运行时注入的,更新一条经验不需要重新训练任何东西,发现一条经验有问题可以立刻下线。
用文章里的话说:「模型负责推理,工具负责执行,知识库提供事实,经验库帮助判断。」这句话我觉得是整篇文章里最值钱的一句。它把经验的位置定得很准——不是替代模型能力,是在模型能力和具体情境之间加一层「过去验证过的判断」。
我不确定的地方
说了这么多好的,说说我不确定的。
最让我没底的是自动挖掘的质量。从几十条轨迹里提炼出「先查安全组再查 iptables」,听起来很合理。但你得想想 Agent 的执行轨迹长什么样——模型会自我解释一大段、会走毫无意义的弯路、会在成功之后输出一堆正确的废话。从这些东西里自动提炼出靠谱的经验,误报率是多少?文章没给。我担心的场景是:挖出来的经验里有两成是错的,注入之后 Agent 反而被带偏,那这个飞轮转得越快越糟糕。
经验的时效性也让我犹豫。工具会升级,接口会变,三个月前有效的经验三个月后可能就是反模式。文章说可以「快速下线」,但问题是——谁来发现它过期了?靠人审,规模一大就审不过来。这个问题我没有好的答案。
还有一个跨 Agent 共享的边界问题,不过这个相对好办。同一个团队、同一类任务里共享大概没问题,不同工具集和权限的 Agent 之间乱共享肯定会出事。文章提到了按 AgentSpace 隔离,具体粒度怎么定,得跑起来才知道。
对那篇旧文的修正
写记忆架构那篇文章的时候,我说语义记忆文件维持在一百行以内,每两周人工审一遍。现在我觉得这个说法需要修正。
一百行以内是对的,人工审也是对的。但我把「人工提炼」当成了唯一的知识沉淀路径,这太窄了。Agent 每天跑那么多任务,成功和失败的轨迹里确实藏着大量我靠人脑总结不过来的模式。与其等踩了十次坑再手动写一条 skill,不如让系统先从轨迹里把候选经验挖出来,我来审。
这跟语义记忆的写入纪律其实是一个思路:不是什么都往里塞,而是系统产出候选、人来把关。只不过以前候选是我自己脑子里产生的,以后候选可以是从轨迹里自动提炼的。把关这一步不能省,但产生候选的方式可以变。
所以如果让我现在重写那篇文章,四层模型的基本框架不用改,但我会加一节讲第五层,并且把「人写 skill」的定位从「程序性知识的唯一来源」改成「程序性知识的来源之一」。另一个来源是自动挖掘的经验,经过人工审核后,可以升级为 skill,也可以继续以碎片化经验的形式存在。
大概就是这么回事。四层变五层,不是什么大改动,但确实有一个之前没想清楚的东西被想清楚了。接下来我打算在实际项目里试着跑一跑经验的自动挖掘,看看误报率到底什么水平。到时候再写。