LangGraph expliqué : graphes, états, routage et modèles de production.
Comment LangGraph modélise les agents sous forme de graphes cycliques dotés d’états typés, de réducteurs, de points de contrôle, de mécanismes de routage, d’outils et de boucles ReAct, ainsi que de modèles pour un usage en production.
Sources: Mastering LangGraph: The Complete Technical Guide to Building Production-Grade Agentic AI Systems
La première vague d’applications basées sur les LLM reposait sur un échange simple : envoyer une demande et recevoir une réponse. Les agents constituent un type de programme différent. Ils raisonnent en plusieurs étapes, décident de ce qu’ils doivent faire en fonction de ce qu’ils ont appris jusqu’à présent, et prennent des actions dans le monde réel. Cela exige une infrastructure conçue autour de boucles, de branches et de mémoire, et non une ligne droite allant de l’entrée à la sortie.
LangGraph est l’un de ces frameworks. Il a été conçu pour des applications à état dans lesquelles un ou plusieurs acteurs pilotés par des LLM travaillent ensemble. Au lieu d’une chaîne linéaire, il permet de décrire un graphe orienté pouvant contenir des cycles, de diriger les flux de manière conditionnelle, de conserver un état persistant et de coordonner les appels aux outils. Ce ne sont pas de simples commodités : un agent qui doit faire face à l’incertitude, se remettre d’erreurs et affiner son travail au fil de plusieurs tentatives a besoin de tout cela.
Ce qui suit explique le fonctionnement interne du framework, pourquoi ses choix de conception sont importants et dans quels cas chaque modèle s’applique. À la fin, vous devriez être en mesure de prendre des décisions architecturales avec confiance, de déboguer le comportement d’un agent qui semble étrange, et d’adapter le framework à vos besoins.
Les graphes en tant que bloc de construction de base
Les outils d’orchestration plus anciens modélisent un flux de travail sous forme de chaîne linéaire ou, au mieux, de graphe acyclique orienté. Cela fonctionne pour des tâches prévisibles, mais échoue lorsque l’agent doit itérer, faire des sauvegardes ou choisir une autre voie en temps réel. LangGraph part d’une hypothèse inverse et considère un graphe orienté contenant des cycles comme sa primitive de base.
Pourquoi une chaîne ne suffit pas
La différence entre les chaînes et les graphes est pratique, et non esthétique. Une chaîne suppose que l’on connaît l’ordre exact des opérations lors de l’écriture du code. Un graphe accepte que le parcours à suivre au sein du système dépende de l’état en temps de exécution, des résultats intermédiaires et de conditions impossibles à prédire.
Pensez à un agent qui étudie une entreprise. Il commence par des données financières. Le fait qu’il poursuive en récupérant des nouvelles, des rapports d’analystes ou des documents des concurrents dépend de ce que révèlent ces données financières. Ce comportement conditionnel et répétitif nécessite à la fois des cycles et des branches, et une chaîne ne peut exprimer aucun de ces éléments.
Le schéma d’agent habituel repose sur une boucle : on réfléchit à ce qu’il faut faire, on agit, on observe le résultat, et on répète jusqu’à ce que l’objectif soit atteint. Avec un outil basé sur des chaînes, on dispose de deux options médiocres : soit on décompose la boucle en un nombre fixe d’étapes, ce qui nuit à la flexibilité, soit on écrit soi-même le flux de contrôle en dehors du framework, ce qui compromet la composabilité. Dans LangGraph, la boucle elle-même est une idée de premier ordre, exprimée sous forme de graphe cyclique avec des arêtes conditionnelles.
Nœuds
Un nœud représente une étape discrète de calcul. Il reçoit l’état actuel, effectue une action et renvoie des mises à jour. Cette action peut être une appel à un LLM pour prendre une décision, un appel à un outil pour interagir avec un système externe, une transformation de données ou une logique de routage.
Les nœuds sont des fonctions Python simples ayant une structure précise : l’état actuel en entrée, un dictionnaire des mises à jour en sortie. Cette interface fonctionnelle les rend composables et faciles à tester. Un nœud ne modifie jamais l’état directement. Il indique les changements souhaités, et LangGraph les fusionne selon les règles que vous définissez.
Les nœuds peuvent être aussi simples qu’une seule appel à un LLM ou aussi complexes que des logiques à plusieurs étapes. Certains appellent d’autres graphes entiers, ce qui permet l’existence d’agents hiérarchiques. D’autres s’exécutent de manière asynchrone ou intègrent une logique de tentative répétée avec un retard exponentiel. Le framework se moque de la complexité interne d’un nœud.
Arêtes
Les arêtes déterminent où se dirige le contrôle ensuite, et il en existe deux types aux séquences sémantiques très différentes.
- Arêtes statiques : elles sont déterministes. Lorsque le nœud A est terminé, le contrôle passe toujours au nœud B. Elles se comportent comme des appels de fonction ordinaires et conviennent aux séquences connues à l’avance. Par exemple, après l’initialisation d’une tâche de recherche, la collecte de données suit toujours.
- Arêtes conditionnelles : elles routent dynamiquement en fonction de l’état. Une fois la collecte de données terminée, il peut être nécessaire de déterminer s’il y a suffisamment de données pour commencer l’analyse ou si les appels API échoués doivent être réessayés. Ce choix ne peut pas être fait au moment de la conception, c’est pourquoi une fonction de routage s’en charge à l’exécution.
Une fonction de routage examine l’état actuel et renvoie une chaîne de caractères indiquant le chemin à suivre. Le framework conserve une correspondance entre ces chaînes et les nœuds de destination. Cela permet de créer des arbres de décision, de la logique de réessai, un traitement des erreurs et des flux adaptatifs, tout en maintenant un routage explicite et testable.
État en tant que mémoire partagée
La gestion de l’état est là où la conception de LangGraph devient particulièrement intéressante. L’objet d’état est une structure partagée qui se déplace à travers le graphe. Chaque nœud lit l’état actuel, et toutes les mises à jour qu’il renvoie sont fusionnées avant que le nœud suivant ne s’exécute. Chaque étape s’appuie donc sur ce que les étapes précédentes ont appris.
Vous définissez l’état à l’aide de dictionnaires typés ou de modèles Pydantic, ce qui vous assure une sécurité de type ainsi qu’un contrat clair entre les nœuds. Le schéma précise quels champs existent, quels types ils ont et comment les mises à jour sont fusionnées. Ce dernier aspect est facile à négliger, mais il est très important.
Lorsqu’un nœud renvoie une mise à jour, LangGraph doit déterminer comment la combiner avec ce qui existe déjà. Pour une chaîne de caractères ou un nombre, remplacer la valeur ancienne est évident. Pour une liste ou un dictionnaire, ce n’est pas le cas. Faut-il ajouter la liste renvoyée, remplacer l’ancienne ou la fusionner élément par élément ? Ce sont les réducteurs qui répondent à cette question.
Réducteurs
Un réducteur est une fonction qui définit la manière dont une mise à jour est fusionnée avec l’état existant. Les réducteurs transforment l’état de LangGraph, qui n’est au départ qu’un conteneur simple, en quelque chose capable de gérer des schémas d’accumulation.
Par défaut, la nouvelle valeur remplace simplement l’ancienne. Cela convient pour la plupart des champs, mais ce n’est pas adapté aux données qui s’accumulent. Imaginez une liste d’erreurs qui collecte les problèmes au cours d’une exécution : vous ne souhaitez pas que chaque élément efface les entrées précédentes, mais plutôt que de nouvelles erreurs soient ajoutées aux anciennes. Le réducteur add_messages suit cette logique, et ce modèle peut être généralisé au-delà des messages.
Vous pouvez écrire un réducteur personnalisé pour n’importe quel champ. Ses entrées sont la valeur déjà présente dans l’état et la nouvelle valeur reçue, et sa sortie correspond à ce que le champ doit contenir par la suite. Pour les erreurs, il concaténerait les listes ; pour les dictionnaires, il fusionnerait profondément les structures imbriquées ; pour les compteurs, il ajouterait des nombres.
Les réducteurs sont associés via les indications de type Annotated de Python, ce qui permet au schéma de rester déclaratif :
from typing import TypedDict, Annotated
def append_lists(existing: list, new: list) -> list:
return existing + new
class AgentState(TypedDict):
query: str # Simple replacement
results: Annotated[list, append_lists] # Custom accumulation
iteration: int # Simple replacement
Cela rend le comportement de fusion explicite et centralisé, au lieu d’être dispersé dans des nœuds individuels.
Création de points de contrôle
Les agents de production fonctionnent souvent pendant longtemps, effectuent des appels API coûteux ou gèrent des opérations qui ne doivent pas être perdues en cas de panne temporaire. La création de points de contrôle est le mécanisme qui permet de gérer cela. Lorsqu’elle est activée, LangGraph enregistre l’état complet après chaque fin de nœud. Si le processus plante ou manque de mémoire, l’exécution peut reprendre à partir du dernier point de contrôle au lieu de recommencer depuis zéro. Un script séquentiel fragile devient ainsi un flux de travail pouvant être repris.
Les points de contrôle permettent également des architectures avec intervention humaine. L’exécution peut être suspendue à un moment choisi pour que quelqu’un puisse examiner ou fournir des informations, puis reprendre une fois que cette personne a réagi. Comme le point de contrôle capture l’état exact au moment de la suspension, il n’a pas d’importance que des jours s’écoulent entre-temps.
Le stockage associé est interchangeable. Les points de contrôle en mémoire conviennent bien au développement, SQLite assure une persistance locale tandis que Redis s’adapte aux systèmes distribués. Le graphe reste identique, seules les implémentations des points de contrôle changent.
Encadrement conditionnel
C’est au niveau de l’encadrement que le comportement devient véritablement dynamique. Le choix de l’étape suivante en temps de exécution, à partir de l’état accumulé, est ce qui distingue une automatisation rigide d’un agent adaptatif.
Fonctions d’encadrement et mappages de bordures
Une fonction de routage est une petite fonction Python qui prend en compte l’état et renvoie une chaîne de caractères. Lorsque l’exécution atteint un nœud conditionnel, LangGraph appelle cette fonction, récupère la chaîne, trouve le nœud correspondant dans la table de correspondance et transfère le contrôle. Comme le routage s’effectue via des chaînes de caractères et non par des références directes aux nœuds, vous pouvez modifier la table de correspondance sans toucher à la fonction, ou remplacer celle-ci par une autre fonction de routage sans changer la structure du graphe.
Les questions de routage typiques portent sur la disponibilité de suffisamment de données pour continuer, sur le succès d’une opération ou la nécessité de la réessayer, sur le fait que la limite de tentatives ait été atteinte, ainsi que sur le degré de fiabilité de l’analyse pour pouvoir agir en conséquence. La fonction peut accéder à l’ensemble de l’état, ce qui lui permet de comparer plusieurs champs, d’effectuer des calculs, de consulter des conditions externes ou d’encoder des règles métier. La seule exigence est qu’elle soit déterministe et pure, afin de fournir toujours la même réponse pour un même état.
Éviter les cycles infinis
Les cycles permettent des itérations puissantes mais ouvrent également la porte aux boucles infinies. Un agent bloqué dans des tentatives répétées peut consommer des ressources indéfiniment, et LangGraph propose plusieurs moyens de l’empêcher.
La solution la plus simple consiste à utiliser un compteur dans l’état. La fonction de routage le compare à une valeur maximale et envoie des instructions vers un nœud de terminaison dès que cette limite est dépassée. Presque tous les agents de production utilisent ce modèle. D’autres options plus avancées incluent la détection de convergence, qui s’arrête lorsque la variation entre les itérations tombe en deçà d’un seuil, ainsi que la terminaison basée sur un délai imparti, où le routage tient compte du temps écoulé.
En résumé, la prévention des boucles relève de la tâche de routage et non d’une limitation du framework. LangGraph vous fournit les éléments nécessaires pour créer des mécanismes de protection adaptés à votre cas, au lieu d’imposer des règles générales.
Outils : de la langue à l’action
Les agents deviennent véritablement utiles lorsque un LLM peut interagir avec des systèmes externes. Les outils permettent de transformer la compréhension du langage en actions concrètes dans le monde réel.
Le modèle d’exécution
Dans LangGraph, une outil est un nœud qui effectue une action en dehors du processus. Il peut appeler une API, interroger une base de données, exécuter du code ou rechercher sur le web. Il reçoit des paramètres depuis l’état, effectue l’opération et renvoie des résultats sous forme de mises à jour de l’état.
Cette architecture devient puissante lorsqu’elle est combinée au jugement de l’LLM. Un nœud LLM lit l’état et décide quel outil appeler. Une fonction de routage envoie le contrôle au nœud d’outil correspondant. L’outil s’exécute et enregistre son résultat dans l’état. Le contrôle revient à l’LLM, qui interprète le résultat et choisit la prochaine action. Ce processus se poursuit jusqu’à ce que l’objectif soit atteint.
Les modèles modernes prennent en charge l’appel de fonctions, ce qui signifie qu’ils émettent une demande structurée indiquant l’outil à utiliser ainsi que ses paramètres. Le nœud LLM analyse une telle demande à partir de la réponse du modèle et enregistre l’outil choisi dans l’état. La fonction de routage lit ce choix et dirige le flux vers le bon nœud d’outil.
Gestion des erreurs des outils
Les systèmes externes échouent, atteignent leur délai d’attente, renvoient des données anormales et contredisent les hypothèses. Les nœuds d’outil doivent prévoir ces situations.
- Attraper et signaler. Capturer les exceptions, les enregistrer et renvoyer des détails d’erreur dans l’état, plutôt que de laisser cela provoquer l’arrêt de l’agent. L’LLM pourra alors identifier ce qui a mal tourné et réessayer avec d’autres paramètres ou adopter une autre approche.
- Délais d’attente. Encadrer les opérations de manière à ce qu’elles se terminent après une durée maximale. Une API lente ne doit pas paralyser tout l’agent.
- Validation. Analyser les réponses et les vérifier contre les schémas. Des données incorrectes doivent déclencher une procédure d’erreur, plutôt que d’être stockées et d’endommager les nœuds suivants.
Le cycle ReAct
ReAct, abréviation de reasoning and acting, est une architecture de base pour les agents que LangGraph exprime naturellement, et l’examiner montre comment les autres concepts s’assemblent.
Comment fonctionne le cycle
Il commence par un nœud de raisonnement. Un LLM examine l’état actuel et décide de la prochaine étape : appeler un outil, demander plus d’informations, fournir une réponse finale ou solliciter une intervention humaine. C’est là que les capacités du modèle deviennent importantes, car il peut évaluer un contexte complexe et prendre une décision nuancée.
Si une action est décidée, le contrôle est transféré à un nœud d’action qui exécute l’opération choisie, qu’il s’agisse d’une appel API, d’un calcul ou d’une requête de base de données. Ce nœud d’action reste déterministe et ciblé, exécutant la demande et renvoyant des résultats.
Ensuite vient un nœud d’observation, qui ajoute ces résultats à l’état actuel et les prépare pour le LLM. Il peut formater les données, filtrer le bruit ou calculer des métriques dérivées afin de faciliter l’interprétation des résultats. Le cycle revient alors à la phase de raisonnement avec un état plus riche. Le LLM observe ce qui s’est passé et choisit l’étape suivante, jusqu’à ce qu’il dispose de suffisamment d’informations pour terminer.
Savoir quand s’arrêter
Décider du moment de mettre fin au cycle est une étape essentielle, et plusieurs schémas se révèlent pratiques dans la réalité.
- Objectif atteint. Cas le plus simple : le LLM indique que la tâche est terminée et fournit une réponse finale. La fonction de routage le détecte et se dirige vers le nœud de terminaison.
- Limite d’itérations. Après un nombre maximal de cycles de raisonnement et d’action, la boucle s’arrête, que l’objectif ait été atteint ou non, de sorte que l’agent s’arrête toujours à un moment donné.
- Seuil de confiance. Si le modèle atteint un degré de certitude suffisant, par exemple 95 %, il peut s’arrêter plus tôt au lieu de continuer à collecter des informations dont les retombées diminuent.
- Erreurs fatales. Lorsque des opérations critiques échouent continuellement ou que l’agent se retrouve face à une situation qu’il ne peut pas gérer, il doit s’arrêter en générant un rapport d’erreur plutôt que de continuer inutilement.
Plusieurs agents travaillant ensemble
Certaines tâches conviennent mieux à une équipe d’agents spécialisés qu’à un seul agent monolithique. Un graphe rend certains schémas de collaboration simples à comprendre.
Hiérarchie
Dans une conception hiérarchique, un planificateur de haut niveau divise le travail et le délègue à des agents spécialisés. Il définit l’objectif global et coordonne les actions, mais ne s’occupe pas des détails concrets. Du point de vue de la mise en œuvre, certains nœuds appellent d’autres graphes compilés. Un nœud de planification peut analyser une tâche complexe, la décomposer et exécuter un graphe spécialisé pour chaque partie. Les résultats reviennent au planificateur, qui les combine pour obtenir le résultat final.
Le principal avantage est la séparation des responsabilités. Chaque spécialiste peut être développé, testé et ajusté indépendamment, et le planificateur n’a besoin de connaître que la manière de les coordonner, pas leur fonctionnement interne.
Équivalents
Les agents peuvent également collaborer sur un pied d’égalité, chacun apportant ses compétences spécialisées. Une équipe d’agents logiciels peut comprendre des agents distincts pour l’architecture, la mise en œuvre, les tests et la documentation, tous communiquant via un bus de messages partagé. On construit cela avec un état partagé que chaque agent peut lire et écrire. Une fonction de routage décide qui agira en suivant en fonction de cet état et des compétences requises. Chaque agent écrit sa contribution, l’attribue de métadonnées indiquant ce qu’elle traite, puis restitue le contrôle ; le routage choisit alors l’agent le plus pertinent suivant.
Les configurations entre pairs apportent des points de vue variés et permettent aux agents de détecter les erreurs des uns et des autres, un agent pouvant ainsi repérer une faille dans le raisonnement d’un autre.
Débat et consensus
Pour les décisions importantes, plusieurs agents peuvent résoudre un problème de manière indépendante avant de négocier afin d’aboutir à un accord. Cette approche s’inspire des idées des IA constitutionnelles et considère les désaccords comme un signe de qualité. Trois agents analysent une situation et chacun propose une solution. Un modérateur anime le débat à tour de rôle, permettant à chaque agent de présenter ses raisonnements, de critiquer les autres et de répondre aux critiques spécifiques. Après quelques tours, une étape de consensus synthétise les discussions en une décision, en donnant éventuellement plus de poids aux arguments les plus convaincants.
Cette méthode permet de mettre en évidence des hallucinations et des erreurs de raisonnement qui échapperaient à un seul agent, mais qui sont détectées lorsque plusieurs agents examinent le problème sous des angles différents.
Récupération de données au sein des agents
La génération augmentée par la récupération de données donne aux agents accès à de grandes bases de connaissances et à du matériel sectoriel, et un graphe rend cette intégration naturelle.
Récupération sur demande
Dans le RAG classique, les informations sont récupérées une seule fois au début d’une tâche. Dans le RAG agent, la récupération devient un outil que l’agent utilise chaque fois qu’il détecte un manque d’informations. L’agent commence alors à raisonner à partir de ses connaissances de base. Lorsqu’il se heurte à une question qu’il ne peut pas répondre ou qu’il a besoin de plus de contexte, il rédige une requête de récupération, utilise l’outil correspondant et poursuit en intégrant les nouvelles informations dans son état actuel.
Cette approche est supérieure à l’approche de chargement préalable pour deux raisons : elle est moins coûteuse, car l’agent ne récupère que ce dont il a besoin, et elle est plus précise, car les requêtes sont formulées en fonction de ce que l’agent comprend actuellement.
Requêtes guidées par l’état
La véritable valeur apparaît lorsque les requêtes prennent en compte tout ce qui a été collecté jusqu’à présent, et non seulement la question initiale. Prenons l’exemple d’une enquête entreprise : elle peut commencer par une requête offrant une vue d’ensemble. Le résultat mentionne une acquisition récente, ce qui suscite une requête ciblée sur cette opération. Celle-ci met en évidence des problématiques réglementaires, ce qui déclenche une recherche des règles pertinentes. Chaque recherche s’appuie sur la précédente, ce qui permet d’obtenir une enquête ciblée plutôt qu’un ensemble de données désordonnées.
Plusieurs sources
Les agents consultent fréquemment des sources présentant des latences, des coûts et des niveaux de fiabilité différents : documents internes, API externes, recherche sur le Web, bases de données spécialisées. LangGraph prend en charge des stratégies multi-sources. Un agent peut d’abord vérifier un cache local rapide, recourir à une API, et n’utiliser la recherche sur le Web coûteuse qu’en dernier recours. Il peut également interroger plusieurs sources en parallèle et demander au LLM de concilier les réponses qui pourraient être contradictoires.
La logique de routage peut choisir la source en fonction du type de question. Les recherches factuelles se font dans une base de données structurée, les questions conceptuelles via une recherche vectorielle sur des documents, les événements récents par une recherche sur le Web, et les questions historiques dans une base de connaissances soigneusement sélectionnée.
Préparation pour le déploiement en production
Il est facile de créer un agent de preuve de concept avec LangGraph. Le déploiement en production introduit des exigences en matière de fiabilité, d’observabilité et d’opérations.
Gestion des erreurs à tous les niveaux
Les agents de production gèrent les pannes à plusieurs niveaux. Les nœuds d’outil détectent les erreurs attendues et les renvoient sous forme de mises à jour d’état, et non en tant qu’exceptions. Les fonctions de routage vérifient les conditions d’erreur et configurent des chemins de tentative avec un retard exponentiel. Le graphe comprend des nœuds dédiés à la gestion des erreurs qui analysent les erreurs accumulées pour décider s’il faut réessayer, recourir à une solution de secours ou terminer de manière propre. Pour les opérations critiques, un circuit breaker peut suspendre les tentatives après des échecs répétés, évitant ainsi des effets en chaîne et épargnant au service défaillant une charge supplémentaire.
Voir ce qui s’est passé
Lorsqu’un problème survient, il est nécessaire de savoir ce que l’agent a fait et pourquoi. LangGraph s’intègre à des plateformes comme LangSmith pour fournir des traces détaillées de l’exécution de chaque nœud, des transitions d’état et des appels aux LLM. Les nœuds doivent générer des journaux structurés contenant suffisamment de contexte pour expliquer leurs décisions. Les temps d’exécution révèlent les goulots d’étranglement, le comptage des tokens aide à estimer les coûts, et le suivi des interactions utilisateur alimente l’évaluation. Rejouer les étapes à partir des points de contrôle est particulièrement utile : on charge l’état exact où une erreur s’est produite et on procède pas à pas pour identifier la cause racine.
Réduire les coûts
Les appels aux LLM représentent la majeure partie des coûts dans la plupart des agents, et quelques stratégies permettent de les réduire sans nuire à la qualité.
- Sélection du modèle. Utilisez un modèle puissant comme GPT-4 uniquement pour des tâches nécessitant un raisonnement complexe. Envoyez les tâches de classification ou d’extraction simples à des modèles plus rapides et moins chers, en utilisant une logique de routage qui analyse la tâche.
- Mémorisation des réponses. Stocker les résultats pour des entrées identiques ou sémantiquement similaires. Lorsque la même analyse se reproduit, le cache élimine les appels redondants, permettant aux embeddings de correspondre à des requêtes formulées différemment mais ayant le même sens.
- Troncature des prompts. Des prompts concis ne contenant que les informations nécessaires permettent d’économiser des tokens. Les modèles avec substitution de variables assurent leur cohérence.
- Arrêt précoce. S’arrêter dès que l’agent dispose de suffisamment d’informations, plutôt que d’épuiser un budget d’itérations fixe.
Directives de conception
Le déploiement d’agents LangGraph montre quels schémas distinguent les systèmes robustes des prototypes fragiles.
Schéma d’état
Le schéma constitue la base. Utilisez des modèles Pydantic plutôt que des dictionnaires non structurés afin que la validation permette de détecter les erreurs tôt, et documentez la signification et l’usage de chaque champ. Les champs optionnels permettent aux différents nœuds de contribuer progressivement des éléments, tandis que les champs obligatoires garantissent la présence des données essentielles. Les unions discriminées gèrent des états qui prennent des formes différentes en fonction du chemin suivi. Évitez les emboîtements trop profonds qui rendent les champs difficiles d’accès. Aplatissez autant que possible la structure, utilisez des noms qui illustrent les relations, et séparez les métadonnées des données de domaine afin que les informations de contrôle restent distinctes.
Limites des nœuds
Les bons nœuds accomplissent bien une seule tâche. Cela les rend réutilisables entre différents graphes et plus faciles à tester et à maintenir. Les nœuds d’outil ne doivent communiquer qu’avec des systèmes externes, sans contenir de logique métier. Les nœuds de transformation effectuent des transformations sans prendre de décisions. Les nœuds de décision orientent le flux sans exécuter d’opérations. Évitez les effets secondaires cachés : les nœuds doivent être aussi purs que possible, en retournant explicitement chaque changement d’état au lieu de modifier des variables globales.
Forme du graphique
La structure doit refléter la manière dont l’agent raisonne. Commencez par une étape de configuration qui vérifie les entrées et prépare le contexte. Ensuite, collectez les données, éventuellement en parallèle. Ajoutez des nœuds d’analyse, puis des nœuds de synthèse qui produisent les résultats, ainsi que des nœuds de finalisation qui nettoient le tout. Placez des arêtes conditionnelles aux véritables points de décision où l’étape suivante dépend des découvertes, et utilisez des arêtes statiques lorsque le flux est déterministe. Gardez chaque graphe à un seul niveau d’abstraction. Si une partie de celui-ci implémente une sous-procédure complexe, extrayez-la dans son propre graphe et appelez-la en tant que nœud.
Testage
Les graphes peuvent être testés à plusieurs niveaux. Testez les nœuds au niveau unitaire en passant des états simulés et en vérifiant les mises à jour. Testez les fonctions de routage en fournissant divers états et en vérifiant le chemin retourné. Testez l’intégralité des graphes avec des entrées connues et vérifiez l’état final. Simulez les réponses des LLM pour que les tests soient rapides et déterministes, et utilisez des réponses réelles enregistrées pour des scénarios plus réalistes. Les tests basés sur des propriétés permettent de vérifier le comportement sur une large gamme d’entrées. Couvrez en détail les chemins critiques, ainsi que les chemins d’erreur, car ils sont difficiles à déclencher en production mais essentiels lorsqu’ils se produisent.
Décider s’il est nécessaire
LangGraph est puissant, mais toutes les applications LLM n’en ont pas besoin.
Cela s’applique lorsque l’agent doit raisonner de manière itérative, en collectant et en analysant des informations avant de décider s’il doit poursuivre ses recherches. Cela convient également lorsque le flux de contrôle dépend de l’état en temps de exécution, comme c’est le cas pour les tentatives répétées, la récupération d’erreurs ou les workflows adaptatifs, lorsque plusieurs outils ou systèmes présentent des dépendances complexes, lorsque l’état doit être conservé entre différentes étapes ou sessions, lorsque l’exécution doit être suspendue et reprise pour permettre l’intervention humaine, ou encore lorsque plusieurs agents collaborent ou forment une hiérarchie.
Un système plus simple suffit lorsque la tâche consiste en une simple demande et une réponse sans boucles ni branches, que le flux est linéaire et connu à l’avance, que le travail peut s’effectuer par une série d’étapes déterministes, que rien n’a besoin de persister au-delà d’une seule exécution, ou que l’application appelle au maximum une ou deux API simples. Dans ces cas, les chaînes LangChain ou des appels API directs produisent un code plus clair et plus facile à maintenir que de forcer le problème à prendre la forme d’un graphe.
Évolution progressive
De nombreuses applications commencent simplement avant de devenir complexes. C’est ce à quoi on s’attend dans un domaine comme la conception sonore. Commencez par une chaîne, mais gardez les prompts, les outils et la logique métier modulaires et peu couplés afin que l’extraction en un graphe soit facile par la suite. Lorsque la chaîne compte cinq à sept étapes, ou lorsque vous ajoutez une deuxième branche conditionnelle, envisagez de migrer avant que la complexité ne devienne incontrôlable.
Techniques avancées
Au-delà des bases, quelques techniques ouvrent la voie à des capacités supplémentaires.
Exécution parallèle. Les nœuds qui ne dépendent pas des résultats des autres peuvent fonctionner en même temps. Par exemple, les nœuds de collecte de données qui s’adressent à des API différentes réduisent le temps total d’exécution lorsqu’ils sont exécutés en parallèle, et le framework rassemble et fusionne les résultats. Il faut des liens parallèles explicites et s’assurer que les nœuds sont véritablement indépendants, sans couplage caché via des ressources partagées ou un état global.
Flux continu. Pour les agents à exécution prolongée, afficher des résultats intermédiaires améliore l’expérience utilisateur. Les nœuds peuvent émettre des mises à jour partielles de leur état que les observateurs voient immédiatement. Cela convient à la génération de rapports, où les paragraphes peuvent apparaître au fur et à mesure qu’ils sont écrits, ainsi qu’aux recherches qui affichent les résultats au fur et à mesure qu’ils sont trouvés.
Subgraphes. Les agents complexes tirent parti d’une décomposition hiérarchique. Les subgraphes sont compilés séparément et invoqués en tant que nœuds au sein d’un graphes parent, recevant un sous-ensemble de l’état de ce dernier et renvoyant des mises à jour à intégrer à nouveau. Différents ingénieurs peuvent être responsables de subgraphes distincts, les déployer et les tester de manière indépendante, ainsi que réutiliser ceux qui sont communs dans plusieurs graphes parents.
Changements dynamiques des graphes. La plupart des graphes restent fixes au moment de la conception, mais certains cas avancés permettent de modifier le graphes en temps de exécution. Un agent de planification peut créer un graphes personnalisé après avoir analysé une tâche, en générant des nœuds et des arêtes au fur et à mesure. Cela rend le comportement plus difficile à comprendre, il convient donc de l’utiliser avec prudence. Cependant, cela permet aux meta-agents de concevoir et d’exécuter des workflows personnalisés pour de nouveaux types de tâches.
Perspective finale
LangGraph incarne un ensemble d’outils en pleine maturation pour les systèmes agents. Sa force réside non pas dans sa complexité, mais dans la similitude entre les primitives et le comportement des agents : ils raisonnent, agissent et observent en boucle, prennent des décisions en se basant sur les connaissances accumulées, orchestrent les outils et s’adaptent lorsque des problèmes surviennent. Vous exprimez directement ces schémas plutôt que de devoir les construire à partir de zéro.
Obtenir de bons résultats nécessite de maîtriser la gestion de l’état, le routage conditionnel et l’intégration des outils en tant que modèles architecturaux, et non simplement comme fonctionnalités. Les meilleures applications présentent une conception soignée du schéma d’état, des responsabilités claires pour chaque nœud, un traitement des erreurs réfléchi et une capacité d’observation approfondie. Le framework fournit des outils, pas des solutions. Vos connaissances sectorielles et votre jugement déterminent l’efficacité de leur utilisation ; commencez donc par quelque chose de simple, testez vos hypothèses tôt et laissez les exigences réelles, et non imaginaires, guider l’architecture.
Lectures complémentaires
- Agent ou flux de travail ? Séparer le raisonnement de l’exécution dans l’IA d’entreprise — Utilisez des agents pour l’interprétation des intentions et la récupération d’informations, ainsi que des flux de travail déterministes pour les transactions : comment RAG, LangGraph, MCP, les processus d’approbation et SQS contribuent à une architecture plus sûre.
- Recommandateur de K-drama multi-agent sensible aux préférences : BERTopic, RAG et fusion de rangs réciproques — Comment un recommandateur de K-drama qui prend en compte les préférences combine les étiquettes BERTopic, la récupération d’informations via ChromaDB, un agent chargé des interviews, l’expansion des requêtes et la fusion de rangs réciproques avant que l’LLM ne procède à un nouveau classement.