Blog Post #36: Exploring Different Agent “Personalities”: Plan-and-Execute vs. ReAct

Imagine you need to solve a complex problem and you can hire one of two experts. The first is a brilliant “Improviser.” You give them the task, they immediately think of the very next logical step, execute it, see the result, and then figure out the step after that. They are fast and can adapt on the fly.

The second expert is the “Master Planner.” You give them the same task. They retreat to their office, analyze the goal from every angle, and emerge with a complete, detailed, step-by-step blueprint for the entire project. Only then do they begin to execute that plan, following it meticulously.

In the world of Agentic AI, these two personalities correspond to the two primary agent architectures: ReAct and Plan-and-Execute. Understanding their differences is key to choosing the right agent for your task.


A Quick Refresher: The ReAct Agent (The Improviser)

The ReAct agent is the one we’ve built and used so far in this series. It operates in a tight, iterative Thought -> Action -> Observation loop.

  • Strengths:
    • Fast & Adaptive: Excellent for simple tasks that require one or two tool calls. It can react to tool errors or unexpected observations and try a different approach in the next step.
    • Efficient: For straightforward problems, it gets to the answer quickly without unnecessary overhead.
  • Weaknesses:
    • Short-sighted: Because it only plans one step at a time, it can take an inefficient path to a complex solution.
    • Prone to Distraction: A surprising or ambiguous intermediate result can lead the agent down a rabbit hole, causing it to lose sight of the original, high-level goal.

ReAct is the go-to for simple Q&A, single-tool operations, and highly dynamic situations where adaptability is paramount.

The Alternative: The Plan-and-Execute Agent (The Master Planner)

This architecture, which we first discussed in Post #20, separates the agent’s work into two distinct phases:

  1. Planning: An LLM-powered “Planner” looks at the user’s overall goal and the list of available tools. It then creates a complete, step-by-step plan to achieve that goal. This plan is created before any tools are actually used.
  2. Execution: A separate “Executor” (which is often a ReAct agent itself) is given the plan. Its only job is to carry out each step of the plan in sequence, feeding the result of one step into the next.

This approach is more deliberate and less prone to getting sidetracked.

The Head-to-Head Challenge

Let’s design a task that highlights the differences between these two agent types.

The Task: “Find the current year, and then use it to determine the age of a person born in 1997. Finally, tell me if that age is a prime number.”

This is a multi-step problem with dependencies:

  1. Get the current year (requires a tool).
  2. Calculate the age (requires a calculator tool using the result of step 1).
  3. Determine if the age is prime (requires a tool or reasoning).

A ReAct agent might get distracted after step 1 or 2, but a Plan-and-Execute agent is designed for this kind of structured workflow.

Building and Running a Plan-and-Execute Agent

LangChain provides a high-level constructor for this pattern in its experimental modules. Let’s build it.

# main.py
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from langchain_experimental.plan_and_execute import PlanAndExecute, load_agent_executor, load_chat_planner
from dotenv import load_dotenv
import math

# --- 1. SETUP and TOOLS ---
load_dotenv()

@tool
def get_current_year() -> int:
    """Returns the current year."""
    from datetime import datetime
    return datetime.now().year

@tool
def is_prime(number: int) -> str:
    """Checks if a number is prime and returns a definitive statement."""
    if number < 2:
        return f"{number} is not prime."
    for i in range(2, int(math.sqrt(number)) + 1):
        if number % i == 0:
            return f"{number} is not a prime number."
    return f"{number} is a prime number."

# Using a generic calculator tool for the subtraction
@tool
def calculator(expression: str) -> str:
    """Calculates a mathematical expression."""
    # Caution: eval is not safe for production. This is for demonstration.
    return str(eval(expression))

tools = [get_current_year, is_prime, calculator]
model = ChatOpenAI(model="gpt-4o", temperature=0)


# --- 2. THE PLAN-AND-EXECUTE AGENT ---
# The Planner is an LLM chain that creates the plan
planner = load_chat_planner(model)

# The Executor is a ReAct agent that executes the steps
executor = load_agent_executor(model, tools, verbose=True)

# The PlanAndExecute agent orchestrates the two
agent = PlanAndExecute(planner=planner, executor=executor, verbose=True)


# --- 3. RUN THE AGENT ---
if __name__ == "__main__":
    query = "Find the current year, and then use it to determine the age of a person born in 1997. Finally, tell me if that age is a prime number."
    
    print(f"Running Plan-and-Execute agent with query:\n'{query}'")
    agent.invoke(query)

The Output: A Perfect Plan

When you run this, the first thing you’ll see in the verbose output is the plan generated by the planner:

> Entering new PlanAndExecute chain...
steps=[
    Step(value="Get the current year using the 'get_current_year' tool."),
    Step(value="Calculate the age of the person by subtracting 1997 from the current year using the 'calculator' tool."),
    Step(value="Check if the calculated age is a prime number using the 'is_prime' tool."),
    Step(value="Provide the final answer including the person's age and whether it's a prime number.")
]
...

The agent then proceeds to execute each of these steps faithfully, calling the tools in the correct order to arrive at the right answer. It’s not improvising; it’s following a blueprint.

Conclusion: Choosing the Right Personality for the Job

Neither agent type is universally “better.” The choice depends entirely on the nature of your task.

  • Use ReAct (The Improviser) for:
    • Simple, single-intent queries (e.g., “What’s the weather?”).
    • Conversational chatbots where you need to react to user input turn-by-turn.
    • Tasks where the path to the solution is unknown and requires exploration.
  • Use Plan-and-Execute (The Planner) for:
    • Complex tasks requiring a sequence of multiple, distinct tool calls.
    • Workflows where you need a predictable, auditable, and repeatable process.
    • Goals where the overall strategy must be maintained without getting sidetracked by intermediate results.

By understanding the trade-offs between these two powerful architectures, you can select the right “personality” for your agent, ensuring it solves problems not just intelligently, but also in the most efficient and reliable way possible.

Author

Debjeet Bhowmik

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com

Leave a Comment