Webhooks

Gateway 可以暴露一个小型 HTTP webhook 端点,供外部系统触发操作。

启用

{
  hooks: {
    enabled: true,
    token: "shared-secret",
    path: "/hooks",
    // 可选:限制显式 `agentId` 路由到这个允许列表。
    // 省略或包含 "*" 表示允许任意 agent。
    // 设为 [] 表示拒绝所有显式 `agentId` 路由。
    allowedAgentIds: ["hooks", "main"],
  },
}

说明:

  • hooks.enabled=truehooks.token 是必填的。
  • hooks.path 默认 /hooks

认证

每个请求必须带上 hook token。推荐用请求头:

  • Authorization: Bearer <token>(推荐)
  • x-openclaw-token: <token>
  • 查询字符串 token 会被拒绝(?token=... 返回 400)。

端点

POST /hooks/wake

请求体:

{ "text": "System line", "mode": "now" }
  • text 必填(string):事件描述(如”收到新邮件”)。
  • mode 可选(now | next-heartbeat):立即触发心跳(默认 now)还是等下次周期检查。

效果:

  • 主会话入队一个系统事件
  • 如果 mode=now,触发立即心跳

POST /hooks/agent

请求体:

{
  "message": "Run this",
  "name": "Email",
  "agentId": "hooks",
  "sessionKey": "hook:email:msg-123",
  "wakeMode": "now",
  "deliver": true,
  "channel": "last",
  "to": "+15551234567",
  "model": "openai/gpt-5.2-mini",
  "thinking": "low",
  "timeoutSeconds": 120
}
  • message 必填(string):给 agent 处理的提示或消息。
  • name 可选(string):hook 的人类可读名称(如”GitHub”),用作会话摘要的前缀。
  • agentId 可选(string):将此 hook 路由到特定 agent。未知 ID 回退到默认 agent。设置后,hook 使用解析到的 agent 的工作区和配置运行。
  • sessionKey 可选(string):标识 agent 会话的键。默认禁止在请求中设置,除非 hooks.allowRequestSessionKey=true
  • wakeMode 可选(now | next-heartbeat):立即触发心跳(默认 now)还是等下次周期检查。
  • deliver 可选(boolean):如果为 true,agent 的响应会发到消息频道。默认 true。纯心跳确认响应会自动跳过。
  • channel 可选(string):投递的消息频道。可选:lastwhatsapptelegramdiscordslackmattermost(插件)、signalimessagemsteams。默认 last
  • to 可选(string):频道的接收者标识(如 WhatsApp/Signal 的电话号码、Telegram 的 chat ID、Discord/Slack/Mattermost(插件)的频道 ID、MS Teams 的对话 ID)。默认用主会话的上次接收者。
  • model 可选(string):模型覆盖(如 anthropic/claude-3-5-sonnet 或别名)。如果有模型限制,必须在允许列表中。
  • thinking 可选(string):思考级别覆盖(如 lowmediumhigh)。
  • timeoutSeconds 可选(number):agent 运行的最大时长(秒)。

效果:

  • 运行一个隔离的 agent 轮次(独立会话键)
  • 始终在主会话中发一条摘要
  • 如果 wakeMode=now,触发立即心跳

会话键策略(破坏性变更)

/hooks/agent 请求体中的 sessionKey 覆盖默认禁用。

  • 推荐:设一个固定的 hooks.defaultSessionKey,关闭请求覆盖。
  • 可选:只在需要时允许请求覆盖,并限制前缀。

推荐配置:

{
  hooks: {
    enabled: true,
    token: "${OPENCLAW_HOOKS_TOKEN}",
    defaultSessionKey: "hook:ingress",
    allowRequestSessionKey: false,
    allowedSessionKeyPrefixes: ["hook:"],
  },
}

兼容配置(旧行为):

{
  hooks: {
    enabled: true,
    token: "${OPENCLAW_HOOKS_TOKEN}",
    allowRequestSessionKey: true,
    allowedSessionKeyPrefixes: ["hook:"], // 强烈建议
  },
}

