devAlice
← Alice 之道

5. Hooks and automation — 操作者忘记时系统记得的东西

Skills 的另一半。系统在事件时自动触发的流程,无需操作者调用。Hooks 覆盖的盲点时刻、晋升标准、实际轮转中的 hooks,以及要避免的陷阱。

这是 Alice Way 系列的第 5 篇。第 4 篇 Skills and slash commands 把反复出现的心智动作压缩成一行名称。本篇关于另一半——让流程即使在操作者没有调用名称时也能触发。

0. Hook 把可遗忘的心智外包给系统

操作者会忘记。昨天的决策、开始新会话前的状态、就在汇报前本该运行的验证——一天一次,轻而易举。

Skills 阻断了部分遗忘——调用名称,流程就运行。但如果调用本身被忘记,skill 就不会触发。有些时刻,即使是一个词的名称也不会浮现。

Hooks 覆盖那些时刻。无需依赖操作者的意识,系统在特定事件时自动触发流程。 这是把操作者心智的一部分外包给系统的行为。

什么值得外包是有约束的:「绝不能忘记但容易忘记」、「条件清晰到可以自动判断」、「触发时机可以绑定到一个事件上」。本篇是对那个外包标准和实际轮转中的 hooks 的记录。

Hook 机制本身借鉴自 Anthropic Claude Code 的 hooks 系统。本篇是如何使用那个机制的记录,而非对它的发明。

1. 有些时刻意识会一片空白

操作者最常忘记的,不是因为流程很难,而是因为流程必须打断注意力集中在其他事情上的时刻

时刻意识状态容易被忘记的流程
会话开始后回想"我做到哪了"检查记忆同步状态
代码修改后如释重负——"完成了"lint / 构建 / 测试验证
起草报告前组织措辞——"怎么表达"检查工作区域外的变更
会话关闭前收尾——"好,今天完了"工作日志、HANDOFF、推送
危险命令前执行——"这就结束了"重新确认实际意图

在所有这些时刻,操作者的心智都在别处。「不要忘记」这样的原则无法阻止这一点,需要在系统层面触发。

Hooks 是触发装置。它们打断意识空白的时刻并强制执行流程。

2. Skill 和 hook 之间的边界

这两者经常被混淆。核心区别是一件事——谁调用它

调用者触发时机操作者意识
Skill / slash command操作者明确操作者决定调用前知晓
Hook系统自动事件决定只看到结果(或根本没注意到)

Skill 需要操作者「做这个」的决定才能触发。Hook 无需它就触发。所以 hook 最大的价值是——即使在操作者没有决定的时刻,流程也得到保证

同一套流程可以两种方式暴露。/verify 可以直接作为 slash command 调用,也可以在「完成」报告前自动触发。操作者有意识调用 = skill;系统自动触发 = hook——进入同一套流程的两个入口。

3. 晋升标准 — 哪些流程被做成 hook

并非每个流程都应该成为 hook。只有通过以下全部五条的才获得自动触发权限。

3.1 跳过代价大,且容易跳过

Hook 有认知成本——系统在操作者不知道的情况下做了某件事。要证明那个成本合理,跳过的代价必须足够大。未经验证的推送、没有新鲜记忆同步就开始的会话——这些损失立即显现。是 hook 领地。

便利级别的流程留作 skills,不是 hooks。

3.2 触发条件是明确的事件

Hook 绑定到特定事件。「会话开始」、「tool use 前」、「发送输出前」、「会话结束」——那类事情。如果事件是模糊的——「感觉对的时候」——它不是 hook。

3.3 决定是可自动判断的

Hook 触发后,做什么必须是可以自动判断的。「如果变更通过 lint,OK;否则阻断」——一个清晰的分支。需要额外操作者判断的流程通过 skill 调用,而不是 hook。

3.4 失败是安全的

如果 hook 失败,整个系统不能崩溃。因为 hooks 在操作者的意识之外运作,失败不会立即被注意到。所以失败必须被隔离影响。

3.5 输出是一个信号

Hook 的结果以一行到达操作者。清晰的信号如「OK」、「已阻断」、「警告」。长而模糊的输出把 hook 变成操作者视野中的噪声。

4. 实际轮转中的 hooks

我每天依赖的一部分 hooks。

4.1 SessionStart — 会话开始时

会话一启动,就打印一行记忆同步状态。"Memory sync: current"或"5 min old — refresh needed"。操作者读那一行,立即做出判断。

没有这个 hook——操作者每次都要有意识地检查「记忆是否是最新的」。注意力集中在别处的时刻,检查被忘记,工作就直接开始了。然后基于过时的状态做出决策。

