Engineering the Agentic Stack · Partie 5

Runtime d’AI agents longue durée : sessions et checkpoints

Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.

Mise à jour de l’article

Publié initialement le 26 mai 2026. Relu et mis à jour le 6 septembre 2026. Cette mise à jour couvre les nouvelles fonctionnalités du runtime et les options de déploiement, avec des comparaisons de plateformes corrigées, des contrôles budgétaires et des liens vers les sources.

L’exécution d’un agent peut durer plusieurs heures, mais son processus worker peut redémarrer à tout moment. Le runtime conserve l’état de l’exécution, exécute ses outils et récupère la situation lorsqu’un tool call s’interrompt à mi-parcours. C’est toujours le modèle qui choisit l’action suivante. La partie 6 couvre le harness : le code qui fournit le contexte, vérifie les tool calls et détermine si le travail est terminé.

En bref : pour mettre en pause et reprendre, utilisez un checkpoint store. Conservez un event log durable pour enregistrer ce qui s’est passé, un sandbox pour l’exécution des outils, une trace pour le debugging et un harness pour exécuter la boucle. Pour la plupart des équipes, commencez avec une queue, un worker et un checkpointer PostgreSQL. Si vous ne pouvez pas identifier le responsable de chaque job, l’agent est encore un prototype.

Qu’est-ce qu’un runtime d’AI agent ?

Un runtime d’AI agent est l’infrastructure qui maintient en fonctionnement un agent utilisant des outils après la fin d’un appel au modèle. Il stocke l’état de session, exécute les outils, enregistre les checkpoints, gère les secrets, écrit les traces, applique les limites de coût et définit le mode de déploiement du service. Le modèle choisit l’action suivante. Le runtime décide où cette action s’exécute, enregistre le résultat et restaure l’exécution après un échec. Le harness décide si une action est autorisée. Ce n’est pas un store, mais il figure dans le tableau parce que le runtime doit bien l’exécuter quelque part.

Primitive à positionnerRôle en productionImplémentation courante
SessionPréserver le journal d’exécution après un redémarrage du processusEvent log en ajout uniquement, thread ID, conversation store
HarnessPiloter les tours modèle/outils jusqu’à la fin de la tâcheGraphe LangGraph, runner Agents SDK, boucle custom
SandboxIsoler le code, les fichiers, le réseau et les outilsContainer renforcé, VM, browser sandbox, workspace managé
CheckpointReprendre sans rejouer toute l’exécutionPostgres, Redis, état de workflow durable
TraceDebugger et auditer les exécutions longues a posterioriSpans OpenTelemetry, LangSmith, traces du fournisseur

Quatre des cinq primitives stockent l’état ou limitent ce que le code peut faire : session, sandbox, checkpoint et trace. Le harness prend les décisions relatives à la mémoire, aux contrats d’outils et aux permissions. Cet article explique les services et les stores dont il a besoin. La partie 6 explique ses vérifications, ses retries et ses tests d’acceptation.


Les exécutions longues remettent en cause les hypothèses des processus stateless

Un endpoint de chat stateless peut conserver l’état de la requête dans un seul processus et le supprimer après la réponse. Une exécution longue d’agent traverse des redémarrages de workers, des déploiements, des resets de contexte et des pauses d’approbation. Le processus worker ne peut donc plus être la source de vérité.

L’équipe OpenAI Codex indique la durée que peuvent atteindre ces exécutions dans son article sur le harness engineering :

« Nous voyons régulièrement des exécutions Codex uniques travailler sur une même tâche pendant plus de six heures (souvent pendant que les humains dorment). »

L’équipe d’ingénierie d’Anthropic décrit le problème d’état correspondant dans Effective harnesses for long-running agents :

« Le défi central des agents longue durée est qu’ils doivent travailler par sessions discrètes, et que chaque nouvelle session commence sans mémoire de ce qui s’est passé auparavant. »

Ces deux observations impliquent la même conception du runtime : persister l’état en dehors du worker et rendre les workers remplaçables.

La session doit vivre en dehors du processus worker. Un store durable enregistre les appels au modèle, les intentions et résultats des tool calls, ainsi que les approbations, afin qu’un autre worker puisse reprendre au dernier point sûr après un crash. Un effet externe en attente doit être réconcilié avant que cette reprise puisse être considérée comme sûre. Les checkpoints permettent également au runtime de démarrer une nouvelle session modèle lorsque la context window est pleine, sans rejouer tout l’historique. Selon la formulation d’Anthropic, les instances du harness deviennent jetables et redémarrables ; l’état durable vit ailleurs.


Cinq primitives à mettre en place avant la mise en production

L’article d’Anthropic Scaling Managed Agents fournit un vocabulaire utile pour cinq responsabilités du runtime. Le harness fait progresser l’agent, tandis que la session enregistre ce qu’il a fait et que le sandbox exécute les commandes. Le checkpoint fournit au worker suivant un point de reprise ; la trace conserve les éléments nécessaires au debugging ultérieur. Une implémentation peut fusionner certains composants, mais les responsabilités et les limites de défaillance doivent tout de même être nommées.

Les cinq primitives du runtimeLes cinq primitives du runtime

Session. Un event log en ajout uniquement, écrit séparément, contenant les appels au modèle, les tool calls demandés et terminés, les erreurs et les approbations. Une base de données de checkpoints facilite la récupération, mais l’historique de l’état du graphe ne remplace pas ce log.

Le terme est ambigu ; cet article adopte donc une convention de nommage applicative pour trois spans. Un thread est la conversation d’un utilisateur sur plusieurs jours. C’est le span dont la durée de vie est la plus longue et il peut contenir plusieurs exécutions.

Une session modèle est la plus courte : une période continue de contexte modèle. La compaction — l’étape qui résume la fenêtre afin de permettre au travail de continuer — prolonge une session modèle au lieu d’y mettre fin. Un redémarrage ou un nouveau départ délibéré y met fin. La partie 6 utilise « session modèle » dans ce sens.

Dans cet article, « session » désigne le log durable d’une exécution. Plusieurs sessions modèle peuvent écrire dans un même log, et un thread de conversation peut contenir plusieurs logs d’exécution. Pour récupérer une exécution, réveillez-la, chargez sa session, réconciliez tout effet externe en attente, puis reprenez après le dernier événement : wake(sessionId) → getSession(id) → reconcile pending effects → resume from last event.

Dans LangGraph, thread_id est la clé de stockage et de récupération utilisée par le checkpointer pour l’historique de l’état du graphe d’un thread (voir LangGraph persistence) ; elle ne définit pas les frontières de conversation, de session modèle ou d’event log de cet article. Donnez à l’event log son propre ID d’exécution ou de session durable, puis choisissez explicitement la façon dont ces IDs se mappent vers les threads LangGraph. L’OpenAI Agents SDK fournit dix backends de session intégrés, dont SQLiteSession, RedisSession, SQLAlchemySession, MongoDBSession et EncryptedSession (voir la documentation Sessions). Ils contiennent un historique de conversation mutable, notamment pour la suppression, l’effacement et la compaction ; mappez un ID de session SDK vers l’ID des événements d’exécution si cela vous est utile, mais ne considérez pas l’historique du SDK comme le log de récupération ou d’audit en ajout uniquement sans garantie équivalente d’immutabilité.

Harness. La boucle d’orchestration, et la seule primitive de cette liste qui prend des décisions. Il assemble le prompt à partir de la mémoire, appelle le modèle, vérifie le tool call proposé par rapport à ses règles de permission, distribue ce qu’il autorise, réécrit les résultats dans la session, applique les règles de retry et détermine si la tâche est terminée. Les aides à la planification et à la gestion du contexte encodent des hypothèses sur les capacités du modèle. L’autorisation et l’isolation obligatoires implémentent également des exigences qui restent valables à mesure que les modèles progressent. Anthropic le souligne directement — la citation apparaît dans la section sur les modes d’échec ci-dessous, qui traite principalement des situations où ces hypothèses deviennent obsolètes.

L’équipe Codex d’OpenAI appelle cela le harness engineering : écrire du software demande toujours des efforts d’ingénierie, mais une part croissante de ces efforts est désormais consacrée au scaffolding plutôt qu’au code lui-même. Le CompiledStateGraph de LangGraph, les Deep Agents de LangChain et leur point d’entrée create_deep_agent, ainsi que Claude Code lui-même, sont tous des harnesses dans ce sens.

Sandbox. L’environnement d’exécution isolé dans lequel les commandes s’exécutent réellement. La page sandbox concepts de l’OpenAI Agents SDK attribue au runtime externe les approbations, le tracing, les handoffs et l’état nécessaire à la reprise des exécutions. Elle attribue les commandes, les modifications de fichiers et l’isolation de l’environnement à la session sandbox.

Dans ce contexte, « runtime externe » désigne le harness ainsi que ses stores d’état. Dans le vocabulaire de cette série, les approbations et les handoffs sont des décisions du harness (partie 4 et partie 6) ; la gestion du tracing et de la reprise relève des primitives session et checkpoint.

