Why This Is Asked
ReAct is the baseline agent pattern, but it has known failure modes on complex multi-step tasks. Plan-and-Execute is the natural next step. Interviewers ask about this to test whether candidates understand agent architecture deeply enough to choose the right pattern for a given task.
Key Concepts to Cover
- ReAct recap — the interleaved think-act-observe loop
- Plan-and-Execute architecture — explicit planning phase before execution
- When ReAct fails — long-horizon tasks, compounding errors
- When Plan-and-Execute wins — structured multi-step workflows
- Hybrid approaches — replanning, adaptive execution
How to Approach This
1. ReAct Recap
ReAct (Reason + Act) interleaves reasoning and tool use in a single loop:
Thought: I need to find the company's latest revenue
Action: search("Acme Corp Q3 2024 revenue")
Observation: [search results]
Thought: The result shows $2.1B. Now I need to compare to Q2.
Action: search("Acme Corp Q2 2024 revenue")
...
Each thought-action-observation cycle produces the next step. The agent has no upfront plan — it discovers the path reactively.
2. Where ReAct Breaks Down
Long-horizon tasks: ReAct is good for 3-5 step tasks. At 10-20 steps, it tends to drift — early decisions constrain later ones in ways the agent doesn't anticipate, and errors compound.
Scope creep: without a plan, the agent can go down tangents and lose sight of the original goal.
Inefficiency with parallelizable sub-tasks: ReAct is inherently sequential. If three sub-tasks are independent, ReAct executes them one at a time.
No error recovery strategy: if step 7 fails, ReAct often retries the same thing or abandons. It has no concept of "this whole plan needs replanning."
3. Plan-and-Execute Architecture
Two distinct phases:
Phase 1: Planning
- A capable LLM (often a larger/stronger model) takes the task and produces a structured plan
- The plan is a sequence of discrete, verifiable steps
- Planning happens once, upfront, before any tools are called
Task: "Research competitor pricing for our Q4 board deck"
Plan:
1. Search for competitor A's pricing page
2. Search for competitor B's pricing page
3. Search for competitor C's pricing page
4. Extract pricing tiers from each
5. Compile into comparison table
6. Draft summary paragraph with key insights
Phase 2: Execution
- An executor agent works through the plan step by step
- Each step is a concrete tool call or sub-task
- The executor can be simpler/faster than the planner — it just needs to execute discrete steps
Optional: Replanning
- After execution of each step, the system can check whether the plan still makes sense
- If a step fails or produces unexpected results, replan from that point
- Full replanning vs. partial: depends on whether the failure invalidates downstream steps
4. Plan-and-Execute vs. ReAct: Decision Framework
| Factor | Use ReAct | Use Plan-and-Execute | |---|---|---| | Task length | Short (< 5 steps) | Long (10+ steps) | | Predictability | Exploratory, unknown path | Structured, decomposable task | | Parallelism | Sequential OK | Sub-tasks can run in parallel | | Error handling | Retry individual steps | Need full replanning capability | | Example | Web search + answer | Research report, code refactor, pipeline orchestration |
Key insight: Plan-and-Execute is better for tasks where the full scope is knowable upfront. ReAct is better for exploratory or dynamic tasks where you genuinely don't know what the next step should be until you see the current result.
5. Implementation Pattern
def plan_and_execute(task: str) -> str:
# Phase 1: Generate plan
plan = planner_llm.generate(f"""
Break down this task into discrete, executable steps:
Task: {task}
Output as a numbered list. Each step should be independently executable.
""")
steps = parse_steps(plan)
results = {}
# Phase 2: Execute each step
for i, step in enumerate(steps):
context = format_prior_results(results)
result = executor_agent.run(step, context=context)
results[i] = result
# Optional: replan if step failed
if result.failed and affects_downstream(step, steps[i+1:]):
remaining = replanner_llm.replan(steps[i+1:], result)
steps[i+1:] = remaining
return synthesize(results)
Common Follow-ups
-
"How do you handle a plan where step 5 depends on the output of step 3, which failed?" Two options: (a) replan from step 3, generating alternative steps given the failure, or (b) if the dependency is optional, mark step 5 as "best-effort" and note the gap in the final output. The right choice depends on whether the downstream step is critical path.
-
"Is the planner always a separate call from the executor?" Not necessarily. For simple tasks, the same model can plan and execute. Separating them is valuable when you want to use a stronger model for planning (GPT-4o, Claude Opus) and a cheaper/faster model for execution (GPT-4o mini, Claude Haiku). The cost savings on execution steps can be significant.
-
"How do you evaluate whether a plan is good before executing it?" Plan review step: before execution, show the plan to an LLM (or a human for high-stakes tasks) and ask it to identify ambiguous steps, missing information, or logical errors. Catch plan-level mistakes cheaply before incurring the cost of execution.