[!NOTE] Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.
AI Boucles de raisonnement des agents en 2026 : ReAct contre ReWOO contre Plan-and-Execute
Première partie de la série « Ingénierie de la pile Agentic »
Un agent reasoning loop gère la manière dont un système planifie ses actions, invoque des outils, interprète les résultats obtenus, et détermine le moment opportun pour s’arrêter. Ce flux de contrôle influence directement les coûts, les délais de réponse, ainsi que la capacité du système à se remettre en marche après qu’un outil ait renvoyé des données inattendues.
Ce post compare les trois modèles AI agent loop qu’il convient de maîtriser en 2026 : ReAct, ReWOO et Plan-and-Execute. L’exemple concret présenté est un agent d’analyse de marché que j’ai développé au sein de LangGraph, dont le code complet est disponible sur GitHub.
Il s’agit de la couche interne de la série. Les parties ultérieures y ajoutent l’état à partir duquel le boucle reprend son exécution, les outils qu’elle peut appeler, la politique qui guide ces appels, le runtime qui permet au processus de rester actif, ainsi que les harness qui effectuent les vérifications permettant de déterminer si le travail est réellement terminé.
En résumé : ReAct est flexible mais coûteux, ReWOO offre une vitesse d’exécution élevée lorsque le flux de travail est prévisible, tandis que la méthode Plan-and-Execute convient aux analyses à plusieurs étapes. Un agent AI en environnement de production peut basculer entre différentes boucles de raisonnement pour chaque requête, en s’appuyant sur un état partagé ainsi que des nœuds LangGraph sauvegardés à des points clés, afin que chaque tâche utilise la boucle adaptée à sa structure.
La boucle permet de contrôler les coûts, la latence et la capacité de récupération
Un agent utile nécessite bien plus qu’un simple prompt performant. Son graphe de contrôle doit relier les processus de raisonnement, les outils et la mémoire, tout en permettant de gérer les pannes.
Le reasoning loop détermine le moment où le modèle planifie une action, lance un outil, lit le résultat et s’arrête. Un choix inadapté entraîne des appels au modèle superflus ainsi qu’une latence accrue. De plus, cela peut empêcher l’agent de se remettre d’un tool result inattendu.
Trois modèles de raisonnement d’agent AI
ReAct : réfléchir, agir, observer, répéter
ReAct Yao et al. (2022) présentent le modèle de base des agents interactifs. Ce dernier exécute une boucle :
- Réflexion : l’agent génère une « réflexion » afin de décomposer l’objectif et de planifier la prochaine étape.
- Action : en se basant sur cette réflexion, il invoque un outil.
- Observation : l’agent analyse le résultat obtenu, ce qui met à jour sa compréhension en prévision de la réflexion suivante.
Avantages :
- Le fait de s’appuyer sur des observations réelles réduit l’usage de faits inventés.
- L’agent peut modifier sa stratégie en temps réel en fonction de ce qu’il vient de percevoir.
- L’historique des appels d’outils et des observations fournit un suivi concret de l’exécution.
Inconvénients :
- L’historique s’accumule et est rétraité à chaque étape, ce qui entraîne une augmentation de la latence et des coûts en fonction de la longueur du cycle.
- Cela est inefficace lorsque le tool calls aurait pu être planifié à l’avance, et c’est précisément le domaine dans lequel ReWOO intervient.
- En l’absence de condition d’arrêt ou de limite de pas, le cycle se poursuivra indéfiniment.
Idéal pour : les tâches exploratoires, le débogage, ainsi que dans les situations où il est impossible de prédire ce qui va se produire.
ReWOO : planifier tout en amont
ReWOO (Reasoning WithOut Observation) constitue une version plus efficace de ReAct. La astuce réside dans le découplage du raisonnement de l’exécution des outils : au lieu de s’arrêter pour observer chaque action, ReWOO planifie l’ensemble de la séquence de tool calls en une seule passe.
- Plan : une seule appel à LLM écrit le plan complet de tool calls, en utilisant des placeholders variables (
#E1,#E2) pour les sorties qui n’existent pas encore. - Worker : un exécutant non-LLM qui exécute les outils prévus séquentiellement ou en parallèle, en remplissant les placeholders.
- Solver : une appel finale LLM qui prend en compte les observations collectées et écrit la réponse.
Avantages :
- Moins d’appels répétés au modèle que avec ReAct tant que le plan initial reste valide.
- Latence réduite. Aucune nouvelle soumission de l’historique à chaque étape.
- Le planificateur peut être affiné indépendamment, sans avoir besoin d’un environnement en temps réel.
Inconvénients :
- Fragile en cas de comportement anormal des outils. Le plan part du principe que tout fonctionne correctement.
- Nécessite des flux de travail prévisibles.
- En l’absence d’une logique de secours explicite, un plan défectueux continue de s’exécuter.
Idéal pour : des captures rapides, des vérifications d’état, des tableaux de bord. Tout contexte où les outils se comportent de manière prévisible.
Plan-and-Execute : une approche hybride
Planification et exécution il se situe entre les deux. Cet article esquisse une séparation simple que la plupart des agents modernes ont adoptée :
- Phase de planification : l’agent génère d’abord un plan qui décompose la tâche en sous-tâches plus petites.
- Phase d’exécution : l’agent exécute ensuite ces sous-tâches.
L’article initial se concentrait sur l’incitation zéro-shot. Les solutions modernes frameworks telles que LangGraph ont évolué cette approche en un modèle d’orchestration complet, prévoyant une exécution séquentielle ainsi que le choix d’un modèle adapté à chaque étape (un modèle de raisonnement puissant pour la planification, un modèle moins coûteux pour l’exécution).
Avantages :
- Raisonnement hiérarchique qui reproduit la manière dont un expert humain décompose un projet.
- Un replanification est possible : il est possible de faire une pause et de réévaluer la situation si le résultat d’une étape s’avère inattendu.
- Spécialisation du modèle : le planificateur peut être coûteux, tandis que l’exécuteur peut l’être moins.
- Complexité bornée, avec une checkpoint claire après chaque étape.
Inconvénients :
- Latence plus élevée que celle de ReWOO, car les étapes s’exécutent séquentiellement.
- Plus d’états à gérer.
- Surdimensionné pour des requêtes ponctuelles.
Idéal pour : des analyses complexes à plusieurs étapes, des tâches de recherche, ou tout travail nécessitant une synthèse finale.
Choisir en fonction des points de défaillance potentiels du plan
| Fonctionnalité | ReAct (2022) | Plan-and-Execute (2023) | ReWOO (2023) |
|---|---|---|---|
| Philosophie fondamentale | Improviser : agir, puis décider de la prochaine action en fonction du résultat obtenu. | Architecte : élaborer un plan complet, l’exécuter, puis le réviser. | Optimiseur : écrivez un « script » contenant des variables et exécutez-le en une seule fois. |
| Flux de travail | Boucle itérative : Réflexion → Action → Observation. | Deux étapes : phase 1 (planification), phase 2 (exécution). | Découplé : le planificateur crée un graphe de tool calls ; les travailleurs les exécutent. |
| Adaptabilité | Maximum : peut changer de direction après chaque tool call. | Niveau intermédiaire : il réplanifie généralement uniquement une fois qu’un ensemble d’étapes a été exécuté. | Minimum : il suit généralement le script initial, sauf si le résolveur échoue. |
| Efficacité | Faible : utilisation élevée de tokens ; il est nécessaire de relire l’ensemble de l’historique à chaque étape. | Moyen : économise des tokens en ne procédant pas à de nouvelles réflexions pendant l’exécution. | Élevé : nombre minimal d’appels à LLM ; il est possible de paralléliser l’exécution des outils afin d’améliorer la vitesse. |
| Idéal pour | Exploration ouvertes, ou tâches dont les résultats sont imprévisibles. | Tâches à long terme nécessitant un objectif stable (par exemple, la rédaction d’un article scientifique). | Des flux de travail structurés et reproductibles (par exemple, la vérification des conditions météorologiques dans 5 villes). |
Ce tableau constitue un point de départ, et non un benchmark résultat final. Préférez le ReAct lorsque chaque observation peut influencer l’action suivante. Optez pour la stratégie Plan-and-Execute lorsque la tâche globale peut être décomposée, mais que chaque étape nécessite encore des retours d’information. Utilisez ReWOO dans les cas où les dépendances sont connues avant l’exécution et où une entrée défectueuse peut bloquer les appels subséquents. Évaluez les performances des trois approches en fonction de la latence de votre outil, du modèle employé, de l’ensemble des tâches à traiter ainsi que de votre politique de tentative répétée, avant de vous baser uniquement sur les coûts.
Exemple concret : l’agent Analyste de marché
Pour concrétiser cela, j’ai développé un Agent d’analyse de marché celui qui intègre les trois modèles dans une même base de code, pour une tâche de recherche de marché.
Il utilise LangGraph pour l’orchestration. Les trois modèles partagent le même objet d’état, ce qui permet au routage de choisir celui à exécuter pour chaque requête :
Définition de l’état
L’état partagé capture tout ce dont l’agent a besoin entre les différents modes :
class PlanStep(BaseModel):
"""A single step in the research plan."""
step_number: int
description: str
tool_hint: str | None = None
completed: bool = False
result: str | None = None
class UserProfile(BaseModel):
"""Structured user context loaded from long-term memory."""
risk_tolerance: str | None = None
investment_horizon: str | None = None
class AgentState(BaseModel):
"""Main state for the Market Analyst Agent graph."""
# Identity and profile context for memory-backed personalization
user_id: str
user_profile: UserProfile = Field(default_factory=UserProfile)
# Message history with LangGraph's add_messages reducer
messages: Annotated[list, add_messages] = Field(default_factory=list)
# Execution mode (set by router)
execution_mode: ExecutionMode | None = None
# Plan-and-Execute state
plan: list[PlanStep] = Field(default_factory=list)
current_step_index: int = 0
# ReWOO state
rewoo_plan: list[ReWOOPlanStep] = Field(default_factory=list)
# Research results
research_data: ResearchData | None = None
# HITL output
draft_report: DraftReport | None = None
report_approved: bool = False
Schéma 1 : Implémentation par planification et exécution
Le mode Plan-and-Execute convient parfaitement aux tâches nécessitant une synthèse en plusieurs étapes. La clé réside dans le fait de séparer la planification de l’exécution : on utilise un modèle puissant pour élaborer le plan initial, puis un boucle ReAct qui permet d’exécuter chaque étape tout en laissant de la marge pour react afin de tool results.
Comment cela correspond au schéma :
- Une seule phase de planification initiale. Une unique invocation de LLM génère l’ensemble du plan sous forme d’une liste de descriptions de étapes.
- Une sortie guidée par un schéma, qui valide le plan avant son exécution.
- Aucune exécution d’outil pour le moment. Le planificateur ne décide que de ce qui doit être fait, et non de la manière de le faire.
- Étapes lisible par un humain. Chaque étape est un texte que l’exécutant interprétera.
# System prompt guides the LLM to think like a research analyst
# creating a strategic plan, not immediate tool calls
PLANNER_SYSTEM_PROMPT = """You are a senior investment research analyst.
Break down stock analysis requests into 4-6 research steps covering:
1. Current price and basic metrics
2. Recent news and announcements
3. Competitor analysis (if relevant)
4. Financial health assessment
5. Risk factors
6. Investment thesis synthesis
Output as JSON with step_number, description, and tool_hint."""
# Schema-Guided Reasoning: Enforce structure with Pydantic
class PlanOutput(BaseModel):
"""Structured output for the planner."""
steps: list[PlanStep] = Field(description="Research steps to execute")
ticker: str = Field(description="The stock ticker being analyzed")
def planner_node(state: AgentState) -> dict:
"""Generate a research plan from the user's request.
This is Phase 1 of Plan-and-Execute: creating the high-level strategy.
"""
# Use a powerful model for strategic planning
llm = ChatAnthropic(model="claude-sonnet-4-5-20250929", temperature=0)
# Ask for a typed plan and validate it before execution.
# The API can still fail, so production code also handles that exception.
structured_llm = llm.with_structured_output(PlanOutput)
# Context from long-term memory personalizes the plan
profile_context = f"""
User Profile:
- Risk Tolerance: {state.user_profile.risk_tolerance}
- Investment Horizon: {state.user_profile.investment_horizon}
"""
# Single LLM call creates the complete plan
result: PlanOutput = structured_llm.invoke([
SystemMessage(content=PLANNER_SYSTEM_PROMPT + profile_context),
HumanMessage(content=f"Create a research plan for: {last_user_message}"),
])
# State update: Store the plan and initialize tracking
return {
"plan": result.steps, # The sequential steps to execute
"current_step_index": 0, # Start at step 0
"research_data": ResearchData(ticker=result.ticker), # Initialize data container
}
Ce llm.with_structured_output(PlanOutput) La ligne correspond au Reasonnement guidé par un schéma (SGR), que j’ai abordé dans un article précédent. Ce schéma permet à l’application de rejeter un plan mal formaté avant que LangGraph n’utilise les champs validés pour générer des arêtes conditionnelles.
Schéma 2 : exécution de ReAct
Une fois le plan défini, l’exécuteur traite chaque étape comme une boucle ReAct indépendante. Il s’agit de la phase 2 : chaque étape est suffisamment petite pour que le cycle Pensée-Action-Observation reste ciblé, permettant à l’agent de react s’adapter à ce que retourne l’outil.
Comment la partie ReAct s’aligne :
- Exécution itérative. Une étape à la fois, avec un retour d’information provenant de l’observation.
- Le cycle Pensée-Action-Observation s’exécute en interne
create_react_agent3. Les résultats de l’étape précédente sont intégrés en tant que contexte pour le raisonnement en cours. - L’agent sélectionne des outils en fonction de la description de l’étape.
- Il peut modifier son approche au cours d’une étape en fonction des résultats fournis par un outil.
# Tools available for the ReAct agent to choose from
TOOLS = [
get_stock_snapshot,
get_price_history,
search_news,
search_competitors,
get_financials,
]
def executor_node(state: AgentState) -> dict:
"""Execute the current step using a ReAct agent.
This is Phase 2 of Plan-and-Execute: adaptive execution of each planned step.
Each step runs as a mini ReAct loop until completion.
"""
# Get the current step from the plan
current_step = state.plan[state.current_step_index]
# Build context from what we've learned so far
# This matters: each step builds on previous observations
previous_context = ""
for step in state.plan[:state.current_step_index]:
if step.result:
previous_context += f"\nStep {step.step_number}: {step.result}\n"
# Create a ReAct agent for this step
# LangGraph's create_react_agent implements the full Thought-Action-Observation loop:
# 1. Agent generates a "thought" about what tool to call
# 2. Agent calls the tool ("action")
# 3. Tool returns result ("observation")
# 4. Agent decides: call another tool or finish
react_agent = create_react_agent(
model=ChatAnthropic(model="claude-sonnet-4-5-20250929"),
tools=TOOLS,
)
# Invoke the ReAct loop for this single step
# The agent will loop internally until it completes the step
result = react_agent.invoke({
"messages": [
SystemMessage(content=EXECUTOR_SYSTEM_PROMPT),
HumanMessage(content=f"""Execute Step {current_step.step_number}:
{current_step.description}
Ticker: {state.research_data.ticker}
Previous findings: {previous_context}"""),
]
})
# Extract the final answer from the ReAct agent's message history
# The last message contains the synthesis after all tool calls
updated_plan = list(state.plan)
updated_plan[state.current_step_index] = PlanStep(
step_number=current_step.step_number,
description=current_step.description,
completed=True,
result=result["messages"][-1].content, # Final observation
)
# State update: Mark step complete and advance to next
return {
"plan": updated_plan,
"current_step_index": state.current_step_index + 1,
}
Voilà le flux fondamental de planification et d’exécution : un modèle puissant élabore le plan, puis ReAct met en œuvre chaque étape avec une grande capacité d’adaptation.
Schéma 3 : ReWOO pour des captures rapides
Lors des briefings rapides, ReWOO omet le raisonnement intercalé et exécute les outils en parallèle. Le planificateur génère au préalable un script compilé contenant tool calls, que l’agent exécute ensuite sans aucune autre intervention de LLM.
Sa forme :
- Trois phases (Planificateur → Travailleur → Résolveur), sans boucles.
- Référence Tool calls
#E1,#E2Des placeholders pour les résultats qui n’existent pas encore. - Aucun LLM pendant l’exécution. Le travailleur se contente d’exécuter des outils.
- Les outils indépendants s’exécutent en parallèle.
- Une seule appel de synthèse à la fin, sur l’ensemble des données en même temps.
Phase 1 : planificateur ReWOO (crée à l’avance le graphe d’exécution complet)
class ReWOOPlanStep(BaseModel):
"""A step in the ReWOO plan with variable placeholders.
Key difference from Plan-and-Execute's PlanStep:
- Contains actual tool_name and tool_args (not just description)
- Uses variable references (#E1) for dependencies
"""
step_id: str # e.g., "#E1" - becomes a variable
description: str
tool_name: str # Exact tool to call
tool_args: dict # May contain variable refs like {"price": "#E1"}
depends_on: list[str] = [] # For dependency ordering
result: str | None = None
class ReWOOPlanOutput(BaseModel):
"""Structured output for ReWOO planner."""
steps: list[ReWOOPlanStep] = Field(description="Planned tool calls with variables")
def rewoo_planner_node(state: AgentState) -> dict:
"""Generate a complete plan of tool calls upfront.
This is the key difference from Plan-and-Execute: instead of creating
human-readable step descriptions, we create EXACT tool calls that
the worker will execute blindly.
"""
llm = ChatAnthropic(model="claude-sonnet-4-5-20250929", temperature=0)
# Schema-Guided Reasoning ensures valid tool call specifications
structured_llm = llm.with_structured_output(ReWOOPlanOutput)
ticker = state.research_data.ticker if state.research_data else "UNKNOWN"
# Single LLM call to plan ALL tool executions
result: ReWOOPlanOutput = structured_llm.invoke([
SystemMessage(content=REWOO_PLANNER_PROMPT),
HumanMessage(content=f"""Create a ReWOO plan for: {query}
Ticker: {ticker}
Output tool calls with:
- step_id: Variable name (#E1, #E2, etc.)
- description: What this accomplishes
- tool_name: Exact tool from the list
- tool_args: Dictionary of arguments
- depends_on: List of step_ids this depends on"""),
])
# State update: Store the complete execution plan
# Worker will execute this without any LLM involvement
return {"rewoo_plan": result.steps}
Phase 2 : travailleur ReWOO (exécute des outils sans raisonnement LLM)
def rewoo_worker_node(state: AgentState) -> dict:
"""Execute all planned tools in parallel (no LLM calls).
This is the key efficiency: Worker is "dumb" - it just runs tools
according to the plan. No LLM calls = massive token savings.
"""
results = {} # Store results keyed by step_id (e.g., "#E1": "$150.23")
# Execute ALL independent steps in parallel using ThreadPoolExecutor
# This is where ReWOO gets its speed advantage
with ThreadPoolExecutor(max_workers=5) as executor:
futures = {
executor.submit(execute_tool, step): step
for step in state.rewoo_plan
if not step.depends_on # Only independent tools for parallel batch
}
# Collect results as they complete
for future in as_completed(futures):
step = futures[future]
results[step.step_id] = future.result()
# No LLM reasoning here - just store the raw tool output
# State update: Store results for the Solver phase
return {"rewoo_plan": updated_steps}
Phase 3 : résolveur ReWOO (il synthétise l’ensemble des résultats au cours d’une seule appel LLM)
def rewoo_solver_node(state: AgentState) -> dict:
"""Synthesize all tool results into a flash briefing.
This is the second efficiency gain: Instead of interleaving
LLM calls with tool execution (like ReAct), we make ONE
final synthesis call with all gathered data.
"""
# Build context from ALL tool results at once
tool_results = []
for step in state.rewoo_plan:
if step.result:
tool_results.append(f"### {step.description}\n{step.result}")
context = "\n\n".join(tool_results)
# Single LLM call to synthesize everything
structured_llm = llm.with_structured_output(FlashBriefingOutput)
result = structured_llm.invoke([
SystemMessage(content=REWOO_SOLVER_PROMPT),
HumanMessage(content=f"Create a flash briefing from this data:\n\n{context}"),
])
return {"draft_report": result}
ReWOO planifie chaque tool call à l’avance et stocke les dépendances dans des placeholders tels que #E1 et #E2L’exécutant peut lancer des appels indépendants en parallèle, sans avoir à demander au modèle quelle action effectuer ensuite. Un dernier appel au modèle combine les résultats, ce qui permet de maintenir des flux de travail prévisibles à un coût faible.
Où chaque motif appelle le modèle
Les trois motifs diffèrent quant au moment et à la manière dont ils appellent le LLM :
| Pattern | LLM appels pendant l’exécution | Mises à jour d’état | Pattern de code clé |
|---|---|---|---|
| Planification et exécution | 1 pour la planification + 1 par étape | Exécution séquentielle des étapes | planner_node() → boucle : executor_node() → reporter_node() |
| ReAct (à l’intérieur de chaque étape) | Plusieurs par étape (cycles pensée-action) | Historique des messages accumulés | create_react_agent() Il effectue des boucles en interne jusqu’à ce que l’étape soit terminée. |
| ReWOO | 1 pour la planification + 0 pendant l’exécution + 1 pour la synthèse | Complétion d’outils en parallèle | rewoo_planner_node() → rewoo_worker_node() → rewoo_solver_node() |
Ce qui diffère entre eux, c’est ce que produit le planificateur. C’est lui qui détermine tout le reste dans la chaîne de traitement.
-
Plan-and-Execute génère des descriptions de étapes lisible par les humains :
# Planner output (list of PlanStep objects) plan = [ PlanStep( step_number=1, description="Get current price and key financial metrics", tool_hint="get_stock_price" ), PlanStep( step_number=2, description="Search for recent news and earnings", tool_hint="search_news" ), # ... more steps ]L’exécuteur lit chaque description et détermine quels outils appeler. Cette approche est flexible, mais elle entraîne un coût équivalent à une invocation de LLM par étape.
-
ReAct ne dispose pas de plan initial. Il fait appel à un raisonnement itératif :
# No planning phase - ReAct works step-by-step with accumulated messages messages = [ HumanMessage(content="Execute Step 1: Get current price"), AIMessage(content="I'll call get_stock_price"), ToolMessage(tool_call_id="1", content="$132.45"), AIMessage(content="Now I need metrics..."), # ... agent continues until step complete ]Plusieurs appels à LLM par étape s’adaptent aux observations et entraînent généralement des coûts supérieurs aux deux modes prévus initialement.
-
ReWOO génère des spécifications explicites et exécutables tool call :
# Planner output (list of ReWOOPlanStep objects) rewoo_plan = [ ReWOOPlanStep( step_id="#E1", tool_name="get_stock_price", tool_args={"ticker": "NVDA"} ), ReWOOPlanStep( step_id="#E2", tool_name="search_news", tool_args={"query": "NVDA earnings", "limit": 5} ), # ... all tool calls planned upfront ]Le travailleur s’exécute de manière autonome, sans aucune intervention de LLM. Toutes les appels au modèle ont lieu au sein du planificateur et du résolveur, ce qui permet de rendre le nombre d’appels au modèle prévisible.
Flux de mémoire et d’état :
- Plan-and-Execute : l’état évolue au fil des mouvements
plan→current_step_index→research_data. - ReAct : l’état s’accumule dans le
messagesarray (l’historique complet de la conversation). - ReWOO : l’état évolue au fil du temps.
rewoo_plan, avecresultchamps remplis par l’opérateur.
Assemblage final : connexion du graphe
Voici comment les trois motifs coexistent au sein d’un même système LangGraph. Ils partagent un AgentState et coexistent au sein d’un même graphe. Un routeur sélectionne le chemin pour chaque requête ; il s’agit donc d’un seul agent disposant de trois modes d’exécution, et non de trois agents agissant indépendamment.
LangGraph conserve une approche déclarative pour la définition des connexions :
def create_graph(checkpointer=None):
builder = StateGraph(AgentState)
# Add nodes
builder.add_node("router", router_node)
builder.add_node("planner", planner_node)
builder.add_node("executor", executor_node)
builder.add_node("reporter", reporter_node)
builder.add_node("rewoo_planner", rewoo_planner_node)
builder.add_node("rewoo_worker", rewoo_worker_node)
builder.add_node("rewoo_solver", rewoo_solver_node)
# Define edges
builder.add_edge(START, "router")
builder.add_conditional_edges("router", route_after_router, {
"planner": "planner",
"rewoo_planner": "rewoo_planner",
})
# Deep Research path
builder.add_edge("planner", "executor")
builder.add_conditional_edges("executor", route_after_executor, {
"executor": "executor", # Loop back for more steps
"reporter": "reporter", # Done with plan
})
builder.add_edge("reporter", END)
# Flash Briefing path (ReWOO)
builder.add_edge("rewoo_planner", "rewoo_worker")
builder.add_edge("rewoo_worker", "rewoo_solver")
builder.add_edge("rewoo_solver", END)
return builder.compile(
checkpointer=checkpointer,
interrupt_before=["reporter"], # HITL pause for approval
)
Sélection automatique de motifs via un routageur
Pour choisir le bon boucleur adapté à chaque requête, j’ai ajouté un classifieur routeur. Celui-ci fait appel au raisonnement guidé par des schémas afin de garantir la fiabilité de la classification :
class ExecutionMode(str, Enum):
"""Execution mode for the agent."""
DEEP_RESEARCH = "deep_research" # Plan-and-Execute + ReAct (thorough)
FLASH_BRIEFING = "flash_briefing" # ReWOO (fast, token-efficient)
class RouterOutput(BaseModel):
"""Structured output for the router."""
mode: ExecutionMode # DEEP_RESEARCH or FLASH_BRIEFING
ticker: str
reasoning: str
ROUTER_SYSTEM_PROMPT = """Classify the user's request:
1. **deep_research**: Complex analysis requiring synthesis
- Examples: "Analyze strategic risks", "investment thesis"
2. **flash_briefing**: Quick snapshots, simple data retrieval
- Examples: "quick snapshot", "current price"
Default to deep_research if unclear."""
structured_llm = llm.with_structured_output(RouterOutput)
Avec cette configuration en place, les utilisateurs n’ont pas besoin de sélectionner de mode. Le routeur dirige automatiquement la donnée « prix actuel » vers ReWOO et la donnée « thèse d’investissement » vers Plan-and-Execute.
Principaux enseignements
- ReAct fournit les points de retour d’information les plus fréquents, au prix de appels répétés au modèle.
- ReWOO diminue le nombre d’aller-retour vers le modèle lorsque les outils sont fiables et que les dépendances sont prévisibles.
- La méthode Plan-and-Execute convient aux analyses complexes qui peuvent être décomposées avant leur exécution tout en nécessitant un retour d’information à chaque étape.
- Un routeur peut choisir parmi ces approches pour chaque requête, ce qui évite aux utilisateurs de devoir le faire eux-mêmes.
- La boucle nécessite un état stocké afin de survivre à une interruption ou à un redémarrage du travailleur. C’est le sujet de la deuxième partie.
La mise en œuvre complète, y compris le routeur et l’état partagé, se trouve dans le Repositoire d’agents analystes de marché.
La couche suivante concerne la mémoire
Partie 2, AI Architecture de mémoire des agents en 2026, il isole les données checkpoints réutilisables de los connaissances inter-sessions ainsi que des documents de projet. Sans cette couche d’état, le routeur et l’exécuteur mentionnés ci-dessus ne fonctionnent que tant qu’un processus unique et une seule fenêtre de contexte sont actifs.
Références
- ReAct : Synergie entre le raisonnement et l’action dans les modèles de langage (Yao et al., 2022)
- ReWOO : Découplage du raisonnement des observations afin d’obtenir des modèles de langage augmentés plus efficaces (Xu et al., 2023)
- Planification et résolution via des prompts : amélioration du raisonnement zéro-shot Chain-of-Thought par les grands modèles de langage (Wang et al., 2023)
- Répertoire des agents analystes de marché
Le code de l’agent Analyste de marché est disponible. GitHub si vous souhaitez suivre le texte en même temps._
Série : Conception de la pile Agentic
- Partie 1 : AI Les boucles de raisonnement des agents en 2026 (cette publication) Partie 2 : AI L’architecture de mémoire des agents en 2026 — checkpoints, les bases de données vectorielles et la mémoire de documents Partie 3 : AI Agent Tool Use en 2026 — MCP, CLI, compétences, exécution de code et ACI Partie 4 : AI La sécurité des agents en 2026 — garde-fous, permissions, sandboxes, HITL, ainsi que le cadrage MCP
- Partie 5 : Agents AI à exécution prolongée Runtime en 2026 — sessions, sandboxes, checkpoints, mécanismes d’orchestration et schémas de déploiement
- Partie 6 : Harness Engineering pour les agents AI (à paraître prochainement) — vérifications d’acceptation, traces, tentatives de réessai, transferts de responsabilités, ainsi que le cycle associé au modèle