Exemple pratique : le bot de mise à jour automatique StageX
stagehand est un bot ZeroClaw en production. Il surveille le flux de versions en amont, incrémente un paquet StageX, le compile, vérifie qu’il est reproductible par digest, pousse la modification, ouvre une pull request en brouillon et annonce le résultat. Aucun humain n’intervient avant que la PR existe.
Il s’agit du déploiement de référence de SOP : le pipeline est un SOP déterministe, le flux de versions arrive sur un canal AMQP, et l’agent déclenche le SOP à l’aide de l’outil sop_execute. AMQP peut également piloter le moteur SOP directement via un fan-in en direct ; cet exemple utilise par choix le modèle agent-fires-it, où le canal injecte chaque version dans la boucle de l’agent et où l’agent lance l’exécution. C’est cette séparation qui rend le modèle réutilisable.
Chaque commande, clé de configuration, nom d’outil, valeur d’état et clé d’audit ci-dessous correspond à une définition concrète dans le code source.
1. Le build
stagehand nécessite que les canaux AMQP et Matrix soient compilés. Les deux sont protégés par des feature flags et désactivés par défaut.
sh
cargo build --release --features channel-amqp,channel-matrix
Le résultat est un binaire zeroclaw qui charge les types de canaux amqp et matrix. Un binaire compilé sans channel-amqp rejette un bloc de canal amqp au démarrage et journalise un avertissement au lieu de le charger.
2. Les artefacts
Trois éléments résident sous la racine d’installation de ZeroClaw :
| Artefact | Emplacement | Rôle |
|---|---|---|
| Configuration ZeroClaw | ~/.zeroclaw/ | L’agent, les canaux AMQP + Matrix et les paramètres sop. |
sops/stagex-update/ | <install>/shared/sops/stagex-update/ | Le pipeline : SOP.toml (métadonnées) + SOP.md (les huit étapes). |
skills/stagex-update/ | <install>/shared/skills/stagex-update/ | La colle qui déclenche la SOP lors d’un événement de release. |
La configuration relie l’agent à deux canaux (amqp.anitya, matrix.announce), l’exécute en autonomie complète de sorte qu’il effectue les commits, les push et ouvre la PR sans point de contrôle, et fait pointer [sop] vers shared/sops en mode d’exécution deterministic. L’agent ne fusionne jamais ; un mainteneur adopte la branche et fusionne via un commit signé.
Le canal AMQP
Le canal amqp.anitya consomme le flux public de Fedora Messaging. Il lie la clé de routage de mise à jour de version d’Anitya sur l’échange amq.topic et se connecte via amqps:// avec TLS mutuel client ; le broker de Fedora exige un certificat client, le canal présente donc les client_cert et client_key configurés. Le canal valide sa configuration au chargement : amqp_url doit utiliser amqp:// ou amqps://, une URL amqps:// nécessite ca_cert, client_cert et client_key doivent être fournis ensemble, l’échange ne doit pas être vide, et au moins une clé de routage doit être liée.
Le corps JSON de chaque livraison est mappé dans le message entrant de l’agent par content_template, dont les espaces réservés {dotted.path} sont résolus par rapport au corps, transformant une livraison de release en “New release: bzip2 1.0.9 (was 1.0.8). Bump the StageX package for bzip2.” Le chemin pointé thread_id_field corrèle les réponses avec l’événement d’origine. La livraison est de type at-least-once par défaut (durable_ack = true) : le canal n’acquitte une release qu’après qu’elle a été remise de manière durable à la boucle de l’agent, de sorte qu’un plantage avant le démarrage de l’exécution entraîne une nouvelle livraison de l’événement au lieu de le supprimer silencieusement. C’est important pour un pipeline à effets de bord sans surveillance ; une release perdue laisserait un paquet discrètement à la traîne. Les identifiants et les certificats sont fournis au moment du déploiement et ne sont jamais commités : le jeton de push Codeberg est une variable d’environnement lue par le shell de l’agent, le jeton d’accès Matrix est défini sur l’instance en cours d’exécution, et les certificats CA et client Fedora sont placés sur l’hôte.
3. Validation
La surface zeroclaw sop se compose de trois sous-commandes. Il n’existe pas de sous-commande run ; les exécutions démarrent à partir d’un déclencheur ou de l’outil sop_execute.
sh
zeroclaw sop list
zeroclaw sop validate stagex-update
zeroclaw sop show stagex-update
La validation signale des avertissements pour un nom ou une description vides, l’absence de déclencheurs, l’absence d’étapes (un fichier SOP.md manquant ou vide) et les écarts dans la numérotation des étapes. Un avertissement d’étapes manquantes signifie que l’exécution échouerait au moment de l’exécution. Lancez les mêmes vérifications depuis l’interface de terminal zerocode lors de vos itérations ; la CLI constitue la vérification reproductible au moment du déploiement.
4. Déploiement
Le bot s’exécute comme un démon de longue durée afin de rester connecté au broker et au salon Matrix.
sh
zeroclaw daemon
Sur un hôte toujours actif, il s’exécute en tant que service géré qui redémarre avec la machine (voir Service & daemon) :
sh
zeroclaw service install
zeroclaw service start
Le canal AMQP se connecte au broker, lie sa clé de routage et consomme les livraisons. Le bot reste inactif jusqu’à ce que l’upstream publie une release.
5. Le parcours d’une release
Anitya publie une livraison de mise à jour de version. Le canal AMQP la reçoit, applique le content_template et transmet à l’agent un message entrant indiquant le paquet, la nouvelle version et l’ancienne version. L’agent déclenche le pipeline :
// tool: sop_execute
// args: { "name": "stagex-update", "payload": "{\"project\":{\"name\":\"bzip2\"},\"version\":\"1.0.9\",\"old_version\":\"1.0.8\"}" }
sop_execute démarre un SopRun avec un déclencheur manuel et transmet le payload dans le contexte d’exécution. Le cycle de vie à partir d’ici est identique à celui de toute autre exécution ; la source du déclencheur est la seule chose qui diffère.
6. L’exécution
Comme [sop] s’exécute en mode deterministic, les étapes s’exécutent séquentiellement sans aller-retour avec le LLM entre elles. La sortie de chaque étape est transmise à la suivante, et seule l’étape de génération du correctif fait appel au modèle, qui est local, de sorte que le code source du paquet ne quitte jamais l’hôte. Une étape de point de contrôle marque une pause pour approbation humaine ; ce pipeline s’exécute d’une traite jusqu’à la PR en brouillon.
running → completed
Les huit étapes, extraites de la section ## Steps de la SOP :
| # | Étape | Ce que cela fait | Outils |
|---|---|---|---|
| 1 | Résoudre | Mapper le projet en amont au paquet StageX réel ; lire la version actuelle ; arrêter si elle n’est pas strictement plus récente. | shell, file_read |
| 2 | Incrément de version + hachage | Définissez la nouvelle version, exécutez make fetch, écrivez le hash source correct, relancez la récupération jusqu’à ce que tout soit correct. | shell, file_write |
| 3 | Générer | Compiler uniquement ce paquet ; réessayer une fois en cas d’échec de hachage. | shell |
| 4 | Corriger si défectueux | En cas d’échec de build, actualisez ou récupérez un correctif à l’aide du modèle local ; signalez les véritables ruptures d’API. | shell, file_read, file_write, http_request |
| 5 | Repro du digest | make digests, lancer une deuxième compilation, vérifier que le digest est inchangé. | shell |
| 6 | Commit + push | Validez (commit) sur une branche par paquet et par version ; poussez vers le fork. | shell, git_operations |
| 7 | Ouvrir une PR en brouillon | Remplissez le modèle de PR, joignez les empreintes (digests), marquez comme prêt uniquement après une compilation reproduite sans erreur. | http_request |
| 8 | Annoncer | Publiez le résultat dans le salon Matrix : paquet, delta de version, statut de reproduction, digest, URL de la PR. | shell |
L’agent termine chaque étape par un appel à sop_advance rapportant le résultat :
// tool: sop_advance
// args: { "run_id": "<run-id>", "status": "completed", "output": "Passage de bzip2 1.0.8 → 1.0.9 ; hachage de la source recalculé et vérifié." }
status est l’une des valeurs completed, failed ou skipped. Lorsque la dernière étape est avancée, l’exécution passe à l’état completed et son horodatage completed_at est défini.
La progression est visible depuis un tour d’agent à tout moment :
// tool: sop_status
// args: { "sop_name": "stagex-update", "include_metrics": true }
Sécurité en mode headless
Lorsqu’une livraison arrive sans qu’aucune boucle d’agent active ne pilote les étapes, le runtime enregistre l’exécution et journalise chaque action en attente plutôt que d’abandonner silencieusement le travail. L’exécution attend un tour d’agent pour la faire avancer.
7. La piste d’audit
SopAuditLogger persiste chaque transition dans le backend Memory configuré sous la catégorie sop. Une exécution de mise à jour laisse ces clés :
| Clé | Contenu |
|---|---|
sop_run_<run-id> | Instantané complet de l’exécution, écrit au démarrage et mis à jour à la fin. |
sop_step_<run-id>_1 … _8 | Un résultat par étape : statut, sortie, horodatages. |
sop_approval_<run-id>_<step> | Un enregistrement d’approbation de l’opérateur, lorsqu’une étape de point de contrôle en requiert un. |
sop_timeout_approve_<run-id>_<step> | Un enregistrement d’approbation automatique par expiration de délai, lorsqu’une approbation de point de contrôle expire. |
include_metrics: true sur sop_status ajoute des agrégats spécifiques aux SOP ; include_gate_status: true ajoute l’état de la phase de confiance et de l’évaluateur de portes. Ces données proviennent de sop_status, pas de Prometheus. Le point de terminaison /metrics, lorsque le backend d’observabilité est prometheus, expose uniquement les familles générales zeroclaw_*.
8. Les garanties
Chaque garantie remonte au pipeline :
- Le code source ne quitte jamais l’hôte. L’étape de recherche dans les sources des correctifs s’exécute avec un modèle local, de sorte que le code source des paquets n’atteint jamais un fournisseur distant.
- Le build fait ses preuves. L’étape 5 effectue deux builds et compare les empreintes ; la PR n’est marquée comme prête que lorsque les deux correspondent.
- Un humain est responsable du merge. Le bot s’arrête à l’étape « draft PR ouverte » ; un mainteneur adopte la branche et effectue le merge via un commit signé. Il n’effectue jamais de merge automatique.
- L’exécution est reconstructible. L’instantané de l’exécution et chaque résultat d’étape sont persistés sous la catégorie
sop, indexés par l’ID d’exécution.
9. Le motif
Un canal entrant ingère un événement, l’agent déclenche une SOP avec sop_execute, et un pipeline déterministe effectue le travail. Remplacez le flux AMQP par n’importe quel canal et les étapes par n’importe quelle procédure : le cycle de vie, les portes d’approbation et les clés d’audit restent identiques. Lorsqu’une étape nécessite un jugement humain, marquez-la comme point de contrôle et l’exécution se met en pause en attendant une approbation avant de continuer ; la seule différence avec le parcours sans intervention est la personne qui fait avancer l’exécution.