Ingénierie des boucles pour les agents d’IA : cinq composants, quatre formes et une méthode de construction avec LangGraph.
Ingénierie des boucles pour les agents d’IA : cinq parties, quatre formes courantes, un agent de recherche basé sur la vérification et la réessai dans LangGraph, des mécanismes de protection contre les pannes, et les cas où il ne faut pas utiliser de boucle.
Sources: Loop Engineering with Agents
Chaque agent d’IA fonctionne déjà en boucle, et presque personne ne conçoit cette boucle intentionnellement. Cet écart sépare un agent qui termine silencieusement sa tâche d’un autre qui épuise son budget en une nuit tout en étant convaincu de progresser. La pratique visant à combler cet écart a un nom : l’ingénierie de boucle.
Sur le plan structurel, il s’agit de peu de choses. À chaque étape, l’agent réfléchit à ce qu’il doit faire, exécute une action telle qu’une appel à un outil ou une recherche, examine les résultats obtenus et réfléchit à nouveau. Ce cycle de raisonnement, d’action et d’observation est au cœur d’outils tels que Claude Code et Cursor. Pendant un certain temps, la compétence recherchée était l’ingénierie de prompts, c’est-à-dire formuler une demande de la meilleure manière possible. Les modèles capables d’agir, de rechercher et de lire leurs propres sorties ont soulevé une question plus importante : qu’est-ce qui choisit la prochaine action de l’agent, et qu’est-ce qui lui indique de s’arrêter ?
L’ingénierie des boucles consiste en l’habitude de répondre délibérément à cette question. Le concepteur choisit l’objectif, les contrôles et le point d’arrêt, puis construit un système compact qui exprime l’objectif une seule fois et permet à l’agent de continuer à itérer jusqu’à ce que la tâche soit terminée. La responsabilité passe de l’instruction étape par étape de l’agent à la création de solutions adaptées à ces instructions.
C’est une idée solide, mais c’est aussi là que commence la partie difficile. Les boucles mal conçues consomment inutilement des ressources, ne s’arrêtent jamais ou se convainquent elles-mêmes qu’elles progressent. Les bonnes boucles sont économiques, s’arrêtent au moment opportun et produisent des résultats fiables. Un prompt plus intelligent ne comble pas cette lacune ; une boucle améliorée, si.
Les exemples ci-dessous utilisent LangGraph car il permet de visualiser facilement la structure d’un boucle, mais rien ici n’est lié à un framework en particulier. Les mêmes principes s’appliquent avec un autre framework d’agent ou du code écrit manuellement. Les frameworks changent, mais les concepts restent les mêmes.
Les cinq composants d’une boucle d’agent
Avant de décider quand une boucle est appropriée, il est utile de savoir de quoi elle est composée. Presque toutes les boucles d’agent comportent cinq composants.
- Un déclencheur. Un événement met les choses en mouvement, comme quelqu’un qui tape « go », le déclenchement d’un planificateur, l’arrivée d’une demande ou l’ouverture d’une demande de fusion. En l’absence de déclencheur, l’agent reste inactif.
- Un objectif vérifiable. Le boucle doit savoir à quoi ressemble une fin, de préférence sous une forme que la machine puisse confirmer. Améliorer l’application conduit à une série infinie d’essais : il faut que tous les tests réussissent, ou bien fournir une réponse dont toutes les affirmations citent des sources, ce qui constitue une véritable ligne d’arrivée.
- Outils. L’agent doit pouvoir agir ainsi que observer le résultat, exécuter du code et lire les erreurs, ou encore rechercher sur Internet et lire les résultats. Si l’environnement ne répond jamais, l’agent ne fait que deviner.
- État. Il s’agit de la représentation en temps réel du travail en cours : les tentatives effectuées jusqu’à présent, les découvertes, le nombre de tours écoulés. C’est la partie la plus délicate de la conception des boucles, car un état trop volumineux enfouit le signal utile sous du bruit.
- Règles d’arrêt. Elles définissent la manière dont la boucle se termine, et il existe trois possibilités : le succès signifie que l’objectif a été atteint, l’abandon signifie que le budget d’essais a été épuisé, et le transfert signifie que la boucle a rencontré un élément risqué ou peu clair et l’a transmis à une personne plutôt que de deviner.
Le reste de la discussion, qui aborde quand il faut utiliser une boucle, quand il ne faut pas et comment le faire, revient à ces cinq points.
Quand une boucle est utile
Une boucle s’avère nécessaire lorsque une seule passe par le modèle n’est pas suffisante, et que la tâche exige réellement que l’agent essaie, vérifie, puis essaie à nouveau. Quatre signaux indiquent cela.
- Les résultats peuvent être vérifiés. C’est ce qui compte le plus. Lorsqu’un résultat peut être contrôlé automatiquement, que ce soit parce que des tests réussissent ou échouent, qu’une réponse cite ou non des sources réelles, ou qu’un en-tête JSON est valide ou non, la boucle peut utiliser cette vérification pour parvenir à la bonne réponse. La vérification agit comme un volant de direction, tandis qu’une boucle qui en est dépourvue ne fait que gaspiller de l’argent.
- La première tentative est souvent erronée mais corrigeable. Le code, les brouillons de recherche et le nettoyage de données chaotiques s’améliorent avec la répétition. L’agent crée quelque chose, remarque les défauts et les corrige.
- Personne ne sait combien d’étapes il faudra. Un problème d’un certain type peut nécessiter deux étapes aujourd’hui et sept demain. Un processus fixe ne peut pas s’adapter de cette manière, contrairement à une boucle qui continue jusqu’à atteindre l’objectif.
Un exemple approprié est un agent de recherche qui audite ses propres résultats. Il rédige une réponse, vérifie si les sources soutiennent chaque affirmation, puis revient examiner celles qui sont faibles. Il continue ainsi en boucle jusqu’à ce que la réponse soit solide ou qu’un limite soit atteinte. Ces quatre signaux sont présents, et c’est l’agent décrit plus loin.
Formes courantes des boucles
La plupart des boucles d’agents sont des variations de quelques formes principales. Les reconnaître aide à déterminer quelle forme un problème adopte avant même de connecter quoi que ce soit.
Générer et vérifier, parfois appelé réflexion. Une première étape crée une sortie et une seconde l’inspecte, et ce cycle se répète jusqu’à ce que l’inspection soit réussie. Le signal de direction est binaire : la vérification approuve ou indique ce qui ne va pas. Cette méthode convient aux situations où la correction peut être testée, comme du code qui doit passer des tests ou des recherches dont les affirmations nécessitent une preuve. C’est la structure qui sera construite par la suite.
+-----------+ +-----------+
-->| Generate |----->| Verify |----- pass -----> [ done ]
+-----------+ +-----+-----+
^ |
+------- fail ------+
Choisissez cette approche lorsqu’il existe un test objectif de correction et que l’agent doit continuer à corriger jusqu’à ce que le test réussisse. Un agent de rédaction SQL qui exécute sa requête en boucle jusqu’à ce que l’instruction soit exécutée et retourne des lignes plausibles en est un exemple classique.
Évaluateur et optimiseur, également appelés générateur et évaluateur de scores. Un évaluateur attribue une note à chaque tentative au lieu de se contenter d’un oui ou d’un non, et la boucle vise à obtenir la note la plus élevée, et non seulement à garantir la correction. Cela est utile lorsque ni succès ni échec clairs n’existent, mais qu’une notion de qualité supérieure peut encore être mesurée, comme lors de l’ajustement d’un prompt, du perfectionnement d’un texte publicitaire ou du classement des résultats.
+-----------+ +-----------+
-->| Generate |----->| Score |--- good enough --> [ done ]
+-----------+ +-----+-----+
^ |
+-- improve --------+
(use the score)
Choisissez-le lorsque la qualité peut être mesurée sur une échelle et qu’un chiffre peut encore lui être attribué. L’élaboration d’un slogan pour un produit, avec une évaluation de la clarté et de l’impact par un système de notation, tandis que la boucle affine le meilleur candidat, illustre cette idée.
Planifier, exécuter, replanifier. Un planificateur définit les étapes et les exécutants les mettent en œuvre ; chaque fois qu’une étape révèle quelque chose d’inattendu, la boucle permet de revenir modifier le plan. La boucle entoure donc le plan plutôt qu’un seul résultat, ce qui la rend adaptée aux tâches ouvertes et à plusieurs étapes, comme la recherche ou un projet logiciel.
+-----------+ +-----------+
-->| Plan |----->| Execute |-- all steps done --> [ done ]
+-----------+ +-----+-----+
^ |
+-- replan ---------+
(hit a surprise)
Choisissez cette option lorsque la tâche comporte de nombreuses étapes et que celles-ci ne sont pas toutes connues au préalable. Migrer un service vers un nouveau framework fonctionne : planifiez les étapes, commencez leur exécution, puis réplanifiez dès qu’une étape révèle une dépendance inattendue.
Boucle planifiée ou de surveillance. Au lieu d’itérer vers un objectif au cours d’une seule exécution, cette variante s’active selon un délai prédéfini ou en réponse à un événement afin d’observer et de réagir, par exemple en triant de nouveaux tickets, en détectant des builds défectueux ou en essayant à nouveau une tâche peu fiable. Elle s’étend dans le temps et ne se limite pas à une seule tâche.
+-----------+ +-----------+ +-----------+
-->| Wait |---->| Check |---->| Act |---+
| (timer / | +-----------+ +-----------+ |
| trigger) | |
+-----------+ <-------------------------------------+
(no fixed end — keeps watching over time)
Choisissez cette approche lorsque aucune ligne d’arrivée unique n’existe et que l’objectif est de surveiller et de réagir en continu, comme en vérifiant sa boîte de réception toutes les quelques minutes ou en examinant chaque nuit les demandes de pull obsolètes.
Ces schémas ne sont pas mutuellement exclusifs. Les systèmes réels les superposent souvent, par exemple un cycle planifié qui exécute des étapes de génération et de vérification à chaque démarrage. Le schéma le plus courant, celui de génération et de vérification, est celui qui est construit de bout en bout ci-après.
Créer un cycle avec LangGraph
L’agent à créer est un chercheur qui ne fait pas confiance à sa première version. Face à une question, il collecte des informations, rédige une réponse, puis vérifie chaque affirmation à l’aide de sources réelles. Une affirmation dépourvue de preuves est renvoyée pour de nouvelles recherches. Le cycle se poursuit jusqu’à ce que la réponse soit complète, ou jusqu’à atteinte d’un plafond de tentatives, auquel cas l’agent renvoie sa meilleure version et indique ce qui reste incertain. En bref, il répond puis se convainc que la réponse est correcte avant de la présenter.
Ce comportement d’auto-vérification correspond exactement au cycle de génération et de vérification, ce qui permet une première version propre.
LangGraph est un bon exemple, car il décrit un agent sous forme de graphe. Les nœuds représentent des éléments qui effectuent des tâches, et les arêtes représentent des instructions déterminant ce qui se passe ensuite. Les arêtes peuvent pointer en arrière, ce qui permet l’existence de boucles. Une chaîne linéaire simple ne peut pas se répéter, mais un graphe le peut.
Le chercheur a trois tâches, d’où trois nœuds. Les deux premiers répartissent le travail entre un créateur et un vérificateur, un exécutant et un critique maintenus séparément, un schéma courant dans les boucles.
+------------------+
START ----------> | Research | <-------------+
| (draft / revise) | |
+--------+---------+ |
| |
v | needs work
+------------------+ | (+ feedback)
| Verify | |
| (check claims) | |
+--------+---------+ |
| |
v |
+-----------+ needs work |
| Decide |-------------------+
| (router) |
+-----+-----+
| verified / out of tries
v
[ END ]
- Recherche : collecte des informations et rédige une réponse provisoire.
- Vérification : examine le brouillon et teste si chaque affirmation est étayée.
- Décision : c’est un petit routeur qui lit le verdict et choisit ce qu’il convient de faire : terminer ou revenir sur les points faibles pour approfondir la recherche.
Cet exemple fonctionne sous Python 3.12. Trois paquets sont nécessaires :
pip install langgraph==1.2.6 langchain-openai==1.3.3 pydantic==2.13.4
langgraphest le moteur de graphes et de boucles, comprenantStateGraph,STARTetEND.langchain-openaiencapsule le modèle de chat d’OpenAI sous la forme deChatOpenAI.pydanticdéfinit le verdict structuré que renvoie le vérificateur.
Une clé API d’OpenAI doit également être présente dans l’environnement avant de l’exécuter :
export OPENAI_API_KEY="your-key-here"
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
# A model client on OpenAI's Responses API, with the built-in web-search tool
# bound on — so the model can search the web itself, no extra package needed.
# "gpt-5" is a reasoning model; swap it for any current model you have access to.
llm = ChatOpenAI(model="gpt-5", use_responses_api=True)
searcher = llm.bind_tools([{"type": "web_search"}])
MAX_ITERATIONS = 3 # a stop rule, decided up front
# STATE — the shared memory passed between every node
class ResearchState(TypedDict):
question: str # what we're answering
draft: str # the current best answer
verdict: str # "verified" or "needs_work"
feedback: str # what the verifier said to fix
iterations: int # how many times we've looped
# The verifier returns a typed result, so the router gets a clean
# "verified" / "needs_work" to branch on instead of parsing prose.
class Verdict(BaseModel):
status: str = Field(description='"verified" or "needs_work"')
feedback: str = Field(description="claims lacking support, if any")
# NODE 1 — the maker: search the web, then draft (or revise) the answer.
def research(state: ResearchState) -> dict:
prompt = "Search the web, then answer the question. Back every claim with a source.\n"
if state.get("feedback"):
prompt += f"A reviewer flagged these gaps — fix them:\n{state['feedback']}\n"
prompt += f"\nQuestion: {state['question']}"
draft = searcher.invoke(prompt).text
return {"draft": draft, "iterations": state["iterations"] + 1}
# NODE 2 — the checker: search for evidence, then critique the draft.
def verify(state: ResearchState) -> dict:
evidence = searcher.invoke(
f"Search the web for evidence to fact-check claims about: {state['question']}"
).text
checker = llm.with_structured_output(Verdict)
result = checker.invoke(
"You are a fact-checker. Using the evidence below, reply 'verified' "
"only if every claim in the answer is supported; otherwise 'needs_work' "
"and list the unsupported claims as feedback.\n\n"
f"Evidence:\n{evidence}\n\nAnswer:\n{state['draft']}"
)
return {"verdict": result.status, "feedback": result.feedback}
# ROUTER — the heart of the loop. Reads the verdict, picks the next step.
def decide(state: ResearchState) -> Literal["research", "__end__"]:
if state["verdict"] == "verified":
return "__end__" # success: goal met
if state["iterations"] >= MAX_ITERATIONS:
return "__end__" # surrender: out of tries
return "research" # loop back and fix the gaps
# WIRE IT UP
graph = StateGraph(ResearchState)
graph.add_node("research", research)
graph.add_node("verify", verify)
graph.add_edge(START, "research") # trigger
graph.add_edge("research", "verify") # always verify a fresh draft
graph.add_conditional_edges("verify", decide, {
"research": "research", # the backward arrow = the loop
"__end__": END,
})
agent = graph.compile()
result = agent.invoke({
"question": "What were the main causes of the 2008 financial crisis?",
"draft": "", "verdict": "", "feedback": "", "iterations": 0,
})
print(result["draft"])
Deux détails se détachent. Premièrement : les deux nœuds accèdent au web en temps réel via l’outil intégré web_search d’OpenAI, associé à bind_tools. Le nœud research effectue des recherches avant de rédiger afin que ses affirmations soient fondées sur des résultats réels. Le nœud verify effectue une deuxième recherche pour tester le brouillon à l’aide de nouvelles preuves plutôt que de la mémoire du modèle, et c’est cette deuxième recherche qui fournit au cycle un signal objectif. Deuxièmement : verify s’appuie sur with_structured_output, qui impose l’utilisation d’un verdict et d’un feedback structurés plutôt que du texte libre, permettant ainsi au routage de fonctionner de manière fiable sans avoir à analyser du texte non structuré.
Les cinq composants du cycle correspondent clairement au code :
- Déclencheur : l’appel à
invoke(...)avec une question démarre une exécution. - Objectif vérifiable : les règles
verifysont soitverified, soitneeds_work. - Outils : les deux nœuds utilisent la recherche web intégrée,
researchpour rédiger etverifypour vérifier. - État : le dictionnaire
ResearchStatetransfère le brouillon, les retours et le compteur d’itérations entre les nœuds. - Règles d’arrêt : le routeur
decidemet fin à l’exécution en cas de succès ou lorsqu’on atteintMAX_ITERATIONS.
Le dernier point est essentiel, car c’est là que réside réellement l’ingénierie des boucles. Une seule ligne, « arrêter si vérifié, arrêter après trois tentatives, sinon revenir en arrière », permet de distinguer un agent qui améliore de manière fiable sa réponse d’un autre qui continue indéfiniment sans résultat.
Cet exemple comporte deux issues. Les boucles de production ont tendance à en ajouter une troisième, qui consiste à transférer la tâche à un humain. Face à une situation risquée ou peu claire, il est préférable pour l’agent de ne ni deviner ni s’arrêter silencieusement, mais plutôt de s’interrompre et d’escalader la situation en présentant tout ce qu’il a collecté. Dans le routeur, il s’agit simplement d’une branche supplémentaire : lorsque la confiance est faible ou que l’action est sensible, une route escalate met fin à la boucle et présente le projet en cours, les questions en suspens ainsi que les tentatives effectuées. Savoir quand ne pas prendre de décision fait partie d’une bonne conception de boucle.
Modes de défaillance et leurs mécanismes de protection
Lorsqu’une boucle fonctionne de manière autonome, une courte liste de défaillances prévisibles apparaît, chacune disposant d’un mécanisme de protection standard.
- La boucle infinie. L’agent ne conclut jamais qu’il a terminé et continue jusqu’à ce que quelque chose cesse de fonctionner ou que l’argent soit épuisé. La limite stricte d’itérations, comme
MAX_ITERATIONSmentionné précédemment, constitue une sortie qui ne dépend pas de l’opinion de l’agent lui-même. - Brûlage de tokens. Chaque passage renvoie une quantité croissante de contexte, ce qui fait augmenter les coûts sans que l’on s’en aperçoive. Maintenez un état léger en ne conservant que ce dont a besoin l’étape suivante : le brouillon actuel et les retours spécifiques, jamais l’historique complet.
- Progrès imaginaire. L’agent annonce des succès qu’il n’a pas réalisés, par exemple en prétendant avoir corrigé un problème qui n’a jamais eu lieu. Ne le laissez pas marquer comme terminé son propre travail sur les points importants. Une étape de vérification distincte, basée sur des tests objectifs, des tests effectivement exécutés ou des sources réellement existantes, permet de s’assurer que ce qui est fait l’est vraiment.
research reçoit le feedback du vérificateur.Quand ne pas utiliser de boucle
Les boucles sont puissantes, ce qui les pousse à être utilisées de manière excessive. Dans ces cas, une solution plus simple est préférable.
- Une seule passe suffit. Résumer un document, traduire du texte, répondre à une question factuelle ou classer un e-mail sont des tâches à exécuter une seule fois. Utiliser une boucle pour ces opérations ne fait qu’ajouter des coûts, des retards et de nouvelles possibilités d’échec. Si une séquence linéaire de étapes fonctionne, optez pour elle.
- Le succès est indiscernable. Lorsque l’objectif est subjectif ou flou, ou que seul un être humain peut le juger, la boucle n’a rien sur quoi s’appuyer et finira de manière aléatoire ou en tournant indéfiniment. Un objectif qui ne peut pas être vérifié crée une machine à sous, et non une boucle.
Règle générale : si les conditions de succès et celles d’abandon ne peuvent pas être écrites, la boucle n’est pas prête à être développée.
Une liste de contrôle avant de mettre en boucle
Le génie des boucles déplace le point d’intérêt. Rédiger une instruction irréprochable importe moins que concevoir le système qui guide l’agent, c’est-à-dire son déclencheur, son objectif, ses outils, son état et ses règles d’arrêt. Néanmoins, une boucle n’est qu’un outil parmi d’autres et ne constitue jamais une solution par défaut. Cinq questions méritent d’être posées en premier :
- Le succès peut-il être vérifié automatiquement ? Si ce n’est pas le cas, omettez la boucle, car elle n’aurait rien sur quoi s’appuyer pour guider l’action.
- La tâche s’améliore-t-elle avec la répétition ? Si une seule tentative suffit, restez simple.
- Que signifie exactement « terminé » ? Écrivez la condition de succès avant de coder.
- Quand doit-elle s’arrêter ? Fixez une limite stricte afin que la boucle ne puisse pas fonctionner indéfiniment.
- Les actions peuvent-elles être répétées en toute sécurité ? Si une itération pourrait causer des dommages réels, ajoutez un point de contrôle humain ou évitez de créer une boucle pour cette étape.
En donnant des réponses honnêtes aux cinq questions, on peut obtenir un cycle fiable et non pas seulement un cycle spectaculaire. Un premier projet modeste est le plus adapté : une seule étape de recherche et de vérification, comme décrit ci-dessus, avec des règles d’arrêt clairement définies avant que quoi que ce soit ne se développe.
Un dernier point : un cycle va au-delà de l’accélération du travail. Il amplifie tout jugement qui a été mis en œuvre, en reproduisant à vitesse machine aussi bien les bonnes que les mauvaises décisions. L’objectif n’est donc pas de le mettre en place puis de s’en désintéresser. La discipline consiste à rester suffisamment proche pour continuer à comprendre ce que fait le cycle une fois qu’il fonctionne seul, afin que son concepteur reste son ingénieur et non simplement la personne qui appuie sur le bouton de démarrage.
Lectures complémentaires
- Harness, Loop et Graph : trois couches imbriquées d’un système d’agents de programmation — Un symptôme de défaillance indique la couche à corriger. Comment s’imbriquent harness, loop et graph, où l’approche multi-agent est utile, ce que les vérifications adversariales ne peuvent pas garantir, ainsi qu’une liste de contrôle.
- Ingénierie des loop : quatre boucles imbriquées pour des agents IA auto-améliorateurs — Comment quatre boucles de contrôle imbriquées (ReAct, tentative répétée, file d’attente, montée en pente) associées à un juge, un compteur de budget et des vérifications de modification rendent un agent fiable, illustré par l’underwriting d’assurances.