Agent Fundamentals: ReAct, Plan-and-Execute
What Are LLM Agents?
An LLM agent is a system where a large language model acts as the central reasoning engine that decides which actions to take, observes the results, and iterates until a goal is met. Unlike a single-shot prompt → response pattern, an agent operates in a loop: it can call external tools (APIs, databases, code interpreters), read their outputs, reflect on progress, and decide what to do next — all autonomously.
The core insight is that LLMs are remarkably good at decomposing problems into steps and selecting the right tool for each step, provided they are given structured access to those tools. An agent combines three capabilities that a standalone LLM lacks:
- Tool use: The ability to invoke external functions — search engines, calculators, REST APIs, SQL databases — and incorporate their outputs into the reasoning trace.
- Memory: Short-term (conversation history / scratchpad) and long-term (vector store retrieval) memory that persists across reasoning steps.
- Planning: The capacity to formulate multi-step plans, revise them when intermediate results are unexpected, and know when the goal has been achieved.
The Observe → Think → Act Loop
Every agent architecture — regardless of framework — can be reduced to a three-phase loop that repeats until a termination condition is met:
- Observe: The agent receives new information. On the first iteration this is the user query; on subsequent iterations it is the output from the previous tool call or environment feedback.
- Think: The LLM processes all accumulated context (the original query, the action history, and the latest observation) and reasons about what to do next. This is where chain-of-thought prompting, self-reflection, and plan revision occur.
- Act: The agent either invokes a tool (e.g.,
search("latest GDP of France")) or produces a final answer to return to the user. If a tool is invoked, its output becomes the next observation and the loop continues.
The loop terminates when the LLM decides it has sufficient information to answer the user, or when a maximum iteration count is reached (a critical safety rail). In pseudo-code:
max_iterations limit. Without it, a confused
agent can loop indefinitely, burning tokens and API credits. A typical default is 5–10 iterations.
ReAct: Reasoning + Acting
ReAct (Yao et al., 2022) is the foundational agent pattern that interleaves reasoning traces with actions in a single prompt. The key innovation is that the LLM explicitly writes out its chain-of-thought before selecting an action, making the decision process interpretable and debuggable. A ReAct trace looks like this:
ReAct outperforms both pure chain-of-thought (no tool use) and pure action-only approaches (no explicit reasoning) because the reasoning trace helps the model stay on track across multiple steps, while tool use grounds the reasoning in real-world data.
In implementation, ReAct is typically achieved through a carefully structured system prompt that defines
the Thought / Action / Observation format and lists available tools with their signatures.
The LLM generates text until it emits an Action: line, at which point the framework parses
the tool call, executes it, appends the result as Observation:, and feeds everything back
to the LLM for the next iteration.
"Observation:") to
prevent the LLM from hallucinating tool outputs. The framework — not the model — should provide observations.
Plan-and-Execute Pattern
While ReAct interleaves planning and execution at each step, the Plan-and-Execute pattern (Wang et al., 2023) separates them into two distinct phases. A planner LLM first generates a complete multi-step plan, and then an executor carries out each step sequentially, optionally re-planning if a step fails or produces unexpected results.
This decomposition offers several advantages for complex tasks:
- Better long-horizon reasoning: The planner sees the full task at once and can allocate steps efficiently, rather than being myopic like step-by-step ReAct.
- Specialization: You can use a stronger (more expensive) model for planning and a cheaper model for execution, optimizing cost.
- Debuggability: The plan is an explicit artifact you can inspect, log, and version-control before any actions are taken.
- Re-planning: If step 3 of 5 fails, the system can re-invoke the planner with updated context rather than blindly continuing.
ReAct
- Interleaved thinking + acting
- One step at a time — reactive
- Simple to implement
- Works well for ≤ 5 tool calls
- Lower latency for short tasks
Plan-and-Execute
- Separate planning and execution phases
- Full plan generated upfront
- More complex, but more robust
- Better for 5–20+ step tasks
- Supports re-planning on failure
Building an Agent Loop in Python
Below is a complete, minimal ReAct agent implementation using the OpenAI function-calling API. This agent can search the web and perform calculations — extend it by adding more tool definitions.
The key design decisions in this implementation:
- Message accumulation: Every LLM response and tool result is appended to the messages list, giving the model full context of its reasoning history.
- tool_choice="auto": Lets the LLM decide whether to call a tool or produce a final
answer. Setting it to
"required"forces a tool call on every turn. - Parallel tool calls: The OpenAI API can return multiple
tool_callsin a single response. The inner loop handles this by executing each one and appending results.
eval() in production for the calculator tool. Use a
sandboxed expression parser like asteval or numexpr to prevent code injection.
Interactive: Agent Execution Loop
Walk through how an agent processes the query "What is the GDP per capita of France?" step by step. Use the controls below to advance or rewind through the execution loop.
When to Use Agents vs Chains
Not every LLM application needs an agent. Agents introduce latency (multiple LLM calls), cost (more tokens), and non-determinism (different runs may take different paths). Use the simplest architecture that solves your problem:
Use a Chain when…
- The steps are known at design time
- No conditional branching is needed
- Latency budget is tight (< 2 seconds)
- The task is a simple transform pipeline
- Predictability > flexibility
Use an Agent when…
- The number of steps is unknown upfront
- The LLM must choose between multiple tools
- Intermediate results affect the next action
- The task requires multi-hop reasoning
- Flexibility > predictability
A practical decision framework: start with a chain. If you find yourself adding more and more
if/else branches to handle edge cases, that's a sign you need an agent. Common scenarios
that benefit from agents include customer support (unpredictable queries), data analysis (dynamic SQL
generation), and research tasks (iterative web search).
To summarize the spectrum of LLM application architectures from simplest to most complex:
- Single prompt: One LLM call, no tools. Good for summarization, translation, classification.
- Chain: Fixed sequence of LLM calls and/or tools. Good for RAG, structured extraction.
- ReAct agent: Dynamic loop with interleaved reasoning and tool use. Good for multi-hop QA, research.
- Plan-and-Execute agent: Upfront planning with iterative execution. Good for complex, multi-step workflows.
- Multi-agent systems: Multiple specialized agents collaborating. Good for software engineering, complex analysis.