4.2 PreToolUse — 危险命令前

rm -rf、force push、破坏性 SQL 等特定命令前触发。要么请求用户确认,要么基于策略阻断。

这个 hook 的价值是——系统强制一个「我真的想要这个吗」的停顿时刻。打断快速执行流程正是重点所在。

4.3 PreToolUse → 自动触发 /verify

在「完成」报告前自动运行 lint、构建、测试的 hook。就在操作者即将写下「完成」时,系统介入并强制验证。如果失败,报告被阻断。

操作者的如释重负时刻(「现在完了」)是最危险的。Hook 在那种释然中强制一次停顿。

4.4 Stop — 会话关闭时

会话即将结束的那一刻,检查工作日志是否已更新,以及 HANDOFF 是否包含下一次会话需要的信息。如果缺少什么,提醒操作者。

没有这个 hook——操作者就在「完成」状态下关闭了。下一次会话从丢失的上下文开始。

4.5 积累效果

这些本身都是小流程。但积累效果很大——系统填补了操作者每天意识空白的 5—6 个时刻。操作者的心智只需专注于决策;「绝不能跳过的流程」由系统持守。

5. 设计原则

我收敛出来的 hook 设计原则。

5.1 简短快速

Hook 打断操作者的流程。如果不够简短,流程就会中断。耗时超过一秒的 hooks 应该异步运行或显示清晰进度。如果操作者开始想「为什么停了」,hook 的价值就变负了。

5.2 输出是一行

Hook 结束时,操作者看到的是一行。详细日志进入单独的文件。"Memory sync: current"、"Verification passed: 3 tests OK"、"Blocked: 2 lint errors"——那种形式。

5.3 失败隔离

Hook 失败不能影响主工作。如果记忆同步失败,会话仍然开始(带警告)。如果验证 hook 失败,阻断报告,但保持工作活跃。

5.4 可绕过

有时操作者有意想绕过 hook——调试、临时工作。必须存在明确的绕过选项。绕过被记录,但不被阻断。

5.5 幂等

同一事件触发两次,应该产生相同结果,或者至少不破坏。Hooks 是自动触发的,所以无法避免重复事件投递。

6. 不应该做成 hook 的东西 — 陷阱

晋升标准的另一面。

6.1 替代操作者决策

「当代码看起来是这样时自动修复」的 hook 是危险的。自动修复往往朝着不同于意图的方向走。Hooks 应该止于通知和阻断;自动修复在操作者调用 skill 时发生。

6.2 触发太频繁

每次按键或每次文件保存都触发的 hooks 变成噪声。事件的自然频率至少应该在分钟量级。亚秒级触发会打断操作者的流程。

6.3 长输出

如果一个 hook 触发了 30 行日志,它会把主工作的输出淹没。长信息进文件;控制台只得到一行信号。

6.4 失败导致主工作崩溃

如果 hook 失败级联导致主工作崩溃,操作者就会关掉那个 hook。一旦关掉,就永远关掉了。所以失败隔离不容商量。

7. 组合 skills 和 hooks

来自第 4 篇——skills第 5 节的网络效应,在加入 hooks 后再扩展一步。

同一套流程以两种方式暴露:

流程Skill 调用Hook 触发
/verify操作者明确想要验证时"完成"报告前自动触发
/start <project>操作者进入项目时(无——操作者意图就是开始)
/session-end操作者声明收尾时(Stop hook 只检查遗漏)
记忆同步(无专用 skill)SessionStart 自动

这样配对——操作者有意识时用 skill,意识空白时用 hook——同一套流程无论哪种方式都得到保证。决策权留在操作者手中;安全网由系统持守。

下载 — settings.json 示例

本文介绍的 hook 布局(SessionStart / UserPromptSubmit / PreToolUse / PostToolUse)加上权限允许/拒绝列表,打包成一个文件。拿去用,把 <project-root> 替换成你自己的项目路径。

settings.json
shasum -a 256 settings.json
# expected: 60b5bf7fec33f92d9ddcc6ab4696747df6bb3dab14e8287b696d45fbd6c1abde

8. 压缩成一条原则

Hook 设计的核心压缩成一句话:

「只有操作者很可能忘记的流程才由系统自动触发。其他一切留作操作者选择调用的 skill。」

这条成立时,hooks 成为减轻操作者心智负担的安全设备。它崩溃时,它们成为劫持操作者意图的噪声。

下一篇涵盖一个智能体不做所有事的结构——多智能体委托,即什么交给其他协作者,什么自己做。