ReAct Pattern: Interleaving Reasoning and Action for LLM Agents › Integration with Real LLMs
Language AI HandbookAll chapters ReAct Pattern: Interleaving Reasoning and Action for LLM Agents › Integration with Real LLMsOne section · Sections in this chapter9 / 14 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
In production systems, the llm_simulator function would be replaced with actual API calls to models like GPT-4, Claude, or open-source alternatives such as Llama or Mistral. Modern models trained with instruction tuning (covered in Part XXXVI) and RLHF (covered in Part XXXVII) typically require minimal few-shot examples to adopt the ReAct pattern effectively, though the specific formatting may need adjustment based on the model's training.
The following example integrates the pattern with the OpenAI API:
import openai
def llm_call(prompt: str, model: str = "gpt-4") -> str:
"""Call OpenAI API with ReAct-formatted prompt."""
client = openai.OpenAI()
response = client.chat.completions.create(
model=model,
messages=[
{
"role": "system",
"content": "You are a helpful assistant that uses tools by thinking step-by-step.",
},
{"role": "user", "content": prompt},
],
temperature=0, # Low temperature for deterministic reasoning
stop=["\nObservation:"], # Stop before generating observation
)
return response.choices[0].message.contentThe stop parameter is important: it prevents the model from hallucinating observations. By specifying that generation should halt before creating an observation line, we ensure that observations come exclusively from actual tool execution rather than the model's imagination. This maintains the integrity of the grounding mechanism that makes ReAct reliable. Without this stop sequence, a sufficiently confident model might generate both the action and its supposed result in a single pass, completely bypassing the external tool call.
The temperature setting also matters. Low temperatures (0.0-0.2) produce more deterministic reasoning that follows the expected format reliably. Higher temperatures can cause format drift, where the model starts omitting the "Thought:" prefix or using slightly different action syntax. For most ReAct applications, temperature 0 is the right choice.
Structured Output Approach
An alternative to parsing free-form text is to use structured outputs or function calling to extract actions. Instead of asking the model to generate Action: search[query] in text and parsing it with regex, you ask the model to generate a JSON object with a defined schema:
import openai
tools_spec = [
{
"type": "function",
"function": {
"name": "search",
"description": "Search for information on a topic",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query",
}
},
"required": ["query"],
},
},
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "Evaluate a mathematical expression",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate",
}
},
"required": ["expression"],
},
},
},
]
def llm_call_structured(messages: list, tools: list) -> dict:
"""Call OpenAI API with structured tool definitions."""
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
tools=tools,
tool_choice="auto",
)
return response.choices[0].messageThe structured approach eliminates the need for regex parsing and reduces format errors significantly. The tradeoff is that the model no longer generates explicit thought text before each action, which reduces the interpretability of its reasoning. Some implementations address this by asking the model to include its reasoning in the tool call arguments or in a separate "thinking" step before calling tools.