经验沉淀与实时召回的打通实践
提出问题:为什么 Agent 没有变得越用越聪明?
AI Agent 应该是”越用越聪明”的——遇到问题时记住教训,下次遇到同类问题时自动规避。OpenClaw 的 self-improvement 技能正是为此设计:当命令执行失败、用户纠正模型、发现 API 故障、或发现更好的做法时,自动将经验记录到 .learnings/ 目录:
.learnings/LEARNINGS.md — 经验教训
.learnings/ERRORS.md — 错误记录
.learnings/FEATURE_REQUESTS.md — 功能请求
但实际观察发现:这些经验在持续积累,却从未被用到过。
Agent 犯过同样的错误,记录过教训,但下次照样犯。self-improvement 循环断了——写入端在转,召回端没接上。越用越聪明只是愿景,现实是越用越浪费。
分析问题:两条管道,一个断裂点
要理解为什么”写了等于没写”,需要看清 OpenClaw 的记忆架构中有两条独立管道。
写入管道
self-improvement 技能负责写入。触发条件明确,写入路径固定(.learnings/ 目录),不依赖运行时配置。这条管道没有问题。
召回管道
active-memory 负责召回。它是一个独立子智能体,在用户发消息之前运行,调用 memory_search 工具搜索相关记忆,将摘要注入主模型上下文。memory_search 的索引范围由 openclaw.json 中的 agents.defaults.memorySearch 配置决定,默认只索引 MEMORY.md + memory/**/*.md。
断裂点
self-improvement -> 写入 .learnings/ -> 不在索引范围
memory_search -> 搜索 MEMORY.md + memory/*.md -> 看不到 .learnings/
active-memory -> 调用 memory_search -> 注入上下文 -> 经验永远缺席
问题的本质:写入和召回是两个独立管道,必须显式接通。.learnings/ 是自定义路径,不在默认索引范围内,而没有人在配置中告诉 memory_search 去索引它。
解决问题:接通管道
第一步:让 memory_search 能搜到
在 openclaw.json 的 agents.defaults.memorySearch 中添加 extraPaths:
{ “agents”: { “defaults”: { “memorySearch”: { “extraPaths”: [“.learnings”] } } } }
配置变更,不改代码。extraPaths 的设计初衷就是处理这类场景——agent 有额外的 Markdown 文件需要被记忆索引覆盖时,通过这个字段声明即可。
验证:配置前索引 51 个文件,配置后索引 54 个文件(多了 .learnings/ 下 3 个)。测试 memory_search 查询 “PPT 模板生成经验教训”,.learnings/LEARNINGS.md 成功出现,排名第 1,得分 0.503。
索引通了。但测试 active-memory 实际召回时,它仍然返回 no_relevant_memory。
第二步:让 active-memory 能召回
单独测试 memory_search 工具能搜到 .learnings/,但 active-memory 子智能体执行后依然输出 NONE。排查发现:
1. active-memory 使用的模型是 deepseek-v4-flash——一个轻量级模型
2. 轻量模型对”是否需要召回”的判断偏保守——即使 memory_search 返回了相关结果,这个模型在摘要生成阶段倾向于认为”当前对话不需要这些记忆”,直接输出 NONE
修复方向有两个:
| 方案 | 做法 | 优点 | 缺点 |
| 换更重的模型 | 将 active-memory 的 model 改为 qwen3.7-plus 等 | 召回判断更精准 | token 成本更高、延迟更大 |
| 调整 promptStyle | 将 promptStyle 从 balanced 改为 recall-heavy | 不增加模型成本,召回更积极 | 可能召回一些边缘内容 |
我们选择了调 promptStyle。将 promptStyle 从 balanced 改为 recall-heavy,让子智能体更积极地召回记忆,对模糊匹配也倾向于返回结果。成本可控,效果立竿见影。
验证:再次测试 active-memory 召回,成功返回了 .learnings/ 中的自我提升经验内容。
管道接通的完整闭环
self-improvement -> 写入 .learnings/ -> extraPaths 索引
memory_search -> 搜索 MEMORY.md + memory/*.md + .learnings/*.md -> 能搜到
active-memory -> recall-heavy 策略 -> 能召回
主模型 -> 上下文中包含历史经验 -> 越用越聪明
关键认知
1. memory_search 能搜到 不等于 active-memory 能召回
索引和工具只是基础设施,中间还隔着一个模型的”是否需要”判断。轻量模型(如 deepseek-v4-flash)可能在摘要阶段丢弃相关结果。必须端到端验证,不能只测工具。
2. 写入和召回是独立管道,必须显式接通
非默认路径的 .md 文件需要被检索覆盖时,应在 extraPaths 中声明。不声明就等于不存在。
3. promptStyle 是精度-召回率的权衡
balanced 适合通用对话,recall-heavy 适合依赖历史经验做决策的场景。宁可多召回一些,也不要漏掉关键经验。
最佳实践
1. 端到端验证。配置变更后,不仅测试 memory_search 工具,还要测试 active-memory 实际召回结果。
2. 声明额外索引路径。自定义目录下的 .md 文件,必须在 extraPaths 中声明。
3. 根据场景选 promptStyle。依赖经验的 agent 用 recall-heavy,通用场景用 balanced。
4. 定期审计 .learnings/ 目录。经验积累多了,过时内容要及时清理。
核心结论:Agent 没有变得越用越聪明,根源在于经验管道断裂。写入了不等于生效了,搜到了不等于召回了——每一环都需要显式验证。
关于作者:
| 昵称:Jack.shang 档案信息:jack.shang 程序员->项目经理->技术总监->项目总监->部门总监->事业部总经理->子公司总经理->集团产品运营支持 联系方式:你可以通过syfvb@hotmail.com联系作者 点击查看Jack.shang发表过的所有文章... 本文永久链接: http://blog.retailsolution.cn/archives/6114 |
对本文的评价:
