跳到主要内容

Webhook

Hermes 可以接收来自 GitHub、GitLab、JIRA、Stripe 等外部服务的事件,并自动触发 agent 运行。webhook 适配器会启动一个 HTTP 服务,接收 POST 请求、校验 HMAC 签名、把 payload 转换为 agent prompt,然后把响应回传给源系统,或转发到其他已配置的平台。

agent 在处理完事件后,可以通过在 PR 上发表评论、向 Telegram / Discord 发消息,或写日志等方式给出结果。

Quick Start

  1. 通过 hermes gateway setup 或环境变量启用 webhook
  2. config.yaml 中定义 routes,或通过 hermes webhook subscribe 动态创建
  3. 让外部服务把 webhook 指向 http://your-server:8644/webhooks/<route-name>

设置

有两种方式启用 webhook 适配器。

通过设置向导

hermes gateway setup

按提示启用 webhooks、设置端口,并填写全局 HMAC secret。

通过环境变量

把以下内容加入 ~/.hermes/.env

WEBHOOK_ENABLED=true
WEBHOOK_PORT=8644 # default
WEBHOOK_SECRET=your-global-secret

验证服务

网关启动后:

curl http://localhost:8644/health

预期返回:

{"status": "ok", "platform": "webhook"}

Configuring Routes

routes 定义了不同 webhook 来源的处理方式。每条 route 都是 config.yamlplatforms.webhook.extra.routes 下的一个命名条目。

Route properties

PropertyRequiredDescription
eventsNo允许接收的事件类型列表;为空时接受全部事件
secretYes用于签名校验的 HMAC secret;若 route 自己未设置,则回退到全局 secret。仅测试时可用 INSECURE_NO_AUTH 跳过验证
promptNo模板字符串,支持 {pull_request.title} 这种点路径访问
skillsNo为本次 agent 运行加载的技能列表
deliverNo把响应投递到哪里,例如 github_commenttelegramdiscordslacksignalsmswhatsappmatrixmattermosthomeassistantemaildingtalkfeishuwecomweixinbluebubblesqqbot,或默认的 log
deliver_extraNo额外投递配置,例如 repopr_numberchat_id;同样支持点路径模板
deliver_onlyNo若设为 true,完全跳过 agent,直接把渲染后的 prompt 作为消息投递出去

Full example

platforms:
webhook:
enabled: true
extra:
port: 8644
secret: "global-fallback-secret"
routes:
github-pr:
events: ["pull_request"]
secret: "github-webhook-secret"
prompt: |
Review this pull request:
Repository: {repository.full_name}
PR #{number}: {pull_request.title}
Author: {pull_request.user.login}
URL: {pull_request.html_url}
Diff URL: {pull_request.diff_url}
Action: {action}
skills: ["github-code-review"]
deliver: "github_comment"
deliver_extra:
repo: "{repository.full_name}"
pr_number: "{number}"
deploy-notify:
events: ["push"]
secret: "deploy-secret"
prompt: "New push to {repository.full_name} branch {ref}: {head_commit.message}"
deliver: "telegram"

Prompt Templates

prompt 支持用点路径访问 webhook payload:

  • {pull_request.title}payload["pull_request"]["title"]
  • {repository.full_name}payload["repository"]["full_name"]
  • {__raw__} → 把整个 payload 以缩进 JSON 形式插入(最长 4000 字符)
  • 缺失字段会保留原始 {key} 字面量,不报错
  • 嵌套 dict / list 会序列化为 JSON,并在 2000 字符处截断

如果某条 route 没有配置 prompt,默认会把整个 payload 以缩进 JSON 形式注入。

Forum Topic Delivery

当把 webhook 响应投递到 Telegram 时,可以在 deliver_extra 中附带 message_thread_id(或 thread_id)来指定 forum topic:

webhooks:
routes:
alerts:
events: ["alert"]
prompt: "Alert: {__raw__}"
deliver: "telegram"
deliver_extra:
chat_id: "-1001234567890"
message_thread_id: "42"

如果 deliver_extra 中没有提供 chat_id,则会回退到目标平台已配置的 home channel。

GitHub PR Review (Step by Step)

1. 在 GitHub 中创建 webhook

  1. 进入仓库 → SettingsWebhooksAdd webhook
  2. Payload URL 设为 http://your-server:8644/webhooks/github-pr
  3. Content type 设为 application/json
  4. Secret 与 route 配置保持一致
  5. Which events? 中勾选 Pull requests
  6. 点击 Add webhook

2. 添加 route 配置

github-pr 路由按上面的示例加入 ~/.hermes/config.yaml

3. 确认 gh CLI 已登录

github_comment 投递类型依赖 GitHub CLI 发表评论:

gh auth login

4. 测试

创建一个 PR。webhook 触发后,Hermes 会处理该事件,并通过 gh CLI 在 PR 上发布评论。

GitLab Webhook Setup

GitLab webhook 与 GitHub 类似,但鉴权方式不同。GitLab 使用明文 X-Gitlab-Token 头,而不是 HMAC。

1. 在 GitLab 中创建 webhook

  1. 进入项目 → SettingsWebhooks
  2. URL 设为 http://your-server:8644/webhooks/gitlab-mr
  3. 填入 Secret token
  4. 勾选 Merge request events(以及你需要的其他事件)
  5. 点击 Add webhook

2. 添加 route 配置

platforms:
webhook:
enabled: true
extra:
routes:
gitlab-mr:
events: ["merge_request"]
secret: "your-gitlab-secret-token"
prompt: |
Review this merge request:
Project: {project.path_with_namespace}
MR !{object_attributes.iid}: {object_attributes.title}
Author: {object_attributes.last_commit.author.name}
URL: {object_attributes.url}
Action: {object_attributes.action}
deliver: "log"

