跳转至

入站 webhooks

Gateway HTTP 钩子:外部服务如何调用 OpenClaw 来唤醒 agent 或提交 agent 回合。属于 Automations 指南的一部分。

Webhooks

Gateway HTTP 钩子允许外部服务唤醒 agent 或提交 agent 回合。它们默认处于禁用状态。这些端点与内部事件钩子(HOOK.md 处理器)相互独立。它们也不同于出站自动化 webhook 投递:此处是外部服务调用 OpenClaw。

启用并测试 agent 钩子

首先需要一个正在运行的 Gateway 和一个能够完成正常回合的 agent。将以下配置合并到你的配置中,将 token 替换为一个长随机值,并将 main 替换为预期配置的 agent:

{
  hooks: {
    enabled: true,
    token: "<long-random-hook-token>",
    path: "/hooks",
    allowedAgentIds: ["main"],
    allowRequestSessionKey: false,
  },
}

使用专门用于钩子的 token,而不是 Gateway 的认证 token 或密码。在 Gateway 主机上使用其 profile/config 运行以下命令。验证配置,重启已安装的服务以加载配置,并查看日志:

openclaw config validate
openclaw gateway restart
openclaw logs --follow

如果你是以前台方式运行 Gateway,而不是作为已安装的服务运行,请改为停止并启动该进程。

在另一个终端中,向本地 Gateway 发送一个无害的测试请求。将 token、agent id 和端口替换为与你的配置匹配的值:

curl --include http://127.0.0.1:18789/hooks/agent \
  -H 'Authorization: Bearer <long-random-hook-token>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: webhook-smoke-001' \
  --data '{"message":"Summarize this test event: the sample import completed.","name":"Webhook smoke test","agentId":"main","deliver":false}'

预期的受理响应是 HTTP 200:

{ "ok": true, "runId": "<hook-request-run-id>" }

这意味着该运行已获得会话/全局占位受理。它并不意味着模型已完成、工具已成功或消息已投递。单个 agent 请求最多可等待 15 秒以获得受理;响应到达时,模型运行时可能仍在准备中。

对于需要在同一请求中获得最终执行和投递事实的调用方,请在直接 /hooks/agent 负载中添加 "waitForCompletion": true。响应在受理后保持打开,当已受理的运行结束时返回 HTTP 200:

{
  "ok": true,
  "runId": "<hook-request-run-id>",
  "completion": {
    "status": "ok",
    "replyDisposition": "silent",
    "delivered": false,
    "deliveryAttempted": true,
    "deliverySuppressionReason": "silent"
  }
}

replyDisposition 记录模型的最终回复是 visible、silent 还是 empty,而不暴露其文本。受理后的执行或投递失败是 completion 中的最终数据,不是可重试的 HTTP 失败。deliveryError 如果出现,是固定的分类值 "delivery-failed";provider、runtime、model、target、session 和诊断详情保持私有。响应从不包含模型输出或摘要。使用幂等键,这样丢失的响应可以重放同一已受理的运行和完成结果,而不会再次调度。

在 openclaw logs --follow 中,搜索 hook agent run completed 和确切的 HTTP runId。状态为 status=ok 且没有显式投递错误的运行在 info 级别记录;所有非 ok 状态(包括被跳过的运行)、抛出的错误和显式投递错误在 warn 级别记录。对于这个 deliver: false 测试,预期 status=ok 且没有成功的通知。带有 status=ok 和 deliveryError 的警告意味着执行成功但投递失败。它不会触发另一次通知尝试。

结构化的最终记录包括已接受的 agentId、jobId、钩子名称和源路径,以及 logicalSessionKey。当 runner 返回它们时,sessionId 关联运行记录,sessionKey 标识运行时会话密钥。精确运行的延续别名可以在完成后弃用;该密钥不保证有单独的持久会话行。缺失的会话事实仍属未知。诊断信息经过脱敏、单行化,并且每个字符串限制为 500 个字符。成功的输出不会记录:请检查 agent 的运行会话以获取该输出。HTTP runId 关联钩子日志;它不是要传递给 openclaw automations runs 的自动化任务 ID。

sessionMode 默认为 isolated,因此此测试会获得一个新的运行会话和一个生成的逻辑 hook:<uuid> 键。存储的会话可以使用 cron:...:run:... 键;逻辑钩子键并不是对记录存储键的承诺。固定的 defaultSessionKey 会将共享该键的请求串行化,即使在 isolated 模式下也是如此;仅当你确实需要这种顺序时才使用它。

身份验证

每个请求都必须通过以下某个请求头包含钩子 token:

  • Authorization: Bearer <token>(推荐)。
  • x-openclaw-token: <token>。

查询字符串 ?token=... 认证会被拒绝。请使用 Content-Type: application/json 发送 JSON。所有钩子端点仅接受 POST。Hooks 参考 列出了负载字段、限制、路由策略和错误响应。

POST /hooks/wake

为所选 agent 的主会话排入可信通知,并可选择请求立即心跳:

curl --include http://127.0.0.1:18789/hooks/wake \
  -H 'Authorization: Bearer <long-random-hook-token>' \
  -H 'Content-Type: application/json' \
  --data '{"text":"The sample import completed","mode":"now","agentId":"main"}'

