
1. 从一次 Webhook 回调丢失说起如果你正在用 OpenClaw 做自动化大概率遇到过这种场景外部系统发来一个 HTTP 请求你希望它触发智能体执行某个动作结果回调没进来或者进来了但不知道卡在哪一步。OpenClaw Hooks 就是解决这类问题的机制——它是一套事件驱动系统让你在智能体命令、会话生命周期、Gateway 启动等节点上挂载自定义逻辑。Hooks 从目录自动发现通过 CLI 管理写法和 Skills 类似一个 TypeScript 函数就是一个 hook。这篇面向需要把 Webhooks 事件接入自动化流程的开发者聚焦 OpenClaw Hooks 在 CLI 与 TypeScript 项目中的落地方式。我会给出可复制的 hooks 配置骨架、CLI 触发命令与本地验证步骤并说明如何通过统一 Key/API 通道管理调用凭证最终完成一次从事件触发到回调验证的闭环。适合已经跑通 OpenClaw 基础流程、想进一步做事件编排的人。Hooks 分两类一类是智能体事件触发时在 Gateway 网关内运行的小脚本比如/new、/reset、/stop或生命周期事件另一类是外部 HTTP webhooks让其他系统触发 OpenClaw 中的工作。本文主要讲第一类同时把 Webhook 回调验证串起来。2. TaoToken 前置统一 Key 与 API 通道在写 hook 之前先把调用凭证这件事理清楚。Hooks 里经常要调用外部 API如果每个 hook 各自维护一套 Key很快就会乱。我试过用统一通道来管理把模型调用和 API 访问收敛到一个入口hook 里只读环境变量不硬编码。TaoToken 提供统一 Key/API 通道官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。你可以在控制台创建 API Key然后在 hook 的配置里通过env注入handler 里用process.env读取。具体操作路径模型对话调试https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite长期编码/Agent 场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite这样做的价值在于hook 代码里不出现任何密钥明文换 Key 只改一处配置审计也方便。下面进入具体配置。3. 可复制配置HOOK.md 与 handler.ts 骨架3.1 目录结构与自动发现Hooks 从三个目录自动发现按优先级顺序目录路径作用域工作区 hooksworkspace/hooks/每个智能体最高优先级托管 hooks~/.openclaw/hooks/用户安装跨工作区共享捆绑 hooksopenclaw/dist/hooks/bundled/随 OpenClaw 附带每个 hook 是一个包含HOOK.md和handler.ts的目录。先建目录mkdir -p ~/.openclaw/hooks/my-hook cd ~/.openclaw/hooks/my-hook3.2 HOOK.md 元数据HOOK.md用 YAML frontmatter 声明元数据加 Markdown 文档--- name: my-hook description: Short description of what this hook does homepage: https://docs.openclaw.ai/automation/hooks#my-hook metadata: { openclaw: { emoji: , events: [command:new], requires: { bins: [node] } } } --- # My Hook Detailed documentation goes here... ## What It Does - Listens for /new commands - Performs some action - Logs the result ## Requirements - Node.js must be installedmetadata.openclaw支持的字段emojiCLI 显示表情符号events要监听的事件数组如[command:new, command:reset]export要使用的命名导出默认defaulthomepage文档 URLrequires可选要求包括binsPATH 中需要的二进制文件、anyBins至少一个存在、env需要的环境变量、config需要的配置路径、os需要的平台always绕过资格检查install安装方法3.3 handler.ts 处理程序handler.ts导出一个HookHandler函数import type { HookHandler } from ../../src/hooks/hooks.js; const myHandler: HookHandler async (event) { // Only trigger on new command if (event.type ! command || event.action ! new) { return; } console.log([my-hook] New command triggered); console.log( Session: ${event.sessionKey}); console.log( Timestamp: ${event.timestamp.toISOString()}); // Your custom logic here // Optionally send message to user event.messages.push( My hook executed!); }; export default myHandler;每个事件包含type、action、sessionKey、timestamp、messages和context。context里有sessionEntry、sessionId、sessionFile、commandSource、senderId、workspaceDir、bootstrapFiles、cfg等字段。3.4 配置注入环境变量在配置里给 hook 注入环境变量把 TaoToken 的 Key 传进去{ hooks: { internal: { enabled: true, entries: { my-hook: { enabled: true, env: { TAOTOKEN_API_KEY: your-key-here, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } } } }handler 里读取const apiKey process.env.TAOTOKEN_API_KEY; const baseUrl process.env.TAOTOKEN_BASE_URL ?? https://taotoken.net/api;3.5 从额外目录加载如果 hook 放在别处用extraDirs{ hooks: { internal: { enabled: true, load: { extraDirs: [/path/to/more/hooks] } } } }4. 验证请求CLI 触发与成功结果4.1 列出与检查# 列出所有 hooks openclaw hooks list # 只显示符合条件的 openclaw hooks list --eligible # 详细输出显示缺失要求 openclaw hooks list --verbose # JSON 输出 openclaw hooks list --json检查资格openclaw hooks check openclaw hooks check --json查看单个 hook 详情openclaw hooks info session-memory openclaw hooks info session-memory --json4.2 启用与触发# 启用 openclaw hooks enable my-hook # 禁用 openclaw hooks disable command-logger启用后重启 Gateway 进程macOS 菜单栏应用重启或重启开发进程然后通过消息渠道发送/new触发事件。4.3 验证回调闭环在 handler 里加一段回调验证逻辑把事件转发到你的 Webhook 端点并检查响应const handler: HookHandler async (event) { if (event.type ! command || event.action ! new) { return; } const payload { sessionKey: event.sessionKey, action: event.action, timestamp: event.timestamp.toISOString(), }; try { const res await fetch(https://your-endpoint.example.com/callback, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${process.env.TAOTOKEN_API_KEY}, }, body: JSON.stringify(payload), }); if (!res.ok) { console.error([my-hook] Callback failed: ${res.status}); return; } const data await res.json(); console.log([my-hook] Callback ok:, data); event.messages.push( Callback verified: ${data.id ?? ok}); } catch (err) { console.error([my-hook] Callback error:, err instanceof Error ? err.message : String(err)); } };成功结果CLI 里看到Registered hook: my-hook - command:new发送/new后终端打印回调响应消息渠道收到Callback verified。4.4 捆绑 Hooks 参考OpenClaw 附带三个自动发现的捆绑 hookssession-memory/new时把上下文保存到workspace/memory/YYYY-MM-DD-slug.mdcommand-logger所有命令事件记录到~/.openclaw/logs/commands.logJSONL 格式boot-mdGateway 启动时运行BOOT.md查看日志tail -n 20 ~/.openclaw/logs/commands.log cat ~/.openclaw/logs/commands.log | jq . grep action:new ~/.openclaw/logs/commands.log | jq .5. 本篇常见错排查5.1 Hook 未被发现检查目录结构ls -la ~/.openclaw/hooks/my-hook/ # 应显示 HOOK.md, handler.ts验证 HOOK.md 格式cat ~/.openclaw/hooks/my-hook/HOOK.md # 应有 YAML frontmatter含 name 和 metadata列出所有发现的 hooksopenclaw hooks list5.2 Hook 不符合条件openclaw hooks info my-hook在输出中查找缺失的要求二进制文件检查 PATH、环境变量、配置值、操作系统兼容性。5.3 Hook 未执行确认已启用openclaw hooks list # 启用的 hook 旁应有 ✓重启 Gateway 进程重新加载 hooks。检查 Gateway 日志中的错误./scripts/clawlog.sh | grep hook5.4 处理程序错误测试 importnode -e import(./path/to/handler.ts).then(console.log)5.5 事件过滤写错常见错误是把events写成通用[command]而不是具体[command:new]导致开销变大。在元数据里指定确切事件metadata: { openclaw: { events: [command:new] } }5.6 处理程序阻塞Hooks 在命令处理期间运行保持轻量// ✓ Good - async work, returns immediately const handler: HookHandler async (event) { void processInBackground(event); // Fire and forget }; // ✗ Bad - blocks command processing const handler: HookHandler async (event) { await slowDatabaseQuery(event); await evenSlowerAPICall(event); };始终包装有风险的操作const handler: HookHandler async (event) { try { await riskyOperation(event); } catch (err) { console.error([my-handler] Failed:, err instanceof Error ? err.message : String(err)); // Dont throw - let other handlers run } };5.7 从遗留配置迁移旧配置格式仍然有效{ hooks: { internal: { enabled: true, handlers: [ { event: command:new, module: ./hooks/handlers/my-handler.ts, export: default } ] } } }迁移到基于发现的新系统mkdir -p ~/.openclaw/hooks/my-hook mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts创建 HOOK.md 并更新配置为entries格式然后验证openclaw hooks list # 应显示: my-hook ✓6. 把凭证与事件流收口到一处事件流打通之后真正容易出问题的往往不是 hook 逻辑本身而是散落各处的调用凭证。我的做法是把所有 hook 的外部调用都指向同一个 API 通道Key 通过配置的env注入handler 里只读环境变量。这样换 Key、加配额、做审计都只在一个地方操作。如果你还在调试模型调用可以先用模型对话入口验证请求格式https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。长期跑编码或 Agent 任务用 Coding Plan 更省心https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。Key 在 API Keys 页面管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入细节看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。最后留一个实用技巧在 handler 里加一行console.log([my-hook] Triggered:, event.type, event.action)配合openclaw hooks list --verbose和 Gateway 日志基本能定位九成以上的“hook 没反应”问题。事件流跑通后再逐步把回调验证、重试、日志落盘补上比一上来就写复杂逻辑稳得多。