POST /hooks/<name>(映射)

自定义 hook 名称通过 hooks.mappings 解析(见配置)。mapping 可以把任意请求体转换成 wakeagent 动作,支持模板或代码转换。

Mapping 选项(摘要):

  • hooks.presets: ["gmail"] 启用内置 Gmail mapping。
  • hooks.mappings 在配置中定义 matchaction 和模板。
  • hooks.transformsDir + transform.module 加载 JS/TS 模块做自定义逻辑。
    • hooks.transformsDir(如果设了)必须在 OpenClaw 配置目录下的 transforms 根目录内(通常是 ~/.openclaw/hooks/transforms)。
    • transform.module 必须解析到有效的 transforms 目录内(路径遍历/逃逸会被拒绝)。
  • match.source 保持通用入口端点(基于请求体路由)。
  • TS 转换需要 TS 加载器(如 buntsx),或运行时用预编译的 .js
  • 在 mapping 上设 deliver: true + channel/to 把回复路由到聊天界面(channel 默认 last,回退到 WhatsApp)。
  • agentId 将 hook 路由到特定 agent;未知 ID 回退到默认 agent。
  • hooks.allowedAgentIds 限制显式 agentId 路由。省略(或包含 *)允许任意 agent。设 [] 拒绝显式 agentId 路由。
  • hooks.defaultSessionKey 设置 hook agent 运行在没有显式键时的默认会话。
  • hooks.allowRequestSessionKey 控制 /hooks/agent 请求体是否可以设 sessionKey(默认 false)。
  • hooks.allowedSessionKeyPrefixes 可选地限制来自请求体和 mapping 的显式 sessionKey 值。
  • allowUnsafeExternalContent: true 禁用该 hook 的外部内容安全包裹(危险;仅用于可信的内部来源)。
  • openclaw webhooks gmail setup 写入 hooks.gmail 配置供 openclaw webhooks gmail run 使用。完整的 Gmail watch 流程见 Gmail Pub/Sub

响应

  • 200/hooks/wake
  • 200/hooks/agent(异步运行已接受)
  • 401:认证失败
  • 429:同一客户端反复认证失败后触发(检查 Retry-After
  • 400:无效请求体
  • 413:请求体过大

示例

curl -X POST http://127.0.0.1:18789/hooks/wake \
  -H 'Authorization: Bearer SECRET' \
  -H 'Content-Type: application/json' \
  -d '{"text":"New email received","mode":"now"}'
curl -X POST http://127.0.0.1:18789/hooks/agent \
  -H 'x-openclaw-token: SECRET' \
  -H 'Content-Type: application/json' \
  -d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}'

使用不同的模型

在 agent 请求体(或 mapping)中加 model 来覆盖该次运行的模型:

curl -X POST http://127.0.0.1:18789/hooks/agent \
  -H 'x-openclaw-token: SECRET' \
  -H 'Content-Type: application/json' \
  -d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}'

如果启用了 agents.defaults.models 限制,确保覆盖的模型在列表里。

curl -X POST http://127.0.0.1:18789/hooks/gmail \
  -H 'Authorization: Bearer SECRET' \
  -H 'Content-Type: application/json' \
  -d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}'

安全建议

  • hook 端点应该放在 loopback、tailnet 或可信的反向代理后面。
  • 用专门的 hook token;不要复用 gateway 认证 token。
  • 反复认证失败的客户端地址会被限流,减缓暴力破解。
  • 如果用多 agent 路由,设 hooks.allowedAgentIds 限制显式 agentId 选择。
  • 保持 hooks.allowRequestSessionKey=false,除非你确实需要调用方自选会话。
  • 如果启用了请求 sessionKey,限制 hooks.allowedSessionKeyPrefixes(例如 ["hook:"])。
  • 避免在 webhook 日志中包含敏感的原始请求体。
  • Hook 请求体默认被视为不可信内容,用安全边界包裹。如果某个 hook 必须禁用这个机制,在该 hook 的 mapping 中设 allowUnsafeExternalContent: true(危险)。