Les sandboxes diffèrent par leur durée de vie et par ce qu’ils mémorisent entre les exécutions. La forme la plus simple est fresh ephemeral : en créer un pour une seule tâche, le détruire à la fin et payer le coût de démarrage à froid à chaque exécution.

Les sandboxes persistent paused conservent le système de fichiers et un snapshot mémoire entre les exécutions. La reprise suivante peut ainsi éviter un démarrage complet. Snapshot or fork crée une branche en copy-on-write depuis un parent préparé, ce qui permet à de nombreuses tâches de partager les dépendances installées et les caches chauds sans partager leur état modifiable.

Les workspaces per-worktree fournissent des checkouts séparés aux tâches ; les Git worktrees partagent l’infrastructure du repository et ne sont pas des sandboxes OS. Restreignez séparément l’exécution avec un container, une VM ou une policy de processus. Une application par tâche peut également disposer de sa propre stack d’observabilité. Des logs, métriques et traces séparés permettent de debugger une exécution sans que son état se propage à une autre. Le tableau des fournisseurs plus loin dans cet article compare les contrats d’isolation et de persistance.

Checkpoint. L’état nécessaire à la reprise : le nœud du graphe exécuté, ses dernières valeurs et ce qui doit s’exécuter ensuite. Un event log répond à la question « que s’est-il passé ? » : les actions demandées et leurs résultats. Un checkpoint ne peut pas reconstituer des événements que le harness n’a jamais enregistrés.

Le PostgresSaver de LangGraph écrit un Checkpoint à chaque frontière de super-step. Un super-step est un tour du graphe, soit un nœud unique, soit un batch exécuté en parallèle. Les écritures par tâche vont dans checkpoint_writes ; les sorties de nœuds réussis ne sont donc pas recalculées lorsqu’un nœud frère échoue.

Un checkpoint est un simple dict (v, id, ts, channel_values, channel_versions, versions_seen, updated_channels). LangGraph le sérialise avec son JsonPlusSerializer basé sur msgpack plutôt qu’avec JSON. datetime, set, Decimal et les dataclasses peuvent être restaurés à l’identique. Le format est documenté sur la page PyPI langgraph-checkpoint-postgres et dans la référence LangGraph sur les checkpoints.

StateSnapshot est la vue séparée et plus riche que graph.get_state() construit au-dessus d’un checkpoint. Un bundle de debugging peut exporter son .values comme dernier état connu du graphe ; il ne peut pas reconstituer les détails d’événements que le harness n’a jamais enregistrés.

Trace. La surface de debugging et d’audit. Chaque appel au modèle, tool call et étape de sous-agent devrait émettre la durée, le statut, le modèle et le fournisseur, les IDs de corrélation, le nombre de tokens et le coût. Les prompts, completions, arguments des outils et résultats des outils sont des contenus opt-in : les recommandations GenAI d’OpenTelemetry utilisent par défaut les métadonnées, car ces champs peuvent contenir des données sensibles. Ne les capturez qu’après avoir défini les règles de redaction ou de filtrage, les contrôles d’accès et la rétention applicables. Lorsqu’une exécution de six heures échoue, c’est la trace que vous consultez pour comprendre ce qui s’est passé. Elle peut appuyer une investigation, mais ce sont l’event log et l’état du checkpoint, avec la gestion de l’idempotence, qui permettent une reprise ou un replay sûr. La sortie du terminal de l’exécution a disparu depuis longtemps. Les conventions sémantiques GenAI d’OpenTelemetry standardisent les noms d’attributs — modèle, fournisseur, nombre de tokens, conversation et workflow. Pour une destination compatible OTLP qui prend en charge ces conventions, la même instrumentation peut exporter la trace vers des systèmes tels que Tempo, Jaeger, Honeycomb ou LangSmith, même si des adaptateurs backend ou une configuration propre à la destination peuvent rester nécessaires.

Policy et secrets traversent les primitives

Deux frontières traversent les cinq primitives. Elles constituent la version runtime de l’argument de sécurité présenté dans la partie 4. La décision de permission elle-même appartient au harness ; ce qui suit indique où se trouvent physiquement les mécanismes qui l’appliquent et l’alimentent.

Application des permissions

La permission ladder de la partie 4 doit bien être exécutée quelque part. La vérification intervient avant chaque tool call et décide s’il peut passer. Deux patterns sont courants en production. Le middleware de permissions du filesystem de Deep Agents peut limiter les outils filesystem intégrés aux chemins déclarés. Il ne contrôle ni les commandes shell du sandbox, ni les outils custom, ni les appels MCP ; appliquez ces règles dans la policy du sandbox ou derrière leur propre proxy d’outils. Anthropic Managed Agents route les tool calls MCP custom via un proxy qui détient les credentials. L’exécution des commandes du sandbox et l’authentification Git utilisent des chemins distincts ; le proxy MCP n’est pas un intercepteur universel de chaque action. Lorsqu’un appel sensible nécessite une approbation humaine, le interrupt() de LangGraph et le hook d’approbation de Deep Agents mettent le graphe en pause jusqu’à la réponse d’une personne.

Secret broker

Le modèle ne devrait pas voir les secrets de longue durée, et le sandbox ne devrait généralement pas les voir non plus. Le pattern Managed Agents est celui à reproduire :

« Pour Git, nous utilisons le token d’accès de chaque repository pour cloner le repository pendant l’initialisation du sandbox, puis nous l’injectons dans le remote Git local. Git push et pull fonctionnent depuis l’intérieur du sandbox sans que l’agent ne manipule jamais lui-même le token. Pour les outils custom, nous prenons en charge MCP et stockons les tokens OAuth dans un vault sécurisé. Claude appelle les outils MCP via un proxy dédié ; ce proxy reçoit un token associé à la session. … Le harness n’a jamais connaissance des credentials. »

Dans la stack de référence market-analyst-agent — un petit agent LangGraph qui récupère des données de marché et rédige un rapport d’analyste, construit tout au long de cette série — le worker appelle localement ses outils de données de marché. Le serveur MCP optionnel expose une surface d’outils ; il n’implémente pas de credential broker entre ce worker et ses fournisseurs. Les deux containers peuvent lire le .env de développement partagé. Un broker de production nécessiterait de déplacer les credentials des fournisseurs dans un store que le worker ne peut pas lire et de router chaque appel concerné via le broker.

Vérifier le positionnement

Une vérification pratique consiste à noter chaque composant et la primitive parmi les cinq qu’il implémente. Postgres peut couvrir la session et le checkpoint. Le container worker est le harness. Un service tel que Daytona, Modal ou E2B fournit le sandbox, tandis que Tempo ou LangSmith stocke la trace.

Examinez ensuite les défaillances couplées. Si deux primitives vivent dans le même processus, un seul crash les fait tomber toutes les deux. Si elles partagent un credential, une fuite franchit les deux frontières. Exemples courants : un worker qui possède également la durabilité des traces, ou un token de sidecar qui déverrouille aussi la base de données des checkpoints.


Modes d’échec d’un runtime d’AI agent en production

Le runtime gère les retries, restaure le travail précédent, isole les workspaces et applique les budgets. À mesure que les exécutions traversent les workers et les context windows, les échecs se déplacent vers l’état, les effets externes dupliqués, la dérive du sandbox et les dépassements de budget.

Les échecs se répartissent en quatre groupes :

  • Échecs de qualité de sortie : l’agent déclare la victoire avant que le travail soit réellement terminé, oublie ce qu’il a fait après un reset de context window, ou fait confiance à sa propre auto-évaluation et livre une sortie défectueuse.
  • Échecs de contrôle des coûts : l’agent reste bloqué dans une retry loop, ou consomme un budget de tokens ou de tool calls sans rien produire d’utile.
  • Échecs d’état et de crash : les workspaces dérivent parce qu’une exécution modifie des fichiers appartenant à une autre, les tool calls sont lancés plusieurs fois parce que les retries les rejouent, ou le travail est perdu lorsqu’un worker meurt entre deux événements.
  • Échecs de context window : le modèle résume puis s’arrête trop tôt parce qu’il pense manquer de place, alors que la fenêtre dispose encore d’une marge suffisante.

Le tableau associe chaque échec à une mitigation, au fondement de la recommandation et au hook du runtime qui l’applique. Le comportement propre à chaque modèle peut changer ; considérez donc les observations des fournisseurs comme des incitations à retester l’hypothèse, et non comme des règles permanentes.

Modes d’échec et mitigationsModes d’échec et mitigations

Mode d’échecMitigationÉlément probantHook du runtime
Achèvement prématuré : l’agent déclare trop tôt la réussiteSéparation generator/evaluator : un evaluator en fresh context — une seconde session modèle qui commence sans historique de l’exécution — lit les fichiers, et non le chat, puis vote « done » ou « not done ». Échouer par défaut à chaque contrôle d’acceptation.Le cwc-long-running-agents d’Anthropic inclut un sous-agent evaluator ; validez le pattern sur votre suite de tâches.Sous-agent sans outils Write/Edit et avec sa propre context window
Amnésie des fonctionnalités entre context windowsL’agent initializer écrit PROGRESS.md, feature-list.json, init.sh. L’agent de coding les lit à chaque cold boot.Exigence de conception du harness ; mesurez le taux d’achèvement des tâches après cold boot avant et après l’ajout des artefacts.Boot hook avant le premier appel au modèle de chaque session
Travail dupliqué après un reset de sessionEvent log en ajout uniquement et fichier de handoff structuré. Chaque nouvelle session commence par pwd → read PROGRESS.md → review tests.Exigence de conception d’un log durable et d’un checkpoint ; testez en rejouant le même handoff de session.Event store écrit séparément, associé au checkpoint LangGraph PostgresSaver et à l’artefact PROGRESS.md
Anxiété liée au contexte : le modèle résume et s’arrête trop tôtLimiter la session active et reconstruire depuis un handoff lorsque le modèle n’utilise plus efficacement le contexte restant. Le workaround de Cognition pour Sonnet 4.5 activait une fenêtre plus grande, mais plafonnait l’utilisation effective à 200k.Les observations des fournisseurs diffèrent entre Sonnet 4.5 et les générations suivantes. Retestez avant de reprendre ce workaround avec un autre modèle ou harness.Le harness limite la durée de session, démarre la suivante et reprend depuis le checkpoint
Optimisme de l’auto-évaluation : le modèle considère son travail comme réussiEvaluator en fresh context, avec ancrage Playwright/MCP dans le DOM réel plutôt que dans des screenshots. Le harness design frontend d’Anthropic pénalise les valeurs par défaut de type « AI ».Pattern de frontend harness d’Anthropic ; validez avec des tests d’acceptation au niveau tâche sur l’application rendue.L’evaluator s’exécute dans une session sandbox distincte, sans outils d’écriture
Boucles bloquées et storms de retriesLimite d’itérations par tour, backoff exponentiel, circuit breaker sur le taux d’erreur des outils. Budget strict sur les tool calls.Exigence de contrôle du runtime ; injectez des échecs répétés d’outils et vérifiez la limite, le backoff et le circuit breaker.Decorator sur le nœud d’exécution des outils ; RetryPolicy sur les Temporal Activities (voir Temporal OpenAI Agents SDK contrib)
Dérive du workspace : l’agent modifie des fichiers sans rapportCommits Git comme checkpoints, mount de workspace par session et permissions filesystem de Deep Agents pour ses outils filesystem intégrés. Placez l’application des règles shell, custom-tool et MCP dans la policy du sandbox ou un proxy d’outils.Exigence d’isolation ; exécutez des sessions concurrentes sur des fixtures et inspectez les modifications de fichiers entre exécutions.FilesystemPermission de Deep Agents pour les outils filesystem intégrés ; policy du sandbox ou proxy MCP pour les autres opérations ; fork par tâche avec Daytona/Runloop
Coût incontrôlé des tokens ou des outilsRéserver atomiquement un budget conservateur par appel avant le dispatch, appels en cours inclus ; borner la sortie et l’utilisation des outils, puis réconcilier l’usage réel.Recommandation de contrôle des coûts ; le récit d’Addy Osmani sur les agents longue durée illustre le risque, tandis que la dépense réelle dépend des prix du modèle et des outils.Ledger de budget sur le chemin de dispatch ; Prometheus et Alertmanager comme monitoring et signaux d’arrêt complémentaires
Tool calls non idempotentsPersister une intention pending et une clé d’idempotence avant le dispatch ; persister le résultat à son retour. À la reprise, interroger ou retenter avec la même clé, puis enregistrer le résultat récupéré ou needs_human.Propriété de retry at-least-once ; validez un crash après le commit du fournisseur mais avant l’écriture du résultat local.Event store durable et lookup d’idempotence du fournisseur, à côté du nœud d’exécution des outils
Travail perdu après un crash du processus ou du sandboxEvent log durable en dehors du processus ; checkpoint après chaque super-step ; réconcilier les effets en attente avant de poursuivre. wake(sessionId) → getSession(id) → reconcile → resume.Exigence de récupération ; injectez un crash entre le succès du fournisseur et la persistance du résultat, puis comparez l’event log réconcilié avec l’effet externe.PostgresSaver pour l’état du graphe avec un event store séparé, ou un Temporal Workflow

Deux idées sous-tendent la plupart de ces lignes. Anthropic, à propos de l’obsolescence des harnesses dans Harness design for long-running application development :

« Chaque composant d’un harness encode une hypothèse sur ce que le modèle ne peut pas faire seul, et ces hypothèses méritent des stress tests, à la fois parce qu’elles peuvent être incorrectes et parce qu’elles peuvent rapidement devenir obsolètes à mesure que les modèles progressent. »

Vercel, à propos du problème lié au trop grand nombre d’outils qui encodent trop d’hypothèses, dans We removed 80% of our agent’s tools :

« Nous en avons supprimé la majeure partie et réduit l’agent à un seul outil : exécuter des commandes bash arbitraires. Nous appelons cela un file system agent. »

La citation décrit le cœur bash ; l’agent livré par Vercel conservait deux outils, ExecuteCommand et ExecuteSQL, en remplacement d’un ancien exemple de code qui nommait dix-sept outils. La partie 3 couvre l’avant/après complet. Leur résultat rapporté sur cinq requêtes représentatives : le taux de réussite est passé de 4/5 à 5/5, et le pire cas est passé de 724 s / 100 étapes / 145 463 tokens (échec) à 141 s / 19 étapes / 67 483 tokens (succès). C’est la ligne de pire cas qui est spectaculaire ; en moyenne sur les cinq requêtes, l’économie de tokens était de 37 %. La leçon n’est pas « supprimez vos outils ». Une aide optionnelle peut devenir redondante lorsque le comportement du modèle change. Retestez l’hypothèse lors d’un changement de modèle.

Cognition a observé le même caractère mouvant concernant la longueur des sessions avec Sonnet 4.5. Dans Rebuilding Devin for Claude Sonnet 4.5, ils décrivent un modèle qui écrit proactivement SUMMARY.md / CHANGELOG.md lorsqu’il détecte l’épuisement du contexte, mais sous-estime le nombre de tokens restants. Leur solution consistait à activer la context window de 1M tokens et à plafonner l’utilisation à 200k afin que le modèle pense toujours disposer d’une marge. Il s’agissait d’un flag beta au moment de leur rédaction.

La documentation d’Anthropic sur les context windows, vérifiée le 6 septembre 2026, indique que Sonnet 5 et Opus 5 disposent par défaut de 1M tokens ; Sonnet 4.5 reste à 200k. Les modèles Sonnet actuels reçoivent automatiquement des mises à jour sur le contexte restant, et la compaction côté serveur est disponible en beta pour les modèles Claude 4.6 et ultérieurs. Avant de reprendre le plafond historique de Cognition, testez le modèle sélectionné avec les contrôles de contexte qu’il prend en charge. Une fenêtre plus grande ou un compteur de budget ne garantit pas une mémoire fiable, et aucun des deux ne remplace une progression durable en dehors du modèle.

L’équipe harness d’OpenAI en donne la version en une ligne : « Les humains pilotent. Les agents exécutent. » Lorsqu’un échec survient, la question utile est de savoir quelle capacité manque et comment la rendre à la fois lisible et applicable pour l’agent.


Le cycle de vie sain d’une exécution

Une exécution bien conçue est ennuyeuse. C’est une chaîne de petites étapes récupérables, et chaque étape terminée écrit un état durable avant le démarrage de la suivante.

Écrire chaque résultat avant de démarrer l’étape suivante limite les dégâts d’un crash. Un effet externe en cours constitue l’exception : un worker peut crasher après le commit du fournisseur mais avant que le harness n’enregistre son résultat. Le worker suivant doit réconcilier cet effet en attente avant de reprendre depuis la dernière étape terminée.

Le cycle de vie d’une exécution d’agent déployéeLe cycle de vie d’une exécution d’agent déployée

  1. Démarrer depuis une session fraîche ou reprise. Lors d’une reprise, monter le workspace dans son dernier état connu, lire les fichiers de progression laissés par la tentative précédente (PROGRESS.md, feature-list.json), charger le dernier checkpoint et inspecter l’event log à la recherche d’intentions d’outils en attente. Réconcilier tout effet externe en attente avant tout nouvel appel au modèle ou aux outils.
  2. Planifier avant le déclenchement de tout tool call. Écrire ce que signifie « terminé », combien l’exécution peut dépenser, quels outils l’agent peut invoquer et ce qui doit arrêter prématurément l’exécution. Ces valeurs de plan deviennent des contrôles du runtime ; sans elles, l’exécution n’a rien qui puisse lui opposer une limite.
  3. Sérialiser ou coordonner explicitement les tool calls qui produisent des effets externes. La vérification des permissions du harness décide si chacun est autorisé. Avant le dispatch, ajouter une intention pending avec sa clé d’idempotence ; après le retour du fournisseur, ajouter le résultat. Les appels indépendants en lecture seule ou idempotents peuvent s’exécuter en parallèle lorsque chacun possède son propre enregistrement durable d’intention/résultat et que leurs résultats sont agrégés de manière déterministe. Si le worker meurt entre l’effet externe et l’écriture du résultat, reprendre en interrogeant ou en retentant le fournisseur avec la même clé, puis ajouter soit le résultat récupéré, soit needs_human. Stripe, par exemple, renvoie le résultat sauvegardé de la première requête lorsqu’une clé d’idempotence est répétée ; un autre fournisseur doit proposer un contrat équivalent de lookup ou de retry.
  4. Créer un checkpoint aux frontières des super-steps, ou après chaque événement dans un harness plus simple. Persister l’état du graphe, le diff du workspace et les références vers les artefacts produits. C’est ce checkpoint que l’étape 1 lit lors de la reprise suivante. Si le checkpoint est absent ou obsolète, la récupération peut nécessiter de reconstruire l’état depuis l’event log, ce qui est beaucoup plus lent.
  5. Évaluer les artefacts lorsque l’agent pense avoir terminé : tests, evaluator en fresh context, validation de schéma, contrôles dans le navigateur. Si le contrôle réussit, l’exécution se termine avec succès. S’il échoue, l’exécution reprend depuis le dernier checkpoint propre, avec le message d’échec ajouté au contexte, puis réessaie.

Aucune étape de cette liste n’exige que l’agent se souvienne de quoi que ce soit entre les exécutions. L’état vit dans la session et le checkpoint, et l’agent le relit à chaque reprise.

Persistez un ID d’opération géré par l’application avant le dispatch et liez-le aux arguments approuvés. Réutilisez-le pour récupérer la même intention métier, même si la replanification produit un nouvel ID de tool call du modèle. Enregistrez séparément ces IDs modèle pour la corrélation. Les mises à jour naturellement idempotentes peuvent plutôt nécessiter une précondition de version. Les recommandations AWS sur les retries expliquent pourquoi l’identité de la requête représente l’intention. Définissez quand une action est réellement nouvelle et combien de temps la déduplication dure : Stripe autorise la suppression des clés après au moins 24 heures. Réconciliez les payloads modifiés et les clés expirées avant toute nouvelle tentative.

Choisissez un writer actif unique ou un lease par thread. Pour les entrées reçues pendant une exécution, rejetez, mettez en queue, interrompez ou annulez explicitement ; le compte rendu du runtime Deep Agents décrit ces choix. Une annulation doit empêcher tout nouveau dispatch, enregistrer la demande et réconcilier les effets en cours ; tuer le worker n’annule pas un appel déjà envoyé au fournisseur.

L’application des budgets doit se trouver à côté du dispatch. Des appels concurrents ne doivent pas dépenser deux fois le même reliquat. Prometheus est un système de monitoring, pas un ledger d’autorité pour la dépense par requête. Réservez de manière conservatrice et réconciliez l’usage réel ; la comptabilisation différée du fournisseur et l’annulation peuvent malgré tout provoquer un dépassement.

Les nouveaux contrôles du modèle aident à réguler l’exécution, mais ne gèrent pas eux-mêmes sa limite de dépenses. Les task budgets beta d’Anthropic fournissent aux modèles compatibles de l’API Messages un budget indicatif pour une agentic loop. Ils peuvent être dépassés ; max_tokens borne une réponse, pas l’ensemble de l’exécution. La prise en charge dépend du modèle : Opus 5 prend en charge les task budgets, contrairement à Sonnet 5. Conservez le ledger de dispatch et le chemin d’annulation même lorsque le modèle reçoit un budget hint.

Les mécanismes d’arrêt de sécurité du fournisseur doivent avoir leur propre chemin terminal. Pour le misalignment_policy_violation d’OpenAI, arrêtez le dispatch, conservez les enregistrements corrélés et demandez une revue par un opérateur au lieu de retenter. Gérez les erreurs de streaming après une sortie partielle et réconciliez les effets précédents ; la partie 4 explique cette frontière de monitoring.

L’évaluation doit inclure des éléments probants extérieurs au contexte de production. Un evaluator en fresh context réduit le biais lié au contexte partagé, tandis que les tests, linters, contrôles navigateur et validations de schéma fournissent des preuves déterministes. Le contrôle peut renvoyer pass, fail ou needs_human. Pour les agents de code, le reviewer peut être une autre session modèle dotée d’outils en lecture seule. Pour les agents de données et de reporting, combinez une validation déterministe avec un reviewer model lorsque le jugement humain ou modèle reste nécessaire.


Onze patterns de déploiement d’AI agents et les critères de choix

Une fois les cinq primitives nommées, la question est de savoir quelle forme de déploiement les exécute. Par « forme », j’entends un agencement de ces primitives : où vit le harness, où l’état est persisté et quel type de sandbox exécute le travail. Une forme est une décision de câblage, pas un choix de fournisseur. Le graphique ci-dessous montre la zone de confort de chaque forme selon la durée d’exécution. Le texte qui suit détaille les critères de choix.

Si vous ne lisez qu’une seule des onze formes, lisez la forme 2 : queue + worker + checkpoint DB. C’est la valeur par défaut que je recommande à la plupart des équipes, la forme utilisée par le repository de référence et le squelette dont dérivent la plupart des autres formes : queue → worker → état durable, avec changement de la source du sandbox, du propriétaire du harness ou du moteur d’état. Lire d’abord la forme 2 rend les autres plus rapides à parcourir.

Formes de déploiement et durées d’exécution adaptéesFormes de déploiement et durées d’exécution adaptées

Le graphique compare les formes selon la durée d’exécution. La matrice ci-dessous les compare selon la responsabilité : chaque cellule encadrée nomme le composant qui fournit cette primitive.

Où vit chaque primitive dans chaque forme de déploiementOù vit chaque primitive dans chaque forme de déploiement

1. SDK dans un app server (synchrone, limité à la requête)

La forme originale. Le SDK de l’agent s’exécute dans un request handler. Convient aux tâches de moins de 30 secondes, aux démos et aux outils internes. Ne convient pas à tout ce dont un client HTTP pourrait se déconnecter. Le timeout HTTP de Cloud Run est plafonné à 60 minutes, et toute panic du web tier tue l’exécution. Le SDK est le harness. L’exécution d’outils non fiables nécessite un sandbox séparé, et l’état vit généralement en mémoire du processus sauf si vous le poussez explicitement ailleurs. N’utilisez pas cette forme pour un travail de plusieurs heures.

2. Queue + worker + checkpoint DB

La valeur par défaut que je recommande à la plupart des équipes, et l’implémentation de démo de forme production dans market-analyst-agent : un worker Python avec un checkpointer PostgreSQL, Redis Streams (ou RabbitMQ) pour la queue entrante et un sidecar MCP pour les outils. Convient aux exécutions de 10 minutes à plusieurs heures avec des étapes idempotentes. Le runner local peut contourner la queue pour le développement synchrone, mais la queue fait partie de la forme de production dès que vous avez besoin de soumission asynchrone et de backpressure.

Dans le pattern de production, l’application accepte une requête, crée une ligne de session, pousse un job et renvoie un ID d’exécution. Le worker récupère le job, exécute le harness, écrit les événements de session et les checkpoints, diffuse le statut et stocke les artefacts au fur et à mesure. Postgres survit, les workers sont remplaçables et la profondeur de la queue fournit la backpressure. Le calcul Spot/Preemptible fonctionne tant que les écritures durables de l’événement et du checkpoint sont terminées avant que le worker n’annonce le succès. Le repository lié démontre cette forme, mais pas une récupération durable vérifiée. Son consumer lit les nouveaux messages sans récupérer les jobs en attente, ACK les exceptions et redélivre le travail avec un nouvel état initial plutôt qu’avec un contrat de reprise défini. La production nécessite un comportement claim/lease/reclaim/ACK et des fault tests avant de pouvoir qualifier cette topologie de récupérable.

Dans cette forme, le worker est le harness. Son container et le workspace par thread fournissent une frontière d’exécution, mais le code non fiable nécessite toujours un sandbox renforcé ou une VM. L’event store possède l’historique de session ; PostgresSaver possède l’état des checkpoints. Ils peuvent partager une base de données uniquement si le harness écrit explicitement les deux schémas. Les traces passent par OpenTelemetry vers la stack d’observabilité que vous utilisez.

3. Moteur de workflow durable (style Temporal)

Le code d’orchestration de l’agent s’exécute dans un Temporal Workflow ; les appels au modèle et les tool calls s’exécutent comme des Activities. L’état du workflow vit dans un event-history log sauvegardé par Cassandra, MySQL ou Postgres, ce qui permet un replay après un échec. Les déploiements de Workflow code qui se chevauchent pendant une exécution nécessitent un Worker Versioning ou des patches compatibles avec le replay ; remplacer le code sans cette discipline peut casser le replay. L’intégration Temporal × OpenAI Agents SDK, généralement disponible depuis mars 2026, fournit un OpenAIAgentsPlugin et un helper activity_as_tool, tandis que l’article sur les agentic sandboxes décrit le fork d’un agent en cours vers un autre fournisseur de sandbox au milieu d’une conversation. Les workflows inactifs consomment zéro compute. Les réserves sont réelles : les agents realtime ne sont pas pris en charge, le streaming est encore marqué expérimental, et LocalShellTool ainsi que ComputerTool sont désactivés car ils ne correspondent pas à un modèle distribué.

Utilisez cette forme lorsque l’exécution comporte de vrais points d’attente : approbations humaines, callbacks externes, longues périodes de sommeil, retries avec règles métier, fenêtres de déploiement — et que l’équipe sait exploiter un versioning de workflows compatible avec le replay. Une approbation humaine devient un sommeil durable qui ne consomme aucun compute, et non une boucle de polling.

Le Workflow code est le harness. Le sandbox vit généralement en dehors de Temporal et est appelé depuis les Activities. L’état de session et de checkpoint se fond dans l’event-history log de Temporal, tandis que la visibilité des traces vient de l’interface Temporal et des spans OpenTelemetry sur chaque Activity.

4. Fournisseur de sandbox par session

Une forme plus récente. Chaque exécution d’agent reçoit sa propre microVM ou son propre container d’un fournisseur de sandbox-as-a-service. Le harness vit dans un endroit durable ; le sandbox est l’environnement d’exécution jetable.

FournisseurContrat d’isolation / d’exécutionLimites de session et de persistance, vérifiées en septembre 2026
E2BMicroVM FirecrackerSessions continues de 1 h en Hobby / 24 h en Pro ; la pause/reprise est un cycle de vie distinct
Vercel SandboxMicroVM Firecracker45 min en Hobby / 24 h en Pro et Enterprise ; l’expiration du snapshot est par défaut de 30 jours après la dernière utilisation et est configurable
DaytonaSandbox configuré par l’administrateur ou le fournisseurCycle d’arrêt/archivage configurable ; prise en charge du fork
ModalgVisor5 min par défaut / 24 h maximum ; les volumes et mécanismes de snapshot pris en charge disposent de contrats de persistance distincts
RunloopLa fiche Marketplace décrit des microVMsSuspend/resume et snapshot/branch disque ; la concurrence à l’échelle de la plateforme n’est pas un quota de compte

Les mesures de démarrage des fournisseurs couvrent des intervalles différents et ne constituent pas un classement de vitesse. Mesurez séparément le délai entre la requête API et la première commande réussie, ainsi que la latence de disponibilité de l’application, en incluant l’état de l’image et du cache, la région, la concurrence et les p95/p99. Le démarrage de container d’environ une seconde de Modal, par exemple, exclut l’initialisation de l’application. Vérifiez les limites de concurrence du compte avant les tests de charge.

Daytona enregistre un lien parent-enfant pour chaque fork indépendant, ce qui conserve la lineage des sandboxes dérivés. Le harness Codex d’OpenAI utilise la variante par worktree : « Codex travaille sur une version entièrement isolée de cette application, y compris ses logs et métriques, qui sont supprimés lorsque la tâche est terminée. »

Choisissez cette forme lorsque l’agent exécute du code non fiable, de l’automatisation de navigateur, des tests ou des installations de packages. Le compromis est un coût et un couplage fournisseur plus élevés qu’avec des workers partagés.

Le fournisseur possède le sandbox, et rien d’autre. Le harness, la session, le checkpoint et la trace restent de votre côté, généralement câblés selon la forme queue + worker de la section 2.

5. Anthropic Managed Agents (harness hébergé)

Anthropic a lancé Managed Agents en public beta le 8 avril 2026, derrière le header beta managed-agents-2026-04-01. Le service fournit une session hébergée, un harness, un sandbox et un proxy MCP adossé à un vault. wake(sessionId) peut initialiser le harness sur un nouveau worker sans perdre l’état durable de la session.

Anthropic facture Managed Agents aux tarifs standard des tokens, plus $0.08 par heure de session. La facturation est précise à la milliseconde et ne s’applique que lorsque le statut de la session est « running » ; le temps d’inactivité est gratuit. Une retry loop incontrôlée ajoute donc un coût d’heures de session au coût des tokens.

Lisez les réserves. La remise de la Batch API ne s’applique pas (« Les sessions sont stateful et interactives. Il n’existe pas de mode batch. »). Managed Agents n’est pas disponible via AWS Bedrock ni Google Vertex AI. Dans la beta, les tunnels MCP et le « dreaming » de l’agent nécessitent un accès supplémentaire en research preview ; la coordination multi-agent et l’auto-évaluation notée par rubric sont documentées comme faisant partie de la beta. Le lock-in est élevé : vous échangez la liberté du harness contre le fait de ne pas exécuter vous-même la boucle.

La configuration cloud par défaut place les cinq primitives chez Anthropic. Avec des sandboxes self-hosted, vous exploitez l’exécution, les systèmes de fichiers et l’egress réseau tandis qu’Anthropic exécute l’orchestration et le modèle. Les entrées et résultats des outils atteignent toujours son control plane ; les skills attachées et la mémoire y sont stockées et synchronisées. Posséder l’exécution ne rend pas l’ensemble du système self-hosted.

Claude Platform on AWS prend également en charge Managed Agents et les sandboxes self-hosted ; il est distinct de Bedrock. Dans cette plateforme, une session autonome a besoin d’un événement user-role pour se réauthentifier après six heures, et les sessions self-hosted ne peuvent pas attacher de memory stores. Managed Agents first-party n’a pas ces deux restrictions. Vérifiez la plateforme autant que le modèle avant de reprendre une conception de session.

6. LangChain Deep Agents Deploy (harness open managé)

deepagents deploy empaquette un deepagents.toml dans un LangSmith Deployment avec exécution durable, mémoire, multi-tenancy, human-in-the-loop, observabilité, exécution de code dans un sandbox et exécutions planifiées. Les modes de déploiement cloud, hybride et self-hosted sont pris en charge. Les fournisseurs de sandbox (LangSmith Sandboxes, Daytona, Modal, Runloop ou custom) peuvent être changés via une seule valeur de configuration. Les fichiers de l’agent et la mémoire vivent dans un filesystem virtuel doté de backends interchangeables ; la persistance des checkpoints est séparée, et la mémoire peut être limitée à l’utilisateur, à l’assistant ou aux deux. Le lock-in est inférieur à celui de Managed Agents : le harness est sous licence MIT, les instructions utilisent le standard ouvert AGENTS.md et les agents sont exposés via MCP, le protocole A2A (Agent2Agent) et Agent Protocol. Voir l’article de LangChain sur le runtime derrière les Deep Agents de production.

Les cinq primitives sont hébergées par défaut, mais chacune peut être remplacée par configuration. Le sandbox est derrière une seule valeur de configuration. Le filesystem mémoire est séparé de la persistance des threads et des checkpoints. La trace va dans LangSmith.

7. Service ou job Google Cloud Run

Cloud Run dispose de deux modes d’exécution distincts, et celui qui convient dépend de la façon dont l’agent est invoqué. Les services sont liés à HTTP et passent à zéro entre les requêtes ; le harness s’exécute comme request handler et renvoie la réponse lorsque l’exécution est terminée. Les jobs s’exécutent jusqu’à la fin sans point d’entrée HTTP ; le harness s’exécute comme worker one-shot qui se termine lorsque la tâche est achevée. Les deux peuvent héberger le harness, mais aucun ne conserve l’état entre les exécutions. Les sessions et checkpoints doivent vivre dans Postgres, Spanner ou un store externe similaire.

Les limites strictes sont très différentes. Timeout des requêtes de service Cloud Run : 300 s par défaut, maximum 3 600 s (60 min). Les WebSockets ont le même timeout. Cloud Run jobs : 10 min par défaut par tâche, maximum 168 h (7 jours) ; pour les tâches utilisant des GPUs, maximum 1 heure. La facturation basée sur l’instance (CPU toujours alloué) autorise toujours le scale-to-zero ; le nombre minimal d’instances est un paramètre distinct ; les jobs n’utilisent pas HTTP et ne font pas d’autoscaling.

Utilisez un service pour les exécutions synchrones jusqu’à 60 minutes. Utilisez un job pour un travail one-shot ou asynchrone plus long. Les Cloud Run Jobs peuvent maintenir une tâche pendant plusieurs jours, mais ne fournissent pas de replay durable entre les déploiements, les changements de version ou le remplacement du worker. Un workflow plus long peut couvrir plusieurs exécutions lorsqu’un orchestrateur externe possède la progression durable.

Cloud Run héberge le harness. L’état de session et de checkpoint vit dans Postgres, Spanner ou un autre store externe, et les traces peuvent passer par Cloud Logging et OpenTelemetry. Le container du service est un environnement d’exécution ; ajoutez un sandbox séparé lorsque l’agent exécute du code non fiable.

8. AWS Lambda : invocations bornées et workflows durables

Le timeout maximal d’une fonction Lambda est de 900 s (15 minutes), sans exception. Si API Gateway est devant la fonction, la limite d’intégration dépend du type d’API. Les HTTP APIs autorisent 30 secondes ; les intégrations REST ont par défaut 29 secondes, tandis que les API REST régionales et privées peuvent configurer un timeout plus long. Les durable functions Lambda, lancées en décembre 2025, ajoutent des checkpoints, étapes et attentes managés entre des exécutions pouvant durer jusqu’à un an. L’invocation active reste bornée, tandis que le workflow durable peut lui survivre. Comparez les runtimes pris en charge, les régions, les règles de replay et l’idempotence des activities avec vos exigences.

