第 8 章 · Hooks 与生命周期扩展

04 · Hook 系统的产品价值

Hook 不是炫技——它让 agent 的行为更稳定、更规范、更容易治理。

Hook 解决的三类问题

回顾这一章的三个 hook 示例,它们分别解决了三类问题:

问题Hook时机
代码格式不规范auto_formatafter_edit
操作不可追溯audit_logafter_tool
危险操作需拦截before_tool skipbefore_tool

这三类问题在真实的 coding agent 产品中普遍存在。Claude Code 用 hooks 来实现"编辑后自动 lint"、"提交前检查"等能力。Codex CLI 用类似的机制做沙箱隔离和操作审计。

Hook 和其他系统的关系

到第 8 章结束时,agent 已经有了多个可扩展的系统:

系统解决什么扩展方式
工具(第 3 章)agent 能做什么注册新 Tool
权限(第 4 章)什么操作需要确认PermissionRule 配置
事件(第 5 章)agent 的状态如何展示注册 EventListener
记忆(第 6 章)agent 记住什么ContextManager 配置
Skill(第 7 章)不同任务怎么工作注册新 Skill
Hook(第 8 章)执行过程中插入逻辑注册新 Hook

每个系统都是正交的——它们解决不同的问题,可以独立使用。RunAgentOptions 是它们的统一入口:

export interface RunAgentOptions {
  maxIterations?: number;
  permissionGuard?: PermissionGuard;  // 第 4 章
  emitter?: AgentEmitter;              // 第 5 章
  contextManager?: ContextManager;     // 第 6 章
  projectRules?: string;               // 第 6 章
  skill?: Skill;                       // 第 7 章
  hookManager?: HookManager;           // 第 8 章
}

所有扩展点都是可选的。不传就保持默认行为——这在教学项目中很重要,每一章的代码都能独立运行。

Hook 的设计取舍

为什么 hook 用类而不是函数数组? HookManager 用 Map 按 timing 分组,比一个大数组更高效——不需要在每次触发时过滤。

为什么 hook handler 是异步的? 大部分 hook 需要做 I/O(执行格式化命令、写日志文件)。同步 hook 无法支持这些操作。

为什么 after_edit 是单独的时机? 可以只用 after_tool,然后在 handler 里检查 ctx.tool === "write_file"。但 after_edit 更语义化——看到 after_edit 就知道这是"文件编辑后的处理",不需要看 handler 内部的判断逻辑。

版本更新

main.ts 的版本号从 v0.7.0 升级到 v0.8.0

本章回顾

第 8 章实现了 hook 系统,让 agent 具备可扩展的生命周期能力:

新增文件作用
Hook 类型src/hooks/types.ts定义 hook 的时机、上下文和结果
HookManagersrc/hooks/manager.ts注册和执行 hook 链
内置 hooksrc/hooks/builtins.ts审计日志、自动格式化、编辑验证
hook 集成src/agent.ts在四个时机调用 hook
hook 使用src/main.ts注册审计日志 hook

加上之前章节的测试,整个项目现在有 168 个测试用例。

登录以继续阅读

解锁完整文档、代码示例及更多高级功能。

立即登录

On this page