HTTP 200 在队列接受唤醒时包含 eventOutcome: "queued",或者在相同唤醒已经是队列中最新的待处理事件时包含 eventOutcome: "coalesced"。使用 mode: "now" 时,无论哪种情况都会请求一次唤醒;该响应并不意味着心跳已完成。使用 mode: "next-heartbeat" 可避免请求立即唤醒。

提供的 agentId 必须指定一个已配置的 agent。当 fleet 没有隐式或保留的旧版所有者时,请显式提供。调用方选择的 sessionKey 需要 mode: "now"、hooks.allowRequestSessionKey: true 以及已配置的前缀策略;延迟 wake 使用主会话。

唤醒文本是系统事件,而不是一个隔离的、带安全包装的邮件读取器回合。只发送你控制的简短通知。将原始邮件、文档或其他不可信内容通过带有受限读取器的 `agent` 操作进行路由。
POST /hooks/agent

提交一个 agent 回合,其中 message 为必填。可选的路由、模型、thinking、timeout 和幂等性字段在 负载参考 中有文档。

保持 sessionMode: "isolated" 以获得全新上下文。仅当重复事件应复用先前上下文时,才设置为 "persistent":此时直接请求需要显式 sessionKey、hooks.allowRequestSessionKey: true,以及非空的 hooks.allowedSessionKeyPrefixes。

对于直接通道投递,请同时提供具体的 channel 和 to;添加 accountId 以选择已启用的通道账户。只提供部分目标、使用 channel: "last",或选择无效账户会在分发前返回 400。直接 hook 不会继承主会话的上一个收件人。

在没有目标时,默认 deliver: true 允许在目标 agent 的主会话上产生完成系统事件。设置 deliver: false 以抑制成功公告并忽略目标字段;完成状态会改为写入日志。非 ok 结果仍会产生失败事件。禁用公告不是工具限制:如果 agent 不得发送消息,请单独限制其工具。

自定义路径通过 hooks.mappings 解析。第一个匹配的映射优先,先于预设。模板或受信任的本地 JS/TS 转换会将负载转换为 wake 或 agent 操作;返回 null 的转换会产生 HTTP 204,且不执行运行。参见 映射详情。

持久化映射 hook 需要稳定的映射 `sessionKey` 或 `hooks.defaultSessionKey`。模板派生的密钥需要与请求密钥相同的调用方密钥选择加入和前缀策略。

`forEach: "<key>"` 会对顶层负载数组进行扇出。每个条目看到的是一元素数组,因此 Gmail 预设中的 `messages[0]` 表示当前邮件。Agent 扇出准入在最多约 8 秒的分发等待后给出答复;待定条目会在后台继续,部分批次会返回非 2xx。重试同一批次会复用待定或已准入的 agent 条目,同时有界内存重放缓存会保留它们。这不是持久化的恰好一次投递;映射的 wake 操作没有重放身份,队列可能会合并重复的 wake。参考文档涵盖批次上限和响应形状。

验证并排查 hook 请求

现象 检查或后续操作
401 检查 hook token,而不是 Gateway 身份验证;确保代理转发身份验证头。
404 检查 hooks.enabled、hooks.path,以及自定义路径是否匹配某个映射。
400 阅读响应错误:JSON、agent 选择、会话策略或投递坐标可能无效。重试前请更正请求。
405、408 或 413 使用 POST;及时发送请求体;保持在文档规定的请求体限制内。
429 重复的身份验证失败已被限流。更正 token 并遵守 Retry-After。
409 重试前解决目标会话冲突。
502 或 503 检查 Gateway 日志中的准备、容量或重启/挂起失败。单次运行准入超时取消排队工作;扇出待定工作仍可能开始。
200,但没有聊天消息 先检查完成日志。deliver: false 会故意抑制成功公告;直接投递需要同时提供 channel 和 to。HTTP 准入不能证明已投递。
204 映射故意未产生任何操作,例如 null 转换或空扇出数组。

对于启用投递的请求,还需在预期通道、 账户和收件人处验证接收情况。检查终端警告中的 deliveryError,包括 status=ok 时。仅 delivered: false 不能证明失败, deliveryAttempted: true 也不能证明已接收。显式抑制和 消息工具投递可能已经满足 runner 的投递处理; 缺失的投递标志仍为未知状态。

对于重试的 agent 请求,复用 Idempotency-Key 和相同负载。 参考 说明了其 范围和生命周期。新测试请使用新密钥;重放的 200 不会再次运行 agent。

Warning

将端点置于回环地址、tailnet 或受信任的反向代理之后。远程调用使用 HTTPS, 并仅暴露所需路径。

  • 使用专用的 hook token 和专用子路径;/ 会被拒绝。
  • 限制 hooks.allowedAgentIds,包括有效的默认代理路径。
  • 除非必要,保持 hooks.allowRequestSessionKey: false;启用时,约束 hooks.allowedSessionKeyPrefixes。
  • 将外部事件内容视为数据。代理 hook 内容默认会进行安全包装,但包装不会移除工具或工作区访问权限。对不可信输入使用受限代理,并保持禁用不安全内容覆盖。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw