Aller au contenu principal
50 % de réduction toutes les offres, durée limitée. À partir de $2.48/mo
18 min left
IA et machine learning

6 modes de défaillance des boucles d'agents IA qui cassent les systèmes en production

S Par Sajjad 18 min de lecture
Production monitoring dashboard showing an AI agent loop with six failure mode warnings: Infinite Loop, Silent Tool Failure, Reasoning Drift, State Loss, Retry Storm, and a Circuit Breaker labeled OPEN.

La boucle a tourné proprement quarante fois en test. Au quarante et unième lancement, en production, elle a appelé le même outil SQL avec la même requête cassée encore et encore, jusqu'à épuiser le budget API de la journée, et c'est une alerte de facturation qui a finalement réveillé quelqu'un. Personne n'a écrit un mauvais modèle. Personne n'a changé le prompt. L'agent n'a tout simplement jamais décidé qu'il avait terminé.

C'est le schéma que j'observe régulièrement chez les équipes qui font passer un agent d'un prototype à une charge de travail 24/7. Les boucles d'agents IA échouent souvent en production non pas parce que le modèle s'est soudainement dégradé, mais parce que la couche d'exécution manque de discipline de terminaison, de contrats d'outils validés, d'un contexte borné et d'un état durable. Une boucle d'agent est un système stochastique qui prend des décisions séquentielles les unes après les autres. Sans quelques garde-fous spécifiques, la défaillance rare devient garantie dès qu'on la fait tourner suffisamment longtemps. Les plateformes d'agents gérés (Vertex AI Agent Builder, Bedrock Agents, Azure AI Foundry) intègrent certains de ces garde-fous ; ce guide s'adresse à ceux qui ont choisi l'auto-hébergement et qui gèrent leur propre boucle.

Les enjeux sont suffisamment réels pour que Gartner prévoie que plus de 40 % des projets d'IA agentique seront annulés d'ici fin 2027, invoquant des coûts croissants et une valeur incertaine. Voici six façons précises dont les boucles cassent en production, le mécanisme derrière chacune, et le pattern harness qui le corrige, avec les détails LangGraph et n8n ainsi que ce qu'il faut pour faire tourner ça 24/7.

La version courte

  • Boucles infinies : L'agent ne décide jamais qu'il a terminé. Combinez un plafond d'étapes strict (le recursion_limitde LangGraph, 25 par défaut) avec une détection d'absence de progression qui interrompt les appels répétés outil+argument.
  • Débordement de contexte : La boucle remplit sa propre fenêtre de contexte avec l'historique accumulé jusqu'à ce que les appels soient tronqués ou échouent. Résumez l'historique à intervalles fixes pour que le contexte actif reste borné.
  • Échecs silencieux d'outils : Un outil retourne une chaîne vide, le modèle l'interprète comme un no-op valide, et l'agent « réussit » en ne faisant rien. Validez chaque résultat d'outil avant que le modèle ne le voie.
  • Dégradation du raisonnement : La qualité se dégrade à mesure que le contexte grossit, même en dessous de la limite stricte. Compressez en milieu de boucle, mais protégez les instructions de sécurité épinglées quand vous le faites.
  • Perte d'état au redémarrage : Un crash signifie repartir de zéro. Faites des checkpoints vers Postgres (LangGraph PostgresSaver), pas SQLite, pour la production.
  • Tempêtes de nouvelles tentatives : Dix agents qui font chacun dix tentatives envoient cent requêtes vers un service en panne. Ajoutez un backoff exponentiel avec jitter et un circuit breaker global.

Ce que ce guide ne couvre pas

