0. 从「记忆回放」到「记忆进化」
前两篇我们把 memory system 拆成了两半:第 4 篇讲「为什么要有」(context window 不够、跨 session 知识断片、verification 没有 anchor),第 5 篇讲「怎么存怎么取」(文件式 storage、index 注入、读时 verify、与 prompt cache 的合作)。
但如果故事到这里就结束,memory 只是一个录音机——你昨天说过什么、做过什么,今天能播放出来。这远远不够。一个真正可用于生产的 agent 必须做到一件事:犯过的错不再犯第二次。这才叫「记忆进化」(memory evolution)。
录音机和进化的区别在于一个闭环:
tool 失败 → hook 捕获 → 写入 memory → 下次 session
system prompt assembly 时读到 → agent 行为改变 → 下次成功
任何一个齿轮缺位,闭环就断。本文沿着这条闭环,依次拆四个齿轮:
- Hooks——闭环的 capture 端,把 runtime 信号引到 memory;
- MCP——独立于本地 memory 的第二条记忆通道,让团队级最佳实践跨 agent 注入;
- CLAUDE.md——项目契约,把人类约定固化为 system prompt 的一部分;
- Skills + Plugins——把好行为制度化,从「每次重新发现」升级为「永久封装」。
本文是系列第 6 篇,也是终篇。文末会回顾整条主线,并埋一个彩蛋:当你把这套纪律推到极致,下一步就是领域特化 agent(domain-specialized agents)。
1. Hooks:Memory 反馈环的注入点
整个闭环里,Hook 是离 runtime 最近的一环。在 claw-code 的 Rust 工作区里,它的定义集中在两个文件:
rust/crates/runtime/src/hooks.rs:定义HookEvent枚举和分发器。rust/crates/plugins/src/hooks.rs:plugin 侧的 hook 协议适配。
我们关心三类事件:
| |
Hook 的返回值结构(PDF §8.5)允许它做四件事:
- 追加 message——把一段文字加到对话里;
- 注入 additionalContext——在下一轮 system prompt assembly 时被读取;
- 阻断 continuation——直接终止 agent 的 next step;
- 更新 MCP tool output——在 output 走回 model 之前重写它。
请注意第 2 条。additionalContext 不只能影响下一个 turn,它可以被持久化。当 hook 同时把这条 context 追加到 MEMORY.md,下次 session 启动时 system prompt assembly 会再次读到它——这就是闭环的 capture 端。
最自然的应用是 PostToolUseFailure:
| |
这一段不到 5 行代码,但它跨越了两个时间尺度:additionalContext 解决本 session 的连续犯错(同一个 turn 里别再调一次失败的 tool),append_to_memory 解决跨 session 的重复犯错(明天另一个 worktree 启动时就知道)。
工程上要记住一句话:Hook 是 memory 唯一可信的 writer。直接让 LLM 自己写 memory 容易引入幻觉(claim without evidence),但 hook 拿到的是真实的 tool 调用结果——它写下去的失败原因是事实,不是叙述。
2. MCP:第二条记忆通道
MCP(Model Context Protocol)通常被介绍为「让外部服务暴露 tool」。但从 memory 的视角看,它是第二条独立的记忆通道。
PDF §7.5 描述 claw-code 的 system prompt assembly 时,会调用 getMcpInstructionsSection(mcpClients):把每个连接的 MCP server 在握手阶段给出的 instructions 字段,拼成 prompt 的一段。
这意味着一台 MCP server 可以同时 ship 两样东西:
- tool schema:它能干什么;
- operator-style instructions:它应该怎么被使用——一段自然语言指南、约定、避坑提示。
为什么这是「第二条记忆通道」?因为本地 MEMORY.md 是用户/项目维度的,每个仓库、每个开发者都可能不一样;而 MCP instructions 是服务维度的,由提供方维护,跨所有连接它的 agent 共享。
工程价值非常大。设想一家公司有内部 DevOps MCP server:
| |
这段话不需要每个团队成员手动加进自己的 CLAUDE.md——只要他们的 agent 连了这台 MCP server,下一轮 system prompt assembly 时这段约定就自动注入。MCP 让「公司级最佳实践」获得了一个集中维护、跨 agent 自动分发的载体。
放回闭环里看,MEMORY.md 是 bottom-up 的(hook 从 runtime 失败里学到),MCP instructions 是 top-down 的(团队从经验里写下)。两条通道在 system prompt assembly 时合流。
3. CLAUDE.md:项目契约
如果说 MEMORY.md 是 agent 的工作笔记、MCP instructions 是服务说明书,那么 CLAUDE.md 是项目契约——人类对 agent 在「这个仓库里应该怎么干」的明确约定。
我们直接看 claw-code 自己的 CLAUDE.md(仓库根目录):
| |
短、操作化、可执行。值得逐段品:
- Detected stack:把「这是个 Rust 项目」写成事实,省掉 agent 每次启动时去 sniff
Cargo.toml。 - Verification:三条命令——
cargo fmt、cargo clippy --workspace --all-targets -- -D warnings、cargo test --workspace——这是「写完代码以后必须跑什么」的契约。第 5 篇讲过,这种可执行 anchor 让 verification 可以自我验证。 - Repository shape:明确
rust/、src/、tests/三处的关系。 - Working agreement:四条工作约定,最后一条是真正的元规则——
Do not overwrite existing CLAUDE.md content automatically; update it intentionally when repo workflows change.
这条是整篇文档的灵魂。它在说:memory 是 workflow 的一部分,不只是 workflow 的描述。当工作流变了,CLAUDE.md 必须被有意识地更新;反过来,CLAUDE.md 的更新也是工作流变化的官方公告。
把三条通道并排看:
| 通道 | 维护者 | 作用域 | 更新频率 |
|---|---|---|---|
MEMORY.md | hook 自动 + 人工 | 项目/用户 | 每次 session |
| MCP instructions | 服务提供方 | 跨 agent | 服务版本 |
CLAUDE.md | 人类有意识 | 项目 | workflow 变更时 |
三者在 system prompt assembly 阶段合流,给 agent 一个多源、有层次的上下文。
4. 协同图景
把上面四节合起来,每一个 turn 实际上长这样:
flowchart LR
subgraph "Each Turn"
SP[System prompt assembly] --> CMD[CLAUDE.md + MEMORY.md + MCP instructions]
CMD --> AG[Agent decides]
AG --> T[Tool exec]
T --> H[PostToolUse hook]
H -->|additionalContext / updatedInput| AG
H -->|append finding| MEM[(Memory files)]
end
MEM -. next session .-> CMD
Plugin[(Plugin/Skill state dirs)] -. next session .-> CMD
注意两条虚线——它们才是「进化」。实线是单 session 内部的回放,虚线是跨 session 的进化。一个 agent 是「录音机」还是「学习者」,区别就在那两条虚线是否真正连通。
5. 长周期失败模式(必须警惕的 4 种)
把闭环画出来容易,运行一年不出问题难。下面四种是工程上反复踩到的坑:
5.1 Silent drift:PromptCacheEvent.unexpected=true 但 fingerprint 稳定
第 5 篇讲过 prompt cache fingerprint 的作用。问题是:fingerprint 稳定不等于语义稳定。当上游 model 静默升级、tokenizer 微调、模板渲染顺序换了,可能 fingerprint 一致但 cache 命中率突然崩盘——unexpected=true 比例飙升。
现象:钱包黑洞。每个 turn 的 prefill cost 翻倍,但 agent 行为看似没变。
防线:把 cache_hit_rate 作为 SLI 持久化到 metrics,跨周做趋势告警,而不是只盯单 session。
5.2 Identity loss:post-compaction 的健康探针失败
run_session_health_probe() 是 compaction 之后的强制 sanity check(PDF 第 6 章)。当它失败,意味着 agent 在压缩之后不知道自己是谁了——project root 丢了、当前任务 id 丢了、CLAUDE.md 摘要被吞掉。
现象:agent 突然开始问「我们刚才在做什么?」或者用通用模板回答原本有项目特化答案的问题。
防线:把健康探针失败当作强制 hard-stop,要求人工介入或回滚到上一个 checkpoint,绝不能让它继续 silently 跑。
5.3 Repeated mistake loop:PostToolUseFailure 没写 memory
这是闭环最常见的断点。Hook 触发了、错误信息也拿到了,但没有 append 到 MEMORY.md——可能是 hook 实现忘了,可能是写入路径权限问题,可能是 atomic write 失败被吞了 exception。
现象:同样的 tool 错误一周内被 agent 触发 50 次,每次都是「初次见面」。
防线:把「failure → memory write」做成 contract test,pre-merge 强制跑一次注入失败的回归 case。
5.4 Verification avoidance + 80% illusion(PDF §6.7)
最隐蔽。Memory 里只存 claim 不存 evidence——「我已经修复了这个 bug」「测试通过了」「部署成功了」。下一次 session 读到这些 claim 当事实信,连锁失败。
PDF §6.7 把它叫做「Verification Avoidance」:agent 倾向于声称完成而不是证明完成。配合 80%-of-the-way illusion——做完 80% 就感觉做完了——memory 就会沉淀一堆假阳性。
防线:memory 写入必须配 evidence anchor。例如「✓ test suite passed」必须带上 cargo test --workspace 的实际 stdout 摘要或 exit code,不能只写一句「passed」。这就是为什么 claw-code 的 CLAUDE.md 里要把 cargo fmt / cargo clippy / cargo test 写明——这些命令本身就是 evidence 生成器。
6. Skills + Plugins:把好行为制度化
闭环跑顺了之后,下一个问题是:怎么让好行为不依赖个体灵感?
PDF §7 给出的答案是 Skills + Plugins。
Skills 是 prompt-native 的 workflow 包,每个 skill 是一个 markdown 文件,frontmatter 声明它需要哪些 tool、什么条件下激活。例如:
| |
这不是 memory,但它复用了 memory 的纪律:把「应该怎么做」固化成可执行 anchor。Skill 的好处是条件性 context 注入——只有匹配 trigger 时才占 prompt 预算,不像 CLAUDE.md 永远在场。
Plugins 是 Skill 的分发载体(PDF §7.2,相关代码在 claw-code 的 src/utils/plugins/loadPluginCommands.ts)。Plugin 在加载时会暴露一组环境变量给 skill 使用:
${CLAUDE_PLUGIN_ROOT}:plugin 安装目录;${CLAUDE_PLUGIN_DATA}:plugin 的可写数据目录(可以放跨 session 的状态);${CLAUDE_SKILL_DIR}:当前 skill 的资源目录;${CLAUDE_SESSION_ID}:当前 session 的唯一 id;${user_config.X}:用户在 plugin manifest 里声明的可配置项。
注意 ${CLAUDE_PLUGIN_DATA}——它就是 plugin 自己的「memory 抽屉」。Memory / Skill / Plugin 三者的关系可以这样理解:
Memory 沉淀经验,Skill 把经验封装成可调用的动作,Plugin 把动作做成可分发的包。
闭环到这里就 self-reinforcing 了:runtime 失败 → hook 写 memory → 经验稳定后被人手 promote 成 skill → skill 被打包成 plugin → plugin 在团队里分发 → 整个团队的 agent 直接拿到「现成的好行为」,不必每个人重新踩一遍坑。
7. 代码 demo:三个 turn 看 memory 进化
完整代码在 cli-agent/code/06-memory-evolution-and-agent/memory_evolution.py。它 stdlib only、<150 LOC,用最小模型还原前文的闭环。
核心结构:
| |
跑 3 个 turn:
- Turn 1:agent 调用
deploy(env="prod"),hook 截获错误「missing dry-run gate」,append 到MEMORY.md。 - Turn 2:新 session 启动,system prompt assembly 把上一条 lesson 注入。Agent 看到后改先跑
verify_dry_run。 - Turn 3:dry-run 通过,verified 事实也被记下。
deploy这次成功。
每个 turn 之间打印 MEMORY.md 的 diff,进化轨迹一目了然。读者可以直接 python memory_evolution.py 跑起来看。
8. 系列回顾 + 下一步可以做什么
到这里,整个《CLI Agent 深入浅出》系列就走完了。回看 6 篇主线:
- 第 1 篇 · 工业级 Agentic Workflow 总览——主循环、turn 边界、显式控制流为什么重要。
- 第 2 篇 · Tool 与 Permission——tool surface 的设计,permission boundary 是 trust 的边界。
- 第 3 篇 · Subagent / Plan / Worktree——并行隔离的三种姿势,沙箱即纪律。
- 第 4 篇 · Memory System 之 Why——为什么单靠 context window 撑不住,memory 是 verification 的 anchor。
- 第 5 篇 · Memory 的存储、检索与失效——文件式 storage、index 注入、读时 verify、与 prompt cache 的合作。
- 第 6 篇 · Memory 与 Agent 的协同演化(本篇)——Hooks/MCP/CLAUDE.md/Skills+Plugins 四个齿轮把闭环 self-reinforcing。
如果只能记一句话,那就是:
工业级 agent = 显式控制流 + 类型化记忆 + 可观测闭环。
显式控制流让你在每一个 turn 都知道控制权在谁手里;类型化记忆让你的 context 不再是字符串拼贴而是有 schema 的事实库;可观测闭环让你的 agent 跑得越久越聪明而不是越漂移。
下一步可以做什么?把这套纪律推到极致,最自然的方向是领域特化 agent(domain-specialized agents):
- DB ops agent:
CLAUDE.md写明 schema 约束、verification 是 explain plan、memory 沉淀慢查询模式、MCP 通道暴露内部 query gateway。 - SRE agent:hooks 直接挂在 incident channel,memory 沉淀 postmortem 关键字,skill 封装 runbook,plugin 跨团队分发。
- Scientific computing agent:CLAUDE.md 写实验规范,verification 是 reproducibility check,memory 存 hyperparameter trace + dataset fingerprint。
通用 agent 解决「能做」,领域特化 agent 解决「做对」。当一个领域里的失败模式被 hook 充分捕获、被 memory 充分沉淀、被 skill 充分封装、被 plugin 充分分发,这个领域的 agent 就真的能上生产了——这正是工业级 agent 这个词最终的意义。
愿你写出的 agent,下次 session 比这次更聪明一点。
引用
- claw-code:
rust/crates/runtime/src/hooks.rs、rust/crates/plugins/src/hooks.rs - claw-code 仓库根
CLAUDE.md(本文 §3 完整引用) - claw-code:
src/utils/plugins/loadPluginCommands.ts(PDF §7.2) - PDF §6.7(Verification 纪律)、§7(Skills/Plugins)、§7.5(MCP instructions)、§8.5(Hook 回馈)
- 本系列 1–5 篇