Agents de longue durée : points de reprise, récupération et idempotence
Pour un agent qui travaille plusieurs heures, la difficulté est souvent de savoir ce qui s'est déjà produit après un redémarrage, un délai dépassé ou une compression du contexte. Un contexte plus grand et une boucle plus longue ne remplacent pas un état de tâche enregistré.
Séparer état de tâche et conversation
La conversation conserve les échanges. L'état récupérable doit aussi préciser objectif, contraintes, actions en attente, résultats confirmés, échecs, budget restant et conditions d'arrêt. Un « terminé » rédigé par le modèle ne prouve rien : il faut un artefact consultable, un résultat d'outil ou une vérification.
Un point de reprise capture cet état à un instant donné. La persistance de LangGraph distingue les instantanés d'un fil d'exécution du stockage partagé entre fils ; elle rappelle que les points en mémoire disparaissent au redémarrage. Un résumé aide le prochain appel du modèle, mais ne doit pas être la seule preuve d'une action externe.
Pour une tâche documentaire fictive — lire, rédiger, enregistrer puis notifier — l'état peut conserver version du brouillon, identifiant de l'écriture et accusé de réception du service de notification. La reprise n'a plus à deviner la dernière étape réussie dans des milliers de lignes.
La faille : exécuté mais non enregistré
Supposons que le service de notification accepte une requête, mais que le client dépasse son délai avant la réponse. Réessayer faute de succès local peut envoyer deux notifications. Enregistrer le succès avant l'envoi crée la faille inverse : un plantage peut laisser une notification jamais envoyée marquée comme terminée.
Un point local et un service distant quelconque ne constituent pas automatiquement une transaction atomique. Le modèle d'exécution des activités Temporal sépare travail externe réessayable et progression du workflow ; l'application doit encore définir le sens d'une répétition. Une infrastructure persistante ne garantit pas, à elle seule, que tous les effets auront lieu exactement une fois.
Identifier l'action logique, pas la tentative
Répéter une opération idempotente n'ajoute pas d'effet supplémentaire. Fixer un fichier à une version donnée se réessaie plus facilement que lui ajouter un paragraphe. Si l'API accepte une clé d'idempotence, toutes les tentatives de la même action doivent la réutiliser, plutôt que créer un nouvel UUID.
Associer cette clé à la tâche, à l'étape et à l'empreinte du contenu. Modifier destinataire ou texte crée une nouvelle action logique ; réutiliser l'ancienne clé peut renvoyer l'ancien résultat. Le destinataire doit refuser une même clé avec des paramètres différents.
Le récepteur doit insérer la clé sous une contrainte d’unicité et appliquer le changement métier dans la même transaction. S’il vérifie d’abord que la clé existe et ne l’écrit qu’à la fin, deux requêtes concurrentes peuvent toutes deux constater « pas de clé » et s’exécuter chacune. Pourquoi cet ordre compte, et comment un outbox gère encore les livraisons en double, est expliqué dans Données relationnelles, SQL et transactions. Un résultat non confirmé reste inconnu, plutôt qu'automatiquement considéré comme un échec.
Reprendre ne signifie pas tout rejouer
Lire le dernier état confirmé et les artefacts externes avant de choisir la suite. Réutiliser les résultats de génération conservés quand cela convient : rappeler le modèle peut changer le texte et les actions suivantes. Des modifications de code, de schéma d'outil ou d'entrée demandent aussi de décider si l'ancien point reste compatible. L'exécution des workflows Temporal décrit une récupération à partir de l'historique ; séparer calcul rejouable et entrées-sorties externes est essentiel.
Traiter chaque échec selon sa cause. Une erreur réseau transitoire peut justifier des reprises espacées et limitées ; des arguments invalides demandent une correction ; des permissions absentes ne se résolvent pas en réessayant ; une attente longue exige une échéance. Comment arrêter une exécution avec ses sous-processus est expliqué dans les boucles d’agent bornées ; une tâche longue doit en plus consigner les effets déjà réalisés avant l’annulation. Arrêter le travail futur n'annule pas le passé.
Relier reprise et compression du contexte
L'instantané garde une progression exploitable par la machine ; le résumé explique au modèle comment poursuivre. Ils peuvent être mis à jour ensemble. Ce que le résumé doit conserver est décrit dans l’ingénierie du contexte ; les gros résultats d'outils restent stockés, tandis que seuls leurs passages utiles reviennent dans le contexte.
La fin dépend de l'objectif. « Brouillon enregistré et citations vérifiées » diffère de « utilisateur notifié ». Réussir l'un ne doit pas masquer l'autre par un statut global. Budget épuisé, attente d'une entrée externe et objectif atteint demandent également des états distincts.
Un test utile interrompt avant l'écriture, après l'écriture mais avant son enregistrement, puis après celui-ci. Vérifier exactitude de l'artefact, absence de duplication et résolution des résultats inconnus. Des fichiers locaux et services simulés permettent ces essais sans envoyer plusieurs vrais messages.
Version agent de code : les commits git comme points de reprise
Quand un agent de code doit terminer un projet sur plusieurs sessions, l’état décrit plus haut peut vivre dans le dépôt lui-même. L’article d’Anthropic sur les harness pour agents de longue durée, publié en novembre 2025, propose une méthode :
- Réserver la première session à la mise en place. Un prompt distinct lui fait écrire un
init.shqui lance le serveur de développement, un journal de progressionclaude-progress.txt, et le premier commit git. - Écrire les exigences sous forme de liste de fonctionnalités en JSON, chaque élément marqué d’abord comme non validé. Les sessions suivantes ne peuvent modifier que le champ
passesde chaque élément, et le prompt précise : « It is unacceptable to remove or edit tests ». Selon l’article, le modèle abîme moins souvent un fichier JSON qu’un fichier Markdown. - Une seule fonctionnalité par session. Chaque session commence par
pwd, lit le fichier de progression et le journal git, puis lance un contrôle de bout en bout élémentaire pour vérifier que la session précédente n’a pas laissé l’application cassée. - Committer et mettre à jour la progression avant de finir. Chaque commit décrit ce qui a été fait ; un mauvais changement peut alors être annulé avec git pour revenir à une version qui marche.
- Tester comme un utilisateur. Avec seulement des tests unitaires ou
curl, l’agent ratait souvent des fonctionnalités qui ne marchaient pas de bout en bout ; invité à piloter un navigateur comme un utilisateur, il faisait bien mieux.
L’historique git et le fichier de progression servent ici de points de reprise, et la liste de fonctionnalités de condition d’achèvement : c’est le même état de tâche que plus haut. Une nouvelle session reprend avec claude -c, codex resume --last ou pi -c ; les commandes de reprise et d’exécution sans surveillance de chaque outil sont réunies dans le tableau à la fin de Harness.