FrameworksAgents.com Logo

LangGraph : guide complet pour construire des agents à états

Guidecalendar_todayMis à jour le 31 mars 2026schedule9 min de lecturelanggraph guidelanggraph python

LangGraph (Python/TS) : StateGraph, nodes, edges, checkpoints — construire des agents IA robustes avec cycles et branchements. Guide technique francophone 2026.

LangGraph : guide complet pour construire des agents à états

Les agents IA basés sur des boucles ReAct simples atteignent rapidement leurs limites dès que le flux d'exécution devient non linéaire : que faire quand un agent doit revenir en arrière, corriger une erreur ou prendre une décision conditionnelle ? LangGraph répond à ce problème en modélisant l'exécution d'un agent comme un graphe d'état orienté. Ce guide explique comment LangGraph fonctionne, comment l'installer et configurer un premier agent, et quand l'utiliser (ou non). Si vous hésitez entre plusieurs stacks, le comparatif des frameworks agents IA résume les compromis ; pour une approche modulaire par skills et le déploiement d'agents autonomes, explorez aussi OpenClaw.


Résumé rapide

CritèreValeur
LangagePython (et JavaScript/TypeScript)
ParadigmeGraphe d'état dirigé (StateGraph)
Cas d'usage principalAgents multi-étapes avec logique conditionnelle
Relation avec LangChainBibliothèque indépendante, compatible LangChain
PersistanceCheckpointers (mémoire, SQLite, PostgreSQL)
LicenceMIT

Qu'est-ce que LangGraph ?

LangGraph est une bibliothèque Python (et TypeScript) développée par LangChain Inc. qui permet de construire des agents et des workflows multi-acteurs sous forme de graphes d'état. Elle est indépendante de LangChain au sens où elle n'en requiert pas l'installation, bien qu'elle soit souvent utilisée avec.

Différence avec LangChain

LangChain est une boîte à outils généraliste pour construire des pipelines LLM : chaînes de prompts, intégrations d'outils, retrievers. Son abstraction centrale est la Chain — une séquence d'étapes exécutées de manière linéaire.

LangGraph part d'un constat différent : la plupart des agents réels ne sont pas linéaires. Un agent de recherche peut avoir besoin de vérifier si le résultat obtenu est suffisant, puis soit terminer, soit relancer une nouvelle recherche. Un agent de correction de code peut boucler jusqu'à ce que les tests passent. Ces comportements nécessitent des cycles, des branchements conditionnels et une persistance d'état entre les étapes — ce que LangChain seul gère mal.

LangGraph expose ces concepts explicitement :

  • Nodes : unités de traitement (fonctions Python ou chaînes LangChain)
  • Edges : transitions entre nodes, pouvant être conditionnelles
  • State : objet partagé mis à jour à chaque étape, visible par tous les nodes
  • Checkpoints : snapshots de l'état sauvegardés pour la reprise et le débogage

L'approche par graphes d'état

Un StateGraph est un graphe orienté dont chaque nœud prend l'état courant en entrée, effectue une opération, et retourne une mise à jour partielle de l'état. LangGraph fusionne ces mises à jour dans l'état global selon des règles définies (par défaut, remplacement simple ; avec des Annotated types, accumulation possible).

Cette architecture présente deux avantages concrets. D'abord, le flux d'exécution est explicite et inspectable — on peut visualiser le graphe, comprendre les transitions possibles et déboguer nœud par nœud. Ensuite, les cycles sont natifs : un nœud peut renvoyer vers un nœud précédent sans hack ni récursion manuelle.


Guide conceptuel : construire un agent avec LangGraph

Installation

pip install langgraph langchain-openai

Pour la persistance, selon le backend souhaité :

pip install langgraph-checkpoint-sqlite   # SQLite
pip install langgraph-checkpoint-postgres # PostgreSQL

Définir l'état

L'état est un TypedDict Python. Chaque nœud reçoit cet état et retourne un dictionnaire de mises à jour.

from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages

class AgentState(TypedDict):
    messages: Annotated[list, add_messages]
    iteration: int
    result: str | None

L'annotation Annotated[list, add_messages] indique à LangGraph d'accumuler les messages plutôt que de les remplacer — comportement essentiel pour un historique de conversation.

Créer le graphe

from langgraph.graph import StateGraph, END

graph = StateGraph(AgentState)

Définir les nœuds (nodes)

