Le prompting ReAct est un schéma où un modèle de langage alterne entre raisonner et agir : il écrit une pensée sur ce qu'il faut faire, effectue une action comme une recherche ou un appel d'outil, lit le résultat, et seulement alors décide de l'étape suivante. Le nom est l'abréviation de Reason + Act (raisonner et agir) et vient de Yao et al. 2022, "ReAct: Synergizing Reasoning and Acting in Language Models". Il n'a aucun lien avec React, la bibliothèque JavaScript pour construire des interfaces.
La plupart des agents d'IA qui naviguent sur le web, exécutent du code ou modifient des fichiers font tourner une version de cette boucle. Une fois que vous l'avez déroulée à la main, le comportement d'un agent devient bien plus facile à prévoir et à déboguer.
La boucle Thought, Action, Observation
Un prompt ReAct demande au modèle d'écrire trois sortes de lignes. Dans les exemples de cette page, les libellés Thought:, Action: et Observation: restent en anglais, car le code Python plus bas recherche Action: tel quel ; le contenu de chaque ligne est en français.
- Thought (pensée) : le raisonnement sur la situation actuelle et sur l'information qui manque.
- Action : un appel d'outil dans un format fixe, comme
search[requête],read_file[chemin]oufinish[réponse]. - Observation : le résultat de cette action. Le modèle n'écrit pas cette ligne. Votre programme (ou vous) exécute l'action et ajoute la vraie sortie à la transcription.
Ensuite, toute la transcription retourne au modèle, qui écrit la pensée suivante. La boucle se termine quand le modèle choisit l'action de fin. Le modèle n'exécute jamais un outil lui-même ; il se contente de le demander, et c'est le code qui l'entoure qui décide d'exécuter ou non la demande.
Pourquoi raisonner et agir bat chacun des deux seul
L'article comparait ReAct avec des prompts qui ne font que raisonner (chain of thought) et des prompts qui ne font qu'agir (appels d'outils sans raisonnement écrit). Sur des tâches de questions-réponses et de vérification de faits avec un outil de recherche Wikipédia, le raisonnement seul bâtissait souvent un argument assuré sur un fait inventé par le modèle, alors que ReAct pouvait vérifier ce fait, et les meilleurs résultats en questions-réponses venaient de la combinaison de ReAct et du chain of thought, en basculant de l'un à l'autre quand le premier ne donnait pas de réponse sûre. L'action seule peinait à décomposer l'objectif et à transformer ce qu'elle trouvait en réponse ; les pensées écrites gardaient le plan visible. Sur deux tâches interactives, un jeu domestique en mode texte et un site de shopping simulé, ReAct avec un ou deux exemples faisait mieux que les modèles de référence entraînés auxquels les auteurs le comparaient.
La leçon générale : le chain of thought aide un modèle à planifier, les outils lui donnent des faits, et aucun des deux ne suffit pour une tâche qui demande les deux.
Un agent ReAct, tour par tour
Le bloc ci-dessous est un petit agent de programmation avec deux outils. Chaque onglet est la même conversation une étape plus tard : les lignes Observation sont ce que le programme a recollé après avoir exécuté l'action précédente. Lisez les réponses dans l'ordre.
Thought: Je ne sais pas quel test échoue ni comment. Lancer les tests montrera l'assertion exacte avant que je lise le moindre code. Action: run_tests[tests/test_cart.py]
Remarquez deux choses. La première action est un lancement de tests, pas une supposition : le modèle a rassemblé des preuves avant de lire le code. Et chaque pensée s'appuie sur la dernière observation, ce que le chain of thought ne peut pas faire.
Essayer ReAct dans une application de chat
Pas besoin de code pour voir la boucle. Dans ChatGPT, Claude ou Gemini, vous pouvez jouer l'outil : le modèle demande une action, vous l'effectuez et collez le résultat.
Réflexion : un ventilateur bruyant au repos signifie en général qu'un processus utilise le processeur en arrière-plan, ou que le ventilateur a du mal à refroidir (poussière, aérations bouchées). Vérifier d'abord l'utilisation du processeur permet de distinguer ces deux cas.
Action : ouvre le Gestionnaire des tâches (Ctrl+Maj+Échap sous Windows) ou le Moniteur d'activité (Applications > Utilitaires sur Mac). Trie les processus par processeur, attends 30 secondes, et donne-moi les trois premiers processus avec leur pourcentage de processeur.
Les mêmes consignes, avec une vraie fonction derrière chaque action, forment un agent.
Une boucle ReAct minimale en Python
Dans le code, le programme envoie la transcription, trouve la ligne Action dans la réponse, exécute la fonction correspondante, ajoute l'Observation et recommence. Ce croquis utilise le SDK Python d'OpenAI et le prompt système de l'agent de programmation ci-dessus. L'expression régulière cherche Action: : si vous traduisez ce libellé dans le prompt système, changez-le aussi ici.
import re
import subprocess
from pathlib import Path
from openai import OpenAI
client = OpenAI()
MODEL = "your-model-id" # e.g. from your provider's model list
PROJECT = Path.cwd().resolve()
READABLE = {".py", ".md", ".txt", ".toml", ".cfg"}
def inside_project(arg):
# The model chooses arg: resolve it and refuse anything outside the project.
path = (PROJECT / arg).resolve()
if not path.is_relative_to(PROJECT):
raise ValueError(f"{arg} is outside the project")
return path
def run_tests(arg):
path = inside_project(arg)
if not (path.is_file() and path.name.startswith("test_") and path.suffix == ".py"):
raise ValueError(f"{arg} is not a test file")
result = subprocess.run(["pytest", str(path), "-q"], capture_output=True, text=True)
return result.stdout[-2000:]
def read_file(arg):
path = inside_project(arg)
if not path.is_file() or path.suffix not in READABLE:
raise ValueError(f"{arg} is not a file this agent may read")
return path.read_text()[:20000]
TOOLS = {"run_tests": run_tests, "read_file": read_file}
def react(task, system_prompt, max_steps=8):
transcript = f"Task: {task}\n"
for _ in range(max_steps):
response = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": transcript},
],
temperature=0,
)
text = response.choices[0].message.content
match = re.search(r"Action: (\w+)\[(.*)\]", text)
if not match:
return text
transcript += text[: match.end()] + "\n"
tool, arg = match.groups()
if tool == "finish":
return arg
try:
observation = TOOLS[tool](arg) if tool in TOOLS else f"Unknown tool: {tool}"
except Exception as error: # a missing file becomes an observation, not a crash
observation = f"Error: {error}"
transcript += f"Observation:\n{observation}\n"
return "Stopped after max_steps without an answer."
Quatre détails comptent. La transcription est coupée juste après l'Action, car les modèles continuent parfois d'écrire et inventent leur propre Observation. Un outil qui échoue (un mauvais nom de fichier, par exemple) devient une Observation à laquelle le modèle peut réagir, au lieu de faire planter la boucle. La limite d'étapes arrête un modèle qui tourne en rond. Et la sortie des tests est tronquée, car un énorme journal de tests remplirait la fenêtre de contexte ; décider de ce qui entre dans cette fenêtre relève du context engineering.
Les deux outils vérifient aussi leur argument avant de faire quoi que ce soit. C'est le modèle qui choisit cet argument, donc les limites se placent dans l'outil : inside_project refuse tout chemin qui aboutit hors du dossier du projet (astuces ../ comprises), run_tests n'accepte que les fichiers test_*.py, et read_file n'ouvre que quelques types de fichiers de code et de texte et renvoie au plus 20 000 caractères, pour qu'un fichier .env ou une clé SSH n'atteigne jamais la requête suivante. Lancer pytest exécute quand même le code de votre projet : faites tourner un agent comme celui-ci dans un conteneur ou une copie jetable, jamais sur une machine qui contient des secrets.
Les API actuelles d'OpenAI, d'Anthropic et de Google proposent aussi l'appel d'outils natif : vous décrivez chaque outil avec un nom et un schéma JSON, et le modèle renvoie un appel d'outil structuré au lieu d'une ligne Action:. La boucle est identique ; seule l'analyse du texte disparaît.
La sécurité dans une boucle ReAct
Un agent lit du texte qu'il n'a pas écrit : pages web, fichiers, sorties d'outils. N'importe lequel peut contenir des consignes destinées au modèle, c'est l'injection de prompt. Donnez à chaque outil le minimum d'accès nécessaire (en lecture seule si possible), demandez à un humain de confirmer tout ce qui supprime, envoie ou paie, et traitez les actions demandées par le modèle comme des entrées non fiables à vérifier, pas comme des commandes à exécuter aveuglément.
Questions fréquentes
Qu'est-ce que le prompting ReAct ?
ReAct (pour Reason + Act, raisonner et agir) est un schéma de prompting où un modèle de langage écrit un court raisonnement, puis une action comme une recherche ou un appel d'outil, puis lit le résultat avant de raisonner à nouveau. Il vient de Yao et al. 2022, "ReAct: Synergizing Reasoning and Acting in Language Models". Il n'a rien à voir avec la bibliothèque JavaScript React.
Que sont Thought, Action et Observation dans ReAct ?
Une Thought (pensée) est le raisonnement du modèle sur ce qu'il doit faire ensuite. Une Action est un appel d'outil dans un format fixe, par exemple search[python 3.13 release notes]. L'Observation est la sortie de l'outil : votre programme exécute l'action pour l'obtenir et l'ajoute au prompt. La boucle se répète jusqu'à ce que le modèle choisisse une action de fin avec sa réponse.
Quelle est la différence entre ReAct et le chain of thought ?
Le chain of thought raisonne à partir de ce que le modèle sait déjà, donc un fait faux au début de la chaîne reste faux. ReAct alterne le raisonnement avec des actions qui vont chercher de vraies informations, si bien que le modèle peut vérifier un fait, voir un test échouer ou lire un fichier avant de continuer. L'article ReAct a montré qu'ancrer le raisonnement dans des résultats de recherche réduisait les faits inventés que produisait le chain of thought seul.
Les agents d'IA utilisent-ils encore ReAct ?
La boucle, oui. La plupart des agents actuels raisonnent, appellent un outil, lisent le résultat et décident à nouveau, ce qui est le cycle ReAct. Ce qui a changé, c'est le format : au lieu d'extraire des lignes Action: du texte, les API actuelles proposent l'appel d'outils natif, où le modèle renvoie une demande d'outil structurée et votre code renvoie le résultat.
Peut-on utiliser ReAct dans ChatGPT sans coder ?
Oui, en jouant vous-même le rôle de l'outil. Demandez au modèle de répondre avec une seule pensée et une seule action, puis de s'arrêter. Vous exécutez l'action (recherche, ouverture d'un fichier, commande), collez le résultat comme observation, et recommencez. C'est lent, mais cela montre exactement comment un agent décide de ce qu'il fait ensuite.