Build a ReAct AI Agent With Tool Calling in 2026

The ReAct pattern—short for Reasoning and Acting—remains one of the most practical foundations for building reliable AI agents. Instead of asking a model to answer everything in a single shot, ReAct interleaves reasoning steps with actions (tool calls), then feeds the results back into the model so it can decide what to do next. In 2026, with mature function-calling APIs across major providers, wiring this loop is more straightforward than ever. This walkthrough shows you how the loop works and how to build one that is production-ready.
What the ReAct Loop Actually Does
A ReAct agent runs a cycle: the model reasons about the task, decides whether it needs a tool, emits a structured call, receives the tool's observation, and repeats until it can produce a final answer. Classic ReAct prompting made this explicit with "Thought / Action / Observation" text blocks. Modern function-calling APIs formalize the "Action" part: the model returns a structured tool-call object instead of free text, so you no longer have to parse brittle strings.
The key insight is that ReAct agent tool calling combines two things: the reasoning traces that help the model plan, and the structured tool invocations that let it interact with the real world—databases, search, code execution, or internal APIs.
Prerequisites and Setup
You need three components:
1. A model that supports tool calling
Most current chat-completions and responses APIs accept a tools parameter describing available functions as JSON Schema. The model then chooses whether to call one and returns arguments matching your schema.
2. A tool registry
Define each tool as a plain function plus a schema. Keep tools small and single-purpose—one tool for search, one for a database lookup, one for math. Narrow tools are easier for the model to select correctly.
3. A control loop
This is the code that calls the model, executes any requested tools, appends results to the conversation, and loops until the model stops requesting tools.
Defining Your Tools
Start with clear schemas. The description fields are not documentation for humans—they are instructions the model reads to decide when and how to call each function. Be specific about units, formats, and constraints.
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city. Returns temperature in Celsius.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g. 'Berlin'"}
},
"required": ["city"]
}
}
}
]On the Python side, map the tool name to the real implementation:
def get_weather(city):
# call a real weather API here
return {"city": city, "temp_c": 14, "conditions": "cloudy"}
TOOLS = {"get_weather": get_weather}Building the ReAct Loop
The loop is the heart of the agent. Send the conversation and tool definitions to the model. If it returns tool calls, execute them, append the results as tool messages, and call the model again. When it returns a plain message with no tool calls, you have your final answer.
import json
def run_agent(client, user_input, max_steps=8):
messages = [
{"role": "system", "content": "Reason step by step. Use tools when needed."},
{"role": "user", "content": user_input},
]
for _ in range(max_steps):
response = client.chat.completions.create(
model="your-model",
messages=messages,
tools=tools,
)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
return msg.content # final answer
for call in msg.tool_calls:
fn = TOOLS[call.function.name]
args = json.loads(call.function.arguments)
result = fn(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
return "Stopped: reached max steps."Notice the max_steps guard. Without a step limit, a confused agent can loop indefinitely, burning tokens and money. Always cap iterations.
Making the Reasoning Explicit
Function-calling APIs handle the "Act" part, but you still benefit from explicit reasoning. A system prompt that asks the model to think before acting and to state what it expects each tool to return improves tool selection accuracy. Some teams also log the model's reasoning between steps for debugging—this trace is invaluable when an agent picks the wrong tool or misinterprets an observation.
Handling Parallel and Multi-Step Calls
Modern models often return multiple tool calls in a single turn. Your loop should iterate over every call in msg.tool_calls, not just the first. When tools are independent, execute them concurrently to cut latency. When one depends on another's output, let the model sequence them across turns—that is exactly what the ReAct loop enables.
Error Handling and Guardrails
Real tools fail. Wrap each execution in a try/except and return a structured error string as the observation rather than crashing. The model can often recover—retrying with different arguments or choosing another approach.
- Validate arguments against your schema before executing, since models occasionally produce malformed values.
- Set timeouts on external calls so a slow API cannot stall the whole loop.
- Restrict destructive tools behind confirmation steps or human approval for anything that writes data or spends money.
- Track token usage per step to catch runaway loops early.
Testing and Observability
Treat your agent like any other system: write tests. Create fixtures with mocked tool outputs and assert the agent reaches the right final answer. Log every message, tool call, and observation with a trace ID so you can replay a full run. In 2026, tracing tools for agents are standard practice—capturing the reasoning-action-observation sequence makes debugging non-deterministic behavior far more manageable.
When to Reach for a Framework
The hand-rolled loop above is intentionally simple, and for many applications it is all you need. Frameworks add memory management, retries, multi-agent orchestration, and pre-built tool integrations. Start with the raw loop to understand the mechanics; adopt a framework once you need its specific features. Understanding what happens under the hood keeps you in control when abstractions leak.
Key Takeaways
A ReAct agent is fundamentally a loop plus tools. The model reasons, calls a function, reads the result, and repeats. Structured function calling removes the fragility of parsing text, while step limits, error handling, and observability turn a demo into something you can ship. Master this pattern and you have the foundation for nearly every practical AI application—retrieval assistants, data pipelines, and autonomous workflows alike.
Ready to build real AI skills? Join the September 2026 cohort at Class For Jobs. Explore Advanced AI — a hands-on, live program to build and ship production AI applications, live and instructor-led with career support, resume help, and job-placement assistance.
Related reading









