生成模型 :Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗 :输入 ~140k tokens,输出 ~8k tokens(本节)
上一节介绍的内部钩子(Internal Hooks)运行在 Gateway 进程内部,通过事件键注册和触发。本节聚焦 OpenClaw 的另一套钩子体系——插件钩子(Plugin Hooks) ,它由插件系统驱动,提供了更结构化的生命周期拦截能力,以及将外部 HTTP 请求映射为 Agent 动作的网关钩子映射机制。
22.2.1 钩子映射(src/gateway/hooks-mapping.ts)
想象这样一个场景:你希望 Gmail 收到新邮件时,自动通知 OpenClaw 的 Agent 进行处理。传统做法需要编写一个中间服务来桥接 Gmail Webhook 和 Agent API。OpenClaw 的**钩子映射(Hook Mapping)**机制直接内置了这个桥接能力——它接收外部 HTTP 请求,按规则匹配后转换为 Agent 可理解的动作。
Copy 外部系统(Gmail/GitHub/自定义服务)
│
▼ HTTP POST /hooks/gmail
┌─────────────────────────────┐
│ Gateway HTTP 端点 │
│ ① Token 鉴权 │
│ ② 路径/来源匹配 │
│ ③ 模板渲染 │
│ ④ Transform 转换(可选) │
│ ⑤ 生成 HookAction │
└─────────────────────────────┘
│
▼
wake(唤醒心跳)或 agent(发送消息给 Agent) Gateway 钩子端点通过配置启用,必须设置鉴权 Token:
Token 从请求中提取,支持两种方式:
Authorization: Bearer <token>
X-OpenClaw-Token: <token>
映射规则定义了"什么请求触发什么动作"。每条规则包含匹配条件和动作模板:
OpenClaw 内置了 Gmail 预设映射:
用户也可以在配置中定义自定义映射规则:
当 HTTP 请求到达钩子端点时,applyHookMappings 按顺序尝试匹配:
消息模板使用类 Mustache 的 {{expr}} 语法,支持以下表达式:
getByPath 支持点号和方括号语法(如 messages[0].from),可以深度访问嵌套的 JSON 数据。
匹配成功后生成两种动作之一:
创建一个新的 Agent 消息,包含 sessionKey、通道、模型等参数
agent 动作是最常用的——它等价于从某个通道发送一条消息给 Agent,但消息内容由外部系统的 Webhook 数据填充。
对于复杂的数据转换需求,模板语法可能不够用。OpenClaw 支持加载自定义 Transform 模块来完全控制映射逻辑:
Transform 函数接收完整的请求上下文,返回部分动作字段(与基础模板渲染结果合并),或返回 null 跳过此请求。Transform 模块带有缓存——同一模块路径只会被 import() 一次。
22.2.2 Agent 生命周期钩子:before_agent_start / agent_end
从这一小节开始,我们进入**插件钩子系统(Plugin Hook System)**的领域。与内部钩子的发布/订阅模式不同,插件钩子通过插件注册表(Plugin Registry)管理,由 createHookRunner 创建的运行器统一调度。
OpenClaw 定义了 14 种插件钩子,覆盖五个生命周期域:
执行模型:Void vs Modifying
插件钩子有两种执行模式,对应不同的使用场景:
衍生解释 :这种双模式设计在中间件架构中很常见。Express.js 的中间件是纯顺序的(每个 next() 调用下一个);Koa 的洋葱模型也是顺序的。OpenClaw 增加了并行模式——对于不需要互相影响的观察型钩子,并行执行能显著提高性能。
before_agent_start
before_agent_start 在 Agent 开始处理请求前触发,允许插件注入额外的系统提示词或上下文:
这是一个 Modifying Hook ——多个插件的结果会被合并:
合并策略是:systemPrompt 后者覆盖前者(最后一个插件说了算),prependContext 则追加拼接(所有插件的前置上下文都保留)。
agent_end 在 Agent 完成处理后触发,是一个 Void Hook (并行执行、无返回值):
典型用途包括:对话质量分析、使用量统计上报、异常监控告警等。
工具钩子是插件钩子中最精细的一组,覆盖了工具调用的完整生命周期。
在 Agent 发起工具调用之前触发。这是一个 Modifying Hook ,插件可以修改参数甚至阻止调用:
合并策略:
这意味着任何一个插件返回 block: true,工具调用就会被阻止——这是安全策略的关键拦截点。例如,一个安全插件可以检查 bash 工具的参数,阻止执行危险命令:
在工具调用完成后触发,是一个 Void Hook (并行、观察型):
典型用途:工具使用统计、性能监控、错误追踪。
tool_result_persist 是整个钩子系统中唯一的同步钩子 ——它在工具结果写入会话记录时触发,必须同步返回:
设计为同步的原因是:此钩子运行在会话记录追加的热路径 上——会话 JSONL 文件的写入是同步操作,如果这里引入异步等待,会破坏写入的原子性和顺序性。
这个钩子采用管道模式 ——每个处理器接收上一个处理器的输出作为输入,最终结果是链式传递的最后一版消息。典型用途:在持久化前过滤敏感信息、压缩大型工具输出、添加元数据标注。
衍生解释 :管道模式(Pipeline Pattern)是一种数据处理模式,数据依次通过一系列处理阶段,每个阶段接收前一阶段的输出并产生新的输出。Unix 的管道操作符 | 是最经典的例子:cat file | grep error | sort。这里的 tool_result_persist 钩子链就是一个同步的内存管道。
22.2.4 消息钩子:message_received / message_sending / message_sent
消息钩子拦截用户与 Agent 之间的消息流,覆盖消息的"进-处理-出"三个阶段:
message_received
用户消息到达时触发,是一个 Void Hook :
用途:消息接收统计、内容审计日志、用户行为分析。
message_sending
Agent 回复即将发送前触发,是一个 Modifying Hook ——插件可以修改内容甚至取消发送:
合并策略:
这个钩子给了插件极大的控制权:
格式转换 :将 Markdown 转为特定通道支持的格式
消息实际发送后触发,是一个 Void Hook :
用途:发送成功率监控、失败重试触发、消息归档。
22.2.5 网关钩子:gateway_start / gateway_stop
网关钩子在 Gateway 服务器的启动和停止时触发,是最外层的生命周期钩子。
Gateway HTTP 服务器启动后触发,是一个 Void Hook :
用途:初始化外部连接(数据库、消息队列)、注册服务发现、发送启动通知。
Gateway 即将关闭时触发:
用途:清理资源、断开外部连接、发送关闭通知、刷新缓冲区。
所有插件钩子通过 createHookRunner 统一创建运行器:
运行器的关键设计决策:
默认容错 :catchErrors 默认为 true,一个插件的钩子失败不会影响其他插件和核心流程。
优先级排序 :处理器按 priority 降序排列——高优先级先执行。对于 Modifying Hook,这意味着高优先级的插件可以先设定默认值,低优先级的可以覆盖。
按需检查 :hasHooks 让调用方可以在不调用运行器的情况下判断是否有注册钩子,避免不必要的事件对象构建开销。
插件通过 OpenClawPluginApi.on() 方法注册钩子处理器:
每个注册会创建一个 PluginHookRegistration 记录,存储在插件注册表中:
至此,我们已经完整介绍了 OpenClaw 的两套钩子系统。以下是它们的关键差异:
维度
内部钩子(Internal Hooks)
插件钩子(Plugin Hooks)
两套系统互不冲突,可以同时使用。内部钩子更适合"运维级"的轻量扩展(如审计日志、会话保存),插件钩子更适合"开发级"的深度集成(如安全拦截、内容转换、外部系统联动)。
钩子映射 是 Gateway 内置的 HTTP→Agent 桥接机制,通过路径/来源匹配和模板渲染将外部 Webhook 请求转换为 Agent 动作,支持预设(Gmail)和自定义映射规则,以及 Transform 模块进行复杂转换。
插件钩子系统 定义了 14 种钩子,覆盖 Agent、消息、工具、会话、网关五个生命周期域,由 createHookRunner 工厂统一调度。
Agent 钩子 中,before_agent_start 允许注入系统提示词(顺序合并),agent_end 用于完成后的观察分析(并行执行)。
工具钩子 提供了最精细的控制——before_tool_call 可以修改参数或阻止调用,tool_result_persist 是唯一的同步管道钩子,在会话记录的热路径上运行。
消息钩子 拦截消息的进-出流程,其中 message_sending 是唯一可以修改或取消消息的拦截点。
两套钩子系统 (内部 + 插件)互补共存——内部钩子面向文件系统级扩展,插件钩子面向编程级深度集成,共同构成了 OpenClaw 完整的可扩展性基础。