Aller au contenu
Développement medium

LangGraph multi-agents : le pattern superviseur

16 min de lecture

logo python

Un agent unique tient mal une tâche qui mêle des compétences différentes : écrire, relire, vérifier des faits demandent des consignes contradictoires dans un même prompt. La réponse : faire collaborer plusieurs agents spécialisés. Ce guide construit une équipe de rédaction avec LangGraph — un rédacteur, un relecteur, un fact-checker — coordonnée par un superviseur, le nœud central qui décide qui intervient et quand. Vous verrez d'abord les trois architectures multi-agents de référence — superviseur, swarm, hiérarchique —, puis l'implémentation concrète du superviseur, avec une boucle de correction qui renvoie le brouillon en révision tant que les faits ne tiennent pas. Public visé : développeur ayant lu le guide sur LangGraph et son modèle de graphe d'états.

  • Pourquoi plusieurs agents spécialisés battent un agent généraliste.
  • Les trois architectures multi-agents : superviseur, swarm, hiérarchique.
  • Structurer l'état partagé d'une équipe d'agents.
  • Écrire un superviseur qui oriente le travail et boucle pour corriger.
  • Situer LangGraph face à CrewAI et AutoGen.

Ce guide prolonge Agents stateful avec LangGraph : son modèle de graphe — état, nœuds, arêtes — est réutilisé tel quel. Il vous faut :

  • Une instance Ollama avec le modèle qwen2.5.
  • Les bases de LangGraph et de Pydantic.
  • Python 3.10+.

Un agent, c'est un modèle, un prompt système, des outils. Tant que la tâche est homogène, un seul suffit. Mais dès qu'elle réclame des postures différentes, le prompt unique craque : demander au même agent d'« écrire avec enthousiasme » et de « vérifier les faits avec scepticisme » lui donne deux consignes qui se neutralisent.

Découper règle le problème. Chaque agent spécialisé reçoit un prompt court et net — une seule posture, une seule responsabilité. Le rédacteur écrit, le relecteur critique, le fact-checker doute. Chacun fait une chose bien, et l'ensemble produit un résultat qu'aucun agent seul n'atteindrait.

Reste à les coordonner : qui passe la main à qui, dans quel ordre, jusqu'à quand. C'est là qu'interviennent les architectures multi-agents — et LangGraph, dont le modèle de graphe se prête naturellement à plusieurs nœuds-agents reliés.

Trois manières d'organiser une équipe d'agents reviennent partout. Les connaître évite de réinventer une coordination bancale.

L'architecture superviseur place un orchestrateur central. Les agents spécialisés ne se parlent pas entre eux : ils reviennent tous au superviseur, seul à décider de la suite. C'est la plus lisible et la plus répandue — un seul point qui détient la logique de coordination.

L'architecture swarm (essaim) supprime le centre : chaque agent peut passer la main directement à un autre quand il juge que ce n'est plus son rôle. Plus souple pour des parcours imprévisibles, mais la logique de coordination se disperse dans tous les agents — plus difficile à suivre et à déboguer.

L'architecture hiérarchique compose : un superviseur de haut niveau orchestre des équipes, chacune étant elle-même un graphe avec son propre superviseur. C'est la réponse au passage à l'échelle, quand une équipe plate devient trop large.

ArchitectureCoordinationQuand la choisir
SuperviseurCentralisée, un orchestrateurDéfaut — la plus lisible et débogable
SwarmDistribuée, passages de main directsParcours ouverts, peu prévisibles
HiérarchiqueSuperviseurs imbriquésBeaucoup d'agents, besoin de découper

Ce guide implémente le superviseur : c'est le bon point de départ, et le seul dont on a besoin pour une équipe de trois agents.

Comme tout graphe LangGraph, l'équipe travaille sur un état partagé — un TypedDict. Ici, c'est le plan de travail du brouillon : chaque agent y lit ce dont il a besoin et y écrit son apport.

from typing_extensions import TypedDict
class EtatRedaction(TypedDict):
sujet: str # le thème du brouillon à produire
brouillon: str # écrit par le rédacteur
revue: str # notes de style du relecteur
verdict: str # "ok" ou "problemes", rendu par le fact-checker
commentaire: str # justification du fact-checker
revisions: int # nombre de passes du rédacteur
prochaine_etape: str # décidée par le superviseur

