Webhooks
從外部服務(GitHub、GitLab、JIRA、Stripe 等)接收事件,並自動觸發 Hermes Agent 運行。Webhook 適配器運行一個 HTTP 服務器,接收 POST 請求,驗證 HMAC 簽名,將有效載荷轉換為 Agent 提示,並將響應路由回源服務或另一個配置的平臺。
Agent 處理事件後,可以回覆評論到 PR、向 Telegram/Discord 發送消息,或記錄結果。
快速入門
- 通過
hermes gateway setup或環境變量啟用 - 在
config.yaml中定義路由 或 使用hermes webhook subscribe動態創建路由 - 將你的服務指向
http://your-server:8644/webhooks/<route-name>
設置
有兩種方式可以啟用 Webhook 適配器。
通過設置嚮導
hermes gateway setup
按照提示啟用 Webhooks,設置端口,並設置全局 HMAC 密鑰。
通過環境變量
將以下內容添加到 ~/.hermes/.env:
WEBHOOK_ENABLED=true
WEBHOOK_PORT=8644 # 默認
WEBHOOK_SECRET=your-global-secret
驗證服務器
一旦網關啟動運行:
curl http://localhost:8644/health
預期響應:
{"status": "ok", "platform": "webhook"}
配置路由
路由定義瞭如何處理不同的 Webhook 源。每個路由是 config.yaml 中 platforms.webhook.extra.routes 下的一個命名條目。
路由屬性
| 屬性 | 必填 | 描述 |
|---|---|---|
events | 否 | 要接受的事件類型列表(例如 ["pull_request"])。如果為空,則接受所有事件。事件類型從 X-GitHub-Event、X-GitLab-Event 或有效載荷中的 event_type 讀取。 |
secret | 是 | 用於簽名驗證的 HMAC 密鑰。如果路由未設置,則回退到全局 secret。僅用於測試時設置為 "INSECURE_NO_AUTH"(跳過驗證)。 |
prompt | 否 | 包含點號表示法有效載荷訪問的模板字符串(例如 {pull_request.title})。如果省略,則將完整 JSON 有效載荷轉儲到提示中。 |
skills | 否 | 為 Agent 運行加載的技能名稱列表。 |
deliver | 否 | 響應發送位置:github_comment、telegram、discord、slack、signal、sms、whatsapp、matrix、mattermost、homeassistant、email、dingtalk、feishu、wecom、weixin、bluebubbles 或 log(默認)。 |
deliver_extra | 否 | 額外的交付配置 —— 鍵取決於 deliver 類型(例如 repo、pr_number、chat_id)。值支持與 prompt 相同的 {dot.notation} 模板。 |
完整示例
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"
提示模板
提示使用點號表示法訪問 Webhook 有效載荷中的嵌套字段:
{pull_request.title}解析為payload["pull_request"]["title"]{repository.full_name}解析為payload["repository"]["full_name"]{__raw__}—— 特殊標記,將 整個有效載荷 以縮進的 JSON 格式轉儲(截斷為 4000 個字符)。適用於監控警報或通用 Webhook,其中 Agent 需要完整上下文。- 缺失的鍵將保留為字面量
{key}(無錯誤) - 嵌套字典和列表將被 JSON 序列化,並在 2000 個字符處截斷
你可以將 {__raw__} 與常規模板變量混合使用:
prompt: "PR #{pull_request.number} by {pull_request.user.login}: {__raw__}"
如果某個路由未配置 prompt 模板,則整個有效載荷將以縮進的 JSON 格式轉儲(截斷為 4000 個字符)。
相同的點號表示法模板也適用於 deliver_extra 值。
論壇主題交付
當向 Telegram 交付 Webhook 響應時,可以通過在 deliver_extra 中包含 message_thread_id(或 thread_id)來定位特定論壇主題:
webhooks:
routes:
alerts:
events: ["alert"]
prompt: "Alert: {__raw__}"
deliver: "telegram"
deliver_extra:
chat_id: "-1001234567890"
message_thread_id: "42"
如果 deliver_extra 中未提供 chat_id,交付將回退到目標平臺配置的主頻道。
GitHub PR 審查(逐步指南)
本指南將設置在每次拉取請求上自動進行代碼審查。
1. 在 GitHub 中創建 Webhook
- 進入你的倉庫 → 設置 → Webhooks → 添加 Webhook
- 設置 有效載荷 URL 為
http://your-server:8644/webhooks/github-pr - 設置 內容類型 為
application/json - 設置 密鑰 以匹配你的路由配置(例如
github-webhook-secret) - 在 哪些事件? 下,選擇 讓我選擇單個事件,並勾選 拉取請求
- 點擊 添加 Webhook
2. 添加路由配置
將 github-pr 路由添加到你的 ~/.hermes/config.yaml,如上例所示。
3. 確保 gh CLI 已認證
github_comment 交付類型使用 GitHub CLI 發佈評論:
gh auth login
4. 測試
在倉庫中打開一個拉取請求。Webhook 觸發,Hermes 處理事件,並在 PR 上發佈審查評論。
GitLab Webhook 設置
GitLab Webhook 的工作方式類似,但使用不同的認證機制。GitLab 以明文 X-Gitlab-Token 頭髮送密鑰(精確字符串匹配,非 HMAC)。
- 進入您的項目 → 設置 → Webhooks
- 將 URL 設置為
http://your-server:8644/webhooks/gitlab-mr - 輸入您的 密鑰令牌
- 選擇 合併請求事件(以及您想要的其他事件)
- 點擊 添加 Webhook
2. 添加路由配置
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"
交付選項
deliver 字段控制 Agent 在處理 Webhook 事件後,將響應發送到何處。
| 交付類型 | 描述 |
|---|---|
log | 將響應記錄到網關日誌輸出中。這是默認選項,適用於測試。 |
github_comment | 通過 gh CLI 將響應作為 PR/問題評論發佈。需要 deliver_extra.repo 和 deliver_extra.pr_number。gh CLI 必須在網關主機上安裝並已認證(gh auth login)。 |
telegram | 將響應路由至 Telegram。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
discord | 將響應路由至 Discord。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
slack | 將響應路由至 Slack。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
signal | 將響應路由至 Signal。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
sms | 通過 Twilio 將響應路由至短信。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
whatsapp | 將響應路由至 WhatsApp。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
matrix | 將響應路由至 Matrix。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
mattermost | 將響應路由至 Mattermost。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
homeassistant | 將響應路由至 Home Assistant。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
email | 將響應路由至電子郵件。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
dingtalk | 將響應路由至釘釘。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
feishu | 將響應路由至飛書/飛書。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
wecom | 將響應路由至企業微信。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
weixin | 將響應路由至微信(WeChat)。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
bluebubbles | 將響應路由至 BlueBubbles(iMessage)。使用主頻道,或在 deliver_extra 中指定 chat_id。 |
對於跨平臺交付,目標平臺也必須在網關中啟用並已連接。如果 deliver_extra 中未提供 chat_id,響應將發送至該平臺配置的主頻道。
動態訂閱(CLI)
除了 config.yaml 中的靜態路由外,您還可以使用 hermes webhook CLI 命令動態創建 Webhook 訂閱。這在 Agent 自身需要設置事件驅動觸發器時特別有用。
創建訂閱
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"
此命令將返回 Webhook URL 和自動生成的 HMAC 密鑰。請配置您的服務向該 URL 發送 POST 請求。
列出訂閱
hermes webhook list
刪除訂閱
hermes webhook remove github-issues
測試訂閱
hermes webhook test github-issues
hermes webhook test github-issues --payload '{"issue": {"number": 42, "title": "Test"}}'
動態訂閱的工作原理
- 訂閱信息存儲在
~/.hermes/webhook_subscriptions.json - Webhook 適配器在每次接收到請求時熱重載該文件(基於修改時間,開銷可忽略)
config.yaml中的靜態路由始終優先於同名的動態路由- 動態訂閱使用與靜態路由相同的路由格式和功能(事件、提示模板、技能、交付)
- 無需重啟網關 —— 訂閱後立即生效
Agent 驅動的訂閱
Agent 可通過終端工具在 webhook-subscriptions 技能的引導下創建訂閱。例如,讓 Agent“為 GitHub 問題設置 Webhook”,它將自動執行相應的 hermes webhook subscribe 命令。
安全性
Webhook 適配器包含多層安全機制:
HMAC 簽名驗證
適配器使用每個源對應的適當方法驗證傳入的 Webhook 簽名:
- GitHub:
X-Hub-Signature-256頭 —— HMAC-SHA256 十六進制摘要,前綴為sha256= - GitLab:
X-Gitlab-Token頭 —— 純密鑰字符串匹配 - 通用:
X-Webhook-Signature頭 —— 原始 HMAC-SHA256 十六進制摘要
如果配置了密鑰但未檢測到可識別的簽名頭,請求將被拒絕。
密鑰為必需項
每個路由都必須設置密鑰 —— 要麼直接在路由中設置,要麼從全局 secret 繼承。未設置密鑰的路由會導致適配器在啟動時失敗並報錯。僅用於開發/測試時,可將密鑰設為 "INSECURE_NO_AUTH" 以完全跳過驗證。
速率限制
每個路由默認限制為 每分鐘 30 次請求(固定窗口)。可全局配置:
platforms:
webhook:
extra:
rate_limit: 60 # 每分鐘請求數
超過限制的請求將收到 429 Too Many Requests 響應。
冪等性
交付 ID(來自 X-GitHub-Delivery、X-Request-ID 或時間戳回退)會被緩存 1 小時。重複的交付(例如 Webhook 重試)將被靜默跳過,並返回 200 響應,從而防止重複執行 Agent。
請求體大小限制
超過 1 MB 的負載在讀取請求體之前即被拒絕。可進行如下配置:
platforms:
webhook:
extra:
max_body_bytes: 2097152 # 2MB
提示注入風險
Webhook 負載包含攻擊者控制的數據——PR 標題、提交信息、問題描述等都可能包含惡意指令。當網關暴露在互聯網時,建議在沙箱環境(如 Docker、虛擬機)中運行。考慮使用 Docker 或 SSH 終端後端以實現隔離。
故障排除
Webhook 未到達
- 確認端口已暴露且可從 Webhook 源訪問
- 檢查防火牆規則——端口
8644(或您配置的端口)必須開放 - 確認 URL 路徑匹配:
http://your-server:8644/webhooks/<route-name> - 使用
/health端點確認服務器正在運行
簽名驗證失敗
- 確保路由配置中的密鑰與 Webhook 源中配置的密鑰完全一致
- 對於 GitHub,密鑰基於 HMAC —— 檢查
X-Hub-Signature-256 - 對於 GitLab,密鑰為明文令牌匹配 —— 檢查
X-Gitlab-Token - 檢查網關日誌中的
Invalid signature警告
事件被忽略
- 檢查事件類型是否在路由的
events列表中 - GitHub 事件使用如
pull_request、push、issues等值(即X-GitHub-Event請求頭的值) - GitLab 事件使用如
merge_request、push等值(即X-GitLab-Event請求頭的值) - 如果
events為空或未設置,則接受所有事件
Agent 無響應
- 以前臺模式運行網關以查看日誌:
hermes gateway run - 檢查提示模板是否正確渲染
- 確認交付目標已正確配置並已連接
重複響應
- 冪等性緩存應可防止此問題——檢查 Webhook 源是否發送了交付 ID 請求頭(
X-GitHub-Delivery或X-Request-ID) - 交付 ID 緩存時間為 1 小時
gh CLI 錯誤(GitHub 評論交付)
- 在網關主機上運行
gh auth login - 確保已認證的 GitHub 用戶對倉庫具有寫入權限
- 檢查
gh是否已安裝且在 PATH 中
環境變量
| 變量 | 描述 | 默認值 |
|---|---|---|
WEBHOOK_ENABLED | 啟用 Webhook 平臺適配器 | false |
WEBHOOK_PORT | 接收 Webhook 的 HTTP 服務器端口 | 8644 |
WEBHOOK_SECRET | 全局 HMAC 密鑰(當路由未指定自身密鑰時作為回退) | (無) |