Lambda peut héberger un harness borné dans sa limite de 15 minutes. L’état des sessions et des checkpoints doit toujours disposer de homes externes explicites ; ajoutez un sandbox distinct pour le code non fiable et exportez les traces vers une télémétrie externe. Un workflow Lambda durable peut orchestrer un travail de plusieurs heures au travers d’invocations bornées.

9. Tâche AWS ECS / Fargate par exécution

Fargate ne documente aucune limite stricte de durée des tâches, contrairement à une invocation Lambda ordinaire. Fargate ne prend pas en charge les tâches GPU ; les workloads GPU ECS nécessitent des instances EC2 adaptées ou un service GPU externe. Fargate fournit une isolation des tâches basée sur la virtualisation, mais les credentials et l’accès réseau autorisé nécessitent toujours un threat model. Les quotas de throttling Fargate autorisent un burst de lancement de 100 et un réapprovisionnement de 20 par seconde, avec des budgets on-demand et Spot distincts. Les quotas de service ECS limitent les services utilisant AWS Cloud Map à 1 000 tâches par service et les clusters adossés à EC2 à 5 000 instances de containers.

Fargate nécessite le mode awsvpc ; chaque tâche obtient donc une interface réseau et une IP privée. Cette forme convient à l’accès aux données internes au VPC. Fargate Spot ajoute un risque d’interruption, et la durabilité reste sous votre responsabilité, car la plateforme n’offre pas de replay de type Temporal.

Fargate héberge le harness et fournit à chaque exécution sa propre tâche. Cela sépare les workspaces et les credentials de tâche, mais ne constitue pas à lui seul une frontière complète pour du code hostile. La session, le checkpoint et la trace vont vers des services externes tels que RDS ou DynamoDB, ainsi que CloudWatch/X-Ray.

Comparez également Amazon Bedrock AgentCore Runtime avant de construire vous-même la couche de session AWS. Il héberge votre code d’agent avec un cycle de vie de session managé et un choix de compute. AWS documente jusqu’à 8 heures sur des microVMs serverless, ou 14 jours sur son type de compute Instances, qui prend également en charge les workloads GPU. Instances utilise des ressources EC2 gérées par AWS dans votre compte, avec un modèle de sécurité différent de l’option serverless. Sélectionnez et testez explicitement ce contrat de compute ; une instance vivant plus longtemps ne garantit toujours pas l’exécution exactement une fois d’un effet externe.

10. Job Kubernetes ou namespace par session

Convient lorsque vous exploitez déjà Kubernetes et souhaitez un sandbox par session avec des contrôles à l’échelle du cluster. Convient moins lorsque vous avez besoin d’un démarrage inférieur à la seconde, car le téléchargement de l’image du container et l’initialisation du pod prennent trop longtemps lors d’un cold start. Le pattern consiste à créer un Job par exécution d’agent, avec activeDeadlineSeconds, un PersistentVolumeClaim pour le workspace et un sidecar pour le serveur MCP. La récupération après crash est à construire vous-même. Adopter Kubernetes uniquement pour héberger des agents coûte cher en surcharge de configuration et en charge opérationnelle. Cela ne vaut le coup que si vous exécutez déjà K8s pour d’autres raisons.

Kubernetes héberge le harness et l’environnement d’exécution par exécution, généralement sous la forme d’un Job et parfois d’un namespace dédié. Une isolation forte dépend toujours de la runtime class, de la network policy, de la pod security et de la frontière sous-jacente de container ou de VM. L’état de session et de checkpoint vit dans une base externe ou sur un PersistentVolumeClaim.

11. Docker Compose local (développement uniquement)

La référence pour la section suivante. L’intérêt de cette forme est qu’elle reproduit la topologie de production un pour un — mêmes primitives, même forme réseau — tout en s’exécutant sur une seule machine. Ce qu’elle ne reproduit pas, c’est l’isolation : un mount de workspace partagé, un Postgres, aucun sandbox renforcé et aucune failure domain distincte entre le worker et son état. Ne mettez rien en production sous cette forme.

Compose reproduit la forme n° 2 sur un seul hôte. Dans la stack de référence, Postgres contient l’état des checkpoints et le container worker est le harness. Une session de forme production nécessite son propre event store en ajout uniquement ; l’historique PostgresSaver ne suffit pas à en fournir un. Le mount de workspace partagé est pratique en développement, mais n’isole pas les exécutions non fiables. La stack OpenTelemetry optionnelle enregistre les traces.


Stack de référence : Docker Compose

La topologie de référence, utilisée dans slavadubrov/market-analyst-agent, est composée d’un worker LangGraph, d’un checkpointer Postgres, de Qdrant pour la retrieval, d’un sidecar MCP, d’une queue Redis pour les exécutions asynchrones de type production et d’une stack d’observabilité optionnelle Prometheus / Grafana / Loki / Tempo / OTel. Dans le compose local, Redis est optionnel uniquement parce que le runner synchrone peut appeler directement le worker. docker compose up démarre localement la topologie principale ; le sidecar MCP et la stack d’observabilité sont des profils opt-in (--profile mcp, --profile observability).

La topologie Docker Compose de référenceLa topologie Docker Compose de référence

Le diagramme montre le PostgresSaver de la démo locale. Une session de forme production ajoute un schéma d’événements écrit séparément pour les intentions et résultats des tool calls ; PostgresSaver reste uniquement l’état des checkpoints.

La seule partie qui mérite d’être montrée inline est le câblage LangGraph canonique. Il s’agit d’un extrait illustratif, et non d’un exemple exécutable depuis le repository. Pour l’exécuter, il faut langgraph, langgraph-checkpoint-postgres et psycopg[binary,pool], une base PostgreSQL accessible avec le droit de créer les tables du checkpointer, POSTGRES_PASSWORD et un StateGraph déjà construit dans builder ; voir la configuration du checkpointer Postgres de LangGraph.

import os
from urllib.parse import quote

from langgraph.checkpoint.postgres import PostgresSaver

password = quote(os.environ["POSTGRES_PASSWORD"], safe="")
DB_URI = f"postgresql://agent:{password}@postgres:5432/agent"
# `builder` is your StateGraph, already built
session_id = "session-123"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
    checkpointer.setup()  # creates tables on first run
    graph = builder.compile(checkpointer=checkpointer)
    result = graph.invoke(
        {"messages": [{"role": "user", "content": "Continue the task"}]},
        {"configurable": {"thread_id": session_id}},
    )

Une observabilité qui survit à l’exécution

Les request handlers courts sont faciles à debugger : lorsqu’un problème survient, vous lisez la réponse et le log en direct. Les agents longue durée n’ont pas ce luxe. Lorsqu’une exécution de six heures échoue, l’événement intéressant s’est produit cinq heures plus tôt, la sortie du terminal en direct a disparu et le worker qui l’a produite a été remplacé. Personne ne va reconstituer l’exécution de mémoire. Vous débuggez donc à partir d’artefacts durables écrits pendant que l’exécution était encore active.

Les stacks de production couvrent généralement quatre types d’artefacts, répartis en deux groupes. Deux sont consultés après l’exécution, pour les postmortems et le replay : un event log interrogeable de chaque étape et les traces OpenTelemetry indiquant où sont partis le temps et les tokens. Deux sont consultés pendant l’exécution. L’un est un live tail de ce que l’agent produit dans le workspace. L’autre est une stack d’observabilité par worktree que l’agent peut interroger lui-même pendant qu’il travaille.

Event log structuré (à lire après l’exécution)

Chaque appel au modèle, tool call, résultat, erreur et approbation est écrit dans un stockage durable, indexé par ID de session et timestamp. Une fois l’exécution terminée, vous l’interrogez comme une table de base de données ordinaire. Addy Osmani fixe clairement le niveau attendu dans Long-running Agents : « Si vous ne pouvez pas reconstituer ce que l’agent a fait au cours des dernières 24 heures depuis un stockage durable, vous avez un long-running shell script qui appelle par hasard un LLM, pas un agent longue durée. »

Traces OpenTelemetry GenAI (à lire après l’exécution)

Les mêmes données étape par étape sont émises sous forme de spans à l’aide des attributs standard des gen_ai.* conventions sémantiques : nom du modèle, fournisseur, nombre de tokens en entrée et en sortie, ID de conversation et nom du workflow. La stabilité des conventions est encore au niveau Development.

En 2026, elles ont quitté le repository principal des conventions sémantiques OpenTelemetry pour rejoindre leur propre repository de conventions sémantiques GenAI. Les noms d’attributs peuvent servir à instrumenter votre système, mais épinglez la révision que vous avez validée plutôt qu’un numéro de version du dépôt principal. Les champs propres aux fournisseurs vivent dans des sous-namespaces (anthropic.*, openai.*) indexés par gen_ai.provider.name. L’intérêt du standard est la portabilité : sur des destinations compatibles OTLP qui prennent en charge ces conventions, changer de backend peut ne pas nécessiter de réinstrumenter le code, même si des adaptateurs backend ou une configuration propre à la destination peuvent rester nécessaires.