Ce dictionnaire est le seul canal de communication entre les agents. Le relecteur ne connaît pas le rédacteur : il lit brouillon, écrit revue. Ce découplage par l'état est ce qui rend l'équipe extensible — ajouter un agent, c'est ajouter un nœud qui lit et écrit des clés, sans toucher aux autres.

Chaque agent est un nœud du graphe : une fonction qui appelle le modèle avec un rôle précis. Le rédacteur écrit le brouillon — ou le révise si le superviseur l'y renvoie après un problème.

from langchain_ollama import ChatOllama
LLM = ChatOllama(model="qwen2.5", base_url="http://localhost:11434", temperature=0)
def redacteur(etat: EtatRedaction) -> dict:
"""Agent rédacteur : écrit le brouillon, ou le révise si on l'y renvoie."""
if etat.get("commentaire"):
consigne = (
f"Révise ce brouillon en corrigeant ce point précis : "
f"{etat['commentaire']}.\n\nBrouillon actuel :\n{etat['brouillon']}"
)
else:
consigne = f"Rédige un brouillon court, un paragraphe, sur : {etat['sujet']}."
reponse = LLM.invoke(
[
("system", "Tu es un rédacteur technique. Tu écris en français, "
"clair et factuel. Tu renvoies uniquement le texte du "
"brouillon, sans préambule ni liste de corrections."),
("human", consigne),
]
)
return {
"brouillon": reponse.content,
"revisions": etat.get("revisions", 0) + 1,
# Une nouvelle version annule la revue et le verdict précédents.
"revue": "", "verdict": "", "commentaire": "",
}

Le fact-checker mérite une attention particulière : son verdict doit être exploitable par le superviseur, pas un paragraphe à interpréter. On lui impose donc une sortie structurée — la technique du guide PydanticAI, ici via with_structured_output.

from typing import Literal
from pydantic import BaseModel, Field
class Verification(BaseModel):
verdict: Literal["ok", "problemes"] = Field(
description="ok si les affirmations du brouillon tiennent"
)
commentaire: str = Field(description="Justification du verdict, une phrase")
def fact_checker(etat: EtatRedaction) -> dict:
"""Agent fact-checker : vérifie les faits et rend un verdict structuré."""
verif = LLM.with_structured_output(Verification).invoke(
[
("system", "Tu es un fact-checker. Tu vérifies si les affirmations "
"du texte sont exactes."),
("human", f"Vérifie les faits de ce brouillon :\n{etat['brouillon']}"),
]
)
return {"verdict": verif.verdict, "commentaire": verif.commentaire}

Le relecteur suit le même moule — un appel au modèle avec un rôle de critique de style — et écrit ses notes dans revue. Trois agents, trois prompts courts, trois responsabilités nettes.

Le superviseur est le cœur du pattern. C'est un nœud qui ne produit aucun contenu : il décide quel agent intervient ensuite, en lisant l'état.

MAX_REVISIONS = 2
def superviseur(etat: EtatRedaction) -> dict:
"""Décide quel agent intervient ensuite — le cœur du pattern."""
if not etat.get("brouillon"):
etape = "redacteur"
elif not etat.get("revue"):
etape = "relecteur"
elif not etat.get("verdict"):
etape = "fact_checker"
elif etat["verdict"] == "problemes" and etat["revisions"] <= MAX_REVISIONS:
etape = "redacteur" # le fact-checker a trouvé un problème : on révise
else:
etape = "FIN"
return {"prochaine_etape": etape}

Sa logique se lit comme une liste de priorités : pas de brouillon → le rédacteur ; un brouillon mais pas de revue → le relecteur ; et ainsi de suite. La force du pattern tient dans un point : toute la coordination est ici, dans cette seule fonction. Pour comprendre l'enchaînement de l'équipe, on lit le superviseur — pas les trois agents.

Le superviseur n'enchaîne pas seulement les agents : il sait revenir en arrière. Quand le fact-checker rend le verdict problemes, le superviseur renvoie au rédacteur — qui révise en tenant compte du commentaire. C'est une boucle de correction : l'équipe itère jusqu'à ce que les faits tiennent.

Sans garde-fou, un fact-checker exigeant pourrait renvoyer sans fin. Le plafond MAX_REVISIONS borne la boucle : passé ce nombre de passes, le superviseur conclut, même si le verdict reste imparfait. Tout système qui boucle a besoin d'une condition d'arrêt — ici, le verdict ok ou le plafond atteint.