Un nœud est une fonction Python qui prend l'état et retourne un dictionnaire partiel :

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini")

def agent_node(state: AgentState) -> dict:
    response = llm.invoke(state["messages"])
    return {"messages": [response], "iteration": state["iteration"] + 1}

def tool_node(state: AgentState) -> dict:
    # Exécution d'un outil, ex. recherche web
    last_message = state["messages"][-1]
    tool_result = run_tool(last_message.tool_calls[0])
    return {"messages": [tool_result]}

graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)

Définir les transitions (edges)

Les edges simples connectent deux nœuds directement. Les conditional edges choisissent la destination selon l'état courant.

from langgraph.graph import END

def should_continue(state: AgentState) -> str:
    last_message = state["messages"][-1]
    # Si le LLM a demandé un appel d'outil
    if last_message.tool_calls:
        return "tools"
    # Sinon, on termine
    return END

graph.set_entry_point("agent")
graph.add_conditional_edges("agent", should_continue)
graph.add_edge("tools", "agent")  # Retour vers agent après l'outil

Compiler et exécuter

app = graph.compile()

result = app.invoke({
    "messages": [{"role": "user", "content": "Quel est le cours du Bitcoin aujourd'hui ?"}],
    "iteration": 0,
    "result": None
})

Checkpoints et persistance

Les checkpoints permettent de reprendre un graphe interrompu ou de l'inspecter après exécution. Exemple avec SQLite :

from langgraph.checkpoint.sqlite import SqliteSaver

with SqliteSaver.from_conn_string("agent_state.db") as checkpointer:
    app = graph.compile(checkpointer=checkpointer)
    config = {"configurable": {"thread_id": "session-42"}}
    result = app.invoke(initial_state, config=config)

Chaque étape est sauvegardée avec son thread_id. On peut relancer l'exécution depuis n'importe quel checkpoint, ou récupérer l'historique complet avec app.get_state_history(config).

Cycle de vie d'un agent LangGraph

  1. Entrée : l'état initial est passé au nœud de départ (entry_point)
  2. Exécution du nœud : le nœud traite l'état et retourne une mise à jour
  3. Fusion : LangGraph applique la mise à jour à l'état global
  4. Checkpoint (si configuré) : l'état fusionné est sauvegardé
  5. Routage : l'edge suivant est évalué (simple ou conditionnel)
  6. Répétition jusqu'à atteindre END

Ce cycle est synchrone par défaut mais LangGraph supporte les nœuds async pour les I/O non bloquants.


Exemple concret : agent RAG avec boucle de correction

Cet exemple construit un agent qui récupère des documents, génère une réponse, puis évalue si la réponse est suffisamment précise — et relance une recherche si nécessaire.

from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

# État
class RAGState(TypedDict):
    question: str
    documents: list[str]
    answer: str | None
    is_sufficient: bool
    attempts: int

# Composants
llm = ChatOpenAI(model="gpt-4o-mini")
vectorstore = FAISS.load_local("my_index", OpenAIEmbeddings())

# Nœuds
def retrieve(state: RAGState) -> dict:
    docs = vectorstore.similarity_search(state["question"], k=4)
    return {"documents": [d.page_content for d in docs]}

def generate(state: RAGState) -> dict:
    context = "\n".join(state["documents"])
    prompt = f"Contexte :\n{context}\n\nQuestion : {state['question']}\nRéponse :"
    response = llm.invoke(prompt)
    return {"answer": response.content, "attempts": state["attempts"] + 1}

def evaluate(state: RAGState) -> dict:
    prompt = (
        f"La réponse suivante est-elle complète et précise pour la question '{state['question']}' ?\n"
        f"Réponse : {state['answer']}\n"
        "Réponds uniquement par 'oui' ou 'non'."
    )
    verdict = llm.invoke(prompt).content.strip().lower()
    return {"is_sufficient": verdict == "oui"}

def should_retry(state: RAGState) -> str:
    if state["is_sufficient"] or state["attempts"] >= 3:
        return END
    return "retrieve"  # Nouvelle recherche

# Construction du graphe
graph = StateGraph(RAGState)
graph.add_node("retrieve", retrieve)
graph.add_node("generate", generate)
graph.add_node("evaluate", evaluate)

graph.set_entry_point("retrieve")
graph.add_edge("retrieve", "generate")
graph.add_edge("generate", "evaluate")
graph.add_conditional_edges("evaluate", should_retry)

