Live 18/11 · Cohorte 318 nov à 19h00 MSK — atelier pratique gratuit sur les agents IA · La Cohorte 3 démarre le 23/11Atelier 18/11 →Cohorte 3 (23/11)
SortieAnalyse · Sur le radarHabr AI→ original

L'agent a terminé, mais Telegram est en panne : la file de livraison d'agent-hub en Rust

Lorsque l'agent a fini son travail et que Telegram est inaccessible, il est exclu de relancer la requête au modèle : cela coûte des tokens et pourrait modifier à nouveau les fichiers. L'auteur d'agent-hub, écrit en Rust, a séparé la réception du résultat de sa livraison. Le texte final est d'abord écrit sur disque, puis une tâche distincte l'envoie par morceaux et réessaie après un échec ou un redémarrage.

Traité par IA depuis Habr AI ; édité par Hamidun News
L'agent a terminé, mais Telegram est en panne : la file de livraison d'agent-hub en Rust
Source : Habr AI. Collage: Hamidun News.
Écouter l'article
Fiche synthèse et chiffres clés
ParamètreDonnées
Source primaireHabr AI ↗
Rédacteur en chef
Chiffre clé #1La réponse est stockée dans un fichier, découpée à l'avance en parties avec suivi de progression
Chiffre clé #2Le délai entre deux tentatives passe de 5 à 600 secondes
Chiffre clé #3Les doublons sont possibles, c'est pourquoi chaque partie porte l'ID du tour et un numéro

Une situation familière : l'agent a lu le code, corrigé les fichiers, vérifié le résultat et rédigé une excellente réponse. Et à cet instant, Telegram est inaccessible. Pour l'agent, le travail est terminé ; pour l'utilisateur, il ne s'est rien passé. Relancer la tâche n'a rien d'attrayant : cela coûte du temps, des tokens et le risque que l'agent modifie à nouveau quelque chose. C'est exactement le problème qu'a rencontré l'auteur d'agent-hub, une application en Rust qui lance des agents IA en local et dialogue avec eux via les sujets d'un groupe Telegram.

Séparer le résultat et la livraison

L'idée principale est simple : recevoir la réponse et l'envoyer sont deux événements distincts. Lorsque le tour de l'agent s'achève avec succès, le hub enregistre d'abord le texte final dans le fichier local topics.results.json et le place dans la file, et ce n'est qu'ensuite qu'il contacte Telegram. Une tâche dédiée gère l'envoi et les nouvelles tentatives. Après un redémarrage, elle relit l'état depuis le disque et poursuit la livraison sans nouvel appel au modèle.

Ce n'est pas toute la conversation qui entre dans la file, mais les blocs de texte consécutifs situés après le dernier appel d'outil affiché. Les pièces jointes, les messages intermédiaires, les questions et les boutons d'autorisation ne sont pas rejoués automatiquement.

Un détail important : le hub conserve les parties déjà préparées, et non le Markdown d'origine. Si la conversion du balisage change après une mise à jour de l'application, les limites des messages restent identiques et le numéro enregistré de la partie suivante ne se décale pas vers un autre morceau de texte.

Comment le système survit aux pannes

Le cycle est le suivant : trouver une entrée prête, la réserver pendant 60 secondes et l'enregistrer sur disque, envoyer la partie courante, noter l'accusé de réception, passer à la suivante. La réservation sert à éviter qu'une entrée reste bloquée à jamais si le processus s'interrompt en pleine requête réseau. La requête vers Telegram est limitée à 20 secondes, et l'envoi se fait au plus à raison d'une partie par seconde.

En cas d'erreur temporaire, les délais s'allongent : 5, 15, 30, 60, 120, 300, 600 secondes. Après huit échecs consécutifs, la livraison s'arrête jusqu'à une relance manuelle. Si Telegram demande lui-même d'attendre (RetryAfter), ce délai est conservé pour la file de tout le groupe et n'est raccourci ni par une relance manuelle ni par un redémarrage. Si Telegram rejette le HTML, le hub tente d'envoyer du texte brut, et si cela échoue aussi, il attend l'intervention d'un humain.

