- Changement de paradigme : Contrairement aux chatbots classiques qui s’arrêtent après une seule réponse, une boucle d’agent tourne de manière itérative dans une structure de code (comme une boucle
while), confiant le contrôle d’exécution à l’IA pour résoudre des tâches complexes. - Le cycle ReAct : La plupart des architectures modernes reposent sur le modèle ReAct (Raisonner + Agir), qui structure chaque itération en étapes claires : percevoir, raisonner, planifier, agir et observer.
- Gestion indispensable des limites : Donner carte blanche à un modèle comporte des risques. Pour éviter de consommer des millions de tokens dans le vide, il faut impérativement mettre en place des conditions d’arrêt strictes (limites d’itérations, timeouts, détection d’emballement).
- Des architectures spécialisées : Du simple ReAct linéaire aux réseaux multi-agents complexes, en passant par le modèle “Planifier et Exécuter” et l’auto-correction, le choix de la structure dépend directement du niveau d’autonomie et de la tolérance aux erreurs requis par votre projet.
Quand on commence à travailler sérieusement avec les grands modèles de langage, on se heurte vite à la limite frustrante de l’interaction linéaire. On pose une question, le modèle génère une réponse statique, puis s’arrête. Si le résultat contient une erreur ou nécessite une étape supplémentaire, c’est à nous, humains, de faire le pont. C’est précisément pour dépasser cette barrière que j’ai commencé à m’intéresser aux boucles d’agents (agent loops).
Une boucle d’agent est un modèle architectural itératif où l’IA évalue en continu une tâche, prend une décision, exécute une action via un outil externe, observe le résultat de cette action, et utilise ce retour d’expérience pour décider de sa prochaine étape, jusqu’à ce que l’objectif final soit atteint. (Et croyez-moi, voir un script corriger lui-même ses propres erreurs de syntaxe à trois heures du matin, cela change radicalement notre rapport au code).
Les étapes clés de l’exécution
La majorité des architectures d’agents reposent sur le modèle ReAct (Reason + Act), qui formalise un cycle répétitif structuré autour de plusieurs phases clés :
- Percevoir : L’agent prend connaissance de la consigne initiale de l’utilisateur, d’un flux de données externes ou du résultat direct de sa propre action précédente.
- Raisonner : Le modèle traite l’ensemble du contexte accumulé dans sa fenêtre de tir pour évaluer les options disponibles et ajuster sa stratégie.
- Planifier : Face à des objectifs complexes, l’agent découpe sa démarche en plusieurs micro-tâches intermédiaires.
- Agir : L’agent déclenche une action concrète en appelant un outil externe, qu’il s’agisse d’interroger une base de données, d’effectuer une recherche sur le web ou de lancer un script.
- Observer : L’agent analyse le retour de l’outil (qu’il s’agisse d’une donnée valide ou d’un message d’erreur) pour évaluer sa progression, avant d’injecter ce retour dans l’itération suivante.
Chatbots classiques vs. boucles d’agents
Les différences fondamentales entre une interaction linéaire standard et une boucle autonome déterminent la manière dont les tâches sont exécutées :
| Caractéristique | Chatbots / Chaînes classiques | Boucles d’agents |
|---|---|---|
| Modèle d’exécution | Passe unique ou chaîne linéaire figée | Cyclique et itératif |
| Flux de contrôle | Prédéfini par le développeur | Déterminé en temps réel par l’IA |
| Gestion des erreurs | Arrêt brutal ou renvoi d’une erreur | Nouveau raisonnement et adaptation de l’action |
| Cas d’usage idéal | Réponses directes, questions-réponses, routage linéaire | Tâches autonomes et ouvertes à étapes multiples |
Éviter les boucles infinies en production
Laisser le contrôle du flux d’exécution à un LLM présente un risque majeur : celui de le voir s’enferrer dans une boucle infinie s’il fait face à des données ambiguës ou des outils contradictoires, vidant votre portefeuille de tokens en quelques minutes. Pour éviter ce genre de dérive, j’ai appris qu’il faut absolument implémenter des conditions d’arrêt strictes :
- Atteinte de l’objectif : Un point d’arrêt naturel et vérifié, déclenché lorsque le modèle compare son travail au but initial et valide sa réussite.
- Limite d’itérations : Un plafond strict qui interrompt l’exécution après un nombre défini de cycles (par exemple,
max_iterations=10). - Timeouts : Une limite de temps absolue pour couper court aux processus qui s’éternisent.
- Détection d’emballement (thrashing) : Un mécanisme de surveillance qui interrompt le script si l’agent envoie plusieurs fois de suite les mêmes arguments d’outils sans modifier l’état du système.
Les différentes architectures de boucles d’agents
Ces architectures constituent les plans de structure qui régissent la mémoire, le raisonnement, l’utilisation des outils et le flux de contrôle de l’IA. Selon la complexité du problème, on s’orientera vers différents modèles :
- Le ReAct Linéaire : La configuration la plus simple, alternant de manière rigide entre raisonnement (Thought), action (Action) et observation (Observation).
- Plan-and-Execute (Planifier et Exécuter) : Un modèle plus élaboré où un agent macro planifie d’abord une séquence complète de sous-tâches, tandis qu’une boucle d’exécution les traite une par une, en faisant un point d’étape global après chaque jalon.
- L’auto-correction (Self-Correction) : Une boucle spécialisée dans l’assurance qualité, conçue pour passer le livrable généré au crible d’un vérificateur automatisé, réinjectant les logs d’erreurs ou les rapports de compilation dans le prompt jusqu’à validation complète.
- Les réseaux multi-agents (Multi-Agent Networks) : Des architectures haut de gamme où plusieurs boucles spécialisées et indépendantes collaborent, s’échangent des tâches ou partagent un état commun.
Gestion de l’état et de la mémoire
Pour éviter que la cohérence logique du système ne s’effondre au fil des cycles, la gestion de l’état est cruciale :
- Boucles à passage d’état (State-Passing Loops) : Le système encapsule chaque itération dans une structure de données (“l’État”) qui accumule l’historique. Chaque tour de boucle reçoit l’état courant, y greffe les nouvelles observations et renvoie l’état mis à jour.
- Fenêtres de mémoire (Memory Windows) : Une boucle longue consommation peut vite saturer la fenêtre de contexte. On gère alors la mémoire à court terme via des fenêtres de tokens glissantes, et la mémoire à long terme par le biais de bases de données vectorielles ou d’étapes de synthèse régulières.
Mécanismes de contrôle du flux
Pour encadrer l’autonomie de ces modèles, on utilise des structures de contrôle précises :
- Nœuds de routage (Router Nodes) : Plutôt qu’une bête boucle
while True, on emploie des nœuds de routage conditionnels qui lisent la dernière réponse de l’IA et appliquent un code déterministe pour diriger le flux vers un outil spécifique, une validation humaine ou la sortie du programme. - Validation humaine (Human-in-the-Loop) : Une architecture hybride qui force la boucle à se mettre en pause avant l’exécution d’actions critiques (comme l’envoi d’un email ou la validation d’une transaction financière), attendant un feu vert ou des corrections manuelles pour reprendre son cours.
Focus : L’architecture Linear ReAct
Théorisé en 2022, le modèle Linear ReAct reste la base de travail indispensable pour tout agent autonome. Il impose à l’IA d’expliciter son raisonnement avant d’agir, créant une séquence rigoureuse :
[ Pensée ] ──> [ Action ] ──> [ Observation ] ──> [ Évaluation ] ──> (Boucle ou Sortie)
- Thought (Pensée) : Le modèle analyse sa situation, formule ses intentions et documente textuellement son raisonnement.
- Action : L’IA sélectionne le bon outil et génère les paramètres requis.
- Observation : Le programme exécute l’outil, intercepte son retour brut et l’ajoute à l’historique de discussion.
- Evaluation : Le modèle analyse la nouvelle situation pour déterminer s’il a atteint son but ou s’il doit repartir pour un tour de boucle.
Exemple d’implémentation en Python
Voici comment coder cette logique de manière déterministe pour garder la main sur le comportement du modèle :
def run_react_agent(user_prompt, tools, max_loops=5):
# 1. Initialisation de l'état avec les consignes et outils
messages = [
{"role": "system", "content": "You are a ReAct agent. You must alternate between Thought: and Action:."},
{"role": "user", "content": user_prompt}
]
for _ in range(max_loops):
# 2. Génération de la pensée et choix de l'action par le LLM
response = llm.generate(messages)
messages.append({"role": "assistant", "content": response})
# 3. Vérification de la condition de sortie
if "Final Answer:" in response:
return extract_final_answer(response)
# 4. Analyse et exécution déterministe de l'action
tool_name, tool_input = parse_action(response)
observation = tools[tool_name].execute(tool_input)
# 5. Réinjection de l'observation dans la boucle
messages.append({"role": "user", "content": f"Observation: {observation}"})
return "Error: Maximum iteration limit reached."
Avantages et limites du Linear ReAct
Pourquoi utiliser ce modèle ? (Et pourquoi s’en méfier ?)
- Explicabilité : Le fait de forcer l’agent à écrire son raisonnement offre une piste d’audit précieuse pour comprendre ses choix.
- Gestion des erreurs : Si un outil échoue, l’étape de pensée suivante permet à l’agent d’analyser le problème et d’ajuster sa méthode.
- Surcharge du contexte (limite majeure) : Accumuler toutes les pensées et retours d’outils fait gonfler la consommation de tokens de manière exponentielle au fil des tours.
- Myopie (limite majeure) : Ce modèle gère mal la planification à long terme. Décider étape par étape fait souvent perdre de vue l’objectif global dès que l’on dépasse 4 ou 5 cycles.
Focus : L’architecture Plan-and-Execute (Planifier et Exécuter)
Pour remédier à la vision court-termiste du ReAct linéaire, l’architecture Plan-and-Execute sépare la phase de réflexion stratégique globale de la phase d’exécution pure :
[ Requête utilisateur ] ──> [ 1. Le Planificateur ] ──> ( Génère le plan d’action )
│
▼
[ 2. La boucle d’exécution ] ──> ( Lance chaque étape via ReAct )
│
▼
[ Résultat Final ] <── [ 3. Le Re-planificateur ] <── ( Évalue l’état et réajuste )
- Le Planificateur (Planner) : Un agent macro qui reçoit l’objectif, étudie les outils disponibles et dresse une feuille de route séquentielle composée de sous-tâches précises.
- L’Exécuteur (Executor) : Un micro-agent (souvent basé sur une boucle ReAct serrée) qui prend en charge une sous-tâche spécifique et se concentre uniquement sur sa réalisation.
- Le Re-planificateur (Replanner) : Un superviseur qui analyse le travail effectué par l’exécuteur, le confronte au plan global, met à jour l’état et décide s’il faut adapter les étapes suivantes ou clore la tâche.
Composants de l’architecture
Cette approche s’appuie sur trois structures de données pour maintenir la cohérence :
- L’état du plan (Plan State) : Une file d’attente dynamique des sous-tâches à mener.
- La boucle d’exécution (Execution Loop) : Le code qui parcourt cette file d’attente et délègue chaque tâche à l’exécuteur.
- La mémoire globale (Global Memory) : Un espace de stockage partagé où l’exécuteur consigne ses découvertes pour que les étapes suivantes puissent s’y référer sans avoir à relire l’historique brut des outils.
Comparatif des approches d’exécution
| Caractéristique | Chatbots / Chaînes classiques | Linear ReAct | Plan-and-Execute |
|---|---|---|---|
| Horizon de traitement | Court (une seule passe) | Moyen (3 à 5 étapes) | Long (flux de plus de 10 étapes) |
| Gestion des tokens | Très sobre | Gourmand (gonflement rapide) | Optimisé (les logs d’outils restent isolés) |
| Gestion des erreurs | Échec immédiat | Correction locale à la volée | Ré-planification et routage global |
| Périmètre d’action | Questions-réponses simples | Exploration dynamique d’outils | Processus complexes parallélisables |
Avantages et inconvénients du Plan-and-Execute
- Stabilité accrue : Isoler l’utilisation des outils dans des sous-tâches indépendantes évite d’encombrer le contexte de planification principal avec des données brutes volumineuses.
- Exécution parallèle : Puisque le plan est découpé en tâches distinctes, on peut faire tourner plusieurs boucles d’exécution en parallèle pour gagner du temps.
- Latence plus élevée : Préparer un plan, lancer une boucle par tâche et appeler le re-planificateur prend du temps et ralentit l’exécution globale par rapport à un modèle linéaire.
- Fragilité du plan initial : Si la planification de départ est bancale, l’exécuteur peut consommer beaucoup de ressources sur des impasses logiques avant que le superviseur ne puisse intervenir.
Focus : L’architecture d’Auto-correction (Self-Correction)
Cette architecture est spécifiquement taillée pour le contrôle qualité et la validation de données. Au lieu de livrer directement le premier jet de l’IA, le système fait passer le résultat dans un filtre d’évaluation avant de valider la sortie :
[ Objectif ] ──> [ 1. Générateur ] ──> ( Premier jet ) ──> [ 2. Évaluateur / Testeur ]
▲ │
│ ▼
( Ajustement du prompt ) <── [ 3. Boucle de retour ] <── ( Échec / Logs )
│
└─> ( Réussite ) ──> [ Livrable Final Validé ]
- Le Générateur : Un LLM spécialisé dans la production (code, texte, JSON). Il s’appuie sur la demande initiale et les retours d’évaluation pour affiner ses propositions.
- L’Évaluateur : Un modèle d’IA dédié ou un outil déterministe (compilateur de code, validateur de schéma JSON, parseur AST, regex).
- La boucle de retour : Si l’évaluateur repère des erreurs, il capture les logs bruts, les structure dans un prompt constructif et les renvoie au générateur pour correction.
Les deux grands types d’auto-correction
On distingue deux grandes manières d’exploiter ce modèle au quotidien :
- Les boucles d’exécution de code : L’agent écrit du code et ses tests unitaires, lance l’exécution dans un bac à sable (sandbox), récupère la trace d’erreur en cas d’échec et ajuste sa syntaxe jusqu’à ce que tous les tests passent au vert.
- Critique et Amélioration (CRITIC) : Destiné aux contenus non structurés (traductions, rédactions juridiques). Un second LLM fait office d’éditeur, évalue le travail selon une grille précise (ton, biais, fidélité aux sources) et propose des axes d’amélioration précis à appliquer lors du cycle suivant.
Comparatif fonctionnel
| Caractéristique | Linear ReAct | Plan-and-Execute | Self-Correction |
|---|---|---|---|
| Objectif principal | Utilisation dynamique d’outils | Gestion de flux complexes à long terme | Fiabilité et validation structurelle |
| Moteur de décision | Observations de l’environnement | Progression dans les sous-tâches | Logs d’erreurs, tests, critères d’évaluation |
| Point fort | Adaptabilité immédiate | Structuration et organisation | Haute qualité des livrables en production |
| Risque majeur | Perte de focus ou dispersion | Blocage face à un plan trop rigide | Boucle infinie sur des bugs complexes |
Prévenir les dérives d’auto-correction
Les boucles d’auto-correction peuvent s’avérer piégeuses : le modèle corrige parfois un bug pour en créer un autre, tournant ainsi en rond indéfiniment. Pour s’en prémunir, j’applique toujours ces trois garde-fous :
- Un nombre maximal de tentatives : On force la sortie après quelques essais (généralement 3 à 5).
- La détection de régression : On interrompt la boucle si l’erreur renvoyée est exactement identique à celle de l’étape précédente, signe que le modèle piétine.
- L’escalade humaine : Le système s’arrête et transmet l’historique et les logs d’erreurs à un développeur si la correction automatique échoue après le nombre d’essais alloué.
Focus : Les réseaux multi-agents
C’est le niveau d’architecture le plus complexe. Au lieu d’avoir un modèle unique qui gère tout (la planification, les outils, l’évaluation), on répartit la charge de travail entre plusieurs boucles d’agents autonomes, spécialisées et collaboratives.
[ Demande Utilisateur ]
│
▼
[ 1. Routeur / Manager ]
╱ │ ╲
╱ │ ╲
▼ ▼ ▼
[ Agent Recherche ] ──> [ Agent Analyste ] ──> [ Agent QA ]
(Boucle ReAct) (Sandbox Python) (Boucle Critique)
Topologies de communication
La façon dont les agents échangent influe directement sur l’efficacité globale du système :
- Hiérarchique (Superviseur-Exécuteurs) : Un agent central reçoit la demande de l’utilisateur, segmente le problème et distribue les tâches à des agents subordonnés. Ces derniers ne communiquent qu’avec le manager.
- Séquentielle (Pipeline / Ligne d’assemblage) : Les tâches suivent un chemin prédéfini. L’agent A termine son travail, met à jour l’état commun, puis passe le relais à l’agent B (par exemple : Recherche ➔ Rédaction ➔ Relecture).
- Collaborative (Réseau libre) : Les agents partagent un espace de discussion ou un bus de messages. Ils échangent librement, s’interrogent mutuellement et se délèguent des tâches de manière autonome selon leurs besoins.
Gestion de l’état partagé
Le grand défi des architectures multi-agents est d’éviter que les intervenants n’écrasent le travail des autres ou ne perdent le fil conducteur. Deux méthodes s’affrontent :
- L’état global partagé (The Blackboard) : Une base de données ou un dictionnaire centralisé et structuré. Chaque agent vient y lire des informations et y ajouter ses résultats, ce qui permet de limiter la taille des fenêtres de contexte individuelles.
- Le passage de messages (Message-Passing) : Les échanges se font sous forme de fil de discussion chronologique. L’agent B utilise la réponse finale de l’agent A comme consigne d’entrée.
Comparatif architectural
| Caractéristique | Linear ReAct / Plan-and-Execute | Réseaux Multi-Agents |
|---|---|---|
| Charge cognitive | Concentrée dans le contexte d’un seul modèle | Répartie sur plusieurs fenêtres de contexte modulaires |
| Complexité du prompt système | Consignes volumineuses et complexes | Personas courts et très spécialisés par agent |
| Coût et latence | Faibles à modérés | Élevés (appels LLM multiples et potentiellement parallèles) |
| Flexibilité fonctionnelle | Difficultés sur des domaines très hétérogènes | Excellent comportement sur des tâches interdisciplinaires |
Frameworks d’orchestration de référence
Coder un réseau multi-agents complet en partant de zéro est un exercice laborieux en termes de gestion d’état et d’asynchronisme. Pour ma part, je m’appuie sur ces outils de référence :
- LangGraph : Développé par l’équipe de LangChain, il permet de modéliser les agents sous forme de nœuds et leurs canaux de communication sous forme d’arêtes dans un graphe d’état très rigoureux.
- CrewAI : Ce framework propose une approche orientée objet qui simule une organisation humaine de travail (on définit des agents avec des rôles et des objectifs précis, et le framework s’occupe de la communication sous-jacente).
- Microsoft AutoGen : Un framework événementiel idéal pour créer des conversations ouvertes et complexes entre agents, qui intègre très bien l’intervention humaine au milieu de la boucle.
Comment construire une boucle d’agent ?
Le principe de base consiste à écrire une boucle d’exécution logicielle permettant à un LLM de faire appel à des outils externes, de traiter leurs retours et de mettre à jour son historique jusqu’au dénouement de la tâche. Vous pouvez l’écrire directement en Python ou vous appuyer sur des frameworks dédiés.
Méthode 1 : Construire une boucle native en Python de A à Z
C’est de loin le meilleur moyen de comprendre la plomberie interne d’un agent. Voici comment mettre en place une boucle ReAct linéaire simple sans aucune dépendance tierce.
1. Définition des outils
On commence par créer la fonction Python que l’agent pourra appeler :
import math
def calculate_square_root(number_string: str) -> str:
"""Calcule la racine carrée d'un nombre donné sous forme de chaîne de caractères."""
try:
num = float(number_string)
return str(math.sqrt(num))
except ValueError:
return "Erreur : Nombre invalide."
# Cartographie pour lier le nom de l'outil à sa fonction exécutable
AVAILABLE_TOOLS = {
"calculate_square_root": calculate_square_root
}
2. Rédaction du prompt système
Le prompt doit contraindre le modèle à adopter un format de réponse strict pour simplifier l’analyse syntaxique dans notre code :
SYSTEM_PROMPT = """You are an autonomous AI Agent operating in a loop.
You solve tasks step-by-step by generating a Thought and an Action.
You have access to the following tools:
- calculate_square_root: Takes a number string and returns the square root.
Your response format MUST look exactly like this:
Thought: [Your reasoning about what to do next]
Action: [tool_name] -> [tool_input]
When you have the final answer, output exactly:
Final Answer: [Your final completed answer]
"""
3. Écriture de la boucle d’exécution principale
Cette boucle gère les requêtes au modèle, le décodage des actions, l’exécution des outils et la réinjection des données dans le contexte :
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
def run_agent(user_goal: str, max_iterations: int = 5):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_goal}
]
print(f"🚀 Lancement de l'agent pour l'objectif : '{user_goal}'\n")
for iteration in range(1, max_iterations + 1):
print(f"--- 🔄 Iteration {iteration} ---")
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
temperature=0.0 # Température à zéro pour un format d'action stable
)
agent_output = response.choices[0].message.content
print(agent_output)
messages.append({"role": "assistant", "content": agent_output})
# Validation de l'objectif final
if "Final Answer:" in agent_output:
print("\n✅ Objectif atteint.")
return agent_output.split("Final Answer:")[-1].strip()
# Extraction et découpage de l'action à exécuter
try:
action_line = [line for line in agent_output.split("\n") if line.startswith("Action:")][0]
parts = action_line.replace("Action:", "").strip().split("->")
tool_name = parts[0].strip()
tool_input = parts[1].strip()
except Exception:
print("❌ Erreur de formatage. Sortie forcée.")
break
# Étape d'action et d'observation
if tool_name in AVAILABLE_TOOLS:
print(f"🛠️ Exécution de {tool_name} avec l'argument : {tool_input}")
observation = AVAILABLE_TOOLS[tool_name](tool_input)
else:
observation = f"Erreur : L'outil '{tool_name}' n'existe pas."
print(f"👁️ Observation: {observation}\n")
# Réinjection du résultat de l'outil dans l'historique
messages.append({"role": "user", "content": f"Observation: {observation}"})
return "❌ Fin de boucle : Nombre maximal d'itérations atteint sans réponse finale."
# Lancement du test d'exécution
result = run_agent("What is the square root of 50125.67?")
print(f"\n🏆 Résultat final : {result}")
Méthode 2 : Industrialiser avec des frameworks dédiés
Si coder une boucle brute en Python permet de bien appréhender les concepts, les besoins réels en production imposent une gestion d’état plus solide, un suivi de l’historique de discussion fiable et parfois des représentations visuelles sous forme de graphes d’exécution.
- LangGraph : Ce framework structure vos boucles d’agents comme de véritables machines à états. Les étapes de calcul deviennent des nœuds, et la logique de transition correspond à des arêtes de routage. Il est idéal pour bâtir des chemins décisionnels fins ou des structures multi-agents en maille.
- CrewAI : Ce framework fait abstraction des graphes mathématiques au profit d’une modélisation inspirée du travail en entreprise. On y configure des profils d’agents (personas), on leur attribue des tâches, et le système orchestre lui-même leurs échanges et interactions de manière transparente.
L’intégration de LangGraph dans l’écosystème LangChain
Dans l’écosystème moderne de LangChain, les anciennes méthodes linéaires comme AgentExecutor ont été abandonnées au profit de LangGraph. Ce changement d’architecture permet de concevoir les boucles de manière explicite et modulaire sous forme de graphes de décision.
Un flux classique avec LangGraph s’articule autour de deux nœuds principaux qui s’activent en boucle jusqu’au déclenchement d’un point de sortie conditionnel :
[ Début ] ──> [ Appel du Modèle ] <──┐
│ │
( Appel d’outil ? ) │
╱ ╲ │
OUI NON │
╱ ╲ │
▼ ▼ │
[ Action Outil ] [ Fin de Boucle ]│
│ │
└────────────────────────────┘
Implémentation technique pas à pas
Voici comment assembler un agent ReAct standard en utilisant LangChain et LangGraph :
Étape A : Définir et lier les outils au modèle
On déclare d’abord nos fonctions métiers et on les associe au modèle de langage :
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
@tool
def multiply_numbers(a: float, b: float) -> float:
"""Multiplie deux nombres et renvoie le résultat."""
return a * b
tools = [multiply_numbers]
# Liaison des schémas d'outils au modèle
model = ChatOpenAI(model="gpt-4o", temperature=0).bind_tools(tools)
Étape B : Configurer les nœuds et l’état global du graphe
On définit la structure de l’état partagé qui circulera de nœud en nœud :
from typing import Annotated, Sequence
from typing_extensions import TypedDict
from langchain_core.messages import BaseMessage
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode
# Définition de l'état partagé de la boucle
class AgentState(TypedDict):
# add_messages permet d'ajouter les nouveaux messages au lieu d'écraser l'historique
messages: Annotated[Sequence[BaseMessage], add_messages]
# Définition du nœud d'appel au modèle
def call_model(state: AgentState):
response = model.invoke(state["messages"])
return {"messages": [response]}
# Initialisation du nœud d'exécution des outils
tool_node = ToolNode(tools)
Étape C : Établir la logique de routage conditionnel
Cette étape permet de déterminer par programmation si l’agent doit continuer à solliciter des outils ou s’il a terminé sa tâche :
def should_continue(state: AgentState):
last_message = state["messages"][-1]
# Si le modèle n'émet pas de demande d'appel d'outil, on s'arrête
if not last_message.tool_calls:
return END
# Sinon, on oriente le flux vers l'exécution de l'outil
return "tools"
Étape D : Assemblage final du graphe d’état
On connecte l’ensemble de nos briques pour composer notre application :
# Initialisation de la structure du graphe
workflow = StateGraph(AgentState)
# Enregistrement de nos nœuds applicatifs
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
# Configuration de la transition d'entrée
workflow.add_edge(START, "agent")
# Ajout du routage conditionnel en sortie du nœud agent
workflow.add_conditional_edges(
"agent",
should_continue,
{
"tools": "tools", # Liaison vers le nœud d'exécution des outils
END: END # Liaison vers le point de sortie du graphe
}
)
# Boucle systématique du nœud d'outils vers le nœud agent
workflow.add_edge("tools", "agent")
# Compilation du graphe pour exécution
app = workflow.compile()
Étape E : Lancer l’exécution de la boucle
On initialise l’état pour lancer notre agent autonome :
inputs = {"messages": [("user", "What is 34.5 multiplied by 12?")]}
for chunk in app.stream(inputs, stream_mode="values"):
# Affichage de l'historique des échanges au fur et d'itérations
chunk["messages"][-1].pretty_print()
Pourquoi LangGraph s’est imposé face aux anciennes approches de LangChain
Le passage à LangGraph répond à des besoins précis de contrôle et d’observabilité qui faisaient cruellement défaut auparavant :
- Maîtrise totale du flux : Les anciens moteurs d’exécution se comportaient comme des boîtes noires étanches. LangGraph expose les étapes sous forme de code ouvert, permettant d’injecter des contrôles personnalisés entre chaque étape de la boucle.
- Persistance de l’état : Le système gère nativement des sauvegardes de contexte (checkpoints), ce qui permet d’interrompre une boucle complexe pour la reprendre plus tard sans perte d’historique.
- Débogage temporel (Time Travel) : Grâce au suivi rigoureux de l’état du graphe, on peut remonter le fil d’une exécution défaillante jusqu’à une itération précise, modifier le prompt et rejouer le scénario pour tester les ajustements en conditions réelles.
Comparaison avec les outils d’automatisation traditionnels
La différence fondamentale réside dans l’autonomie décisionnelle au moment de l’exécution. Les outils classiques imposent des chemins de décision figés et câblés par le développeur, tandis qu’une boucle d’agent confie cette logique à l’IA, qui décide elle-même de ses actions et de ses corrections en fonction des retours du système.
| Caractéristique | RPA (Robotic Process Automation) | iPaaS / Flux Linéaires (Zapier, Make) | Code Classique (Scripts, API) | Boucles d’Agents (IA) |
|---|---|---|---|---|
| Moteur décisionnel | Clics et sélecteurs de l’interface utilisateur | Événements déclencheurs et actions figés | Conditions logiques codées en dur (if/else) | Raisonnement et planification par le LLM |
| Gestion de l’ambiguïté | Échec complet immédiat | Arrêt ou nécessite une intervention manuelle | Levée d’exceptions non gérées | Redéfinition de la stratégie et contournement |
| Résistance aux changements de format | Très fragile (casse au moindre changement d’interface) | Sensible aux modifications de schémas d’API | Sensible aux modifications de schémas d’API | Très résilient (compréhension sémantique des formats) |
| Complexité d’installation | Élevée (enregistrement d’écrans et cartographie) | Faible à moyenne (interfaces de glisser-déposer) | Élevée (développement et tests de code) | Faible (instructions en langage naturel et outils clés) |
| Comportement déterministe | Oui | Oui | Oui | Non (probabiliste) |
| Usage recommandé | Saisie de données répétitives sur logiciels anciens | Synchronisation de données entre services SaaS | Opérations rapides, calculs exacts et volumétrie élevée | Recherche exploratoire, saisie floue, traitement de l’imprévu |
Détail des différences de comportement
Pour mieux cerner ces différences, penchons-nous sur des scénarios concrets :
- RPA vs. Boucles d’agents : Un robot RPA configuré pour télécharger des factures en cliquant sur des coordonnées de pixels précises ou un sélecteur CSS cassera dès que le site web changera sa mise en page. Une boucle d’agent équipée d’un outil de navigation web analysera la page de manière sémantique. Si le bouton de téléchargement change de place ou de libellé pour s’appeler “Récupérer la facture”, l’agent comprendra l’intention et effectuera l’action correctement malgré le changement de design.
- iPaaS vs. Boucles d’agents : Des plateformes comme Zapier déplacent des données le long de rails prédéfinis (par exemple : si un nouvel email arrive, extraire la pièce jointe et l’enregistrer dans Drive). Face à un imprévu, comme un email sans pièce jointe ou un fichier compressé (.zip) au lieu d’un PDF, le flux plante. Une boucle d’agent, elle, examine son état de progression. Si elle reçoit un fichier .zip, son étape d’évaluation constatera qu’elle ne peut pas lire ce format directement. Elle appellera alors d’elle-même un outil de décompression pour extraire le PDF et mener à bien sa tâche initiale.
- Scripts classiques vs. Boucles d’agents : Un script brille par sa vitesse d’exécution et sa précision mathématique pour traiter des millions de lignes de données structurées. En revanche, le développeur doit prévoir et coder chaque cas limite à la main. La boucle d’agent est certes plus lente et plus coûteuse car elle requiert des appels fréquents à l’API du modèle de langage, mais elle excelle pour interpréter le langage naturel non structuré, synthétiser des rapports de sources hétérogènes ou explorer des problèmes ouverts.
L’automatisation hybride : le juste compromis
En pratique, je constate qu’il est rarement judicieux d’utiliser une boucle d’agent isolée pour l’ensemble d’un processus, principalement pour des raisons de coût en tokens et de latence. La tendance est plutôt à la mise en place de systèmes hybrides :
- La structure déterministe gère le cadre : L’ingestion des données, la validation des formats et la distribution finale restent confiées à des outils iPaaS ou du code classique pour garantir la fiabilité et la rapidité du système.
- La boucle d’agent gère le traitement adaptatif : Les données complexes, les emails rédigés en langage naturel ou les exceptions non répertoriées sont routés vers une boucle d’agent pour permettre à l’IA de raisonner, d’exploiter ses outils spécifiques et de renvoyer un résultat propre dans le flux de production principal.
L’avenir des systèmes autonomes
Nous assistons actuellement à une transition : nous quittons l’ère des chatbots d’assistance individuels (co-pilotes) pour entrer dans celle de réseaux d’agents synchronisés intégrés à nos infrastructures (auto-pilotes), fonctionnant sous supervision humaine par exception.
Les évolutions technologiques attendues
Quatre axes de développement majeurs se dessinent pour les prochaines années :
- La montée en puissance du calcul au moment de l’inférence (Test-time compute) : Plutôt que de générer une réponse de manière immédiate mot après mot, les futures boucles d’agents consacreront des ressources de calcul en amont pour simuler différents chemins d’exécution possibles, tester leurs idées dans des bacs à sable internes et valider leur stratégie avant de lancer l’appel à un outil concret.
- La spécialisation métier poussée (Deep semantic verticalization) : Les modèles généralistes cèdent du terrain face à des essaims d’agents très spécialisés. En recherche biologique, en développement logiciel ou en analyse juridique, on intègre des nœuds de vérification hautement spécialisés qui garantissent la conformité et la rigueur scientifique des résultats générés.
- L’intégration avec le monde physique : Les passerelles entre le virtuel et le réel se multiplient. Les modèles VLA (Vision-Language-Action) permettent à des systèmes robotiques (drones d’inspection, bras industriels, robots de logistique) d’interpréter des environnements non structurés et de corriger leurs actions physiques en continu, sans programmation préalable de chaque mouvement.
- Des garde-fous de sécurité programmatiques : Pour déployer ces solutions dans des secteurs sensibles, les environnements d’exécution des agents sont de plus en plus cloisonnés (sandbox). Les droits d’accès aux ressources système s’ajustent dynamiquement en fonction du niveau de risque de la tâche à accomplir et de la fiabilité constatée de l’agent.
Feuille de route technologique des capacités autonomes
| Horizon de déploiement | Modèle d’architecture principal | Gestion de l’état et de la mémoire | Cas d’usage types |
|---|---|---|---|
| Court terme | Graphes d’exécution avancés | Mémoire contextuelle court terme, bases vectorielles de routage local | Orchestration d’applications interconnectées, correction de code automatisée, recherche documentaire poussée |
| Moyen terme | Réseaux multi-agents autonomes | Mémoire globale persistante d’une session à l’autre | Audits financiers autonomes, maintenance de micro-services de code, optimisation de lignes de production industrielles |
| Long terme | Boucles décisionnelles physiques embarquées | Couches de connaissances mondiales distribuées, suivi sensoriel temps réel | Gestion de flottes de véhicules autonomes, traitement de télémétrie spatiale, recherche en laboratoire scientifique automatisée |
Les freins qui restent à surmonter
Malgré la vitesse d’évolution de ces technologies, plusieurs défis techniques restent à relever avant d’envisager une adoption généralisée :
- La dérive des erreurs en cascade (Compound error rates) : Dans une boucle à long horizon, une erreur de compréhension ou une mauvaise exécution d’outil à la deuxième étape va fausser l’ensemble des raisonnements suivants. Arrivé à la dixième itération, l’agent se retrouve souvent dans une impasse logique complète.
- Les failles de sécurité par injection indirecte : Les boucles d’agents sont vulnérables aux attaques par injection de prompt cachées dans des contenus tiers (un email, une page web externe). Si l’agent traite une donnée externe piégée par un attaquant, celui-ci peut prendre le contrôle du flux pour dérober ou détruire des données sensibles.
- La rentabilité économique du modèle : Faire tourner des boucles complexes requiert un grand nombre de requêtes aux LLM. Tant que l’efficacité computationnelle de la coordination multi-agents n’aura pas progressé, le développement de scripts déterministes classiques restera privilégié pour toutes les tâches à fort volume et à faible marge commerciale.