Hermes Webhook:无需巨型万能提示的事件驱动智能体
中级7 分钟阅读自动化

Hermes Webhook:无需巨型万能提示的事件驱动智能体

使用符合事件来源要求的身份验证、8644 端口健康检查和小型命名路由配置 Hermes Agent webhook,让事件触发目标明确、交付位置清楚的智能体运行。

您应该能够做到的事情

事件刚发生时,webhook 通常比 cron 更合适。按来源要求的身份验证方式保护每条 Hermes 路由,在 8644 端口验证 /health,并为每类事件配置范围收窄的提示与明确交付目标。

仅在此浏览器中保存。
本文内容

Cron 会问“现在到时间了吗?”,Webhook 则会说“刚刚发生了这件事,请采取行动”。对智能体工作而言,这一区别很重要。定时检查收件箱,与“Stripe 争议已创建”或“有人发起了以 main 为目标分支的 PR”是完全不同的任务。

Hermes Agent Webhook 会把经过身份验证的 HTTP POST 事件转换为智能体运行,并将结果发送到已配置的交付目标。使用得当,它们是带锁、任务明确的窄入口。使用不当,它们就会变成暴露在外的端口,试图用一个巨型提示处理互联网发来的任何 JSON 负载。

本文涵盖路由设计、符合事件来源要求的身份验证、文档所述的健康检查,以及一项实用的冒烟测试。在把任何接口暴露到本机之外前,请先落实 Hermes 第一周中的加固措施。

何时 webhook 是正确触发器

在以下情况优先用 webhook:

  • 延迟很重要(趁作者还没有完全切换到别的任务时评审 PR)。
  • 源系统本身会发送事件(GitHub、GitLab、Jira、Stripe、内部表单)。
  • 每个事件应成为一个目标明确的任务,而非漫长对话会话。

在以下情况优先用 cron:

  • 你在轮询状态变化(“是否有证书将在 14 天内过期?”)。
  • 源系统无法主动推送。
  • 你需要定期得到简报,而不是被每个事件打断。

官方 Hermes 指南与这种划分一致:使用 Cron 进行定时检查,使用 Webhook 进行事件触发的运行。

一图看架构

来源系统(GitHub / GitLab / n8n / 自定义应用)
        |  HTTPS POST + 符合来源要求的身份验证
        v
Hermes webhook 适配器(默认端口 8644)
        |  路由:/webhooks/<name>
        v
命名路由配置(过滤条件 + 提示 + 交付目标)
        v
智能体运行(技能和工具受你的审批策略约束)
        v
已配置的交付目标(聊天频道、GitHub 评论或日志)

n8n 可以位于左侧,充当验证器和聚合层:验证字段、过滤无用数据,再把精简后的载荷 POST 到 Hermes。这是 Hermes 与 n8n:按任务选择中的示例架构,不是供应商已记录的开箱即用集成。如果 n8n 需要把智能体结果带回工作流,应使用 Bearer 认证调用默认端口 8642 上独立的 Hermes API 服务器,而不是把 Webhook 适配器当作同步回调。

设置路径(对照线上文档核实)

官方 Webhook 文档 描述了以下路径:

  1. 启用 webhook 平台(hermes gateway setup 或环境变量如 WEBHOOK_ENABLED=true)。
  2. 为每条路由配置一个密钥。根据源系统选择使用 GitHub 的 HMAC 请求头、GitLab 的明文令牌请求头,或通用 V2 时间戳 HMAC。
  3. 在配置文件中创建一个 命名 的路由,或通过 hermes webhook subscribe(根据当前文档的命令)创建。
  4. 健康检查:curl http://localhost:8644/health
  5. 将外部系统指向 https://your-host/webhooks/<name>
  6. 发送一个经过身份验证的测试负载;确认你期望的路由、提示、工具范围和交付目标。

文档规定的默认端口为 8644。文档所述的默认值还会把每条路由限制为每分钟 30 个请求,并拒绝大于 1 MB 的请求体。如果你更改了这些值,请测试实际配置的限制,不要再依赖默认值。

更改静态配置后,可能需要按已安装版本的文档重新加载或重启网关。通过 hermes webhook subscribe 创建的动态路由无需重启即可热加载,并会自动生成密钥。无论哪种情况,请确认网关进程读取的是预期的配置文件和环境;在交互式 shell 中成功执行命令,并不能证明守护进程使用了同一套配置。

路由认证是强制性的

