
1. OpenClaw Webhook 到底是什么为什么你需要它OpenClaw Webhook 是 OpenClaw 网关对外暴露的 HTTP 回调入口它让 GitHub、Stripe、n8n 这类外部服务在事件发生时主动把 JSON 数据 POST 进来OpenClaw 收到后转成一次唤醒或一次完整的代理运行。简单说它把 OpenClaw 从「你问它才答」的聊天助手变成「有事它自己动」的响应式系统。适合谁适合手上已经有 OpenClaw 实例、又想让外部事件自动触发处理逻辑的开发者尤其是用 JavaScript/TypeScript 写转换逻辑的那批人。我先把一个容易混淆的点讲清楚因为很多人第一次配 OpenClaw Webhook 就栽在这里。OpenClaw 里有两个都叫「钩子」的东西一个是 HTTP Webhook是外部服务通过 HTTP 调用的入站端点另一个是内部钩子是跑在网关进程内部的本地事件处理器。你要接 GitHub、Gmail、Stripe 或者家里的传感器用的是 HTTP Webhook你想「每次新会话开始时写个小记忆文件」用的是内部钩子。两者可以一起用但解决的问题完全不同。本文只聚焦 HTTP Webhook 这条链路从回调机制一路讲到 TypeScript 事件处理。为什么值得花时间搞懂它因为 Webhook 是成本最低的自动化入口。你不需要写轮询脚本不需要定时任务去问「有没有新事件」外部服务在事件发生的那一刻就把数据推过来了。GitHub 在 PR 提交时通知 OpenClawStripe 在支付失败时通知 OpenClawn8n 按计划通知 OpenClawOpenClaw 接收后转成代理运行或轻量唤醒再把结果路由回你实际用的渠道。整条链路跑通一次你就能把它复制到几十个场景里。但「跑通一次」和「稳定跑」之间隔着不少坑令牌怎么放、签名怎么验、重试怎么去重、转换函数写在哪、本地怎么调试。下面我按可跟做的顺序拆开讲每一步都给可复制的配置和代码。你跟着走一遍应该能在一个下午内把完整闭环跑起来。2. TaoToken 前置统一 Key 与 API 通道的鉴权联调在写 Webhook 处理逻辑之前先把鉴权通道理顺否则你会在「到底是 Webhook 令牌错了还是模型调用失败了」之间反复横跳。OpenClaw 的 Webhook 本身用共享令牌保护入站请求但 Webhook 触发代理运行后代理去调用模型时还需要一套模型侧的 Key。这两套鉴权是分开的很多人把它们混在一起排查浪费大量时间。我的做法是用 TaoToken 统一模型侧的 Key 和 API 通道让 Webhook 只管入站鉴权模型调用走一条稳定的通道。TaoToken 的 API 地址是 https://taotoken.net/api 官网在 https://taotoken.net/ 。你需要在控制台创建一个 API Key然后把它配到 OpenClaw 调用模型的地方。这样 Webhook 收到事件、触发代理运行时代理用的就是这把统一的 Key不用在每个集成里各配一套。具体操作上先到控制台生成 Key。打开 https://taotoken.net/console 登录后进 API Keys 页面新建一把命名建议带上用途比如openclaw-webhook-prod方便以后轮换时知道哪把在用。生成后立刻复制保存页面刷新后就看不到了。这一步别偷懒用短 Key也别把生产 Key 和测试 Key 混用。拿到 Key 之后把它写进 OpenClaw 的环境变量而不是硬编码进配置文件。原因很直接Webhook 的配置文件经常会被复制、被版本管理、被贴到 issue 里求助硬编码的 Key 一旦泄露就得全部重来。用环境变量的话配置文件里只留${OPENCLAW_HOOKS_TOKEN}这种占位符安全得多。如果你还想在联调阶段直接验证模型通道是否通可以用模型对话页面手动发一条消息确认 Key 有效、额度正常。地址是 https://taotoken.net/models 发一条简单的中文消息能正常返回就说明模型侧通道没问题。这一步能帮你把「模型调用失败」这个变量提前排除掉后面调试 Webhook 时就只剩入站鉴权和转换逻辑两个变量了。对于长期跑编码类或 Agent 类任务的场景可以考虑 Coding Plan它更适合高频调用。地址是 https://taotoken.net/coding-plan 。Webhook 触发的代理运行如果频率很高比如 CI 每次构建都触发用包月方案比按量更可控。接入文档在 https://taotoken.net/doc 里面有各语言的调用示例配 OpenClaw 时对着看就行。这里要强调一个排查顺序先确认模型通道通再确认 Webhook 入站通最后确认转换逻辑对。顺序反了你会在一个报错上卡半天却找错方向。我试过先调 Webhook 再调模型结果 401 出现时以为是 Webhook 令牌问题其实是模型 Key 没配白白折腾了一小时。3. 可复制配置hooks 块、映射与 TypeScript 转换现在进入配置环节。OpenClaw 的 Webhook 配置位于配置文件的hooks代码块里文件名因安装方式而异但结构一致启用钩子、设置令牌、确定 URL 路径然后按需加映射。下面这份 JSON 配置你可以直接改改就用注意令牌走环境变量。{ hooks: { enabled: true, path: /hooks, token: ${OPENCLAW_HOOKS_TOKEN}, mappings: [ { id: github-pr, match: { path: github-pr }, action: agent, name: GitHub, messageTemplate: GitHub PR {{body.action}} in {{body.repository.full_name}} by {{body.pusher.name}} }, { id: stripe-payment, match: { path: stripe-payment }, action: agent, name: Stripe, transform: transforms/stripe.ts } ] } }这份配置里有两个映射。第一个用模板路径/hooks/github-pr收到请求后用messageTemplate拼一条消息给代理。第二个用转换函数路径/hooks/stripe-payment收到请求后交给transforms/stripe.ts处理。模板适合简单场景转换函数适合需要判断逻辑的场景。令牌这块${OPENCLAW_HOOKS_TOKEN}从环境变量读。你在启动 OpenClaw 的 shell 或 systemd 单元里设置它值用一条长随机字符串比如openssl rand -hex 32生成。别用secret、123456这种Webhook 端点会被全网扫描弱令牌等于没锁门。接下来是 TypeScript 转换函数。转换函数接收请求体返回一个规范化的 action 对象返回null就跳过这个事件。下面这个例子处理 Stripe 的支付事件只对payment_failed和invoice_paid做不同路由其他事件直接跳过。// transforms/stripe.ts interface StripeEvent { id: string; type: string; data: { object: { id: string; amount: number; customer_email?: string; }; }; } interface HookAction { action: agent | wake; name: string; message: string; sessionKey?: string; channel?: string; } export default function transform(body: StripeEvent): HookAction | null { // 去重用事件 ID 作为会话键的一部分避免重试导致重复处理 const sessionKey stripe-${body.data.object.id}; if (body.type payment_failed) { return { action: agent, name: Stripe, message: 支付失败${body.data.object.customer_email}金额 ${body.data.object.amount / 100} 元请分析原因并通知财务频道。, sessionKey, channel: finance-alerts }; } if (body.type invoice_paid) { return { action: agent, name: Stripe, message: 发票已支付${body.data.object.customer_email}金额 ${body.data.object.amount / 100} 元。, sessionKey, channel: accounting }; } // 其他事件类型不处理直接跳过省模型代币 return null; }这段代码有几个设计点值得说。第一sessionKey用事件对象 ID 拼出来保证同一个支付事件无论重试几次都落到同一个会话配合去重逻辑就不会重复提醒。第二不同事件类型路由到不同频道payment_failed去财务告警频道invoice_paid去会计频道。第三不关心的事件返回null直接跳过不消耗模型代币。这三点在生产环境里能省掉大量噪音和成本。转换文件的存放位置要注意权限。把它放在一个专用目录里目录权限设成只有运行 OpenClaw 的用户能读写因为转换函数本质就是代码能改它就能改代理行为。别放在 Web 可访问的目录下也别放进会被自动同步的云盘目录。如果你用的是 Cline MCP 或 Codex 这类工具配合 OpenClaw配置里同样要写全三件套Base URL、Key、Model ID。Base URL 用 https://taotoken.net/api Key 用你在控制台生成的那把Model ID 按你实际选的模型填。三件套缺一个都会报鉴权或模型找不到的错。4. 验证请求从 curl 到完整事件闭环配置写完先别急着接真实服务用 curl 手动打一发确认端点活着、令牌对、转换逻辑跑得通。这一步能把大部分低级错误挡在门外。先测最简单的唤醒端点。假设你的网关在http://127.0.0.1:8080令牌是test-token-abc请求如下curl -X POST http://127.0.0.1:8080/hooks/github-pr \ -H Authorization: Bearer test-token-abc \ -H Content-Type: application/json \ -d { action: opened, repository: { full_name: demo/repo }, pusher: { name: alice } }如果配置正确你会看到 OpenClaw 返回一个接受响应通常是 200 加一个 JSON 体里面可能带事件 ID 或会话标识。同时网关日志里会出现一条代理运行的记录。如果返回 401说明令牌不对检查环境变量有没有正确注入如果返回 404说明路径不对检查path和match.path拼出来的完整路径是不是/hooks/github-pr。再测转换函数那条链路。用 Stripe 的模拟事件打/hooks/stripe-paymentcurl -X POST http://127.0.0.1:8080/hooks/stripe-payment \ -H Authorization: Bearer test-token-abc \ -H Content-Type: application/json \ -d { id: evt_test_001, type: payment_failed, data: { object: { id: pi_test_001, amount: 9900, customer_email: userexample.com } } }预期结果是代理被触发往finance-alerts频道发一条支付失败的分析消息。如果转换函数返回null的事件类型比如把type改成customer_created你应该看到请求被接受但没有代理运行日志里显示事件被跳过。这个对比测试能确认你的过滤逻辑真的生效了。本地调试时我建议开两个终端一个跑 OpenClaw 并实时看日志一个发 curl。日志里重点看三样东西请求有没有进来、令牌校验过没过、转换函数返回了什么。很多问题看一眼日志就定位了比盲猜快得多。如果你要模拟真实服务的签名头比如 Stripe 的Stripe-Signature可以在 curl 里手动加一个假签名头先确认你的边缘校验逻辑能读到这个头。真正的签名验证要等接真实服务时再开本地用假值测通路即可。完整闭环跑通的标志是curl 发出请求 → 网关日志显示接收 → 转换函数执行 → 代理运行被触发 → 结果消息出现在目标频道。这五步都看到说明链路通了。接下来把 curl 换成真实服务的 Webhook 配置填上你的公网地址和令牌就能接生产事件了。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节按真实报错来对。Webhook 接入过程中报错信息往往指向好几个不同的层分清楚才能快速修。401 Unauthorized。这是最常见的。原因通常有三个令牌没配、令牌不匹配、请求头格式不对。先确认环境变量OPENCLAW_HOOKS_TOKEN真的被进程读到了可以在启动脚本里echo一下确认。再确认请求头是Authorization: Bearer token注意Bearer后面有一个空格大小写敏感。有些发送方默认用X-Hook-Token之类的自定义头那就得在中间层转成 Bearer或者改配置支持自定义头。如果用的是 TaoToken 的模型 Key 报 401那是模型侧的问题检查 Key 是否过期、是否复制完整控制台里可以重新生成。local proxy failed。这个报错通常出现在你通过本地代理或隧道转发 Webhook 请求时。含义是代理层没能把请求送到 OpenClaw 网关。排查顺序先确认网关本身在监听curl http://127.0.0.1:8080/health之类的健康检查能不能通再确认代理配置的目标地址和端口对最后确认代理进程有权限访问网关端口。如果是容器环境注意容器网络和宿主网络的端口映射127.0.0.1在容器里指向容器自己不是宿主。reading choices 相关报错。这类报错一般出现在模型返回体解析阶段提示读取choices字段失败。根因通常是模型通道返回了非预期结构比如返回了一个错误对象而不是正常的 completion 结构。排查时先把模型通道单独测通用模型对话页面发一条消息确认返回正常。如果模型通道正常但 Webhook 触发时报这个错检查转换函数返回的 action 对象字段是否符合 OpenClaw 期望的结构字段名拼错会导致后续解析异常。另外确认 Base URL 是 https://taotoken.net/api 路径拼错会返回 404 页面而不是 JSON解析自然失败。OAuth 相关报错。如果你接的是需要 OAuth 的服务比如某些 Google 系服务报错可能出现在令牌刷新环节。OAuth 令牌有有效期过期后需要 refresh。排查时确认 refresh token 还在、scope 没变、回调地址没改。如果 OAuth 流程和 Webhook 混在一起建议把 OAuth 令牌管理放在中间层Webhook 只接收已经带好鉴权的事件别让 OpenClaw 直接处理 OAuth 刷新。Codex auth.json 相关。如果你用 Codex 配合 OpenClawauth.json里的配置要写全 Base URL、Key、Model ID 三件套。缺 Base URL 会走默认地址导致连不上缺 Key 会 401缺 Model ID 会报模型不存在。检查auth.json的 JSON 格式是否合法多余逗号是常见低级错误。CC Switch 或 Cline MCP 配置报错。这两类工具接入时同样确认三件套齐全。MCP 配置里服务器地址、鉴权头、模型标识都要对。如果报连接超时先确认网络能到 https://taotoken.net/api 再确认本地防火墙没拦。排查的通用心法把链路拆成「入站鉴权 → 转换逻辑 → 模型调用 → 结果路由」四段每段单独验证。哪段报错修哪段别在四段之间来回猜。日志是你最好的朋友把每段的日志都打开问题基本无处藏身。6. 语义一致 CTA把这条链路接到你的真实场景链路跑通之后接下来就是把它接到你真实的工作流里。如果你主要卡在排障和接入环节建议先把 API Keys 和接入文档过一遍地址是 https://taotoken.net/api-keys 和 https://taotoken.net/doc 里面有完整的鉴权说明和调用示例对着检查你的配置能省不少时间。如果你只是想先验证模型通道是否正常用模型对话页面发几条消息最直接地址是 https://taotoken.net/models 。确认通道没问题再回头调 Webhook变量就少了一个。如果你打算长期跑编码类或 Agent 类任务Webhook 触发频率高按量计费可能不太划算可以看看 Coding Plan地址是 https://taotoken.net/coding-plan 包月方案对高频场景更友好。最后给一个实用建议把 Webhook 的令牌和模型 Key 分开管理定期轮换。轮换时先加新 Key确认新 Key 工作正常再删旧 Key避免服务中断。转换函数当成正式代码来维护加注释、做版本管理、写测试用例。这样你的 OpenClaw Webhook 链路才能从「跑通一次」变成「稳定跑一年」。