Chronologie des tool calls et diffs du workspace (à lire pendant l’exécution)

Le moyen le plus rapide de savoir ce que fait un agent à l’instant présent est de suivre ce qu’il produit dans le workspace, et non de chercher dans un log de session. Le Harness Primitives for Long-Running Claude Agents d’Anthropic fournit un quick-start avec une boucle de monitoring en deux panneaux : watch -n 5 'git log --oneline -8' affiche les derniers commits effectués par l’agent et watch -n 5 'find screenshots -name "*.png" | tail -5' affiche les derniers screenshots qu’il a pris. Deux panneaux de terminal actualisés toutes les cinq secondes suffisent à déterminer si une exécution progresse réellement ou tourne en rond.

Stack éphémère par worktree (lue par l’agent lui-même pendant l’exécution)

Selon l’article d’OpenAI sur le harness : « Les logs, métriques et traces sont exposés à Codex via une stack d’observabilité locale, éphémère pour chaque worktree. » Chaque worktree d’agent reçoit ses propres Loki + Prometheus + Tempo de courte durée, limités à cette exécution. L’agent les interroge pendant son travail. C’est ce qui permet à un prompt tel que « aucun span de ces quatre parcours utilisateur ne dépasse deux secondes » de devenir quelque chose que l’agent peut vérifier directement, plutôt qu’une simple supposition.

(L’evaluator en fresh context du tableau des modes d’échec lit ces artefacts pour décider si le travail est « done ». Il relève de l’évaluation, pas de l’observabilité ; voir la section sur le cycle de vie sain d’une exécution. Il dépend de toutes les surfaces ci-dessus.)

Une stack d’observabilité self-hosted minimale

Pour quelque chose comme market-analyst-agent :

  1. OpenTelemetry Collector avec le GenAI Normalizer Processor (contrib, alpha) pour les attributs GenAI pris en charge. Utilisez les processors génériques Attributes ou Transform pour filtrer ou réécrire les champs gen_ai.*.
  2. Tempo (ou Jaeger) pour les traces, indexées par gen_ai.conversation.id / thread_id.
  3. Loki pour les entrées de l’event log structuré.
  4. Prometheus pour gen_ai.client.token.usage, gen_ai.client.operation.duration et gen_ai.client.operation.time_to_first_chunk — les métriques gen_ai.server.* proviennent du model server ; vous ne les obtenez donc que si vous hébergez les weights (voir les conventions de métriques GenAI).
  5. Grafana pour les dashboards indexés par gen_ai.agent.name et gen_ai.request.model.

Alternatives hébergées (choisissez-en une, pas trois) :

  • LangSmith : intégration LangGraph native ; également cible de déploiement pour Deep Agents Deploy.
  • Braintrust : meilleur choix si les suites de régression eval-first sont prioritaires.
  • Arize Phoenix : OSS, natif OTLP (le protocole filaire OpenTelemetry), associé à l’instrumentation OpenInference.
  • Dashboard de tracing d’OpenAI : automatique lorsque vous utilisez l’OpenAI Agents SDK ou son intégration Temporal.
  • Tracing Claude d’Anthropic : pour les sessions exécutées dans Managed Agents.

Instrumenter le nœud LangGraph

Il s’agit d’un extrait illustratif, ignoré par le runner d’exemples du repository. Il suppose que le nœud LangGraph dispose déjà d’un span OpenTelemetry actif, du thread_id courant et d’un objet de réponse fournisseur usage avec input_tokens et output_tokens ; la configuration du tracer, de l’export et du mapping de l’usage propre au fournisseur sort du périmètre de l’extrait.

# In the LangGraph node, around the model call:
span.set_attribute("gen_ai.operation.name", "chat")
span.set_attribute("gen_ai.provider.name", "anthropic")
span.set_attribute("gen_ai.request.model", "<your-model-id>")
span.set_attribute("gen_ai.response.model", "<your-model-id>")
span.set_attribute("gen_ai.conversation.id", thread_id)
span.set_attribute("gen_ai.agent.name", "market-analyst")
span.set_attribute("gen_ai.workflow.name", "research_then_write")
span.set_attribute("gen_ai.usage.input_tokens", usage.input_tokens)
span.set_attribute("gen_ai.usage.output_tokens", usage.output_tokens)

Noms d’attributs repris tels quels du registre des conventions sémantiques GenAI d’OpenTelemetry.

Trois requêtes utiles à avoir dans un dashboard

# Loki: output tokens per agent in the last hour (one completion event per call)
sum by (gen_ai_agent_name) (
    sum_over_time({service_name="market-analyst-agent"} | json | event = "model_call_completed" | unwrap gen_ai_usage_output_tokens | __error__="" [1h])
)
# PromQL: p95 model latency per model
histogram_quantile(0.95,
    sum by (le, gen_ai_request_model) (
        rate(gen_ai_client_operation_duration_bucket[5m])
    )
)
# TraceQL: long-running tool calls
{ span.gen_ai.operation.name = "execute_tool" && duration > 30s }

L’agrégation LogQL suppose exactement un événement de completion enregistré par appel au modèle. Dédupliquez ces événements avant l’ingestion ; rate renverrait le nombre de tokens par seconde plutôt que ce total d’une heure. Validez le mapping des champs par rapport à votre stream Loki déployé.

Pattern du debug bundle

