Cycle de vie d’exécution du canal
Les canaux se trouvent à la périphérie de ZeroClaw. Ils interagissent avec les plateformes de chat, les webhooks, les éditeurs et les sources d’événements, puis transmettent le travail normalisé au runtime des agents.
Utilisez cette page lorsqu’un changement touche les écouteurs de canaux, les webhooks de gateway, le dispatch des messages, l’intention de réponse, les brouillons en streaming, le rechargement par canal, le comportement de santé/backoff, ou la frontière entre les adaptateurs spécifiques à la plateforme et le traitement des tours géré par le runtime.
Limite cible et transition actuelle
La limite cible est simple :
- Les adaptateurs de canal gèrent les E/S spécifiques à la plateforme.
- Le code appartenant au runtime gère le cycle de vie du tour de l’agent.
- Les gestionnaires de webhook Gateway gèrent les détails du transport HTTP générique, puis entrent dans le même cycle de vie de tour de canal que les écouteurs longue durée.
Le code actuel est encore en transition. zeroclaw-channels contient un grand module orchestrator avec ChannelRuntimeContext, run_message_dispatch_loop et process_channel_message. Ce code effectue actuellement un travail de taille runtime : routage des messages, hooks, garde-fous de self-loop, contexte passif, enrichissement média/liens, sauvegarde automatique, rappel de mémoire, intention de réponse, invocation de la boucle d’outils, mises à jour de brouillons, annulation, accusés de réception, suivi des coûts et livraison finale.
C’est du code qui fonctionne, pas une raison de bloquer chaque changement de canal. La règle de revue est plus étroite : le travail sur un nouveau canal, un webhook ou du streaming doit réutiliser ce cycle de vie partagé lorsque c’est possible et ne doit pas ajouter un autre mini-orchestrateur local.
Qui possède quoi
| Surface | Propriétaire | Règle de revue |
|---|---|---|
| Écouteur de plateforme ou adaptateur d’entrée de canal | Module de canal ou plugin de canal | Conservez les vérifications de signature, le décodage du payload, les tentatives sur la plateforme, la vérification du fournisseur, la gestion des défis et la construction de ChannelMessage au sein de l’adaptateur de transport. |
| Route webhook de la passerelle | Gestionnaire de passerelle | Conservez la gestion des routes, le proxy, le comportement des timeouts, l’acquittement rapide et la politique de réponse HTTP générique au niveau de la passerelle. N’y ajoutez pas de nouveaux parsing spécifiques à la plateforme, sauf conformément à la dette de transition documentée. |
| Message entrant normalisé | ChannelMessage de zeroclaw-api | Préserver l’expéditeur, la cible de réponse, le canal, l’alias, le fil, les pièces jointes, le sujet, le contexte passif et la portée de la conversation. Ajouter des métadonnées structurées plutôt que de masquer les signaux de routage dans le texte visible par l’utilisateur. |
| Propriété de l’agent pour un alias de canal | start_channels / AgentRouter et liaisons de canaux actives | Résoudre l’agent propriétaire à partir des liaisons configurées. Ne pas se rabattre silencieusement sur un agent non lié lorsqu’un canal est sans propriétaire ou désactivé. |
| Dispatch et annulation des messages | Boucle de répartition de canal partagé | Réutiliser le suivi in-flight, /stop, l’annulation de l’expéditeur/du thread, les limites maximales in-flight et la concurrence des workers. |
| Traitement du tour | Cycle de vie du runtime/canal partagé | Hooks, garde anti-boucle, contexte passif, enrichissement média/liens, commandes runtime, routage des modèles, sauvegarde automatique, rappel de mémoire, intention de réponse, exécution d’outils, reçus, coût et livraison doivent être centralisés dans un seul chemin. |
| Accusé de réception du webhook de la passerelle | Gestionnaire de passerelle | Les transports à acquittement rapide peuvent renvoyer HTTP 200 avant la fin du modèle, mais le traitement en arrière-plan doit tout de même entrer dans le cycle de vie du canal partagé. |
| État de santé du canal et reconnexion | Superviseur d’écouteur | Les échecs de listener réessayables utilisent un backoff exponentiel borné et un arrêt conscient de l’annulation. Les échecs non réessayables doivent s’arrêter ou remonter clairement. |
| Rechargement à l’exécution | Chemin de rechargement du daemon et de redémarrage du canal | Une sauvegarde de la configuration ne suffit pas. Les écouteurs à longue durée de vie n’appliquent les modifications des canaux, fournisseurs et ordonnanceurs qu’après un rechargement du daemon ou un redémarrage du processus. |
Forme entrante
Les canaux longue durée et les canaux basés sur des webhooks ont des points d’entrée du transport différents, mais ils doivent converger vers la même structure de message :
flowchart LR
A["Platform event"] --> B["Transport adapter"]
B --> C["ChannelMessage"]
C --> D["Channel dispatch loop"]
D --> E["Agent turn lifecycle"]
E --> F["Channel send / draft / reply"]
Les adaptateurs doivent conserver les traitements que seule la plateforme peut comprendre :
- résolution des routes et des alias ;
- limites de taille du corps et décodage ;
- vérification de signature ou de jeton ;
- règles d’analyse spécifiques à la plateforme ;
- appairage, liste d’autorisation ou extraction de l’identité de l’expéditeur ;
- points de terminaison de défi ou de vérification du fournisseur;
- politique d’acquittement immédiat.
Ensuite, transmettez un ChannelMessage normalisé. Ne copiez pas le reste du cycle de vie dans l’adaptateur, sauf si l’exception est limitée, documentée et testée.
Responsabilités des tours d’exécution
Le cycle de vie partagé devrait posséder le comportement qui doit être cohérent entre les canaux :
- hooks tels que message-received et message-sent;
- protection contre les boucles sur soi-même via
Channel::self_handle()etdrop_self_messages; - enregistrement de contexte passif sans effets de bord sur le modèle/fournisseur ;
- réactions d’acquittement anticipées et nettoyage des no-reply ;
- prétraitement des médias et des liens avant l’appel au fournisseur ;
- commandes d’exécution telles que
/new,/model,/models,/configet/stop; - clés de sauvegarde automatique et d’historique de session ;
- rappel de mémoire et élagage de l’historique ;
- classification d’intention de réponse pour les canaux de groupe et ambiants ;
- mises à jour de brouillon en streaming et comportement multi-messages ;
- approbation des outils, exécution, reçus, événements d’observateur et suivi des coûts ;
- annulation, délai d’attente, restauration et livraison de la réponse finale.
Si une PR modifie l’une de ces responsabilités pour un seul canal, les réviseurs doivent se demander si elle relève du cycle de vie partagé ou des métadonnées de capacité de canal typé.
Webhooks de passerelle
Les webhooks de la passerelle ont une exigence spécifique légitime : la requête HTTP peut devoir répondre rapidement même lorsque le tour de l’agent est lent. Nextcloud Talk en est l’exemple le plus clair, car les modèles locaux lents peuvent dépasser les délais d’attente des webhooks du fournisseur.
Cette exigence d’accusé de réception rapide ne doit pas amener la passerelle à gérer un cycle de vie d’agent distinct. Les gestionnaires actuels adossés à la passerelle utilisent encore un chemin d’acheminement post-vérification spécifique à la passerelle. Considérez cela comme une dette de migration et un contexte de transition, et non comme le modèle cible pour les nouveaux travaux sur les canaux adossés à des webhooks. Un gestionnaire de webhook suit un ordre fixe :
- vérifier la requête ;
- décoder la charge utile ;
- analyser une ou plusieurs valeurs
ChannelMessage; - choisir le dispatch synchrone ou en arrière-plan ;
- retourne la réponse HTTP appropriée au transport.
Pour les webhooks de canaux qui distribuent des messages, les étapes 1 et 4 sont structurelles, et non conventionnelles. Le module webhook_ingress de la passerelle définit un contrat d’entrée authentifiée :
- chaque adaptateur de webhook chargé de distribuer les messages déclare son mode d’authentification dans un registre unique (
MESSAGE_DISPATCHING_WEBHOOKS), et les tests de protection contre la dérive vérifient la concordance entre la table de routage de la passerelle et ce registre ; authenticateapplique la politique de refus en cas d’échec des informations d’identification. Un secret requis manquant, vide ou non résolu entraîne le refus de la requête avec401, avant l’analyse du moindre octet de la charge utile. L’algorithme de signature et le format d’en-tête propres au fournisseur restent dans le gestionnaire de transport, sous la forme d’une fermeture qui ne s’exécute qu’après résolution des informations d’identification ;- une vérification réussie génère une preuve
VerifiedWebhookIngressqui contient les octets vérifiés. La consommation deparse_messagesfournit au parseur ces octets exacts et renvoie une valeur privéeVerifiedWebhookMessages. Aucune de ces preuves ne peut être construite ou clonée ailleurs ; dispatch_verified_webhookest l’utilitaire partagé de gateway-webhook pour le journal entrant courant, la clé de session, la sauvegarde automatique, le dispatch de l’agent, le mécanisme de repli quickstart, la livraison des réponses/erreurs et l’exécution synchrone ou avec accusé de réception rapide. Il consomme la preuve analysée, de sorte que le contenu du webhook ne peut pas accéder au dispatch de l’agent sans un résultat de vérification et une étape d’analyse liés à la même requête.
Cet utilitaire supprime les chaînes parse -> autosave -> chat -> send dupliquées de la passerelle et fournit à l’entrée authentifiée un point de passage unique obligatoire. Il appelle toutefois toujours le chemin de chat de la passerelle ; il ne constitue donc pas le cycle de vie partagé d’un tour de canal décrit ci-dessus. Les webhooks de la passerelle doivent encore converger vers ce cycle de vie pour les hooks, le contrôle des boucles, le contexte passif, la gestion des médias/liens, les commandes d’exécution, l’annulation, l’intention de réponse, les accusés de réception et le suivi des coûts. Cette future convergence doit préserver la preuve de l’entrée authentifiée ainsi que le comportement de réponse synchrone ou avec accusé rapide propre à chaque transport.
Chaque adaptateur de webhook distribuant des messages dans le registre déclare une information d’authentification obligatoire pour chaque alias et est rejeté avant l’analyse lorsque cette information est absente, vide ou non résolue. Le registre ne propose aucun mode de vérification facultative : le passage silencieux n’est pas un mode d’authentification. Un adaptateur ne disposant d’aucun mécanisme d’authentification entrant ne peut donc pas être enregistré aujourd’hui pour distribuer des messages ; en ajouter un nécessiterait d’étendre le registre avec une stratégie explicite de refus uniquement, plutôt que d’assouplir la vérification.
Lors de l’examen des modifications de webhook, comparez les gestionnaires synchrones et les gestionnaires fast-ack séparément :
- les gestionnaires synchrones doivent préserver les codes d’état existants, le comportement en cas de signature invalide, les clés de sauvegarde automatique et la livraison des réponses ;
- les gestionnaires fast-ack doivent prouver que l’accusé de réception HTTP se produit avant que l’appel au modèle ne puisse bloquer le timeout du fournisseur ;
- Même si le chemin propre à la passerelle demeure, les deux formes doivent passer par
dispatch_verified_webhookpour entrer dans le dispatch, plutôt que d’ajouter une autre chaîneparse -> autosave -> chat -> send. Un inventaire figé des sites d’appel fait échouer le build lorsqu’un gestionnaire contourne le flux authentifié. Cette exigence ne fait pas du helper le cycle de vie du canal cible.
Rechargement et cycle de vie de l’écouteur
La configuration du canal peut être enregistrée avant que l’écouteur en cours d’exécution ne la voie. Le daemon possède le graphe du sous-système à longue durée de vie, de sorte que les modifications de l’écouteur de canal ne prennent effet que lorsque le daemon recharge ou redémarre le sous-système concerné. Les démarrages de la passerelle autonome peuvent nécessiter un redémarrage du processus pour que les modifications de l’écouteur de canal soient prises en compte.
Examinez les modifications sensibles au rechargement en vérifiant :
- si la valeur modifiée est enregistrée dans
config.toml; - si le contexte de canal en cours d’exécution lit la nouvelle valeur immédiatement, au rechargement, ou seulement après redémarrage ;
- si les tâches d’écoute s’arrêtent par annulation plutôt que d’orpheliner les anciennes connexions ;
- si les liaisons de canaux actives restent la source de vérité pour déterminer quel agent possède quel alias de canal.
Streaming, brouillons et annulation
Le streaming est une frontière de capacités. Un canal peut prendre en charge les éditions de brouillon, le streaming multi-messages, les indicateurs de frappe, ou uniquement le comportement d’envoi final. Le cycle de vie partagé décide de la manière dont ces capacités sont utilisées pendant un tour.
Examinez les modifications en streaming en demandant :
- le canal déclare-t-il la capacité au lieu de coder en dur le comportement dans la boucle de tours ?
- les messages brouillons sont-ils finalisés, annulés ou remplacés sur chaque chemin de succès, de non-réponse, d’échec et d’annulation ?
- est-ce que
/stopannule la portée correcte de l’expéditeur/du thread ? - les tours interrompus évitent-ils de persister une réponse partielle de l’assistant comme si elle était complète ?
- le comportement visible par l’utilisateur reste-t-il cohérent dans les messages directs, les discussions de groupe et les réponses en fil ?
Santé et backoff
Les écouteurs à exécution longue doivent échouer de manière compréhensible pour les opérateurs. Les défaillances de plateforme récupérables doivent retarder et réessayer ; les erreurs de configuration ou d’authentification non récupérables doivent être clairement signalées plutôt que de tourner en boucle infinie.
Pour les modifications du listener, vérifiez le chemin pertinent :
- arrêt sain du listener en cas d’annulation ;
- échec d’API réessayable effectue un backoff et reprend ;
- un échec non réessayable arrête ou signale un problème de configuration durable ;
- un canal bloqué ne coince pas les écouteurs frères ni la livraison aux observateurs.
Liste de contrôle du relecteur
Pour les modifications de canal, de webhook ou de channel-runtime, répondez-y avant la validation du réviseur :
- Quel travail spécifique au transport reste dans l’adaptateur, et pourquoi ?
- Où le code crée-t-il ou reçoit-il pour la première fois un
ChannelMessage? - Quel agent possède l’alias de canal pour ce message ?
- La modification réutilise-t-elle le dispatch partagé et le cycle de vie du tour ?
- S’il ajoute un comportement du cycle de vie spécifique au canal, quel hook partagé ou quelle fonctionnalité a été envisagé et pourquoi est-il insuffisant ?
- Comment sont transmis la boucle interne, l’adressage, le contexte passif et l’intention de réponse ?
- Les médias, les liens, les pièces jointes et les résultats d’outils sont-ils limités avant d’entrer dans le contexte visible par le fournisseur ?
- L’acquittement rapide, le cas échéant, conserve-t-il le même comportement de tour en arrière-plan que le dispatch synchrone ?
- Que se passe-t-il en cas de rechargement, d’annulation de l’écouteur, de timeout du fournisseur,
/stop, de non-réponse et d’échec d’envoi ? - Quel test ciblé ou smoke manuel prouve la limite qui a changé ?
Pointeurs source
Documentation Canonical :
- Cycle de vie des requêtes
- État d’exécution et persistance
- Cycle de vie de la mémoire et du payload
- Cycle de vie de la configuration
- Présentation des canaux
- API HTTP de la passerelle
- FND-001 : Architecture intentionnelle
- Protocole de plugin
Principaux points d’entrée du code :
- Trait Channel et structure du message :
crates/zeroclaw-api/src/channel.rs - ABI du contexte d’ingress :
crates/zeroclaw-api/src/ingress.rs - Dispatch des canaux et cycle de vie du tour :
crates/zeroclaw-channels/src/orchestrator/mod.rs - Boucle de tour runtime :
crates/zeroclaw-runtime/src/agent/turn/ - Point d’entrée de processus générique du runtime :
crates/zeroclaw-runtime/src/agent/loop_.rs - Chemin du webhook/chat de Gateway :
crates/zeroclaw-gateway/src/lib.rs