La file se pilote depuis le sujet : /last affiche la dernière réponse enregistrée sans appeler le modèle, /outbox liste les envois en attente avec les boutons « Réessayer » et « Supprimer ». Dans l'interface, en cas d'erreur de lecture du stockage, c'est « inconnu » qui s'affiche et non zéro, afin qu'une panne de disque ne ressemble pas à une file vide.

Où s'arrêtent les garanties

L'auteur ne promet pas, en toute honnêteté, une livraison exactement une fois. Telegram a pu accepter le message alors que l'accusé s'est perdu ; ou le hub n'a pas eu le temps de l'écrire sur disque avant l'arrêt. La partie sera alors renvoyée. C'est pourquoi chaque partie commence par l'ID du tour et un numéro du type « partie 2/3 » : ce marqueur n'élimine pas le doublon, mais montre qu'il s'agit d'un renvoi et non d'une nouvelle réponse.

Il existe aussi des limites strictes : jusqu'à 50 réponses en attente et 8 Mio dans la file, conservation jusqu'à 7 jours, jusqu'à 64 Kio par texte. Si la file est pleine, les anciennes entrées ne sont pas évincées, et la nouvelle réponse est envoyée sans nouvelle tentative automatique et avec un avertissement. Le fichier est créé avec les droits 0600, mais il contient des réponses d'agent, il faut donc penser aux sauvegardes.

Les tests ont été réalisés sous Linux avec un Telegram simulé et un stockage temporaire : réseau indisponible, redémarrage après envoi partiel, perte d'accusé, RetryAfter, erreur HTML, débordement, changement de groupe. La coupure d'alimentation n'a pas été simulée.

Ce qu'il faut retenir

Ce pattern est universel pour tout outil à base d'agents : enregistrez le résultat avant la livraison, conservez la progression par parties, donnez des identifiants aux renvois et ne promettez pas l'exactly-once là où il n'existe pas. C'est en somme un petit pattern outbox, bien connu du backend, appliqué à des agents pour lesquels une relance est coûteuse et risquée. Le code est ouvert sous licence MIT.

Dossier

Questions clés sur cet article

Que sait-on sur Séparer le résultat et la livraison ?

L'idée principale est simple : recevoir la réponse et l'envoyer sont deux événements distincts. Lorsque le tour de l'agent s'achève avec succès, le hub enregistre d'abord le texte final dans le fichier local topics.results.json et le place dans la file, et ce n'est qu'ensuite qu'il contacte Telegram. Une tâche dédiée gère l'envoi et les nouvelles tentatives. Après un redémarrage, elle relit l'état depuis le disque et poursuit la livraison sans nouvel appel au modèle.

Comment le système survit aux pannes?

Le cycle est le suivant : trouver une entrée prête, la réserver pendant 60 secondes et l'enregistrer sur disque, envoyer la partie courante, noter l'accusé de réception, passer à la suivante. La réservation sert à éviter qu'une entrée reste bloquée à jamais si le processus s'interrompt en pleine requête réseau. La requête vers Telegram est limitée à 20 secondes, et l'envoi se fait au plus à raison d'une partie par seconde. En cas d'erreur temporaire, les délais s'allongent : 5, 15, 30, 60, 120, 300, 600 secondes.

Que sait-on sur Où s'arrêtent les garanties ?

L'auteur ne promet pas, en toute honnêteté, une livraison exactement une fois. Telegram a pu accepter le message alors que l'accusé s'est perdu ; ou le hub n'a pas eu le temps de l'écrire sur disque avant l'arrêt. La partie sera alors renvoyée. C'est pourquoi chaque partie commence par l'ID du tour et un numéro du type « partie 2/3 » : ce marqueur n'élimine pas le doublon, mais montre qu'il s'agit d'un renvoi et non d'une nouvelle réponse.

ZK
Zhemal Khamidun — CPO d'Alpina Digital, product manager d'AlpinaGPT. Conçoit des produits IA depuis 2019. Hamidun News est un projet personnel devenu un agrégateur en production avec plus de 6 000 lecteurs.
✦ Unified AI Workspace · Nomad

Test Frontier LLMs & Autonomous Agents in One Workspace

Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.

Try Nomad AI →Launch Nomad Agent
Qu'en pensez-vous ?
Chargement des commentaires…