Lorsqu’une exécution échoue, le worker devrait déposer un /workspaces/${THREAD_ID}/_debug/ contenant les artefacts demandés lors d’un postmortem :

  • events.jsonl : export depuis l’event store en ajout uniquement écrit séparément par le harness, incluant les intentions d’outils, les résultats, les approbations et les erreurs.
  • checkpoints.jsonl : historique de l’état du graphe depuis checkpointer.list({"configurable": {"thread_id": ...}}), étiqueté comme checkpoints et non comme event log.
  • last_state.json : StateSnapshot.values du dernier super-step réussi.
  • trace.json : spans exportés en OTLP pour l’exécution ; les métadonnées sont la base, et tout contenu capturé suit la trace policy.
  • tool_calls.csv : (ts, tool, input_hash, latency_ms, status, error).
  • workspace.tar.zst : le répertoire du workspace et git diff par rapport au commit initializer.
  • screenshots/*.png : ce que l’agent a vu.
  • PROGRESS.md, feature-list.json et tout autre fichier de progression écrit par l’agent.
  • env.txt : tags d’image, version du modèle et SHA du commit du harness.

Ensemble, ces artefacts peuvent fournir à un humain ou à un reviewer agent suffisamment d’éléments pour reconstituer l’échec, à condition que le harness ait écrit l’event store pendant que l’exécution était active. « L’agent est resté bloqué » est vague. Un rapport illustratif est concret : la session s_123 a consacré 71 % de ses tokens à répéter trois commandes après l’échec de npm install.


Choisir la bonne forme : guide de décision

La plupart de la comparaison précédente se résume à quelques décisions.

Commencer par la durée d’exécution

Utilisez la durée d’exécution comme premier filtre :

  • Moins de 30 secondes, idempotent : SDK lié au cycle de vie de la requête dans un app server.
  • De 30 s à 60 min : queue + worker + checkpoint DB.
  • De 60 min à 24 h : même queue + worker, ou Cloud Run Job pour un travail one-shot. Utilisez un moteur de workflow durable si vous avez également besoin de versioning et de replay.
  • Plus de 24 h, avec obligation de survivre aux déploiements : moteur de workflow durable (style Temporal). Les Cloud Run Jobs peuvent maintenir un travail long jusqu’à leur limite de tâche, mais ne fournissent pas de sémantique de replay.
  • Boucles d’entraînement de reinforcement learning sur plusieurs jours : K8s Job + volume + Temporal.

Après ce filtre grossier, vérifiez les effets externes, la récupération, le replay, l’isolation, l’emplacement des données et l’équipe qui exploitera le système.

Adéquation de la plateforme par cas d’usage

Adéquation de la plateforme par cas d’usageAdéquation de la plateforme par cas d’usage

La matrice est dense, et aucune cellule verte ne décide à elle seule de l’architecture ; ce sont généralement les cellules conditionnelles — lorsqu’une plateforme ne prend en charge quelque chose qu’avec une réserve — qui tranchent. Une couverture large des workloads est utile, mais elle ne montre ni la résidence des données, ni la sémantique de replay, ni la dépendance au fournisseur, ni la maturité opérationnelle, ni le coût d’un déplacement ultérieur de l’état.

Les cellules conditionnelles suivent la même règle pour chaque plateforme. Les options AWS/VPC et GPU de Deep Agents dépendent d’un déploiement hybride ou d’un fournisseur de sandbox ; Managed Agents peut utiliser une exécution opérée par le client tout en conservant une orchestration hébergée. La ligne consacrée au choix du sandbox inclut une intégration avec un fournisseur externe que vous construisez sur un runtime que vous possédez ou que vous configurez dans un harness managé. Elle ne promet pas un snapshot de l’état en cours d’exécution. Un Kubernetes Job nécessite également une couche API ou une queue pour une requête interactive ; se terminer rapidement n’en fait pas un service HTTP. Comparez l’accès réseau, le hardware, la récupération et le chemin d’export de l’état du déploiement sélectionné avant de le choisir. La ligne relative au code du harness concerne l’accès à l’implémentation de la boucle, pas la portabilité d’un déploiement managé ni de son état. L’exécution GPU sur Kubernetes nécessite aussi des nœuds GPU, des drivers et un device plugin.

Managed Agents nécessite Claude et une orchestration opérée par Anthropic. Son sandbox self-hosted optionnel peut convenir à une exécution sur réseau privé, mais une exigence de self-hosting de l’inférence ou du control plane l’exclut toujours. Vérifiez quelles entrées d’outils, quels résultats, skills et éléments de mémoire peuvent franchir cette frontière. Un travail de coding interne peut convenir lorsque ces flux de données sont acceptables et que l’équipe souhaite déléguer l’exploitation du harness.

La tarification mérite d’être modélisée avant l’engagement, pas après. La ligne d’heure de session est de $0.08/heure, en plus du coût standard des tokens. Si une session unique fonctionnait en continu, cela représenterait environ $58/mois par session. Pour 100 sessions fonctionnant en continu, cela représente environ $5 800/mois avant les tokens. Multipliez $0.08 par le nombre d’heures de sessions concurrentes prévu, ajoutez ce montant à votre facture de tokens et comparez-le au coût d’une stack queue + worker sur votre propre infrastructure. Migrer plus tard depuis Managed Agents est un exercice de re-platforming, pas un changement de configuration.

Harness hébergé ou harness possédé

La distinction porte ici sur la personne qui exploite le harness, et non sur celle qui a écrit son code. Hébergé signifie que le fournisseur exécute la boucle du harness sur son infrastructure et que vous appelez une API. Possédé signifie que vous exécutez la boucle sur votre propre infrastructure, même si le code du harness provient d’un fournisseur.

LangChain apparaît des deux côtés de cette distinction, ce qui prête à confusion. Ils fournissent LangGraph, une librairie sous licence MIT que vous self-hostez (possédée), et Deep Agents Deploy, un produit managé qui exécute un harness Deep Agents sur LangSmith Deployment dans son mode cloud par défaut (hébergé). Même entreprise, deux modèles opérationnels distincts. Ce que vous choisissez, c’est qui exécute la boucle, et non le logo affiché sur la librairie. (Deep Agents Deploy propose également un mode self-hosted pour les équipes qui souhaitent l’ergonomie du harness sans le composant cloud ; ce mode appartient à la catégorie possédée.)

Choisissez un harness hébergé lorsque sa prise en charge des modèles, sa frontière de données, son comportement de récupération et ses points d’extension correspondent déjà à vos besoins. Choisissez un harness possédé lorsque ces contraintes sont des exigences susceptibles d’évoluer. Migrer entre les deux modifie l’état, l’observabilité et les frontières d’exécution ; testez donc le chemin de sortie avant que des données de production n’en dépendent.

Sandbox hébergé ou environnement d’exécution possédé

Choisissez un sandbox hébergé lorsque les propriétés d’isolation, de pause/reprise ou de fork du fournisseur correspondent au threat model et au budget de démarrage. Docker ou Fargate peuvent convenir à des workloads internes de confiance qui nécessitent un accès VPC ou une stricte résidence des données, mais un container standard ne constitue pas une frontière suffisante pour du code hostile. La partie 4 présente le menu d’isolation adapté à ce cas.

Stores d’état : Git, DB et object storage côte à côte

Les agents longue durée utilisent généralement trois stores d’état simultanément, car chacun possède un artefact différent.

Git stocke l’état du workspace : le code, les documents et les fichiers de progression modifiés par l’agent. Chaque commit donne au harness un point de récupération stable et à la session suivante un historique compact.

La base de données des checkpoints stocke l’état du graphe : ce qui a été décidé, les nœuds exécutés, les résultats renvoyés et ce qui doit s’exécuter ensuite. L’artefact store contient les sorties finales volumineuses telles que les PDF, fichiers Parquet et screenshots. Ces artefacts n’ont pas leur place dans Git ou dans la base de données des checkpoints.

Quand utiliser git comme état

Utilisez git lorsque le workload a la forme de code — modifications multi-fichiers, refactorings, génération d’application — ou qu’il est suffisamment orienté documents pour que l’historique des fichiers ait de la valeur. Le pattern est simple : créer une branche d’exécution, effectuer un commit initializer, puis committer aux frontières significatives : après le setup, après chaque feature, après le passage des tests et après le nettoyage final. Stockez le dernier SHA du commit du workspace à côté de la ligne du checkpoint. Lors de la reprise, le worker suivant checkout la branche, lit git log --oneline -8, inspecte git status et le dernier diff, puis lit PROGRESS.md ou le fichier de handoff écrit par la session précédente.

Git devient ainsi une surface de récupération pour l’artefact en cours de modification, et non un remplacement de la checkpoint DB. Git peut répondre à deux questions : qu’est-ce qui a changé et quelle version a passé les tests ? Il ne peut pas indiquer au harness quel nœud du graphe doit s’exécuter ensuite, quel tool call attend une approbation ni quel retry a déjà utilisé sa clé d’idempotence. Le harness d’Anthropic utilise des commits initializer et des commits par feature comme source de vérité pour la récupération du workspace ; le modèle lit git log --oneline -8 pour récupérer l’état. Ignorez git lorsque le produit est une réponse conversationnelle unique. La surcharge n’est alors pas rentable.

Quand utiliser le checkpointing en DB

Utilisez un checkpointing de type PostgresSaver lorsque l’agent possède une structure de graphe comportant plusieurs nœuds dont l’état intermédiaire est important (planner → researcher → writer → verifier). Le repository de référence l’utilise précisément pour cette raison. Ne placez pas des artefacts de workspace à l’échelle du téraoctet dans le checkpoint ; ils doivent aller dans l’object storage.

Quand utiliser un artifact store (S3 / GCS)

Utilisez l’object storage lorsque :

  • la sortie est trop volumineuse pour être transportée par la base de données des checkpoints ;
  • les consommateurs en aval ont besoin d’un artefact adressable par URL sans passer par l’agent ; ou
  • le livrable et l’état de l’exécution ont des fenêtres de rétention différentes.

Vous pouvez, par exemple, supprimer le log de session après 30 jours tout en conservant le rapport final pendant plusieurs années. Structurez les clés selon (thread_id, checkpoint_id, artifact_name) afin que l’exécution productrice reste reconstituable.

Quand demander une approbation humaine

Définissez les exigences d’approbation selon le risque de l’action, l’autorité déjà accordée et la policy de déploiement. Une écriture réversible dans une base de données de brouillons diffère d’une facturation client ou d’une modification destructive en production. Lorsqu’une approbation est nécessaire, affichez l’action réelle, ses arguments et sa destination, persistez la décision et revérifiez-la si le call proposé change ; n’exécutez pas un call rejeté. Le interrupt() de LangGraph et le middleware d’approbation de Deep Agents peuvent mettre l’exécution en pause pour cette décision. La partie 4 explique pourquoi il s’agit d’une décision de permission, et non d’une instruction de prompt.


Checklist pratique de production

Avant de mettre en production un agent longue durée, répondez concrètement aux questions suivantes en termes d’infrastructure.

  1. Quel store possède les événements de session et les checkpoints ?
  2. Que se passe-t-il si le worker meurt au milieu d’un tool call ?
  3. Une exécution peut-elle corrompre le workspace d’une autre ?
  4. Quelles actions nécessitent une approbation ?
  5. Le modèle ou le sandbox peut-il lire des credentials bruts ?
  6. Quels tool calls peuvent être retentés sans risque ?
  7. Où la limite de coût par exécution est-elle appliquée ?
  8. Quels éléments probants déterministes décident de la fin, et quels critères restants nécessitent un reviewer ?
  9. Où les sorties finales vivent-elles une fois le sandbox supprimé ?
  10. Pourrons-nous expliquer demain une exécution échouée sans la relancer ?

Si la réponse à l’une de ces questions est « le prompt dit à l’agent de faire attention », le système n’est pas encore déployé. C’est toujours une démo.

La couche suivante est la boucle du harness

Ce runtime peut maintenir une exécution active et récupérable, mais la durabilité ne prouve pas que le travail est correct. La partie 6, Harness Engineering for AI Agents, ouvre la primitive harness du tableau ci-dessus : comment une trace vous indique lequel de plusieurs échecs vous avez réellement, où vivent les règles de retry et d’arrêt, ce qu’un handoff doit préserver et comment un contrôle d’acceptation externe décide qu’une exécution est terminée. C’est également le dernier article de la série.

Références

Articles d’ingénierie

LangGraph et Deep Agents

OpenAI Agents SDK

Temporal

Plateforme Anthropic

Fournisseurs de sandbox

Timeouts et quotas des plateformes cloud

Observabilité


Le code de l’agent Market Analyst (worker LangGraph, checkpointer Postgres, mémoire Qdrant, sidecar MCP et topologie Docker Compose décrite ci-dessus) se trouve sur GitHub.