Skip to content

ReAct: how one AI agent uses tools

One agent chooses a tool, checks the result, and decides what to do next. How the ReAct loop works and where to set limits.

Updated September 28, 20265 min read
ReAct: how one AI agent uses tools
On this page

You ask an assistant to check an order and explain why it is late. It looks up the order, sees a carrier reference, checks the shipment, and answers using both results. The second lookup uses information returned by the first.

The single-agent tools pattern, often described as a ReAct loop, lets one model choose the next action after each result. Your application runs the tools and decides which actions are allowed.

The order lookup could also be a fixed workflow. Use code when the required steps and error paths are known. An agent is an option when requests vary and deciding what to do next benefits from interpreting language and tool results.

TL;DR One model chooses an action, your application runs it, and the model uses the result to decide what to do next. Give each tool a clear purpose and provide the information the agent needs. Limit how long the loop can run and inspect failures before adding another agent.

How the ReAct loop works

ReAct combines reasoning and acting: a model uses observations from the environment to decide what to do next. The original paper demonstrated this with reasoning text interleaved with actions. Current tool-calling APIs can represent the action as a structured request instead.

The loop has two participants. The model selects a tool and supplies arguments, or produces an answer. The runtime validates the request, runs the tool, and returns its result. A model that supports tool calling does not, by itself, execute your Python function or contact your database.

The runtime returns each tool result to the model.

A run ends when the model answers or the runtime stops it. A step limit, exhausted budget, rejected action, or unrecoverable tool error can all stop the run before the task is complete. Record that distinction so an interrupted run does not look like a successful answer.

LangChain's agent runtime implements this model-tool loop. Its built-in tool support replaces the need to parse action names out of free-form text, but the application still owns permissions, tool behavior, and error handling.

Follow one order lookup

Suppose the user asks: "Where is order 1042, and why is it late?" The agent has two read-only tools: get_order and get_tracking.

StepModel decisionRuntime result
1Call get_order(order_id="1042")The order shipped with tracking reference ZX9
2Call get_tracking(reference="ZX9")The carrier reports a weather delay and a revised delivery date
3Answer the userThe response explains the delay and attributes the date to the carrier

The model does not need to predict every step at the start. If the order lookup returns "not found," it should ask the user to check the identifier instead of inventing a tracking reference. If the carrier lookup fails, it can report the confirmed shipment status and say that the latest delivery estimate is unavailable.

That is why the tool result must distinguish a legitimate empty result from a timeout or permission error. A vague response such as "no data" makes the next decision harder.

The following framework wiring assumes a configured tool-calling model and the two lookup functions:

from langchain.agents import create_agent
 
agent = create_agent(
    model=model,
    tools=[get_order, get_tracking],
    system_prompt=(
        "Answer order questions using the lookup tools. "
        "Ask for missing identifiers. Do not invent shipment details."
    ),
)
 
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Where is order 1042, and why is it late?",
    }],
})

Source: LangChain, Agents. Authorization to view an order belongs in the lookup implementation; a prompt is not an access-control check.

What makes the loop unreliable

Tool ambiguity is one cause. If find_order, search_orders, and lookup_purchase appear to do the same thing, the model has to infer a distinction that the interface should have made clear. Rename tools around their inputs and responsibilities, or consolidate them. Different tasks may need different tool subsets rather than a permanently growing list.

Context is another constraint. Each observation adds material to the next decision unless the runtime removes or summarizes it. A long carrier response may contain hundreds of irrelevant events while the useful status occupies one line. Return the fields the agent needs, and retain the original record separately when it is needed for inspection.

Chroma's context-rot experiments found that performance varied with input length and content across the models and tasks tested. That supports testing your own context strategy; it does not establish a single safe context length for every agent. Summaries can also drop details, so check whether they preserve identifiers, constraints, and unresolved questions.

Long conversations introduce a different problem: the task itself can change. An order lookup can become a request to cancel or refund. Refresh the active goal and check permissions before taking the new action. Do not treat an earlier read-only request as authorization for a later write.

Improve tools, context, and runtime limits before splitting the agent.

Bound the runtime and measure the cost

A step cap prevents an agent from retrying forever, but it does not explain why the agent stopped making progress. Repeatedly calling a failing carrier API might require a retry policy, a clearer error message, or a fallback. Hitting the cap is a reason to inspect the run, not automatic proof that the task needs multiple agents.

Also distinguish a model turn from a tool call. Some models request several tools in one turn. Those calls may run concurrently when independent; calls that depend on earlier results need another decision. Count both turns and tool executions when estimating work.

Model cost depends on input tokens, output tokens, caching, and any additional billed reasoning. Tool services may charge separately. Without context management, later model turns carry more history. That can raise the cost of the run even if each tool response is short.

In its research-system write-up, Anthropic reported agents using about four times as many tokens as chat interactions in its observations. That is a workload-specific reference, not a minimum price for an agent. Measure representative requests, including retries and unsuccessful runs, with the model and tools you will use.

What to log before adding another agent

Record the tool name, arguments, result status, elapsed time, and model usage for each step. Keep sensitive values out of general logs. At the run level, record the final status and whether the user's task was actually resolved.

These records answer different questions. Repeated wrong-tool choices suggest an interface or routing problem. Correct tool choices followed by unsupported answers suggest a grounding problem. A growing history with declining answer quality suggests a context-management problem. More agents will not necessarily fix any of them.

Delegation becomes useful when a responsibility can be separated cleanly. A router can select the relevant tool set before the work begins. A supervisor can ask specialists for bounded results. Independent research branches may benefit from the orchestrator-worker pattern.

For the order lookup, one agent is enough while it can choose the two tools correctly, handle missing data, and give a grounded answer within the budget. Change the architecture when a trace shows what the current one cannot handle. The agent-pattern overview compares the available options.

Sources

Common questions

What is a ReAct agent?

A ReAct agent chooses a tool, reads its result, and decides what to do next. The model requests an action; application code runs the tool and sends the result back.

What is the difference between a single agent with tools and a multi-agent system?

A single agent keeps one main decision loop, while a multi-agent system delegates work to agents with their own instructions and contexts. Delegation can separate responsibilities, but it also adds messages, coordination, and failure handling.

What happens when an agent has too many tools?

Tools with overlapping names or responsibilities can make selection harder. Improve descriptions, merge duplicates, or expose only the relevant tools before assuming that more agents are necessary.

Is ReAct prompting still necessary with modern LLMs?

Models with native tool calling usually do not need the original text-based ReAct prompt format. They still need a runtime to execute tool requests, return observations, and enforce limits.

When should you switch from one agent to multiple agents?

Consider splitting when distinct responsibilities need different tools, permissions, or contexts, or when independent work benefits from parallel execution. Check whether better tool design and context management solve the observed failure first.