Déclencheurs web (webhooks)
Un déclencheur web lance l’agent lorsqu’un service externe envoie un événement à Diadems : nouvelle commande, formulaire reçu, alerte ou changement de statut.
Diadems relaie la requête vers le webhook natif de la capsule. La signature, le filtrage des événements, le déclenchement et la livraison sont gérés par Hermes ; Diadems ne maintient pas de second moteur de file ou de reprise.
Créer un déclencheur
Section intitulée « Créer un déclencheur »- Ouvrez Agent → Tâches → Webhooks ou demandez à l’agent de créer la connexion avec sa compétence Webhooks Diadems.
- Donnez un nom stable au déclencheur, par exemple
nouvelle-commande. - Rédigez la consigne que l’agent devra exécuter.
- Indiquez les types d’événements acceptés.
- Choisissez la destination : portail, Telegram, e-mail ou retour vers votre application.
- Enregistrez et testez avec un événement non destructif.
Créez une route distincte lorsque la consigne, la destination, les champs du retour ou les permissions diffèrent. Par exemple, une commande à analyser et une question posée par un employé ne doivent pas partager une route simplement parce qu’elles viennent du même logiciel.
Diadems affiche une URL HTTPS et un secret propres à la route. Le service émetteur doit signer le corps JSON avec ce secret.
Choisir ce qui alimente la mémoire
Section intitulée « Choisir ce qui alimente la mémoire »Chaque webhook dispose du réglage Enregistrer automatiquement en mémoire dans sa configuration. Sur les agents compatibles, il est désactivé par défaut, y compris pour les webhooks existants sans choix enregistré. Activez-le pour les événements apportant une décision, un engagement ou un changement durable. Les notifications répétitives et les contrôles sans nouveauté peuvent rester sans sauvegarde automatique.
Le choix d’un webhook ne modifie pas les autres. Le résultat reste dans l’historique, les souvenirs existants sont conservés et l’agent peut encore les consulter ou répondre à une demande explicite de mémorisation. Si le moteur doit être mis à jour, le formulaire le précise ; ce réglage n’est pas encore appliqué sur cet agent.
Faire préparer l’intégration par un agent développeur
Section intitulée « Faire préparer l’intégration par un agent développeur »Lorsque votre application est maintenue avec l’aide d’un agent développeur, commencez généralement par lui demander d’analyser l’événement métier. Il connaît le code, le moment exact où l’événement devient définitif et les données réellement disponibles. Il prépare le contrat ; votre agent Diadems configure ensuite la réception sans avoir besoin d’accéder au dépôt de l’application.
Transmettez cette page à votre agent développeur avec une demande simple :
Je veux connecter cette application à mon agent Diadems lorsqu’un nouvelévénement <décrivez l’événement> se produit.
Analyse le code et prépare le dossier de raccordement Diadems décrit dans ladocumentation. Ne programme pas encore l’envoi : je te transmettrai ensuitel’URL et le secret HMAC créés par mon agent Diadems.L’agent développeur doit remettre un dossier de raccordement contenant :
- le nom et la finalité de l’événement ;
- une valeur stable pour
event_type, par exempleorder.created; - le point précis du code où l’événement doit être envoyé, uniquement après la validation métier ou la transaction concernée ;
- un exemple réaliste du corps JSON avec un
event_idunique et stable ; - la liste des champs obligatoires, facultatifs et des données sensibles à exclure ;
- la stratégie d’idempotence, de réessai, de délai maximal et de journalisation ;
- les fichiers ou modules qui devront être modifiés ;
- le résultat attendu de l’agent et, si nécessaire, les informations permettant de rapprocher une réponse asynchrone de l’événement initial.
Le dossier peut suivre ce modèle :
# Dossier de raccordement Diadems
- Application : <nom>- Événement : <description métier>- event_type : <type stable>- Déclenchement dans le code : <fichier, fonction et moment>- Identifiant idempotent : <origine de event_id>- Résultat attendu : <action ou analyse demandée à l’agent>- Retour applicatif : <non, ou besoin et identifiants de corrélation>
## Exemple de payload{ "event_type": "<type stable>", "event_id": "<identifiant unique>", "occurred_at": "<date ISO 8601 facultative>", "data": {}}
## Champs- Obligatoires :- Facultatifs :- Interdits ou sensibles :
## Livraison- Réessais : erreurs réseau, 429 et 5xx avec attente exponentielle et aléa- Idempotence : même event_id et même X-Request-ID pour un même événement- Délai maximal :- Journaux autorisés, sans payload sensible :
## Modification prévue- Fichiers ou modules :- Tests à ajouter :- Retour arrière :Donnez ensuite ce dossier à votre agent Diadems :
Crée le déclencheur web correspondant à ce dossier de raccordement, configureune consigne sûre et teste-le. Remets-moi ensuite le nécessaire à transmettreà mon agent développeur pour terminer le branchement.Votre agent Diadems doit vous remettre un kit de branchement comprenant le nom de la route, l’URL publique, le secret HMAC nouvellement créé, les en-têtes attendus, les types d’événements acceptés et le résultat du test. Le secret n’est affiché qu’à sa création : transmettez-le par un canal confidentiel et faites-le enregistrer comme variable d’environnement ou dans le gestionnaire de secrets de l’application.
Redonnez enfin ce kit à l’agent développeur. Il peut alors programmer l’envoi,
ajouter les tests et déclencher un événement non destructif. L’intégration n’est
terminée qu’après vérification de la réception dans Diadems et d’un nouvel envoi
avec le même X-Request-ID, qui ne doit produire aucun traitement métier en
double.
Contrat du corps JSON
Section intitulée « Contrat du corps JSON »Le corps doit être un objet JSON. Pour une intégration générique Diadems, utilisez au minimum cette enveloppe :
{ "event_type": "order.created", "event_id": "backice:order.created:1234:v1", "occurred_at": "2026-08-05T10:00:00Z", "data": { "order_id": "1234" }}| Champ | Statut | Rôle |
|---|---|---|
event_type |
Obligatoire | Type stable utilisé par la route pour accepter ou ignorer l’événement. |
event_id |
Obligatoire | Identifie cette occurrence métier. Utilisez la même valeur dans X-Request-ID. |
occurred_at |
Facultatif | Date ISO 8601 de l’événement métier. Elle est transmise à l’agent, mais Diadems ne l’utilise pas comme limite de fraîcheur. |
data |
Recommandé | Objet contenant uniquement les données nécessaires au traitement. |
L’enveloppe est ouverte : des champs supplémentaires à la racine sont acceptés. Ils sont disponibles pour la consigne, mais une route bien configurée ne doit référencer que ceux dont elle a besoin. Les champs obligatoires propres au métier sont vérifiés par la consigne de la route ; Diadems ne devine pas leur sens.
event_id identifie une occurrence, pas seulement une ressource. Si une commande
doit être analysée une seconde fois volontairement, utilisez un nouvel identifiant
d’occurrence, par exemple backice:order.analysis:1234:2. Ne réutilisez jamais
un identifiant pour un corps différent.
Appeler le webhook — signature v2
Section intitulée « Appeler le webhook — signature v2 »Le corps utilisé pour calculer la signature doit être strictement identique au corps transmis.
POST <URL affichée par Diadems>Content-Type: application/jsonX-Webhook-Timestamp: <timestamp Unix en secondes>X-Webhook-Signature-V2: <HMAC-SHA256 hexadécimal de timestamp + "." + corps brut>X-Request-ID: <event_id>
<corps JSON brut>Exemple Node.js :
import { createHmac } from "node:crypto";
const body = JSON.stringify({ event_type: "order.created", event_id: "order-1234", occurred_at: new Date().toISOString(), data: { order_id: "1234" },});
const timestamp = Math.floor(Date.now() / 1000).toString();const signature = createHmac("sha256", process.env.DIADEMS_WEBHOOK_SECRET) .update(`${timestamp}.${body}`, "utf8") .digest("hex");
const response = await fetch(process.env.DIADEMS_WEBHOOK_URL, { method: "POST", headers: { "Content-Type": "application/json", "X-Webhook-Timestamp": timestamp, "X-Webhook-Signature-V2": signature, "X-Request-ID": "order-1234", }, body,});
if (response.status === 429 || response.status >= 500) { // Replacer le même événement dans la file locale avec attente exponentielle.}Le timestamp doit se trouver dans une fenêtre de cinq minutes autour de l’horloge
du serveur. Pour réessayer le même événement, conservez exactement le même
X-Request-ID et le même corps ; recalculez la signature avec un nouveau
timestamp uniquement si l’ancien a expiré.
Une réponse 202 Accepted confirme la réception et le lancement asynchrone du
traitement, pas sa réussite finale. Le service émetteur doit conserver une file
ou un journal local durable s’il doit pouvoir réconcilier les événements dont il
n’a pas reçu le résultat final.
Vecteur de test HMAC
Section intitulée « Vecteur de test HMAC »Ce vecteur est volontairement figé. Le corps est une seule ligne UTF-8, sans espace final ni retour à la ligne.
Secret : test-secretTimestamp : 1785920400Corps brut : {"event_type":"order.created","event_id":"order-1234","occurred_at":"2026-08-05T10:00:00Z","data":{"order_id":"1234"}}Données signées : 1785920400.{"event_type":"order.created","event_id":"order-1234","occurred_at":"2026-08-05T10:00:00Z","data":{"order_id":"1234"}}Signature hexadécimale attendue : 64ac9877128813c8e1c57b266da2fa2c38d6940606cad92cc7d770bc0c156b8dSi votre bibliothèque ne produit pas exactement cette signature, ne branchez pas encore le service réel : vérifiez l’encodage UTF-8, l’ordre des propriétés, les espaces et les retours à la ligne.
Réponses HTTP et politique de réessai
Section intitulée « Réponses HTTP et politique de réessai »Le corps JSON de la réponse doit être lu même lorsque le statut vaut 200 :
ignored et duplicate sont des résultats normaux, pas des pannes.
| HTTP | Signification | Réessayer ? |
|---|---|---|
200 avec status: ignored |
Type d’événement non accepté ou filtre non satisfait. Aucun agent n’est lancé. | Non. Corriger la route ou l’événement si ce résultat est inattendu. |
200 avec status: duplicate |
Même identifiant déjà reçu pendant la fenêtre de déduplication. | Non. Le premier envoi reste la référence. |
202 avec status: accepted |
Événement reçu et traitement asynchrone lancé. | Non, sauf absence de résultat détectée par une procédure de réconciliation. |
400 |
Corps illisible ou JSON invalide. | Non, corriger la requête. |
401 |
Signature absente, invalide, timestamp absent ou hors fenêtre. | Non avec les mêmes paramètres ; corriger l’horloge, le secret ou la signature. |
403 |
Route désactivée ou configuration de sécurité incomplète. | Non, corriger la configuration. |
404 |
URL, agent, profil ou route inconnu ou supprimé. | Non, sauf pendant une migration explicitement prévue. |
413 |
Corps supérieur à 1 Mo. | Non, réduire le payload ou transmettre une référence sûre. |
429 |
Limite de débit atteinte. L’en-tête Retry-After indique le nombre de secondes à attendre. |
Oui, après Retry-After, puis avec attente exponentielle et aléa. |
502 ou 503 |
Relais ou capsule temporairement indisponible. | Oui, avec attente exponentielle et aléa. |
autre 5xx |
Erreur temporaire non prévue. | Oui, avec un nombre de tentatives borné. |
Chaque route Diadems accepte 30 requêtes par minute. Cette valeur est fixe
dans la version actuelle du cockpit : elle n’est pas configurable route par
route. Toute réponse 429 publique contient Retry-After: 60. Pour un import ou
une resynchronisation, placez les événements dans une file côté application et
lissez le débit au lieu d’envoyer une rafale.
Hermes conserve les X-Request-ID vus dans un cache d’une heure. Un doublon dans
cette fenêtre reçoit 200 avec status: duplicate et ne relance pas l’agent.
Cette protection de transport ne remplace pas une idempotence métier durable :
le service émetteur et le destinataire d’un callback doivent enregistrer les
événements déjà appliqués. Ils doivent notamment rester sûrs après un redémarrage
ou un rejeu effectué plus d’une heure après le premier envoi.
Recevoir la réponse dans votre application
Section intitulée « Recevoir la réponse dans votre application »La destination Retour applicatif ferme la boucle de manière asynchrone.
Lorsque l’agent termine, Diadems effectue un POST vers l’URL HTTPS publique
configurée sur la route. Les redirections, les adresses locales et les adresses
privées sont refusées.
La route définit :
- l’URL HTTPS du callback ;
- la méthode d’authentification :
HMAC SHA-256,Bearerou aucune ; - le nom d’une variable secrète déjà enregistrée dans le coffre de l’agent ;
- le nom du champ contenant la réponse, généralement
content; - jusqu’à 16 champs de corrélation recopiés depuis l’événement, dont
event_idobligatoirement.
Exemple de corps reçu :
{ "event_id": "order-1234", "order_id": "1234", "content": "La commande a été analysée…"}Les en-têtes communs sont :
Content-Type: application/jsonIdempotency-Key: order-1234X-Request-ID: order-1234User-Agent: Hermes-HTTP-Callback/1.0Avec l’authentification Bearer, Diadems ajoute
Authorization: Bearer <secret>. Avec HMAC SHA-256, Diadems ajoute
X-Webhook-Timestamp et X-Webhook-Signature-V2 en signant exactement
timestamp + "." + corps brut, comme pour le webhook entrant.
Le callback accepte tout statut 2xx comme une réussite. Après que l’agent a
produit sa réponse finale, Diadems effectue au maximum 7 tentatives dans une
fenêtre totale de 5 minutes. Chaque requête expire après 30 secondes. Les
erreurs réseau, 429 et 5xx sont réessayées ; les autres 4xx sont
définitives. L’attente progresse approximativement selon
1 s, 4 s, 15 s, 45 s, 90 s, 120 s, avec un léger aléa. Sur un 429,
Retry-After est respecté jusqu’à 120 secondes, sans dépasser la fenêtre totale.
Le récepteur doit traiter event_id ou Idempotency-Key de façon durable et
répondre 2xx uniquement après avoir enregistré le résultat de manière sûre.
Le corps de réponse du callback n’est pas utilisé.
Livraison asynchrone, pas une file garantie
Hermes v0.21.0 n’expose pas de GET public permettant d’interroger l’état d’un
événement par event_id. Diadems ne simule pas cet endpoint et ne maintient pas
une seconde file à côté d’Hermes. Le callback est donc une livraison bornée et
non une garantie de remise après redémarrage de la capsule.
Si le résultat est indispensable, l’application émettrice doit conserver une
ligne locale pending après le 202 accepted, la passer à completed lors du
callback idempotent, puis la placer en needs_review après son propre délai
métier. La réconciliation se fait alors avec la session webhook visible dans le
cockpit. N’émettez pas automatiquement un nouvel event_id : le premier run peut
encore terminer et produire un second effet. Une relance doit être explicite,
idempotente côté métier et effectuée après vérification.
Rotation du secret entrant
Section intitulée « Rotation du secret entrant »Une route existante conserve son secret pendant une modification. Pour le faire tourner sans perdre d’événement :
- créez une nouvelle route avec un nouveau nom et un nouveau secret ;
- configurez l’émetteur pour envoyer temporairement vers les deux routes, ou basculez-le avec une file de reprise ;
- validez un événement réel et un doublon sur la nouvelle route ;
- arrêtez l’ancienne destination ;
- supprimez l’ancienne route après vidage des événements en vol.
Une route supprimée invalide immédiatement son URL et son secret. Elle ne se renomme pas en place.
Bonnes pratiques
Section intitulée « Bonnes pratiques »- envoyez uniquement les données nécessaires à la mission ;
- n’envoyez jamais de mot de passe ou de clé API dans le corps ;
- utilisez le même
event_iddans le JSON etX-Request-ID; - journalisez le statut HTTP,
status,event_id, le numéro de tentative et la durée, jamais le secret ni le payload sensible ; - conservez localement l’état
pending,completedouneeds_reviewdes résultats indispensables ; - n’automatisez jamais une relance avec un nouvel
event_idsans vérification métier préalable ; - consultez le résultat dans Sessions ou dans la destination choisie.
Le bouton Tester l’événement envoie un événement de contrôle signé. Supprimez un déclencheur inutilisé ; son URL et son secret cessent alors d’être valides.
Retrouver les réglages et l’aide
Section intitulée « Retrouver les réglages et l’aide »Tâches → Webhooks ouvre la liste. La création et la modification s’effectuent dans une page dédiée ; le fil d’Ariane revient aux déclencheurs. Les choix de livraison et d’authentification s’ouvrent eux aussi dans une sous-vue. Le bouton Demander à [nom de l’agent] de Tâches ouvre une nouvelle conversation et envoie votre demande d’aide. Indiquez que votre demande concerne un webhook et transmettez ce guide : l’agent peut gérer ses souscriptions natives avec sa compétence Webhooks Diadems.