Systèmes Multi-Agents avec LangGraph en Python : Guide Pratique (2026)

Apprenez à construire des systèmes multi-agents en Python avec LangGraph. Ce guide couvre le pattern superviseur, les agents ReAct, la gestion d'état persistante et les bonnes pratiques de production avec du code fonctionnel.

Introduction : Pourquoi les Systèmes Multi-Agents Dominent en 2026

Soyons honnêtes : en 2026, un agent IA seul, ça ne suffit plus. Les tâches réelles — analyser un marché, automatiser un workflow de support client, orchestrer une pipeline de recherche — tout ça exige la collaboration de plusieurs agents spécialisés. On ne parle plus de chatbots isolés dans leur coin. On parle de véritables équipes d'agents IA qui communiquent, se délèguent des tâches, et partagent un état commun.

C'est exactement là que LangGraph entre en jeu.

Développé par l'équipe LangChain, LangGraph s'est imposé comme le framework de référence pour orchestrer des systèmes multi-agents en production. Son approche basée sur les graphes — avec des nœuds, des arêtes, et une gestion d'état persistante — offre un niveau de contrôle que les architectures linéaires ne peuvent tout simplement pas égaler. Et croyez-moi, une fois qu'on y a goûté, on ne revient plus en arrière.

Dans ce guide, on va construire ensemble un système multi-agents complet en Python : depuis un agent simple avec des outils, jusqu'à une architecture superviseur orchestrant plusieurs agents spécialisés. Chaque section inclut du code fonctionnel que vous pouvez copier-coller et exécuter immédiatement.

Les Fondamentaux de LangGraph : Graphes, État et Nœuds

Avant de se lancer dans la construction d'agents, il faut comprendre les briques de base de LangGraph. Le framework repose sur trois concepts fondamentaux, et c'est important de bien les maîtriser avant d'aller plus loin.

Le StateGraph : Le Cœur du Système

Un StateGraph, c'est un graphe orienté où chaque nœud est une fonction Python et les arêtes définissent les transitions entre ces fonctions. L'état — un dictionnaire typé — circule entre les nœuds et s'enrichit à chaque étape. Pensez-y comme une chaîne de montage, mais intelligente.

from langgraph.graph import START, END, StateGraph
from typing_extensions import TypedDict
from typing import Annotated
from langgraph.graph.message import add_messages

# Définir la structure de l'état partagé
class EtatAgent(TypedDict):
    messages: Annotated[list, add_messages]
    tache_courante: str
    resultats: dict

# Créer le graphe
graphe = StateGraph(EtatAgent)

# Définir les nœuds (fonctions Python)
def analyser_requete(state: EtatAgent) -> dict:
    """Analyse la requête utilisateur et détermine la tâche."""
    dernier_message = state["messages"][-1].content
    return {
        "tache_courante": "analyse",
        "resultats": {"requete_analysee": dernier_message}
    }

def generer_reponse(state: EtatAgent) -> dict:
    """Génère une réponse basée sur l'analyse."""
    return {
        "tache_courante": "generation",
        "resultats": {**state["resultats"], "reponse": "Réponse générée"}
    }

# Assembler le graphe
graphe.add_node("analyser", analyser_requete)
graphe.add_node("generer", generer_reponse)
graphe.add_edge(START, "analyser")
graphe.add_edge("analyser", "generer")
graphe.add_edge("generer", END)

# Compiler et exécuter
app = graphe.compile()
resultat = app.invoke({
    "messages": [("user", "Quels sont les tendances IA en 2026 ?")],
    "tache_courante": "",
    "resultats": {}
})
print(resultat["resultats"])

Arêtes Conditionnelles : Le Routage Intelligent

Bon, la vraie puissance de LangGraph, elle est là : les arêtes conditionnelles. Contrairement à un pipeline linéaire, le graphe peut prendre des décisions de routage dynamiques basées sur l'état courant. C'est ce mécanisme qui permet de construire des boucles de raisonnement — l'agent réfléchit, agit, observe, puis décide s'il doit continuer ou s'arrêter.

from langgraph.graph import START, END, StateGraph

def router(state: EtatAgent) -> str:
    """Décide quel nœud exécuter ensuite."""
    if "erreur" in state["resultats"]:
        return "corriger"
    elif state["tache_courante"] == "analyse":
        return "generer"
    else:
        return END

graphe.add_conditional_edges(
    "analyser",
    router,
    {
        "generer": "generer",
        "corriger": "corriger",
        END: END
    }
)

Construire un Agent ReAct avec des Outils

Le pattern ReAct (Reasoning + Acting), c'est le fondement des agents autonomes. L'idée est simple mais puissante : l'agent alterne entre une phase de raisonnement (quel outil utiliser ?) et une phase d'action (exécuter l'outil), jusqu'à ce qu'il estime avoir assez d'informations pour répondre.

LangGraph fournit create_react_agent pour construire rapidement un agent ReAct avec des outils personnalisés. Et franchement, c'est assez élégant.

Définir des Outils Personnalisés

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
import json
import requests

@tool
def recherche_web(requete: str) -> str:
    """Recherche des informations sur le web pour une requête donnée."""
    # Simulation — en production, connectez une vraie API de recherche
    return f"Résultats de recherche pour : {requete}\n- Article 1 : Tendances IA 2026\n- Article 2 : LangGraph en production"

@tool
def calculer(expression: str) -> str:
    """Évalue une expression mathématique et retourne le résultat."""
    try:
        resultat = eval(expression)  # En production, utilisez un parser sécurisé
        return f"Résultat : {resultat}"
    except Exception as e:
        return f"Erreur de calcul : {str(e)}"

@tool
def lire_fichier(chemin: str) -> str:
    """Lit le contenu d'un fichier et retourne son texte."""
    try:
        with open(chemin, "r", encoding="utf-8") as f:
            contenu = f.read()
        return contenu[:2000]  # Limiter la taille
    except FileNotFoundError:
        return f"Fichier non trouvé : {chemin}"

Créer l'Agent ReAct

# Initialiser le modèle LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# Créer l'agent ReAct avec les outils
agent = create_react_agent(
    model=llm,
    tools=[recherche_web, calculer, lire_fichier],
    name="assistant_recherche",
    prompt="Tu es un assistant de recherche expert. Utilise tes outils pour répondre aux questions de manière précise et complète. Réponds toujours en français."
)

# Exécuter l'agent
resultat = agent.invoke({
    "messages": [
        ("user", "Combien font 15% de 2450 ? Puis cherche les tendances IA 2026.")
    ]
})

# Afficher la conversation complète
for message in resultat["messages"]:
    print(f"{message.type}: {message.content[:200]}")

Ce qui est intéressant ici, c'est que l'agent va automatiquement décider d'utiliser l'outil calculer pour le calcul, puis recherche_web pour la recherche — le tout dans une boucle ReAct autonome. Pas besoin de coder la logique de décision vous-même, LangGraph gère la boucle think-act-observe en arrière-plan.

Architecture Superviseur : Orchestrer Plusieurs Agents

Allez, on passe au cœur du sujet : le pattern superviseur. C'est probablement la partie la plus intéressante de ce guide.

Dans cette architecture, un agent central — le superviseur — coordonne plusieurs agents spécialisés. Chaque agent a son propre domaine d'expertise et ses propres outils. Le superviseur décide à qui déléguer chaque sous-tâche, un peu comme un chef de projet qui répartit le travail dans son équipe.

Pourquoi ce pattern ? Parce qu'un agent unique qui essaie de tout faire devient rapidement ingérable (et croyez-moi, j'en ai fait l'expérience). La séparation des responsabilités permet un débogage plus facile, une meilleure scalabilité, et des résultats nettement plus fiables.

Installer les Dépendances

pip install langgraph langgraph-supervisor langchain-openai langchain-core

Créer les Agents Spécialisés

from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor
from langchain_core.tools import tool

# --- Outils pour l'agent de recherche ---
@tool
def recherche_articles(sujet: str) -> str:
    """Recherche des articles récents sur un sujet donné."""
    return f"""Articles trouvés sur "{sujet}" :
1. "Les systèmes multi-agents en production" - TechBlog, Fév 2026
2. "LangGraph vs CrewAI : benchmark comparatif" - AI Weekly, Jan 2026
3. "Architectures agentiques pour l'entreprise" - InfoQ, Fév 2026"""

@tool
def extraire_donnees_web(url: str) -> str:
    """Extrait les données principales d'une page web."""
    return f"Données extraites de {url} : [contenu simulé pour la démonstration]"

# --- Outils pour l'agent d'analyse ---
@tool
def analyser_sentiment(texte: str) -> str:
    """Analyse le sentiment d'un texte (positif, négatif, neutre)."""
    # En production, utilisez un vrai modèle de sentiment
    mots_positifs = ["excellent", "innovant", "progrès", "amélioration"]
    score = sum(1 for mot in mots_positifs if mot in texte.lower())
    if score > 1:
        return "Sentiment : Positif (confiance : 85%)"
    return "Sentiment : Neutre (confiance : 70%)"

@tool
def resumer_texte(texte: str, longueur_max: int = 100) -> str:
    """Résume un texte en conservant les points essentiels."""
    mots = texte.split()
    if len(mots) <= longueur_max:
        return texte
    return " ".join(mots[:longueur_max]) + "..."

# --- Outils pour l'agent rédacteur ---
@tool
def generer_plan(sujet: str, sections: int = 4) -> str:
    """Génère un plan structuré pour un article."""
    return f"""Plan pour "{sujet}" :
1. Introduction et contexte
2. État de l'art et tendances actuelles
3. Analyse comparative et recommandations
4. Conclusion et perspectives"""

@tool
def verifier_orthographe(texte: str) -> str:
    """Vérifie l'orthographe et la grammaire d'un texte."""
    return f"Vérification terminée : aucune erreur détectée ({len(texte)} caractères analysés)"

# Créer les agents spécialisés
llm = ChatOpenAI(model="gpt-4o", temperature=0)

agent_recherche = create_react_agent(
    model=llm,
    tools=[recherche_articles, extraire_donnees_web],
    name="chercheur",
    prompt="Tu es un expert en recherche documentaire. Trouve des informations pertinentes et récentes sur les sujets demandés. Réponds en français."
)

agent_analyse = create_react_agent(
    model=llm,
    tools=[analyser_sentiment, resumer_texte],
    name="analyste",
    prompt="Tu es un analyste de données textuelles. Analyse les textes qui te sont soumis pour en extraire les informations clés. Réponds en français."
)

agent_redacteur = create_react_agent(
    model=llm,
    tools=[generer_plan, verifier_orthographe],
    name="redacteur",
    prompt="Tu es un rédacteur technique spécialisé en IA. Rédige du contenu clair, structuré et engageant. Réponds en français."
)

Assembler le Superviseur

# Créer le workflow superviseur
workflow = create_supervisor(
    agents=[agent_recherche, agent_analyse, agent_redacteur],
    model=ChatOpenAI(model="gpt-4o", temperature=0),
    prompt="""Tu es un chef de projet éditorial qui coordonne une équipe de trois spécialistes :
- "chercheur" : recherche des informations et des sources
- "analyste" : analyse les données et extrait les insights
- "redacteur" : rédige le contenu final

Pour chaque demande, décompose la tâche et délègue aux bons agents dans l'ordre logique.
Commence toujours par la recherche, puis l'analyse, et enfin la rédaction."""
)

# Compiler avec gestion de mémoire
from langgraph.checkpoint.memory import InMemorySaver

checkpointer = InMemorySaver()
app = workflow.compile(checkpointer=checkpointer)

# Exécuter le système multi-agents
resultat = app.invoke(
    {
        "messages": [
            ("user", "Fais une analyse des tendances en IA agentique pour février 2026 et rédige un résumé exécutif.")
        ]
    },
    config={"configurable": {"thread_id": "session-001"}}
)

# Afficher les échanges entre agents
for msg in resultat["messages"]:
    role = getattr(msg, "name", msg.type)
    print(f"[{role}] {msg.content[:300]}")
    print("---")

Gestion d'État et Mémoire Persistante

Un des avantages majeurs de LangGraph sur les autres frameworks, c'est sa gestion d'état native. Et honnêtement, c'est un vrai game-changer. Chaque nœud du graphe reçoit l'état courant et renvoie les modifications à appliquer. Concrètement, ça signifie que vous pouvez inspecter, persister et même rejouer n'importe quel point de l'exécution.

État Partagé entre Agents

Dans un système multi-agents, l'état partagé est le mécanisme de communication principal. Plutôt que de faire passer des messages libres entre agents (ce qui devient vite le chaos), on structure l'information dans un état typé.

from typing_extensions import TypedDict
from typing import Annotated, Optional
from langgraph.graph.message import add_messages
from pydantic import BaseModel, Field

# État structuré pour un workflow de recherche
class EtatRecherche(TypedDict):
    messages: Annotated[list, add_messages]
    sources: list[dict]          # Sources trouvées par le chercheur
    analyse: Optional[str]       # Résultat de l'analyse
    rapport_final: Optional[str] # Rapport rédigé
    statut: str                  # "recherche" | "analyse" | "redaction" | "termine"

# Validation avec Pydantic pour la production
class SourceDocument(BaseModel):
    titre: str = Field(description="Titre du document source")
    url: str = Field(description="URL de la source")
    pertinence: float = Field(ge=0, le=1, description="Score de pertinence")
    resume: str = Field(description="Résumé du contenu")

Persistance avec SQLite

Pour un déploiement en production, vous allez vouloir persister l'état entre les redémarrages du serveur. Bonne nouvelle : LangGraph supporte nativement plusieurs backends de persistance.

from langgraph.checkpoint.sqlite import SqliteSaver
import sqlite3

# Persistance SQLite pour la production
conn = sqlite3.connect("agent_checkpoints.db", check_same_thread=False)
checkpointer_sqlite = SqliteSaver(conn)

# Compiler le workflow avec persistance SQLite
app_production = workflow.compile(checkpointer=checkpointer_sqlite)

# Chaque conversation est identifiée par un thread_id
config = {"configurable": {"thread_id": "projet-alpha-001"}}

# Premier appel
resultat_1 = app_production.invoke(
    {"messages": [("user", "Recherche les dernières avancées en RAG agentique.")]},
    config=config
)

# Deuxième appel — reprend avec tout le contexte précédent
resultat_2 = app_production.invoke(
    {"messages": [("user", "Maintenant, compare ces avancées avec ce qu'on avait l'année dernière.")]},
    config=config
)

# L'agent se souvient de la conversation précédente
print(resultat_2["messages"][-1].content)

Construire un Graphe Manuel avec ToolNode

Pour ceux qui veulent un contrôle total sur le flux d'exécution, il est possible de construire le graphe manuellement au lieu d'utiliser create_react_agent. Cette approche est particulièrement utile quand vous avez besoin de logique conditionnelle complexe, de nœuds de validation, ou de routage personnalisé entre les outils.

C'est plus de travail, certes, mais la flexibilité en vaut la peine.

from langgraph.graph import START, END, StateGraph, MessagesState
from langgraph.prebuilt import ToolNode, tools_condition
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.messages import SystemMessage

# Définir les outils
@tool
def consulter_base_connaissances(question: str) -> str:
    """Consulte la base de connaissances interne pour répondre à une question technique."""
    base = {
        "langgraph": "LangGraph est un framework pour construire des agents IA stateful basés sur des graphes.",
        "react": "Le pattern ReAct combine raisonnement et action dans une boucle itérative.",
        "superviseur": "Le pattern superviseur utilise un agent central pour coordonner des agents spécialisés."
    }
    for cle, valeur in base.items():
        if cle in question.lower():
            return valeur
    return "Aucune information trouvée dans la base de connaissances."

@tool
def envoyer_notification(destinataire: str, message: str) -> str:
    """Envoie une notification à un utilisateur."""
    return f"Notification envoyée à {destinataire} : {message}"

outils = [consulter_base_connaissances, envoyer_notification]

# Configurer le LLM avec les outils
llm = ChatOpenAI(model="gpt-4o", temperature=0)
llm_avec_outils = llm.bind_tools(outils)

# Définir le nœud assistant
def noeud_assistant(state: MessagesState) -> dict:
    """Le nœud principal qui raisonne et décide des actions."""
    system_msg = SystemMessage(
        content="Tu es un assistant technique expert en systèmes multi-agents. "
                "Utilise tes outils quand c'est nécessaire. Réponds en français."
    )
    reponse = llm_avec_outils.invoke([system_msg] + state["messages"])
    return {"messages": [reponse]}

# Construire le graphe manuellement
builder = StateGraph(MessagesState)

# Ajouter les nœuds
builder.add_node("assistant", noeud_assistant)
builder.add_node("outils", ToolNode(outils))

# Définir les arêtes
builder.add_edge(START, "assistant")
builder.add_conditional_edges(
    "assistant",
    tools_condition,  # Route vers "outils" si le LLM appelle un outil, sinon vers END
)
builder.add_edge("outils", "assistant")  # Retour à l'assistant après l'exécution de l'outil

# Compiler
agent_manuel = builder.compile()

# Tester
resultat = agent_manuel.invoke({
    "messages": [("user", "Explique-moi ce qu'est LangGraph, puis envoie une notification à Pierre pour lui dire que le rapport est prêt.")]
})

for msg in resultat["messages"]:
    if hasattr(msg, "content") and msg.content:
        print(f"[{msg.type}] {msg.content[:300]}")

Patterns de Communication entre Agents

LangGraph supporte plusieurs stratégies de communication entre agents. Le choix du bon pattern dépend vraiment de votre cas d'usage — il n'y a pas de solution universelle ici.

Pattern Séquentiel

Les agents s'exécutent dans un ordre prédéfini, chaque agent recevant le résultat du précédent. C'est le pattern le plus simple et le plus prévisible. Idéal pour les pipelines de traitement linéaires — extraction, nettoyage, analyse, rapport.

from langgraph.graph import START, END, StateGraph

class EtatPipeline(TypedDict):
    messages: Annotated[list, add_messages]
    donnees_brutes: str
    donnees_nettoyees: str
    analyse: str
    rapport: str

graphe = StateGraph(EtatPipeline)

# Chaîne séquentielle : chaque agent enrichit l'état
graphe.add_node("extracteur", agent_extraction)
graphe.add_node("nettoyeur", agent_nettoyage)
graphe.add_node("analyste", agent_analyse_fn)
graphe.add_node("rapporteur", agent_rapport)

graphe.add_edge(START, "extracteur")
graphe.add_edge("extracteur", "nettoyeur")
graphe.add_edge("nettoyeur", "analyste")
graphe.add_edge("analyste", "rapporteur")
graphe.add_edge("rapporteur", END)

Pattern Parallèle avec Consolidation

Là, ça devient intéressant. Plusieurs agents travaillent simultanément sur différents aspects d'un problème, puis un agent consolidateur synthétise les résultats. Parfait pour les analyses multi-perspectives — et on gagne un temps considérable par rapport au séquentiel.

from langgraph.constants import Send

class EtatParallele(TypedDict):
    messages: Annotated[list, add_messages]
    requete: str
    resultats_partiels: Annotated[list, lambda x, y: x + y]
    synthese: str

def distribuer_taches(state: EtatParallele):
    """Distribue la tâche à plusieurs agents en parallèle."""
    return [
        Send("agent_technique", {"requete": state["requete"], "perspective": "technique"}),
        Send("agent_marche", {"requete": state["requete"], "perspective": "marché"}),
        Send("agent_legal", {"requete": state["requete"], "perspective": "juridique"}),
    ]

graphe_parallele = StateGraph(EtatParallele)
graphe_parallele.add_node("agent_technique", analyser_technique)
graphe_parallele.add_node("agent_marche", analyser_marche)
graphe_parallele.add_node("agent_legal", analyser_legal)
graphe_parallele.add_node("consolidateur", consolider_resultats)

graphe_parallele.add_conditional_edges(START, distribuer_taches)
graphe_parallele.add_edge("agent_technique", "consolidateur")
graphe_parallele.add_edge("agent_marche", "consolidateur")
graphe_parallele.add_edge("agent_legal", "consolidateur")
graphe_parallele.add_edge("consolidateur", END)

Pattern Conditionnel (Routage Dynamique)

Le superviseur route dynamiquement les tâches vers l'agent le plus approprié en fonction du contenu de la requête. C'est le pattern le plus flexible et, d'après mon expérience, le plus couramment utilisé en production.

def router_intelligent(state: EtatAgent) -> str:
    """Route vers l'agent spécialisé en fonction de la tâche."""
    dernier_message = state["messages"][-1].content.lower()

    if any(mot in dernier_message for mot in ["cherche", "trouve", "recherche", "source"]):
        return "chercheur"
    elif any(mot in dernier_message for mot in ["analyse", "compare", "évalue", "sentiment"]):
        return "analyste"
    elif any(mot in dernier_message for mot in ["rédige", "écris", "résume", "rapport"]):
        return "redacteur"
    else:
        return "superviseur"  # Le superviseur gère les cas ambigus

graphe.add_conditional_edges(
    "superviseur",
    router_intelligent,
    {
        "chercheur": "chercheur",
        "analyste": "analyste",
        "redacteur": "redacteur",
        "superviseur": "superviseur"
    }
)

LangGraph vs CrewAI vs AutoGen : Quel Framework Choisir ?

La question qui revient tout le temps. En 2026, trois frameworks dominent l'écosystème multi-agents, et chacun a ses forces. Voici comment ils se comparent concrètement.

Tableau Comparatif

CritèreLangGraphCrewAIAutoGen
PhilosophieContrôle total via les graphesÉquipes basées sur les rôlesConversations multi-agents
Courbe d'apprentissageModérée à élevéeFaibleModérée
Gestion d'étatNative, persistante, typéeBasiquePar conversation
DébogageExcellent (replay, inspection)LimitéMoyen
Production-readyOui (LangGraph Platform)En progressionExpérimental
Cas d'usage idéalWorkflows complexes, compliancePrototypage rapide, contenuBrainstorming, débats
Protocoles ouvertsMCP (en cours)A2A supportéPas encore

Quand choisir LangGraph ? Si vous avez besoin d'un contrôle fin sur le flux d'exécution, de persistance d'état, de rejouabilité (le fameux « time travel »), ou si vous déployez dans un contexte réglementé — finance, santé, juridique. LangGraph est aussi le meilleur choix quand il faut garantir l'observabilité de chaque étape du workflow. Chaque décision de l'agent est traçable, et en production, ça n'a pas de prix.

Quand choisir CrewAI ? Pour du prototypage rapide, des pipelines de contenu, ou des workflows métier où les rôles sont clairement définis. Les benchmarks de 2026 montrent que CrewAI est 5 à 6 fois plus rapide à déployer pour des tâches structurées.

Quand choisir AutoGen ? Pour des systèmes conversationnels multi-agents, des scénarios de brainstorming ou de débat, et des workflows avec boucle humaine fréquente. C'est un excellent choix quand la collaboration entre agents passe principalement par le dialogue.

Bonnes Pratiques pour la Production

Déployer un système multi-agents en production, c'est une autre histoire que de faire tourner un prototype sur son laptop. Voici les leçons qu'on retient après quelques déploiements réels.

1. Observabilité avec LangSmith

En production, vous devez pouvoir tracer chaque appel LLM, chaque utilisation d'outil, et chaque transition entre agents. Sans ça, le débogage devient un cauchemar. LangSmith s'intègre nativement avec LangGraph et la mise en place est triviale.

import os

# Activer le tracing LangSmith
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "votre_cle_langsmith"
os.environ["LANGSMITH_PROJECT"] = "multi-agents-production"

# Le tracing est automatique — chaque invocation du graphe
# est enregistrée dans LangSmith avec tous les détails

2. Gestion des Erreurs et Timeout

Les boucles infinies, ça arrive. Surtout au début. Mettez en place des garde-fous dès le départ.

from langchain_core.runnables import RunnableConfig

# Configuration avec limites
config = RunnableConfig(
    recursion_limit=25,     # Limite les boucles infinies
    configurable={
        "thread_id": "prod-session-001"
    }
)

# Wrapper avec gestion d'erreurs
async def executer_avec_securite(app, messages, config):
    """Exécute le workflow avec gestion d'erreurs robuste."""
    try:
        resultat = await app.ainvoke(
            {"messages": messages},
            config=config
        )
        return resultat
    except RecursionError:
        return {"erreur": "Le workflow a dépassé la limite de récursion."}
    except TimeoutError:
        return {"erreur": "Le workflow a dépassé le temps imparti."}
    except Exception as e:
        return {"erreur": f"Erreur inattendue : {str(e)}"}

3. Human-in-the-Loop

Pour les décisions critiques — et il y en a toujours en production — LangGraph permet d'interrompre le workflow et d'attendre une validation humaine avant de continuer. C'est indispensable dans les contextes où une erreur de l'agent peut avoir des conséquences réelles.

from langgraph.types import interrupt, Command

def noeud_validation_humaine(state: EtatAgent) -> Command:
    """Interrompt le workflow pour validation humaine."""
    decision = interrupt({
        "question": "Approuvez-vous cette analyse ?",
        "donnees": state["resultats"],
        "options": ["approuver", "rejeter", "modifier"]
    })

    if decision == "approuver":
        return Command(goto="generer_rapport")
    elif decision == "rejeter":
        return Command(goto="relancer_analyse")
    else:
        return Command(goto="modifier_parametres")

4. Streaming des Réponses

Le streaming en temps réel, c'est essentiel pour l'expérience utilisateur. Personne n'a envie de fixer un écran blanc pendant 30 secondes en attendant que trois agents terminent leur travail.

# Streaming en temps réel — essentiel pour l'UX
async for event in app.astream_events(
    {"messages": [("user", "Analyse ce marché")]},
    config=config,
    version="v2"
):
    if event["event"] == "on_chat_model_stream":
        token = event["data"]["chunk"].content
        if token:
            print(token, end="", flush=True)
    elif event["event"] == "on_tool_start":
        print(f"\n🔧 Outil appelé : {event['name']}")
    elif event["event"] == "on_chain_start":
        print(f"\n📍 Nœud actif : {event['name']}")

FAQ

Quelle est la différence entre LangChain et LangGraph ?

LangChain est un framework de haut niveau pour construire rapidement des applications LLM avec des chaînes et des agents. LangGraph, lui, c'est le framework d'orchestration bas niveau qui fonctionne sous le capot. En 2026, LangChain utilise LangGraph en interne. En résumé : utilisez LangChain pour du prototypage rapide et LangGraph quand vous avez besoin d'un contrôle fin sur le flux d'exécution, la gestion d'état, et la persistance.

Combien d'agents peut-on orchestrer avec LangGraph ?

Il n'y a pas de limite technique stricte. En pratique, les systèmes en production qu'on voit en 2026 utilisent typiquement entre 3 et 15 agents spécialisés. Au-delà, il vaut mieux adopter une architecture hiérarchique avec des superviseurs intermédiaires — un superviseur principal qui coordonne des sous-superviseurs, chacun gérant un sous-ensemble d'agents.

LangGraph est-il compatible avec des modèles autres que OpenAI ?

Absolument. LangGraph fonctionne avec n'importe quel LLM compatible avec LangChain : Claude d'Anthropic, Gemini de Google, Mistral, Llama via Ollama, les modèles Amazon Bedrock, et bien d'autres. La syntaxe simplifiée model="anthropic:claude-sonnet-4-20250514" est d'ailleurs supportée pour les modèles les plus courants avec create_react_agent.

Comment déboguer un système multi-agents qui ne fonctionne pas comme prévu ?

LangGraph offre plusieurs mécanismes de débogage, et c'est un de ses gros points forts. Le « time travel » permet de rejouer l'exécution depuis n'importe quel checkpoint. LangSmith fournit une trace complète de chaque appel LLM et outil. Vous pouvez aussi ajouter des nœuds de logging dans votre graphe pour inspecter l'état à chaque transition. Et en dernier recours, la méthode get_state() permet d'inspecter l'état du graphe à tout moment.

Peut-on utiliser le protocole MCP avec LangGraph ?

Oui, et c'est une combinaison puissante. Depuis 2025, LangGraph supporte les serveurs MCP (Model Context Protocol) via la bibliothèque langchain-mcp-adapters. Ça permet à vos agents d'utiliser des outils standardisés MCP — se connecter à des bases de données, des API tierces, ou des systèmes de fichiers — sans écrire de connecteurs personnalisés. Le support du protocole A2A (Agent2Agent) de Google est attendu courant 2026.

À propos de l'auteur Editorial Team

Our team of expert writers and editors.