Overview
The prebuilt ReAct agent implements a classic pattern:- Reason/Plan with an LLM planner step
- Act by executing a tool requested by the LLM
- Repeat until you have a final answer
react_agent(...) is built on top of agent_loop(...), so it supports checkpointing, budgets, and interrupts.
Required state shape
ReAct expects state to be either adict or a Pydantic model with fields that behave like:
messages: list of chat messages (recommended)llm_response: the lastLLMResponsefrom the plannertool_name,tool_args,tool_call_id: metadata for the current tool calltool_result: output of the toolfinal: final assistant text (used as the stop signal)
Planner (LLM step)
The planner must be a step created byllm_step(...) and should attach an LLMResponse into state (default key: llm_response).
When tool specs are present in LLMConfig.tools, the provider can return tool calls in LLMResponse.tool_calls.
Tools (tool steps)
Tools must be steps created viatool_step(...) (annotation kind="tool").
At runtime, the agent:
- Validates that all tools are Steps and are marked as tools
- Resolves tool calls by tool name
- Executes exactly one tool call per iteration (first call in the list)
Loop behavior and termination
ReAct stops whenfinal is not None.
If the LLM requests a tool that does not exist, ReAct raises a KeyError.
If a tool runs but does not set tool_result (or your configured result key), ReAct raises an error so you can fix the tool wrapper.