Le graphe se construit autour du superviseur, qui en est le moyeu : tous les agents y reviennent après leur tour.

from langgraph.graph import END, START, StateGraph
def router(etat: EtatRedaction):
"""Traduit la décision du superviseur en destination du graphe."""
etape = etat["prochaine_etape"]
return END if etape == "FIN" else etape
constructeur = StateGraph(EtatRedaction)
constructeur.add_node("superviseur", superviseur)
constructeur.add_node("redacteur", redacteur)
constructeur.add_node("relecteur", relecteur)
constructeur.add_node("fact_checker", fact_checker)
constructeur.add_edge(START, "superviseur")
constructeur.add_conditional_edges(
"superviseur", router, ["redacteur", "relecteur", "fact_checker", END]
)
constructeur.add_edge("redacteur", "superviseur")
constructeur.add_edge("relecteur", "superviseur")
constructeur.add_edge("fact_checker", "superviseur")
equipe = constructeur.compile()

Chaque agent a une arête fixe vers le superviseur — il revient toujours au centre. Le superviseur, lui, a des arêtes conditionnelles : il part vers l'agent que router désigne. C'est cette topologie en étoile qui matérialise le pattern superviseur.

Lancée sur un sujet, l'équipe enchaîne ses agents et, si besoin, révise :

Passes du rédacteur : 3
Verdict fact-check : problemes — quelques approximations à corriger
--- Brouillon final ---
Les conteneurs Linux offrent de nombreux avantages pour le déploiement
d'applications. Tout d'abord, leur petite taille et leur rapidité de
démarrage permettent une utilisation efficace des ressources...

Le nombre de passes varie d'une exécution à l'autre : le fact-checker peut accepter le brouillon du premier coup ou exiger plusieurs révisions. Le graphe s'arrête toujours — sur un verdict ok ou au plafond.

La suite de tests le vérifie sur quatre contrôles. Le routage du superviseur est testé sans modèle, de façon déterministe : on lui passe des états et on vérifie sa décision — y compris l'arrêt au plafond de révisions. Un test d'intégration exécute ensuite l'équipe complète et confirme qu'elle produit un brouillon, une revue et un verdict.

LangGraph n'est pas seul sur le multi-agent. CrewAI propose une abstraction de plus haut niveau — on décrit des « rôles » et des « tâches », le framework orchestre ; c'est rapide à mettre en place, au prix d'un contrôle plus indirect sur le parcours. AutoGen met l'accent sur la conversation entre agents qui dialoguent jusqu'à un accord.

L'intérêt de LangGraph est le contrôle explicite : le parcours est un graphe que l'on dessine, lit et teste nœud par nœud — la même propriété qui le rendait précieux pour un agent unique. Pour une équipe dont on veut maîtriser et déboguer l'enchaînement, c'est un atout décisif. Le bon choix dépend du besoin : prototypage rapide ou contrôle fin.

SymptômeCause probableSolution
GraphRecursionErrorLa boucle ne s'arrête jamaisVérifier la condition d'arrêt et MAX_REVISIONS
Un agent ne voit pas le travail d'un autreClé d'état mal nommée ou non écriteVérifier les clés lues et renvoyées par chaque nœud
Le superviseur saute une étapeOrdre des conditions incorrectOrdonner les tests du plus précoce au plus tardif
La révision ignore le retour du fact-checkercommentaire non transmis au rédacteurLire etat["commentaire"] dans le nœud rédacteur
Le verdict du fact-checker est du texte libreSortie non structuréeUtiliser with_structured_output avec un Literal
  • Plusieurs agents spécialisés — un prompt court chacun — battent un agent généraliste sur une tâche hétérogène.
  • Trois architectures : superviseur (centralisée, le défaut), swarm (distribuée), hiérarchique (à l'échelle).
  • L'état partagé est le seul canal entre agents — c'est lui qui les découple.
  • Le superviseur concentre toute la coordination : on le lit pour comprendre l'équipe.
  • Une boucle de correction réinjecte le travail tant qu'un critère n'est pas tenu — avec un plafond obligatoire.
  • LangGraph privilégie le contrôle explicite du parcours, là où CrewAI et AutoGen abstraient davantage.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn