
1. OpenClaw webhook 消息通知到底解决什么问题OpenClaw webhook 消息通知说白了就是给 agent 装一个「门铃」外部系统按一下发个 HTTP 请求OpenClaw 收到后决定要不要叫醒 agent、让 agent 生成什么内容、最后把结果推到哪个渠道。对需要把任务完成、异常告警推到微信的开发者来说这套机制的价值在于——你不需要为每种通知单独写一套发送逻辑只要把事件字段丢进 webhook剩下的路由、模板渲染、渠道投递都由 OpenClaw 统一处理。我见过太多团队的通知系统是「一个脚本一个 webhook 地址」CI 一套、监控一套、定时任务又一套改个收件人要翻五个文件。OpenClaw 的思路不一样它把 webhook 当成入口把 agent 当成内容加工厂把渠道当成出口三者解耦。你新增一个通知场景往往只是在hooks.mappings里加一段配置而不是新写一个服务。这篇文章聚焦一个最小可跑通的场景外部 POST 请求命中/hooks/wechat-notifyOpenClaw 按模板生成通知文本通过openclaw-weixin渠道发到固定微信目标。适合谁看适合已经在跑 OpenClaw、想让 agent 事件自动推到微信的开发者也适合刚接触 webhook 通知、想找一个结构简单、调试容易的落地案例的人。整条链路可以这样理解HTTP 请求进来 → OpenClaw 校验 Bearer token → 命中hooks.mappings里的wechat-notify→ 把payload.title / text / level / source渲染进messageTemplate→ 创建或复用 sessionagent:main:hook:wechat-notify→ agent 执行这条消息 → 生成最终通知文本 →delivertrue→channelopenclaw-weixin→ 微信收到通知。这里有个关键认知webhook 不是「直接发微信」的裸转发器。它中间隔了一层 agent所以你可以让 agent 对原始事件做整理、润色、格式化甚至根据 level 决定语气。这也是它比传统 webhook 转发灵活的地方——你传的是结构化字段agent 负责把它变成人话。如果你现在的通知需求是「输入结构简单、输出结构简单、不需要复杂条件分支」那这套最小配置就够用了。等哪天你要做多收件人、多级别样式、甚至先跑一段本地 JS 处理 payload再往上加 transform 也不迟。先把最小闭环跑通比一上来就设计大而全的架构靠谱得多。2. TaoToken 前置准备与 OpenClaw 环境打通在动手配 webhook 之前得先把 OpenClaw 的模型调用链路准备好。因为 agent 生成通知文本这一步是要走模型的模型不通webhook 收到请求也只会卡在 agent 执行阶段。这里我用 TaoToken 来做模型接入它的 API 地址是https://taotoken.net/api兼容常见的 OpenAI 风格调用方式配置起来比较直接。先说你需要在 TaoToken 侧拿到什么。登录后进控制台创建一个 API Key这个 Key 就是后面 OpenClaw 调用模型时的凭证。控制台地址是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。拿到 Key 之后先别急着填进 OpenClaw建议先用模型对话页做一次连通性验证地址是https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite随便发一句「你好」能正常返回就说明 Key 和网络都没问题。接下来是 OpenClaw 侧的模型配置。OpenClaw 的模型供应商配置通常写在openclaw.json里你需要把 Base URL 指向 TaoToken 的 API 地址把刚才拿到的 Key 填进去并指定一个 Model ID。这三件套缺一不可Base URL 决定请求发到哪Key 决定能不能过鉴权Model ID 决定用哪个模型。很多人配完发现报 401八成是 Key 没填对或者 Base URL 多写了斜杠。如果你用的是 Claude Code 这类工具做辅助开发TaoToken 也提供了对应的接入文档地址是https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。Claude Code 的接入方式在https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite有说明照着配就行。这一步不是必须的但如果你后面想用 Claude Code 来改 OpenClaw 的插件代码提前配好会省事。环境打通之后建议做一次最小验证在 OpenClaw 里手动触发一次 agent 对话确认它能正常调用模型并返回文本。因为 webhook 的messageTemplate最终是要交给 agent 执行的如果 agent 本身跑不通后面 webhook 调试会分不清是路由问题还是模型问题。我一般会先确保「agent 能正常回话」再往上叠 webhook 这层。还有一点容易被忽略OpenClaw 的 gateway 默认监听在127.0.0.1:18789如果你后面要用外部系统调 webhook得确认这个端口对调用方是可达的。本地测试用127.0.0.1没问题跨机器调用就要考虑网络配置。这个先记着等配 webhook 的时候会用到。3. 可复制的 openclaw.json webhook 配置片段这一节是核心直接给你可以抄的配置。OpenClaw 的 webhook 能力由几个配置项共同组成hooks.enabled打开 webhook 能力hooks.token用于 Bearer 鉴权hooks.path是 webhook 基础路径hooks.mappings是路由规则决定不同子路径如何处理请求。先看openclaw.json里 hooks 部分的完整结构。下面这段配置里wechat-notify映射的含义是当请求命中/hooks/wechat-notify就把请求体里的title / text / level / source套进模板作为一条 agent 消息执行并把最终结果投递到微信渠道openclaw-weixin收件人固定为那个im.wechat地址。{ hooks: { enabled: true, token: shared-secret, path: /hooks, mappings: [ { match: { path: /wechat-notify, method: POST }, action: { sessionKey: agent:main:hook:wechat-notify, messageTemplate: 来源: {{source}}\n级别: {{level}}\n标题: {{title}}\n内容: {{text}}, deliver: true, channel: openclaw-weixin, to: o9cq808hBSqYVWf89mnLZPQYBussim.wechat } } ] } }几个字段要重点说。match.path是子路径最终完整路径是hooks.path加上它也就是/hooks/wechat-notify。match.method限定 POST避免 GET 请求误触发。sessionKey决定这次 webhook 触发复用哪个会话固定成agent:main:hook:wechat-notify的好处是同一类通知的上下文能延续也方便在记录库里按 session 查。messageTemplate是模板{{}}里的变量会从请求体里取。deliver为 true 才会真正投递channel和to指定投递目标和收件人。如果你想让不同级别的通知有不同标题前缀可以在模板里做文章比如【{{level}}】{{title}}这样微信里一眼就能看出是 INFO 还是 ERROR。模板语法本身不复杂关键是字段名要和请求体里传的 key 对上对不上就会渲染成空。改完openclaw.json之后必须重启 gateway配置才会生效。这一步很多人会忘然后拿着旧配置测半天以为是自己请求写错了。重启命令按你的部署方式来如果是 systemd 管理的就systemctl restart openclaw如果是前台跑的进程就 CtrlC 再起。另外提一句落库插件。如果你装了session-sqlite-recorder-pluginwebhook 触发的 agent 执行会在before_message_write阶段被记录写进独立的session_history_plugin.sqlite3。这个库和主库分开好处是通知类消息不会污染主会话历史排查问题时直接查这个库就行。插件版会话记录器的代码在index.js里需要改记录逻辑的话从那里入手。配置这块的核心思路就一句话外部只传结构化字段OpenClaw 用模板拼成 agent 输入agent 负责整理成最终通知文本然后直接回发到微信。开发重点不是写代码而是把映射规则设计清楚。4. 验证请求与成功结果确认配置重启之后第一件事是发一条测试请求确认整条链路通了。用 curl 直接打本地 gateway 就行注意路径是/hooks/wechat-notify鉴权头是Authorization: Bearer shared-secret这个 secret 要和openclaw.json里hooks.token一致。curl -sk -X POST https://127.0.0.1:18789/hooks/wechat-notify \ -H Authorization: Bearer shared-secret \ -H Content-Type: application/json \ -d { source: manual-test, level: INFO, title: Webhook 测试通知, text: 这是一条通过 wechat-notify webhook 发送的测试消息。 }这里用-k是因为本地可能用了自签证书跳过证书校验生产环境建议换成正式证书别一直-k。-s是静默模式避免进度条干扰输出。请求体里的四个字段正好对应模板里的四个变量source标记来源level标记级别title和text是通知主体。成功的话会返回类似这样的 JSON{ok:true,runId:e0a683ce-aec5-4b7d-b8cf-0fd40056a422}ok:true表示 webhook 已被接收并触发runId是这次执行的唯一标识后面排查问题可以拿它去日志里搜。注意这个返回只代表「请求被受理」不代表微信一定收到了。要确认微信侧得看手机或微信客户端有没有弹出通知。如果微信收到了你会看到一条按模板渲染出来的消息内容大致是「来源: manual-test / 级别: INFO / 标题: Webhook 测试通知 / 内容: 这是一条通过 wechat-notify webhook 发送的测试消息。」。如果 agent 对文本做了润色措辞可能略有不同但核心信息都在。再进一步去session_history_plugin.sqlite3里查一下这次执行有没有被记录。用 sqlite3 命令行或者任意数据库工具打开查agent:main:hook:wechat-notify这个 session 的最新记录应该能看到刚才那条问答。这一步能验证落库插件是否正常工作也能确认 webhook 触发的 agent 执行确实走了完整的消息写入流程。整个验证动作覆盖了这几条链路webhook 鉴权是否生效、hooks.mappings是否生效、agent 是否被成功触发、微信渠道是否可投递、会话记录插件是否能记下问答。所以这条wechat-notify既是一个业务功能也是一个系统联通性测试用例。跑通一次后面加新场景就有底气了。5. 本篇常见错误排查配 webhook 最容易踩的坑集中在鉴权、路由和模型调用这三块。下面按真实报错来对。401 Unauthorized这是最常见的。原因通常是Authorization头没带、Bearer 后面少了空格、或者 token 和openclaw.json里的hooks.token不一致。先检查 curl 命令里的 secret 有没有写错再确认配置文件改完重启了 gateway。还有一种情况是请求打到了错误的端口比如 gateway 实际在 18789你打到了 18790那连鉴权都到不了。local proxy failed这个报错一般出现在 agent 调用模型这一步说明 OpenClaw 到 TaoToken 的请求没发出去。检查openclaw.json里模型供应商的 Base URL 是不是https://taotoken.net/apiKey 有没有填对网络能不能通到外网。如果你在容器里跑 OpenClaw还要确认容器的 DNS 和出网策略没问题。reading choices 相关报错这类报错通常意味着模型返回的结构和预期不符可能是 Model ID 填错了或者 Base URL 指向了一个不兼容 OpenAI 格式的端点。回到 TaoToken 的模型对话页确认这个 Model ID 可用再检查 Base URL 有没有多写路径。有时候是 Key 权限不够换一个 Key 试试。OAuth 相关报错如果你用的是 Claude Code 那套接入方式可能会碰到 OAuth 流程的问题。确认你走的是 API Key 方式而不是 OAuthTaoToken 的接入文档里有说明。Claude Code 的配置在https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite照着配一般不会出 OAuth 问题。微信没收到但返回 ok:true说明 webhook 受理了但投递环节出了问题。检查channel是不是openclaw-weixinto那个im.wechat地址有没有写错以及openclaw-weixin渠道本身是否在线。有时候是渠道掉线了重启一下渠道就好。模板变量渲染成空请求体里的 key 和模板里的{{}}对不上。比如模板写{{title}}请求体传的是subject那渲染出来就是空。把请求体和模板逐字段对一遍大小写也要一致。排查的时候有个通用思路先看 HTTP 返回码401 是鉴权问题404 是路径问题500 是服务端问题再看 OpenClaw 日志里有没有 agent 执行记录最后看微信渠道和落库记录。一层层往下查比瞎改配置快得多。6. 从最小通知到长期 Agent 通知体系wechat-notify跑通之后它其实是一个很好的扩展起点。因为它满足路径固定、收件人固定、字段少、易测试这几个条件你在这个基础上加场景成本很低。最直接的扩展是加多个路径。比如/hooks/build-alert专门发 CI/CD 构建通知/hooks/server-alert发服务器告警/hooks/daily-report发日报完成提醒。每个映射可以有不同的messageTemplate和收件人互不干扰。服务器异常告警就传titleCPU 过高、text具体指标直接发微信CI/CD 构建成功失败、部署完成也都能通过 webhook 发过来。再进一步是加级别样式。INFO、WARN、ERROR 用不同的标题前缀甚至不同的模板语气。ERROR 级别的通知可以让 agent 更强调紧急性INFO 级别就平铺直叙。这个在messageTemplate里用条件或者直接拼{{level}}就能实现。如果你希望通知内容完全可控、不走模型润色可以把模板文本原样投递省掉 agent 生成这一步。这样结果更确定延迟也更低。OpenClaw 支持在映射里配置 transform用本地 JS 模块先处理 payload再决定最终 message。适合那些格式要求严格、不允许模型自由发挥的通知。收件人也可以按映射区分。不同 webhook 映射到不同微信目标比如告警发给运维群构建通知发给开发群日报发给负责人。这样一套 OpenClaw 就能覆盖多个通知场景不用维护多个发送脚本。当你的通知场景越来越多、逻辑越来越复杂甚至需要 agent 做多步处理、调用工具、查数据库的时候就该考虑升级到 Coding Plan 了。Coding Plan 地址是https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite适合长期编码和 Agent 类任务能支撑更复杂的 agent 工作流。如果你的通知还停留在「收到事件、生成文本、发出去」这个层面那当前这套 webhook 配置就够用不用急着升级。一句话收尾这套 webhook 的本质是把外部事件通过 OpenClaw 映射成一条 agent 消息再通过微信渠道发出去。当前wechat-notify是一个非常适合练手和落地的最小通知场景结构简单、调试容易、扩展空间也很大。先把这一条跑稳后面加场景就是复制粘贴改字段的事。