app = graph.compile()

result = app.invoke({
    "question": "Quels sont les avantages de LangGraph sur LangChain ?",
    "documents": [],
    "answer": None,
    "is_sufficient": False,
    "attempts": 0
})
print(result["answer"])

Cet agent boucle au maximum 3 fois. À chaque itération, il récupère des documents, génère une réponse, l'évalue et décide s'il recommence. Le should_retry combine deux critères d'arrêt : qualité suffisante ou limite d'itérations atteinte.


Bonnes pratiques

Erreurs fréquentes

État mal typé : oublier l'annotation Annotated sur les listes provoque un remplacement à chaque nœud au lieu d'une accumulation. Toujours utiliser add_messages pour les historiques de conversation.

Cycles infinis : un conditional edge qui retourne toujours vers le même nœud sans condition de sortie bloque indéfiniment. Toujours inclure un compteur d'itérations ou une condition d'échec explicite.

Nœuds trop gros : regrouper plusieurs responsabilités dans un seul nœud rend le graphe difficile à déboguer. Chaque nœud doit avoir une responsabilité unique et observable via les checkpoints.

Ignorer les erreurs d'outil : les appels d'API externes échouent. Gérer les exceptions dans les nœuds tool et mettre à jour l'état avec un message d'erreur explicite plutôt que de laisser propager l'exception.

Quand ne pas utiliser LangGraph

  • Pipelines linéaires simples : si votre agent suit toujours les mêmes étapes dans le même ordre, une simple chaîne LangChain ou même une fonction Python suffit. LangGraph ajoute de la complexité sans bénéfice.
  • Prototypage rapide : la définition explicite du graphe ralentit l'itération initiale. Commencez par un script simple, migrez vers LangGraph quand la logique conditionnelle devient nécessaire.
  • Équipes non familières avec les graphes : le modèle mental du graphe d'état demande un temps d'apprentissage. Sur de petites équipes avec peu de temps, ce coût peut dépasser le bénéfice.

Gestion des cycles

Utilisez toujours une limite d'itérations dans l'état et une condition de sortie sur cette limite. Pour les agents longs, configurez recursion_limit à la compilation :

app = graph.compile()
app.invoke(state, config={"recursion_limit": 10})

FAQ

LangGraph est-il une alternative à LangChain ou un complément ?

LangGraph est un complément. Il peut fonctionner sans LangChain, mais il est souvent utilisé avec pour bénéficier des intégrations LLM, des outils et des retrievers déjà disponibles. LangChain gère les appels LLM et les outils ; LangGraph orchestre leur séquençage conditionnel.

LangGraph supporte-t-il les agents multi-acteurs ?

Oui. LangGraph permet de définir plusieurs sous-graphes (un par acteur) et de les faire communiquer via un état partagé ou via des Send events. C'est l'approche recommandée pour les systèmes où plusieurs agents spécialisés collaborent sur une même tâche.

Peut-on utiliser LangGraph en production ?

Oui, LangGraph est utilisé en production par plusieurs entreprises. Pour un déploiement robuste, utiliser un checkpointer PostgreSQL pour la persistance, configurer des timeouts sur les nœuds I/O et activer LangSmith pour le traçage des exécutions.

Quelle est la différence entre LangGraph et AutoGen ?

AutoGen (Microsoft) modélise les agents comme des entités communicantes via des messages. LangGraph modélise l'exécution comme un graphe d'état explicite. LangGraph donne plus de contrôle sur le flux ; AutoGen facilite la collaboration entre agents hétérogènes avec moins de code de plomberie.

LangGraph fonctionne-t-il avec des modèles autres qu'OpenAI ?

Oui. LangGraph est agnostique au modèle LLM. Il fonctionne avec tout modèle supporté par LangChain (Anthropic Claude, Mistral, Ollama, Cohere, etc.) ou directement avec n'importe quel callable Python qui retourne une réponse.


Articles liés

LangGraph s'inscrit dans un écosystème plus large de frameworks d'agents IA. Pour aller plus loin, plusieurs ressources sur ce site couvrent des frameworks complémentaires ou alternatifs.

Restez informé sur les agents IA

Nouveaux tutoriels, comparatifs et guides pratiques directement dans votre boîte mail.

homeAccueilcodeFrameworkssmart_toyAgentsmenu_bookTutorielsTwitter