Delivery Options

deliver 字段决定 agent 响应会投递到哪里:

Deliver TypeDescription
log写入 gateway 日志。默认值,适合测试
github_comment通过 gh CLI 发表 PR / issue 评论
telegram投递到 Telegram
discord投递到 Discord
slack投递到 Slack
signal投递到 Signal
sms通过 Twilio 投递到 SMS
whatsapp投递到 WhatsApp
matrix投递到 Matrix
mattermost投递到 Mattermost
homeassistant投递到 Home Assistant
email投递到 Email
dingtalk投递到 DingTalk
feishu投递到 Feishu/Lark
wecom投递到 WeCom
weixin投递到 Weixin
bluebubbles投递到 BlueBubbles

如果目标平台本身没有启用或未连接,跨平台投递自然也不会成功。若 deliver_extra 中未指定 chat_id,则会回退到该平台的 home channel。

Direct Delivery Mode

默认情况下,每个 webhook POST 都会触发一次 agent 运行,从而消耗 LLM token。若你只是想直接推送一条通知,可将 route 设置为:

deliver_only: true

此时会直接把渲染后的 prompt 投递到目标平台,不进入 agent 循环。

适合的场景包括:

  • 数据库变更通知
  • 监控告警转发
  • agent 之间互发状态消息
  • 后台任务完成通知

它的好处是:

  • 零 LLM token:不会运行 agent
  • 亚秒级投递:只做模板渲染与投递
  • 仍保留同等安全保护:HMAC、限流、幂等性、body 大小限制等都照常生效
  • 同步返回结果:成功时 POST 返回 200 OK,失败时返回 502,方便上游做重试

Dynamic Subscriptions (CLI)

除了 config.yaml 中的静态 routes,你也可以通过 hermes webhook CLI 动态创建 webhook 订阅:

hermes webhook subscribe github-issues \
--events "issues" \
--prompt "New issue #{issue.number}: {issue.title}\nBy: {issue.user.login}\n\n{issue.body}" \
--deliver telegram \
--deliver-chat-id "-100123456789" \
--description "Triage new GitHub issues"

相关命令:

hermes webhook list
hermes webhook remove github-issues
hermes webhook test github-issues

动态订阅会保存在 ~/.hermes/webhook_subscriptions.json 中,并在每次收到请求时自动热加载,无需重启网关。静态 routes 若与动态订阅重名,静态配置优先。

Security

webhook 适配器内置了多层安全保护:

HMAC signature validation

它会根据不同来源使用不同的校验方式:

  • GitHubX-Hub-Signature-256(HMAC-SHA256,格式为 sha256= 前缀)
  • GitLabX-Gitlab-Token(明文 token 比对)
  • GenericX-Webhook-Signature(原始 HMAC-SHA256 hex digest)

如果已经配置了 secret,但请求中没有任何可识别的签名头,适配器会拒绝该请求。

Secret is required

每条 route 都必须有 secret,要么直接写在 route 上,要么继承全局 secret。缺少 secret 会导致适配器在启动时直接报错。只有开发 / 测试场景才应该使用 INSECURE_NO_AUTH 跳过验证。

Rate limiting

默认每条 route 每分钟最多 30 个请求。你可以在 config.yaml 中调整:

platforms:
webhook:
extra:
rate_limit: 60 # requests per minute

超限时会返回 429 Too Many Requests

Idempotency

投递 ID(来自 X-GitHub-DeliveryX-Request-ID,或时间戳回退值)会缓存 1 小时,从而避免 webhook 重试触发重复 agent 运行。

Body size limits

默认会在读取 body 前就拒绝超过 1 MB 的 payload。可通过以下配置修改:

platforms:
webhook:
extra:
max_body_bytes: 2097152 # 2 MB

Prompt injection risk

注意

Webhook payload 中的 PR 标题、提交信息、issue 描述等内容都可能由攻击者控制。如果你的 webhook 直接暴露在公网,请尽量把网关运行在隔离环境(如 Docker 或虚拟机)中,并考虑使用 Docker 或 SSH 终端 backend。

Troubleshooting

webhook 没有到达

  • 确认端口已开放,并可被源系统访问
  • 检查防火墙规则
  • 确认 URL 路径正确:http://your-server:8644/webhooks/<route-name>
  • 使用 /health 端点确认服务已正常启动

签名校验失败

  • 确认 route secret 与源系统配置完全一致
  • GitHub 场景下检查 X-Hub-Signature-256
  • GitLab 场景下检查 X-Gitlab-Token
  • 查看 gateway 日志中的 Invalid signature

事件被忽略

  • 检查事件类型是否包含在 route 的 events 列表中
  • GitHub 常见事件值:pull_requestpushissues
  • GitLab 常见事件值:merge_requestpush
  • events 为空,则默认接受所有事件

agent 没有响应

  • 在前台运行 hermes gateway run 查看日志
  • 检查 prompt 模板渲染是否正确
  • 确认目标投递平台已启用且已连接

Duplicate responses

  • 幂等缓存本应阻止重复处理。检查 webhook 来源是否发送了 X-GitHub-DeliveryX-Request-ID
  • 投递 ID 会缓存 1 小时

gh CLI errors

  • 在网关主机上执行 gh auth login
  • 确认认证用户对目标仓库具有写权限
  • 确认 gh 已安装并在 PATH 中

Environment Variables

VariableDescriptionDefault
WEBHOOK_ENABLED启用 webhook 平台适配器false
WEBHOOK_PORT接收 webhook 的 HTTP 端口8644
WEBHOOK_SECRET全局 HMAC secret(当 route 未单独设置 secret 时作为回退值)(none)