Blog · Guide · 29 octobre 2026
Déclencher un workflow AEGIS par un webhook signé
Transparence : 100monkeys.ai développe AEGIS, lisez donc ce guide comme le récit de son fabricant. Il a été rédigé par l'un de nos agents d'IA à partir de la documentation publique d'AEGIS (en anglais), la page Configuring Webhooks, puis relu par l'entreprise ; cette version française est une traduction du guide original en anglais. Chaque commande et chaque bloc de code ci-dessous est copié de cette page ; rien n'a été exécuté pour ce guide. Les citations restent en anglais, avec leur traduction à côté. Là où la documentation laisse une question ouverte, la dernière section le dit.
AEGIS by 100monkeys.ai, in beta, peut lancer un workflow quand un autre système lui envoie un événement : un push sur GitHub, un job de CI qui se termine, n'importe quel service capable d'envoyer une requête HTTP. L'émetteur n'a besoin d'aucun compte sur votre nœud. Dans les mots de la documentation : "Authentication is handled by HMAC-SHA256 signature verification, not OAuth." (L'authentification passe par la vérification d'une signature HMAC-SHA256, pas par OAuth.) Ce guide configure une source de bout en bout, du secret partagé à une requête testée, et couvre les erreurs que vous rencontrerez en chemin.
Étape 1. Nommer la source
Chaque webhook arrive sur POST /v1/webhooks/{source}. La source est "a lowercase slug that identifies the system sending the event" (un identifiant en minuscules qui désigne le système émetteur), par exemple github, stripe ou my-ci. Prenez-en une par système émetteur : le secret, la route et la détection des doublons en dépendent tous.
Étape 2. Poser le secret partagé sur l'orchestrateur
Les secrets valent par tenant et par source, si bien que deux tenants qui appellent tous deux leur source github détiennent des "completely independent secrets" (secrets entièrement indépendants). Chaque paire est une variable d'environnement de l'orchestrateur, nommée selon ce motif :
# 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"
Le tenant u-abc123 avec la source my-ci lit donc AEGIS_WEBHOOK_SECRET_U_ABC123_MY_CI. Si la variable manque pour la paire résolue, la requête est refusée avec 401 secret_not_found. Donnez le même secret à l'émetteur et à personne d'autre.
Étape 3. Router la source vers un workflow
Une route directe associe la source à un workflow, le routage est donc "instant and deterministic" (immédiat et déterministe). Dans la version actuelle, les routes directes sont "configured via orchestrator workflow routing configuration" (configurées dans la configuration de routage des workflows de l'orchestrateur), et la page précise : "there is no aegis stimulus routes CLI command yet" (il n'existe pas encore de commande CLI aegis stimulus routes). Sans route directe, le pipeline se rabat sur un RouterAgent configuré, qui classe l'événement avec un modèle de langage. Sans l'un ni l'autre, la requête échoue avec 422 no_router_configured. Pour un émetteur unique et connu, la route directe est celle qu'il vous faut : le même événement lance toujours le même workflow.
Étape 4. Signer le corps brut chez l'émetteur
L'émetteur calcule un HMAC-SHA256 du corps brut de la requête avec le secret partagé et l'envoie dans X-Aegis-Signature avec le préfixe sha256=. L'exemple Python de la documentation :
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,
},
)
La page donne aussi l'équivalent en Node.js. La seule règle qu'elle met en gras : calculer le HMAC sur les octets bruts du corps, avant toute analyse, car "Computing over a re-serialized object will produce a different signature." (Calculer sur un objet resérialisé produit une signature différente.) Signez exactement les octets que vous envoyez.
Étape 5. Tester le point d'accès avec 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"
Une réussite répond avec deux identifiants :
{
"stimulus_id": "stim-uuid",
"workflow_execution_id": "wfex-uuid"
}
Le second est l'exécution de workflow que l'événement a lancée ; suivez-la comme n'importe quelle autre.
Étape 6. Bloquer les livraisons en double
Les émetteurs réessaient. Transmettez l'identifiant de livraison du fournisseur dans X-Idempotency-Key : pour GitHub c'est X-GitHub-Delivery, et pour votre propre émetteur "Any stable per-event UUID" (tout UUID stable par événement). L'orchestrateur déduplique sur la source et la clé pendant 24 heures, et une répétition répond 409 :
{
"error": "idempotent_duplicate",
"original_stimulus_id": "stim-original-uuid"
}
Étape 7. Lire l'erreur reçue
Le tableau des erreurs de la page, dans l'ordre où vous risquez de les rencontrer :
401 missing_signature: pas d'en-têteX-Aegis-Signature.400 malformed_signature: l'en-tête n'a pas la formesha256=<hex>;400 invalid_hex: la partie hexadécimale contient d'autres caractères.401 secret_not_found: aucune variable pour le tenant et la source résolus.401 invalid_signature: l'empreinte ne correspond pas ; un corps resérialisé avant la signature est le cas contre lequel la page met en garde.409 idempotent_duplicate: déjà traité dans les 24 heures.422 classification_failed: la confiance du RouterAgent était sous son seuil ;422 no_router_configured: ni route directe ni RouterAgent.
Étape 8. Utiliser le point d'accès authentifié pour les appelants internes
Un service qui possède déjà un compte Keycloak peut se passer du secret partagé et envoyer plutôt à POST /v1/stimuli avec un jeton bearer, en donnant source, content et une idempotency_key dans le corps. Gardez la route webhook pour les systèmes que vous n'exploitez pas.
Ce que la documentation laisse ouvert
- Comment écrire une route directe. La page dit que les routes vivent dans la configuration de routage des workflows de l'orchestrateur, sans clé, fichier ni exemple, et la Configuration Reference n'est pas liée depuis cette étape.
- Comment un webhook est enregistré. Le tenant "is resolved from the (tenant, source_name) registration written when the webhook was registered" (est résolu à partir de l'enregistrement (tenant, source_name) écrit lors de l'enregistrement du webhook) ; la page ne montre pas cet enregistrement.
- Ce que reçoit le workflow. La page ne dit pas comment la charge utile et les en-têtes apparaissent dans l'entrée ou le blackboard du workflow lancé.
- Faire tourner un secret. Aucune fenêtre de chevauchement n'est décrite, et la page ne dit pas si une variable modifiée prend effet sans redémarrer l'orchestrateur.
Et ensuite
Le workflow qu'un webhook lance est une machine à états que vous écrivez. Notre guide États et transitions d'un workflow AEGIS, pas à pas en construit une. AEGIS s'installe avec la commande affichée sur 100monkeys.ai :
curl -fsSL https://get.100monkeys.ai | bash