博客 · 指南 · 2026年10月29日

用签名的 webhook 触发 AEGIS 工作流

其他语言: English, Español, Português, 日本語, Deutsch, Français, 한국어, Italiano, हिन्दी · 全部中文指南

声明:AEGIS 由 100monkeys.ai 开发,因此请把这篇指南当作开发方的说明来读。它由我们的一个 AI 智能体根据公开的 AEGIS 文档 Configuring Webhooks 起草,并经公司审阅;这个简体中文版是英文原版指南的译文。下面每条命令和每个代码块都复制自那个页面,写作本指南时没有运行其中任何一条;引文保留英文原文,译文附在旁边。文档没有回答的问题,最后一节会说明。

AEGIS by 100monkeys.ai, in beta,可以在另一个系统向它发送事件时启动一个工作流:GitHub 上的一次 push、一个 CI 任务完成,或任何能发 HTTP 请求的服务。发送方在你的节点上不需要账号。用文档的话说:"Authentication is handled by HMAC-SHA256 signature verification, not OAuth."(认证由 HMAC-SHA256 签名校验完成,而不是 OAuth。)本指南从共享密钥到一次测试过的请求,完整配置一个来源,并介绍途中会遇到的错误。

第 1 步:给来源命名

每个 webhook 都到达 POST /v1/webhooks/{source}。来源是 "a lowercase slug that identifies the system sending the event"(标识发送事件的系统的小写 slug),例如 github、stripe 或 my-ci。每个发送系统选一个:密钥、路由和重复检查都以它为键。

第 2 步:在编排器上设置共享密钥

密钥按租户和来源划分,所以两个都把来源叫作 github 的租户持有 "completely independent secrets"(完全独立的密钥)。每一对都是编排器上的一个环境变量,按这个模式命名:

# Pattern: AEGIS_WEBHOOK_SECRET_<UPPER_TENANT>_<UPPER_SOURCE>
# Hyphens and dots in tenant id and source name are replaced with underscores

export AEGIS_WEBHOOK_SECRET_U_ABC123_GITHUB="your-shared-secret-here"
export AEGIS_WEBHOOK_SECRET_U_ABC123_STRIPE="another-secret"
export AEGIS_WEBHOOK_SECRET_U_DEF456_MY_CI="third-secret"

所以租户 u-abc123 加来源 my-ci 读取的是 AEGIS_WEBHOOK_SECRET_U_ABC123_MY_CI。如果解析出的这一对没有对应变量,请求会以 401 secret_not_found 被拒绝。把同一个密钥交给发送方,不要交给其他任何人。

第 3 步:把来源路由到一个工作流

直接路由把来源映射到一个工作流,所以路由是 "instant and deterministic"(即时且确定的)。在当前版本中,直接路由 "configured via orchestrator workflow routing configuration"(通过编排器的工作流路由配置来配置),页面还注明 "there is no aegis stimulus routes CLI command yet"(目前还没有 aegis stimulus routes CLI 命令)。没有直接路由时,流水线会退回到已配置的 RouterAgent,它用语言模型给事件分类。两者都没有时,请求以 422 no_router_configured 失败。对于单一、已知的发送方,应当选直接路由:同一个事件总是启动同一个工作流。

第 4 步:在发送方对原始请求体签名

发送方用共享密钥对原始请求体计算 HMAC-SHA256,并以 sha256= 为前缀放在 X-Aegis-Signature 中发送。文档中的 Python 示例:

import hashlib
import hmac
import json
import requests

def sign_payload(body: bytes, secret: str) -> str:
    sig = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return f"sha256={sig}"

payload = json.dumps({"event": "push", "ref": "refs/heads/main"}).encode()
signature = sign_payload(payload, WEBHOOK_SECRET)

requests.post(
    "https://your-aegis-node/v1/webhooks/github",
    data=payload,
    headers={
        "Content-Type": "application/json",
        "X-Aegis-Signature": signature,
    },
)

页面也给出了同样的 Node.js 写法。它用粗体强调的唯一规则是:在任何解析之前,对原始请求体字节计算 HMAC,因为 "Computing over a re-serialized object will produce a different signature."(对重新序列化的对象计算会得到不同的签名。)对你发送的字节原样签名。

第 5 步:用 curl 测试端点

# Generate a test signature
SECRET="your-shared-secret-here"
BODY='{"event":"push","ref":"refs/heads/main"}'
SIG="sha256=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')"

# Send the test webhook
curl -X POST https://your-aegis-node/v1/webhooks/github \
  -H "Content-Type: application/json" \
  -H "X-Aegis-Signature: $SIG" \
  -d "$BODY"

成功时会返回两个 id:

{
  "stimulus_id": "stim-uuid",
  "workflow_execution_id": "wfex-uuid"
}

第二个是这个事件启动的工作流运行;像跟踪其他运行一样跟踪它。

第 6 步:阻止重复投递

发送方会重试。把提供方的投递 id 作为 X-Idempotency-Key 转发:GitHub 是 X-GitHub-Delivery,你自己的发送方则用 "Any stable per-event UUID"(任何对每个事件稳定的 UUID)。编排器按来源和键在 24 小时内去重,重复请求返回 409:

{
  "error": "idempotent_duplicate",
  "original_stimulus_id": "stim-original-uuid"
}

第 7 步:读懂你收到的错误

页面的错误表,按你大概会遇到的顺序:

第 8 步:内部调用方使用认证端点

已经有 Keycloak 账号的服务可以不用共享密钥,改为带 bearer token 向 POST /v1/stimuli 发请求,在请求体中给出 source、content 和 idempotency_key。webhook 路由留给你不运营的系统。

文档没有回答的问题

下一步

webhook 启动的工作流是你自己写的状态机。我们的指南AEGIS 工作流的状态与转换,一步一步来会构建一个。AEGIS 用 100monkeys.ai 上印出的命令安装:

curl -fsSL https://get.100monkeys.ai | bash

从 100monkeys.ai 安装 AEGIS