Ce guide porte sur le harness, c'est-à-dire l'ingénierie autour de la boucle, pas le modèle à l'intérieur. Quelques sujets connexes sont délibérément hors périmètre :

  • Défaillances de coordination multi-agents (lectures périmées, état orphelin entre agents) : un problème différent qui mérite son propre article.
  • Sécurité des agents (injection de prompt, empoisonnement d'outils) : une catégorie de défaillance distincte avec son propre modèle de menace.
  • Sélection et fine-tuning de modèles. Ce guide suppose que vous avez choisi un modèle et que vous déboguez le système autour de lui.
  • Services d'agents gérés, mentionnés ci-dessus ; les patterns ici s'appliquent au chemin auto-hébergé.

Boucles infinies : quand l'agent ne décide jamais qu'il a terminé

Diagram of an AI agent loop with guardrails: a Step Ceiling cost backstop and a Repeat Hash Check for no-progress detection, with a Circuit Breaker labeled No-Progress Detection at the bottom.

Un agent boucle indéfiniment quand il n'a ni plafond d'étapes strict ni moyen de détecter qu'il a cessé de progresser. Le correctif se compose de deux parties : conserver un plafond strict comme filet de sécurité budgétaire, et ajouter une détection d'absence de progression qui hache chaque appel outil+argument et se termine quand elle détecte le même appel qui se répète. Dans LangGraph, ce plafond est le recursion_limit(25 étapes par défaut) ; le dépasser fait lever une exception au graphe, et la GraphRecursionError.

documentation de LangGraph décrit cette limite comme l'atteinte du "nombre maximum d'étapes avant de toucher une condition d'arrêt". Voici le piège à comprendre : la recursion limit n'est pas une protection contre les boucles. C'est un filet de sécurité qui se déclenche après une fois que la boucle a déjà gaspillé vingt-cinq étapes et les coûts API qui vont avec. La logique de terminaison apprise par l'agent lui-même est censée l'arrêter bien avant cela, et cette logique peut échouer indépendamment. Un cas LangGraph signalé montre un agent text-to-SQL qui boucle jusqu'à atteindre la recursion limit malgré des conditions d'arrêt claires dans le prompt. Il continuait d'appeler le même outil de requête avec le même SQL défaillant, et le problème a été fermé comme "non planifié". J'y lis un signal clair : ne traitez pas le plafond comme votre condition d'arrêt. C'est votre ceinture de sécurité, pas vos freins.

Augmenter le plafond est simple ; vous le passez via la config quand vous invoquez le graphe :

# The hard ceiling -- a backstop, not loop protection
graph.invoke(
    {"messages": [("user", "Generate the quarterly report")]},
    {"recursion_limit": 50},
)

Ce qui arrête réellement une boucle bloquée, c'est la détection de progression. Le mécanisme est simple : hachez le nom de l'outil plus ses arguments à chaque étape, maintenez une fenêtre courte des hachages récents, et arrêtez quand vous en voyez un qui se répète.

import hashlib

def step_signature(tool_name: str, tool_args: dict) -> str:
    payload = f"{tool_name}:{sorted(tool_args.items())}"
    return hashlib.sha256(payload.encode()).hexdigest()

# Inside your loop: terminate if the same tool+args repeats within the window
seen = recent_signatures[-WINDOW:]
sig = step_signature(tool_name, tool_args)
if sig in seen:
    raise StopReason("no_progress: repeated tool call detected")
recent_signatures.append(sig)

Cela détecte l'agent qui est techniquement "en cours d'exécution" (appel d'outils, génération de tokens) mais qui tourne en boucle sur la même action échouée. Le mode de défaillance nommé ici correspond à ce que la taxonomie MAST (IBM Research et UC Berkeley) appelle Unaware of Termination Conditions (FM-1.5), l'un des modes de défaillance que leur analyse associe à l'échec pur et simple de la tâche.

Un plafond d'étapes stoppe les coûts incontrôlés. La détection d'absence de progression stoppe la boucle qui « avance » techniquement mais se répète. La production a besoin des deux.

Débordement de fenêtre de contexte : quand la boucle remplit son propre contexte de déchets

Une boucle longue accumule chaque sortie d'outil, chaque pensée intermédiaire et chaque message qu'elle a produit, puis les réinjecte tous dans la fenêtre de contexte à chaque tour. La fenêtre finit par se remplir, et les appels sont soit tronqués silencieusement, soit échouent complètement. Le correctif est la résumé de contexte à intervalles fixes : toutes les N étapes, compressez l'historique accumulé en un résumé courant pour que le contexte actif reste borné.

Imaginez un agent de recherche qui tourne depuis une heure. À l'étape 60, il transporte le texte intégral de chaque page qu'il a récupérée, chaque résultat de recherche, chaque trace de raisonnement. Rien de cet historique brut ne l'aide à l'étape 61, pourtant tout cela compte dans la fenêtre, et le modèle consomme du budget d'attention sur des tokens dont il n'a plus besoin. Quand la fenêtre se remplit, le fournisseur tronque d'un côté, et l'agent perd silencieusement l'instruction qu'on lui avait donnée au départ.

Le déclencheur est une décision de réglage, et il existe un point de référence utile. Le compte-rendu de Mem0 sur un système de production réel note que le compresseur de l'agent Hermes "se déclenche à 50 % de la fenêtre de contexte du modèle par défaut", avec un filet de sécurité secondaire à 85 % pour les sessions qui explosent entre les tours. Cinquante pour cent est un point de départ raisonnable : compressez suffisamment tôt pour qu'une seule sortie d'outil volumineuse ne puisse pas dépasser la limite avant la prochaine compression planifiée.

Remarque : L'overflow et la dégradation du raisonnement sont deux problèmes distincts, et la section suivante traite du second. L'overflow est une limite stricte : vous êtes à court de tokens. La dégradation, elle, est progressive : le modèle perd en qualité. avant d'atteindre le mur. Vous devez gérer les deux, et le seuil de déclenchement ci-dessus protège contre le mur dur.

Un contexte borné est une responsabilité du harness, pas une fonctionnalité du modèle. Résumez à intervalles avant que la fenêtre ne force une troncature silencieuse.

Échecs silencieux d'appels d'outils : quand l'agent « réussit » sans rien faire

Un appel d'outil retourne une chaîne vide ou un message doux "aucun résultat trouvé", le modèle l'interprète comme un résultat valide, et l'agent continue comme si l'étape avait fonctionné, semblant réussir tout en ne faisant absolument rien. Le correctif est une porte de validation sur chaque retour d'outil : vérifiez le schéma ou la cohérence de la sortie avant que le modèle ne la voie, et exposez un vrai échec que la boucle doit gérer plutôt qu'un succès vide.

Celui-là est insidieux parce que rien ne plante. Un développeur décrivant des modes d'échec silencieux dans les agents de production l'a dit directement : les modèles interprètent les chaînes vides génériques comme des no-ops valides et continuent à s'exécuter sans être conscients de l'échec. La requête de base de données qui a retourné zéro lignes parce que la connexion a coupé est identique, pour le modèle, à la requête qui n'a légitimement rien trouvé. L'agent rapporte donc "aucun enregistrement correspondant" et passe à la suite, et vous découvrez une semaine plus tard qu'un tiers de ses exécutions étaient silencieusement cassées.

La porte de validation se place entre l'outil et le modèle :

def gate_tool_result(tool_name: str, result):
    # Reject empties and soft errors before the model can rationalize them
    if result is None or (isinstance(result, str) and not result.strip()):
        raise ToolFailure(f"{tool_name} returned empty -- treat as failure, not no-op")
    if isinstance(result, str) and result.lower().startswith(("error", "exception")):
        raise ToolFailure(f"{tool_name} returned a soft error: {result[:120]}")
    return result  # validated -- safe to hand back to the model

L'enjeu n'est pas les vérifications exactes ; les vôtres dépendront de ce que chaque outil retourne légitimement. L'enjeu est qu'une valeur de retour non validée est une décision que vous avez confiée à un modèle stochastique, et le comportement par défaut du modèle est de continuer.

Un retour d'outil non validé est un échec silencieux en attente de se produire. Validez la sortie, ne faites pas confiance à l'appel.

Dégradation du raisonnement sur de longs contextes : quand l'agent se dégrade au fil du temps

Flowchart showing how messy accumulated history (tool outputs, old messages, logs, search results) causes context overflow and declining reasoning quality, then passes through a Compression Gate that filters noise, summarizes, and preserves pinned constraints (System Rules, Safety Instructions, Active Task Spec) to produce a clean bounded context.

Même quand vous restez sous la limite stricte de contexte, la qualité du raisonnement se dégrade à mesure que le contexte grossit. C'est l'effet "lost in the middle", où le modèle prête attention de façon fiable au début et à la fin d'un long contexte mais perd le milieu. Le correctif est une compression en milieu de boucle qui préserve les contraintes épinglées : compressez le bruit, protégez les instructions porteuses.

Le mécanisme a un nom. Le blog d'ingénierie d'Anthropic y fait référence sous le terme context rot: (pourriture de contexte) : "à mesure que le nombre de tokens dans la fenêtre de contexte augmente, la capacité du modèle à rappeler avec précision des informations de ce contexte diminue". Parce que "chaque token est attentif à chaque autre token", on obtient n² relations par paires pour n tokens, et l'attention du modèle s'étire d'autant plus finement que le contexte s'allonge.

Ce qualificatif, protéger les instructions porteuses, est tout l'enjeu, et il existe un incident documenté qui montre pourquoi. Dans un cas signalé, un agent OpenClaw a supprimé en masse la boîte de réception d'un utilisateur lors d'une compaction de contexte, parce que l'instruction de sécurité qui lui avait été donnée ("ne prends aucune action avant que je te le dise") a été retirée du contexte actif quand l'historique a été compressé. La contrainte qui aurait dû être la dernière à disparaître a été traitée comme un historique ordinaire et résumée.

Donc un naïf "résume tout ce qui est plus ancien que N tours" est dangereux. La compression doit savoir ce qu'elle ne doit jamais supprimer :

PINNED = {"system_constraints", "safety_instructions", "active_task_spec"}

def compress_history(messages):
    pinned = [m for m in messages if m.tag in PINNED]      # never summarized
    transient = [m for m in messages if m.tag not in PINNED]
    summary = summarize(transient)                          # lossy is fine here
    return pinned + [summary]                               # constraints survive intact

Cela est distinct du problème de débordement de la section précédente. Le débordement concerne le manque de place ; la dégradation concerne le modèle qui se dégrade alors qu'il reste encore de la place. Vous pouvez être à 60 % de votre fenêtre et raisonner déjà mal.

Remarque : Une compression qui supprime une contrainte de sécurité est une classe de bug différente d'une compression qui perd un résultat de recherche périmé. Étiquetez les contraintes, la spécification de tâche et toute instruction "ne faites pas X" comme épinglées, et excluez-les entièrement du résumeur.

Une compression qui supprime une instruction de sécurité est pire qu'aucune compression. Protégez les contraintes épinglées quand vous compressez.

Perte d'état au redémarrage : quand un crash signifie repartir de zéro

Architecture diagram showing three agents connected to a Reliability Layer with Postgres Checkpoints, Redis Shared State, and a Global Circuit Breaker. On restart, agents rehydrate from the Last Saved Step rather than starting over.

Quand un agent de longue durée plante, que ce soit à cause d'un redémarrage, d'un kill OOM ou d'une connexion réseau coupée, il n'y a pas de reprise depuis un checkpoint par défaut. La boucle repart de zéro : elle refait le travail déjà terminé et, pire, peut ré-exécuter des actions déjà effectuées, comme envoyer le même email deux fois ou relancer un appel API payant. Le correctif est le checkpointing : persistez l'état de la boucle après chaque étape pour qu'un redémarrage se réhydrate depuis là où elle s'était arrêtée plutôt que depuis le début.

Dans LangGraph, le choix du backend de checkpoint est le choix entre développement et production. La documentation de persistence de LangGraph décrit SqliteSaver comme "idéal pour l'expérimentation et les workflows locaux" et PostgresSaver comme "idéal pour une utilisation en production", et le dernier est ce sur quoi LangSmith lui-même tourne. Les deux sont délibérément parallèles dans le code, ce qui rend le contraste facile à voir :

# Development -- single file, no server, do not ship this
from langgraph.checkpoint.sqlite import SqliteSaver

# Production -- survives the box it runs on
from langgraph.checkpoint.postgres import PostgresSaver

Deux détails qui piègent les gens. Premièrement, les packages de checkpoint s'installent séparément de LangGraph core (langgraph-checkpoint-sqlite et langgraph-checkpoint-postgres sont leurs propres dépendances), donc une machine fraîche n'aura pas le saver Postgres tant que vous ne l'ajoutez pas. Deuxièmement, chaque opération de checkpoint a besoin d'un thread_id dans la config. Cet ID est ce qui lie une exécution donnée à son état sauvegardé, et un redémarrage sans le bon thread_id ne réhydrate rien.

Astuce de pro : Les packages de checkpoint LangGraph sont des installations séparées. langgraph-checkpoint-postgres n'est pas inclus dans le package de base langgraph donc épinglez-le dans votre fichier de dépendances de production avant de le découvrir à la dure lors d'un incident.

n8n a la même séparation développement-production, juste sous des noms différents. Son option de mémoire intégrée s'appelle aussi Simple Memory (ou Buffer Window Memory), et le chemin de production est le noeud Postgres Chat Memory pour un état qui doit survivre à un redémarrage. La mémoire intégrée conserve la conversation dans le processus en cours, ce qui convient pour les tests mais est une vulnérabilité pour une charge de travail 24/7. Des praticiens qui font tourner des agents n8n en production rapportent avoir dû migrer vers un store Postgres après que la mémoire en-processus ait grossi jusqu'à faire tomber l'instance. Si vous êtes sur n8n et que votre agent doit se souvenir de quoi que ce soit à travers un redémarrage, connectez-le à Postgres Chat Memory dès le départ.

Le checkpointing SQLite est une commodité de développement. Survivre à un redémarrage en production signifie Postgres (LangGraph) ou un store Postgres (n8n).

Tempêtes de nouvelles tentatives : quand vos propres agents DDoSent un service en panne

Quand un service en aval tombe, des nouvelles tentatives naïves par exécution transforment votre flotte d'agents en déni de service auto-infligé. Le correctif a deux volets : un backoff exponentiel avec jitter sur chaque agent pour étaler les nouvelles tentatives dans le temps, et un circuit breaker global qui se déclenche après un seuil partagé de défaillances et empêche tout le troupeau de marteler un service clairement en panne.

Les chiffres sont impitoyables. Comme l'exprime un article sur les patterns de nouvelles tentatives , avec dix agents parallèles qui font chacun dix tentatives, vous envoyez cent requêtes à un service déjà au sol, parce que le backoff de chaque agent est par exécution, pas global. Le backoff par agent seul ne résout pas ça. Dix agents qui reculent chacun poliment reculent quand même à l'unisson s'ils ont tous démarré en même temps, donc ils réessaient en vagues synchronisées. Le jitter brise la synchronisation en randomisant l'attente de chaque agent ; le circuit breaker brise le troupeau en partageant un seul état de défaillance entre tous.

Le volet backoff est un problème résolu en Python ; la bibliothèque tenacity gère l'exponentiel-avec-jitter proprement :

from tenacity import retry, stop_after_attempt, wait_random_exponential

@retry(wait=wait_random_exponential(multiplier=1, max=60), stop=stop_after_attempt(5))
def call_flaky_service(payload):
    return downstream.post(payload)

Le circuit breaker est le volet qui doit être global: partagé entre tous les agents, pas réinstancié par exécution. Quand les défaillances dépassent un seuil, il s'ouvre, chaque agent échoue rapidement plutôt que d'appeler, et après un temps de récupération il laisse passer une seule sonde pour tester si le service est revenu. Un breaker qui vit dans le propre processus de chaque agent ne protège rien, parce que rien n'est partagé ; le service en panne reçoit quand même les cent requêtes.

Le backoff par exécution laisse quand même dix agents marteler un service en panne à l'unisson. Le circuit breaker doit être global pour arrêter le troupeau.

Les six défaillances en un coup d'oeil

Avant la partie infrastructure, voici le catalogue complet en un seul endroit : la défaillance, le mécanisme qui la cause, le correctif harness, et où le paramètre concerné se trouve dans chaque framework.

Mode de défaillanceMécanismeCorrectif harnessParamètre de framework
Boucle infiniePas de plafond d'étapes ni de vérification de progressionPlafond strict + détection d'absence de progressionLangGraph recursion_limit (25) / n8n Max Iterations
Débordement de contexteL'historique grossit jusqu'à remplir la fenêtreRésumé à intervallesAu niveau applicatif (comprimer à ~50 % de la fenêtre)
Échec silencieux d'outilLes retours vides/doux lus comme des no-ops validesPorte de validation sur chaque résultat d'outilWrapper d'outil au niveau applicatif
Dégradation du raisonnementL'attention se dégrade à mesure que le contexte grossit ("context rot")Compression en milieu de boucle qui protège les contraintes épingléesAu niveau applicatif, avec connaissance des contraintes
Perte d'état au redémarragePas de checkpoint ; la boucle repart de zéroCheckpointing persistantLangGraph PostgresSaver / n8n Postgres Chat Memory
Tempête de nouvelles tentativesLes nouvelles tentatives par exécution cascadent sur un service en panneBackoff + jitter + circuit breaker globaltenacity + état partagé du breaker

Une note pour les lecteurs sur CrewAI, AutoGen, Dify, ou une boucle Python faite maison : les paramètres de framework changent, mais les six patterns non. La déduplication, la résumé à intervalles, la validation par schéma, la compression avec connaissance des contraintes, le checkpointing et un circuit breaker global sont des concepts indépendants du framework. Les spécificités LangGraph et n8n ici sont des points d'ancrage concrets, pas la limite d'applicabilité des patterns.

Dimensionner un déploiement d'agents en production

Tous les patterns ci-dessus supposent que vous contrôlez le gestionnaire de processus, la base de données et le comportement au redémarrage. Le checkpointing ne sert à rien si une boucle qui plante ne redémarre jamais, et un circuit breaker global a besoin d'un endroit pour stocker son état partagé. Ce contrôle est exactement ce que l'auto-hébergement vous donne et qu'une boîte noire gérée ne donne pas, donc la dernière décision est de dimensionner la machine qui fait tourner ça 24/7.

Pour la plupart des déploiements à agent unique (un agent, appels LLM vers une API externe, checkpointing Postgres basique), une petite instance suffit : environ 2 GB RAM, 1 vCPU, and 60 GB of NVMe storage. Le calcul lourd est du côté du fournisseur de modèle ; votre machine orchestre, fait des checkpoints et maintient l'état, elle ne fait pas tourner l'inférence. Passez à environ 4 GB RAM, 2 vCPU, and 120 GB NVMe quand l'agent est avec état et multi-étapes avec checkpointing Postgres plus Redis pour la réhydratation de session, ou quand vous faites tourner des workflows concurrents qui partagent l'hôte.

La raison pour laquelle cela nécessite un VPS auto-géré plutôt qu'une plateforme contrainte est la même raison pour laquelle les correctifs fonctionnent du tout : ils ont besoin du root. Votre propre Postgres pour le checkpointing, votre propre Redis pour l'état de session, et un vrai gestionnaire de processus comme systemd or pm2, pour que quand une boucle meurt, le superviseur la redémarre et qu'elle se réhydrate depuis son dernier checkpoint au lieu de recommencer le job depuis le début. Toute cette histoire de récupération dépend de la maîtrise du cycle de vie des processus.

Parce que nous faisons tourner n8n comme application en un clic dans notre propre marketplace, cette partie de la configuration est le chemin le plus court de notre côté : vous pouvez déployer n8n sur un VPS Cloudzy avec la configuration Postgres que le chemin de production requiert, sur une instance où vous avez l'accès root pour ajouter votre propre Redis et supervision de processus. C'est la même empreinte auto-hébergée décrite ci-dessus, où vous possédez la base de données et le comportement au redémarrage, ce qui fait que le checkpointing et la récupération automatique fonctionnent réellement.

Les patterns harness ne sont fiables qu'à la mesure de la machine sur laquelle ils tournent. Le checkpointing ne sert à rien si le processus ne redémarre jamais.

Foire aux questions

Comment empêcher mon agent LangGraph de boucler indéfiniment ?

Utilisez deux mécanismes ensemble. Définissez recursion_limit comme plafond d'étapes strict (la valeur par défaut est 25) pour qu'une boucle incontrôlée ne puisse pas brûler un budget illimité, et ajoutez une détection d'absence de progression qui hache chaque appel outil+argument et se termine quand le même appel se répète dans une fenêtre récente. Le plafond seul est un filet de sécurité qui se déclenche après le gaspillage, pas une vraie protection contre les boucles. La détection de progression est ce qui arrête réellement une boucle bloquée.

Quelle est la bonne valeur de recursion_limit pour LangGraph en production ?

Il n'y a pas de chiffre universel. Dimensionnez-le au nombre maximum d'étapes légitimes que votre agent devrait jamais avoir besoin, plus une marge, et traitez-le strictement comme un filet de sécurité budgétaire. Augmenter la limite ne fait pas converger un agent en boucle. Si votre agent atteint une limite élevée, le correctif est la détection de progression, pas un plafond plus haut.

Pourquoi mon agent IA n8n continue-t-il d'atteindre Max Iterations ?

Atteindre le plafond Max Iterations signifie que l'agent ne converge pas : il prend plus d'étapes que la limite ne le permet sans atteindre un arrêt. N'augmentez la limite que si la tâche nécessite légitimement plus d'étapes ; sinon, traitez-le comme un signal que l'agent est bloqué. Méfiez-vous d'un piège spécifique : l'issue GitHub #22771 rapporte que quand la limite d'itérations est atteinte avec "On Error: Continue" activé, l'exécution peut se router vers la sortie Success au lieu de la sortie Error, donc une exécution plafonnée et échouée peut ressembler à un succès dans votre workflow.

Comment persister l'état d'un agent à travers les redémarrages ?

Dans LangGraph, utilisez le checkpointing PostgresSaver plutôt que SqliteSaver, qui est destiné au développement local. Dans n8n, utilisez le noeud Postgres Chat Memory plutôt que la mémoire intégrée en-processus. Les deux nécessitent une base de données persistante, et dans LangGraph chaque opération de checkpoint a besoin d'un thread_id qui lie une exécution donnée à son état sauvegardé.

Qu'est-ce qui cause la dégradation du raisonnement dans les longues exécutions d'agents ?

La qualité du raisonnement baisse à mesure que le contexte grossit, même avant d'atteindre la limite stricte de tokens. C'est l'effet "lost in the middle", où le modèle prête attention au début et à la fin d'un long contexte mais perd le milieu. Le blog d'ingénierie d'Anthropic fait référence au mécanisme sous-jacent comme "context rot" : parce que chaque token est attentif à chaque autre token, vous obtenez n² relations par paires et l'attention du modèle s'étire d'autant plus finement que le contexte s'allonge. Le correctif est une compression en milieu de boucle qui résume l'historique périmé tout en gardant les contraintes épinglées et les instructions de sécurité intactes.

Share

Plus d'articles du blog

Continuez la lecture.

Prêt à déployer ? À partir de 2,48 $/mois.

Cloud indépendant, depuis 2008. AMD EPYC, NVMe, 40 Gbps. Remboursement sous 14 jours.