每条路由必须继承或定义一个密钥,否则适配器将在启动时失败。认证方式因提供方而异:GitHub 使用 X-Hub-Signature-256,GitLab 使用精确匹配的 X-Gitlab-Token,而通用自定义发送方应使用 V2 时间戳 HMAC。发送方认证用于证明持有密钥的发送者发送了请求,但不会使负载指令变得可信。

适用于生产环境的可靠规则:

  • 生成一个长随机密钥;将其存储在密钥管理器或权限受限的环境文件中,绝不要放在智能体可随意读取的技能 Markdown 中。
  • 当系统具有不同的信任级别(如 GitHub 应用、内部表单、合作伙伴 webhook)时,优先使用 每条路由的独立密钥
  • 在边缘层拒绝未签名的请求或签名无效的请求;不要执行“记录并继续”操作。
  • 仅将 INSECURE_NO_AUTH 用于临时的回环测试。如果该值与非回环绑定(如 0.0.0.0 或 LAN 地址)组合使用,适配器将拒绝启动。

使用 Hermes 当前的 通用 V2 方案处理自定义发送方:X-Webhook-Timestamp 是 Unix 秒数;X-Webhook-Signature-V2<timestamp>.<raw-body> 的小写十六进制 HMAC-SHA256 摘要。Hermes 会拒绝超出 ±300 秒窗口的时间戳。V1 只对正文签名,缺少重放保护,因此不要基于它构建新的发送方(官方 Webhook 安全协议)。

可复现的签名冒烟测试

创建名为 support-triage 的路由后,把非敏感负载写入 payload.json。启动该 shell 前,使用已经批准的密钥注入机制设置 WEBHOOK_SECRET;不要在命令历史中输入生产密钥。下面的 Node 命令从环境变量读取密钥,不会把它展开到进程参数中,并按文件的原始字节计算签名:

: "${WEBHOOK_SECRET:?inject a disposable route secret before running this test}"
timestamp="$(date +%s)"
signature="$(TIMESTAMP="$timestamp" node -e '
  const { createHmac } = require("node:crypto");
  const { readFileSync } = require("node:fs");
  const hmac = createHmac("sha256", process.env.WEBHOOK_SECRET);
  hmac.update(`${process.env.TIMESTAMP}.`, "utf8");
  hmac.update(readFileSync("payload.json"));
  process.stdout.write(hmac.digest("hex"));
')"

curl --fail-with-body \
  -H 'Content-Type: application/json' \
  -H "X-Webhook-Timestamp: $timestamp" \
  -H "X-Webhook-Signature-V2: $signature" \
  --data-binary @payload.json \
  http://127.0.0.1:8644/webhooks/support-triage

然后分别在同时去掉两个签名请求头、以及使用超过 300 秒窗口的旧时间戳时重复测试。两种请求都必须被拒绝。不要把真实密钥粘贴到截图、工单或 shell 历史中;文档测试应使用一次性路由密钥,并在测试后轮换。

暴露的 Webhook 可能把攻击者控制的文本送到具备终端能力的智能体面前,带来远程工具执行风险。身份验证限制谁能提交事件,但通过验证的载荷文本仍可能带有对抗性。请使用 TLS 和网络控制,尽量缩减载荷内容,限制或禁用终端、文件和出站操作工具,并让执行环境与主机隔离。审批提示用于确认操作者意图,不是隔离对抗性输入的沙箱。

负载中应包含什么

给智能体一个契约,而不是未经筛选的原始数据洪流:

{
  "event_type": "github.pull_request.opened",
  "repo": "acme/api",
  "pr_number": 1842,
  "title": "Add billing retry worker",
  "author": "ada",
  "base_ref": "main",
  "html_url": "https://github.example.invalid/acme/agent-service/pull/1842",
  "task": "Summarize risk for main. List missing tests. Do not approve or merge."
}

删除未使用的字段。庞大的工作流数据转储会浪费上下文,并诱发混乱的工具调用。本文建议采用「小而明确的负载,并给出清晰任务」,这是一项设计建议,并不是在宣称存在官方 n8n 集成。

路由设计:多个窄入口

不要建 /webhooks/everything。建带过滤器与提示的命名路由:

路由名称来源任务交付
gh-pr-openedGitHub PR 创建风险摘要 + 测试缺口工程 Telegram 主题
stripe-disputeStripe 争议创建检查清单草案财务 Slack + 日志
support-formn8n 验证后分类 + 草拟回复配置的私有 Slack 频道
uptime-alert监控 Webhook收集最近部署上下文值班人员频道

每个路由应回答:

  1. 接受哪些事件?
  2. 期望的单一输出是什么?
  3. 此路由的智能体配置允许哪些工具?
  4. 结果去哪里?
  5. 失败时怎么办(重试、进入死信队列,还是通知人工值守人员)?

Webhook 载荷通常包含电子邮件、账户 ID 或消息正文。在到达 Hermes 之前尽量减少字段数量。路由 schema 并未提供每条路由独立的记忆写入开关。请使用已禁用记忆功能的专用配置文件,或启用 memory.write_approval,并测试哪些内容会被持久化。如果不需要智能体推理,请改用文档中说明的 deliver_only 模式,而不是运行智能体。

健康检查与可运维性

文档列出的健康端点是 http://localhost:8644/health (或你的主机/端口)。它可用于:

  • 启用后的本地冒烟测试
  • Docker/Kubernetes readiness 探针
  • 从外部检查私有健康 URL 的可用性,而不是探测未经认证的 webhook 路由

同时记录:

  • 签名失败(可能攻击或密钥配置错误)
  • 载荷校验失败
  • 智能体运行时长与工具审批拒绝
  • 下游交付失败(聊天 API 宕机等)

如果没有这些信号,「智能体感觉不稳定」就会成为你唯一的事故报告。这些记录可以提高可观测性,但不会自动构成完整且防篡改的审计记录。

示例:GitHub PR 创建 → 目标明确的运行

目标: 当有人向 main 开 PR 时,Hermes 为人类起草风险说明。除非你后来添加经审核的交付路径,否则不合并、不批准、不评论。

  1. 创建路由 gh-pr-opened。如果由 GitHub 直接发送事件,请配置用于验证 X-Hub-Signature-256 的共享密钥;如果通过通用 n8n 中继发送,则改用 V2 时间戳 HMAC 协议。
  2. 仅接受 pull_request / opened / 目标分支 main
  3. 提示契约:总结目的、影响范围、缺失的测试和上线风险;标记未知项;不得给出合并指令。
  4. 工具:如果已配置 GitHub 访问,则只允许读取;shell 应禁用或必须经过审批。
  5. 交付:将 Markdown 发布到内部频道;由人工决定下一步操作。

下面展示一份合格智能体输出的结构(仅为示例,实际模型措辞可能不同):

PR #1842:添加账单重试 worker(ada 提交到 main)

事实
- 涉及账单 worker 与队列配置(根据已提供的标题和文件列表)。
- 关联 URL:`https://github.example.invalid/acme/agent-service/pull/1842` (示例)

风险
- 若缺少退避机制,可能发生重试风暴 [inference; verify in diff]
- 标题未提及幂等键 [unclear]

需要确认的缺失测试
- 重复交付与毒消息处理
- 重试预算耗尽时的告警

不得根据这份说明合并。需要人工审查。

这是一次带有停止规则的事件驱动智能体运行,不是一个可以自主行使权限的代码负责人。

练习:启用一个之前先设计三个路由

在纸上(或运行手册中)为你的技术栈写三个 webhook 路由。对每个填写:

  • 名称
  • 来源 + 事件过滤器
  • 认证方法和密钥所有者
  • 载荷字段:从最多 10 个开始,作为有意设置的小规模练习预算
  • 提示:先限制在最多 8 行,然后只补充该路由评测确实需要的内容
  • 允许的工具
  • 交付目标
  • 失败行为

先只实施风险最低的路径,通常是内部警报或仅生成草稿的 PR 摘要。先用 curl 检查 /health,再发送一次通过身份验证的测试 POST 和一次身份验证无效的测试,最后在非生产仓库或预发布项目中触发一次真实事件。

预期的失败模式

  • 轮换后密钥不匹配: 身份验证失败;修复网关进程实际使用的环境,而不只是你笔记本电脑上的 shell 环境。
  • 提示过于宽泛: 智能体会临场选择工具;拆分该路由。
  • 重试风暴: 源端会重复发送 POST 请求。Hermes 会缓存交付 ID 一小时,但有效去重需要稳定的 X-GitHub-DeliveryX-Request-ID。客户可见的操作仍需要持久的业务幂等性,其保留时间应与重放窗口匹配。
  • 记忆污染: 高频警报会进入持久记忆;请使用专用配置文件和明确的记忆设置。
  • 端口暴露: 健康检查和 webhook 接口在缺少预期 TLS 与网络控制的情况下即可访问;在添加工具之前先修复网络配置。

值得随时查阅的参考资料

只有当每条路由职责明确、经过身份验证、可观测,并配置了交付目标时,事件驱动智能体才真正有用。Webhook 适配器是事件入口,不是使用 Bearer 认证的请求/响应 API。请按照这一区别进行设计和测试。

继续阅读

通过下一篇文章继续沿着相同的学习路径进行学习。