Création d’un agent ReAct dans LangChain : les exécuteurs, les blocs de notes et leurs limites
Créez un agent ReAct capable d’utiliser des outils, observez comment l’agent et AgentExecutor se partagent le travail, et découvrez pourquoi LangGraph gère mieux le flux de contrôle, les cycles et l’état.
Qu’est-ce qu’un agent
Un agent d’IA est un système qui prend un objectif de haut niveau défini par une personne, puis planifie, prend des décisions et agit de sa propre initiative. Il exécute une série d’étapes en utilisant des outils externes, des API ou des sources de connaissances, conserve le contexte tout au long du processus, raisonne à travers plusieurs étapes, s’adapte lors de l’arrivée de nouvelles informations et travaille vers le résultat souhaité.
En termes simples, un agent est un LLM associé à certains outils. Le LLM s’occupe du raisonnement et de la prise de décisions, tandis que les outils s’occupent de l’action concrète.
Caractéristiques d’un agent
- Guidé par un objectif. Vous indiquez ce que vous voulez, sans préciser comment l’obtenir.
- Planifie de lui-même. L’agent divise le problème en tâches et les organise sans aide extérieure.
- Utilise des outils. Il fait appel à des API, des calculateurs, des moteurs de recherche et autres outils similaires. Le LLM sait quels outils existent et quand chacun doit être utilisé.
- Conscient du contexte. Il conserve la mémoire entre les étapes afin que les résultats précédents influencent les actions ultérieures.
- Adaptatif. Lorsqu’un changement survient, comme une erreur d’API ou l’absence de données, il révise son plan.
Un agent fonctionnel en code
Le script ci-dessous crée un petit agent doté de deux outils : une recherche sur le Web via DuckDuckGo et une consultation météo. Il lui pose ensuite une question en deux parties. L’appel météo nécessite votre propre clé API fournie par le fournisseur météo, représentée ici par un espace réservé.
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
import requests
from langchain_community.tools import DuckDuckGoSearchRun
from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub # It is a place from where we can get many type of prompts, so if we want any predefined prompt, we can get it from here
# Step 1: Creating tool definitions
search_tool = DuckDuckGoSearchRun()
@tool
def get_weather_data(city: str) -> str:
"""
This function fetches the current weather data for a given city
"""
url = f'https://api.weatherstack.com/current?access_key=4d1d8ae207a8c845a52df8a67bf3623e&query={city}'
response = requests.get(url)
return response.json()
llm = ChatOpenAI()
# Step 2: Pull the ReAct prompt from LangChain Hub
prompt = hub.pull("hwchase17/react") # pulls the standard ReAct agent prompt
# The agent which we are gonna make is a ReAct agent (reasoning + action = ReAct)
# ReAct is a design pattern
# Step 3: Create the ReAct agent manually with the pulled prompt
agent = create_react_agent(
llm=llm,
tools=[search_tool, get_weather_data],
prompt=prompt
)
# Step 4: Wrap it with AgentExecutor
agent_executor = AgentExecutor(
agent=agent,
tools=[search_tool, get_weather_data],
verbose=True # whatever the agent thinks, it will be visible to us
)
# Step 5: Invoke
response = agent_executor.invoke({"input": "Find the capital of Madhya Pradesh, then find it's current weather condition"})
print(response)
'''
Entering new AgentExecutor chain...
I should first find out the capital of Madhya Pradesh and then check the current weather condition for that city.
Action: duckduckgo_search
Action Input: "capital of Madhya Pradesh" Madhya Pradesh, state of India that is situated in the heart of the country. It has no coastline and no international frontier. Its physiography is characterized by low hills, extensive plateaus, and river valleys. The capital is Bhopal, in the west-central part of the state. Bhopal, city, capital of Madhya Pradesh state, central India. Situated in the fertile plain of the Malwa Plateau, the city lies just north of the Vindhya Range, along the slopes of a sandstone ridge. It is a major rail junction and has an airport. Pop. (2001) 1,437,354; (2011) 1,798,218. Bhopal was Indore (/ ɪ n ˈ d ɔːr / ⓘ; ISO: Indaura, Hindi: [ɪn̪d̪ɔːr]) is the largest and most populous city in the Indian state of Madhya Pradesh. [15] It is the commercial hub of Madhya Pradesh. It is consistently ranked as the cleanest city in India. [16] It serves as the headquarters of both the Indore District and the Indore Division.It is also considered the state education hub and ... In 1956, Bhopal became part of the state of Madhya Pradesh. Bhopal district was carved out on October 2, 1972, and is one of the 45 districts in the state. 4. Why is Bhopal famous? Bhopal is the capital city of the Indian state of Madhya Pradesh. It is known as the City of Lakes due to the presence of various natural and artificial lakes. In 1948, Madhya Bharat was created, with Indore designated as its summer capital and Gwalior as its winter capital. This arrangement highlights Indore's significance even then. However, Madhya Bharat was a temporary entity, and the map of central India was soon to be redrawn. The Creation of Madhya PradeshNow that I know the capital of Madhya Pradesh is Bhopal, I can use the get_weather_data function to check its current weather condition.
Action: get_weather_data
Action Input: Bhopal {'request': {'type': 'City', 'query': 'Bhopal, India', 'language': 'en', 'unit': 'm'}, 'location': {'name': 'Bhopal', 'country': 'India', 'region': 'Madhya Pradesh', 'lat': '23.267', 'lon': '77.400', 'timezone_id': 'Asia/Kolkata', 'localtime': '2025-05-01 17:52', 'localtime_epoch': 1746121920, 'utc_offset': '5.50'}, 'current': {'observation_time': '12:22 PM', 'temperature': 40, 'weather_code': 116, 'weather_icons': ['https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png'], 'weather_descriptions': ['Partly Cloudy '], 'astro': {'sunrise': '05:47 AM', 'sunset': '06:48 PM', 'moonrise': '08:38 AM', 'moonset': '11:01 PM', 'moon_phase': 'Waxing Crescent', 'moon_illumination': 15}, 'air_quality': {'co': '510.6', 'no2': '1.665', 'o3': '180', 'so2': '10.175', 'pm2_5': '29.045', 'pm10': '68.635', 'us-epa-index': '2', 'gb-defra-index': '2'}, 'wind_speed': 12, 'wind_degree': 302, 'wind_dir': 'WNW', 'pressure': 1005, 'precip': 0, 'humidity': 7, 'cloudcover': 25, 'feelslike': 40, 'uv_index': 1, 'visibility': 6, 'is_day': 'yes'}}The current weather condition in Bhopal, Madhya Pradesh is partly cloudy with a temperature of 40°C.
Final Answer: The capital of Madhya Pradesh is Bhopal, and the current weather condition in Bhopal is partly cloudy with a temperature of 40°C.
> Finished chain.
{'input': "Find the capital of Madhya Pradesh, then find it's current weather condition", 'output': 'The capital of Madhya Pradesh is Bhopal, and the current weather condition in Bhopal is partly cloudy with a temperature of 40°C.'}
'''
response['output']
# The capital of Madhya Pradesh is Bhopal, and the current weather condition in Bhopal is partly cloudy with a temperature of 40°C.
Les cinq étapes numérotées du script couvrent les définitions des outils, la récupération de l’instruction standard ReAct depuis le hub LangChain, la création de l’agent, son emballage dans un exécuteur et son invocation. Le trace affiché à la fin montre que l’agent décide d’abord de rechercher la capitale puis de vérifier la météo.
ReAct
LangChain prend en charge plusieurs approches de conception pour les agents. Celle présentée ici est ReAct, abréviation de Reasoning plus Acting. Elle permet à un modèle d’alterner entre la réflexion interne, correspondant à la phase de pensée, et des actions externes telles que l’appel à des outils, au sein d’un cycle structuré comprenant plusieurs étapes.
Le modèle ne produit pas sa réponse d’un seul coup. Il réfléchit étape par étape, décide de ce qu’il doit faire ensuite et peut faire appel à des outils tels que des API, des calculateurs ou des recherches sur le web pour obtenir de l’aide.
Ce modèle s’applique aux :
- problèmes nécessitant plusieurs étapes ;
- tâches qui requièrent des outils ;
- Les cas où l’on souhaite que le raisonnement soit visible et vérifiable.
Par exemple, demandez au modèle la population de la capitale de la France. Il commence par déduire qu’il doit identifier la capitale, la cherche, constate que la réponse est Paris, puis déduit qu’il a besoin de la population de Paris, cherche à nouveau et donne finalement la réponse.
ReAct compte cinq éléments :
- Pensée. Le raisonnement privé de l’agent, au cours duquel il évalue l’état actuel et planifie le prochain mouvement. Il explique pourquoi un outil particulier a été choisi ou ce qui reste inconnu.
- Action. La décision d’utiliser un outil parmi ceux disponibles, identifié par la fonction ou l’API à appeler.
- Entrée de l’action. Les arguments transmis à cet outil. Si l’action est
search, l’entrée correspond au texte exact de la requête, comme par exemple « le temps à Delhi ». - Observation. Les données brutes que l’outil renvoie une fois que l’exécuteur l’a lancé. L’agent les lit pour déterminer si le travail est terminé ou s’il faut encore des étapes.
- Réponse finale. La réponse de clôture, générée lorsque l’agent estime disposer d’informations suffisantes, qui combine toutes les observations en langage simple.
Le modèle de prompt qui pilote ce cycle ressemble à ceci :
Answer the following questions as best you can. You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action …
(this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad} —
Dans ce modèle, une Observation correspond simplement à ce qui est retourné après l’exécution d’une outil.
Le carnet de travail de l’agent
Le carnet de travail sert de mémoire à court terme ou de cahier de travail de l’agent. Il enregistre l’historique de la tâche en cours : les réflexions antérieures, les actions effectuées, telles que les appels d’outils, ainsi que les Observations qui ont été retournées.
En consultant ce carnet, l’agent se souvient qu’il a déjà déterminé la capitale de la France et qu’il doit maintenant trouver la population de Paris. Il s’agit d’un stockage temporaire, mis à jour chaque fois que l’exécuteur fournit de nouvelles informations. Une fois que la réponse finale est envoyée à l’utilisateur, le carnet de travail est généralement effacé ou archivé, car sa fonction pour cette tâche est terminée.
Le nom prend tout son sens lorsque l’on se souvient qu’un LLM est sans état : il ne se souvient pas naturellement de ce qui s’est passé il y a quelques secondes au sein d’une boucle de code. LangChain prend donc l’ensemble de l’historique de la boucle en cours et le réinsère dans la demande chaque fois qu’il demande à l’agent ce qu’il doit faire ensuite.
Agent versus AgentExecutor
Ces deux composants ont des tâches distinctes.
L’agent est celui qui réfléchit, un peu comme un chef de projet. Il lit la demande, la divise en étapes plus petites et décide quels outils sont nécessaires. Ses entrées comprennent à la fois la question de l’utilisateur et tout ce qui a été fait jusqu’à présent.
L’AgentExecutor est celui qui agit, plus proche d’un assistant. Il écoute les instructions de l’agent, exécute réellement le code correspondant à chaque outil et lui retourne les résultats.
Une autre façon de le voir : l’agent est l’architecte qui dessine les plans, tandis que l’exécutant est l’équipe de construction qui réalise le bâtiment. Sans l’agent, il n’y a pas de plan, et sans l’exécutant, le plan ne quitte jamais le papier.
L’exécutant orchestre tout le processus :
- Il envoie les données d’entrée et les messages précédents à l’agent afin que celui-ci connaisse la question et ce qui s’est passé.
- Il reçoit l’action suivante de l’agent.
- Il exécute l’outil avec les données fournies.
- Il ajoute l’observation de l’outil à l’historique.
- Il envoie l’historique mis à jour ainsi que la question de l’utilisateur back à l’agent, et ce cycle se répète jusqu’à ce que l’agent indique une « Réponse finale ».
Prenez une demande concernant la température à Delhi et multipliez-la par 10. L’agent décide qu’il a besoin de l’outil météorologique, l’exécutant l’appelle, les données d’observation reviennent, l’agent décide qu’une multiplication est nécessaire, l’exécutant l’effectue et l’agent donne finalement la réponse. L’exécutant met en œuvre tout ce que l’agent juge utile.
Limites de cette approche
L’exécutant prédéfini fonctionne bien pour les cas simples, mais il présente de réelles faiblesses lorsque les agents deviennent plus complexes. La comparaison ci-dessous concerne LangGraph, la bibliothèque basée sur des graphes de LangChain. Notez également que les versions plus récentes de LangChain incitent les utilisateurs à utiliser LangGraph pour les agents ; vérifiez donc la documentation actuelle avant de travailler avec les anciennes classes d’exécutant.
1. La boîte noire
Le AgentExecutor standard est prédéfini. Il lui suffit d’être équipé d’outils et d’une instruction ; une boucle while invisible continue de fonctionner jusqu’à ce que la tâche soit terminée. Il est difficile d’intervenir. Si vous souhaitez que l’agent demande toujours l’approbation d’un humain avant de dépenser de l’argent, ou qu’il suive un ordre fixe comme d’abord l’étape A puis l’étape B, l’exécuteur s’y oppose, car il a été conçu pour être entièrement autonome.
Imaginons un agent disposant des outils search_flights et book_flight. À l’intérieur de l’exécuteur de LangChain, le LLM décide de ce qui se passe ensuite au sein d’une boucle invisible. Lorsqu’on lui demande de réserver un vol, il peut effectuer des recherches et effectuer la réservation immédiatement sans demander l’avis de l’utilisateur, ce qui peut entraîner un tarif de dix mille dollars alors que l’utilisateur voulait d’abord approuver toute acquisition. Des étapes intermédiaires comme une approbation obligatoire ne peuvent pas être appliquées strictement, car le flux de contrôle est implicite et géré par le modèle.
Dans LangGraph, le flux de travail est défini comme une série d’étapes explicites, ou de nœuds, tels que la recherche de vols, la demande d’approbation et la réservation. Ces éléments sont reliés de manière à ce que le système doive obtenir l’approbation avant de procéder à la réservation. Cela permet un contrôle total et facilite l’application de règles, l’ajout de points de contrôle humains, de tentatives de réessai ou de branches conditionnelles.
2. Cycles et boucles
Les flux de travail réels sont rarement linéaires. Ils impliquent des retours en arrière, la correction d’erreurs et des itérations sur des ensembles de documents.
- Les chaînes de LangChain sont principalement conçues comme des graphes acycliques dirigés, de sorte que les données circulent dans une seule direction.
- LangGraph a été conçu pour gérer les cycles. Il modélise le flux sous forme de une carte dans laquelle les nœuds représentent des fonctions et les arêtes les chemins entre elles.
Pour une tâche de réponse à des questions sur des documents, un pipeline LangChain peut récupérer des documents, écrire une réponse et la renvoyer. Si la réponse est incorrecte ou incomplète, il ne revient pas naturellement en arrière pour tenter à nouveau de récupérer des informations ou affiner la requête sans une logique écrite supplémentaire. Une fois qu’il a avancé, il ne peut pas facilement revenir en arrière pour s’améliorer.
LangGraph vous permet de dessiner des boucles de manière explicite : récupérer des données, répondre, vérifier la qualité, et si le résultat est médiocre, affiner la requête et la récupérer à nouveau, en répétant le processus jusqu’à obtenir un bon résultat. Le système peut alterner entre les nœuds jusqu’à ce qu’une condition soit remplie, ce qui convient aux tâches nécessitant itération, correction et retour d’information.
3. État et persistance
Cela est particulièrement important pour la scalabilité.
La mémoire de LangChain concerne principalement le contexte de la conversation, comme se souvenir des messages précédents afin que le modèle puisse répondre de manière plus efficace. Elle n’est pas étroitement liée au flux de travail et ne suit pas l’avancement d’une tâche. À moins d’être stockée explicitement, elle est généralement perdue lors du redémarrage du système, ce qui rend les tâches longues à exécuter peu fiables.
LangGraph considère la mémoire comme l’état complet du flux de travail et non seulement l’historique des conversations. À chaque étape, il enregistre ce qui a été fait, quels résultats ont été générés et quelle étape suit. Si le processus s’arrête en cours de route, il peut reprendre exactement à l’endroit où il s’était arrêté. Il permet également de mettre en pause, d’examiner et d’éditer l’état en présence d’un humain, voire de revenir à une étape antérieure, ce qui rend les tâches complexes à plusieurs étapes beaucoup plus robustes.
Imaginez une tâche longue, comme le traitement de dix documents un par un, qui plante à l’étape 7. Sans mécanisme de persistance intégré, tout est perdu et vous devez recommencer à zéro, sans aucune trace de progression par défaut. Avec un état enregistré après chaque étape, vous pouvez redémarrer à l’étape 7. Vous pouvez également faire une pause, permettre à quelqu’un de consulter ou de modifier l’état, puis reprendre, ou revenir à une étape antérieure, ce qui revient à une sorte de voyage dans le temps. Les workflows longs deviennent ainsi fiables, reproductibles et plus faciles à déboguer ou à auditer.
En résumé, l’exécuteur de base rend difficile la création d’agents scalables et adaptés à un usage en production, c’est pourquoi des outils basés sur des graphes existent pour cette tâche.
Lectures complémentaires
- Prises de vue de la mémoire de l’agent, compétences, dégradation et ciblage par branche — Quatre améliorations pour une couche mémoire basée sur un vecteur-DB intégré destinée aux agents de programmation : des prises de vue portables pouvant être fusionnées, une activation de compétences, une dégradation avec vérification des conflits, ainsi qu’une mémoire ciblée par branche.
- Votre premier agent LangGraph : un assistant de football doté d’outils et de fonctionnalités de routage — Tutoriel étape par étape sur LangGraph : état partagé, outils, nœud de planification, arêtes conditionnelles et résumé en markdown, conçu autour d’un assistant fictif pour les statistiques de football.