方寸 Portal

AI Engineer Portal

Your personal operating system for career transition.

Private mode

Knowledge Note

Agent architecture patterns compared

A practical comparison of ReAct, Plan-Execute, and Tree-of-Thought agent architectures with a decision matrix covering latency, token cost, reliability, and complexity trade-offs.

Category

agents

Tags

agents · architecture · react · planning · patterns

Sources

2 linked references

Agent architecture patterns compared

Three patterns dominate production agent design today: ReAct, Plan-Execute, and Tree-of-Thought. Each solves a different problem. Picking the wrong one costs you in latency, money, or reliability before you understand why.

This article gives you a practical comparison so you can make the call fast when designing a new agent.


ReAct

ReAct (Reasoning + Acting) interleaves thought steps with tool calls in a single loop. The model reasons about what to do, calls a tool, observes the result, reasons again, calls another tool, and eventually produces a final answer.

Thought: I need to look up the user's account status
Action: get_account(user_id="u_123")
Observation: {"status": "active", "plan": "pro"}
Thought: Now I need to check their recent invoices
Action: list_invoices(user_id="u_123", limit=3)
Observation: [{"id": "inv_1", "amount": 49, "status": "paid"}, ...]
Thought: I have enough to answer
Final Answer: Your account is active on the Pro plan. Your last invoice was $49 and has been paid.

When it works well:

  • Short-horizon tasks (2–6 tool calls)
  • Unpredictable branching where the next action depends on the previous result
  • Conversational agents where the user can steer mid-loop
  • Exploratory tasks where you do not know the path ahead of time

When it breaks:

  • Long-horizon tasks with many steps — the context window fills with intermediate traces
  • Tasks that require parallel work — ReAct is inherently sequential
  • Production systems where every intermediate step costs tokens you do not need

Token cost: High relative to the work done, because every thought and observation stays in the context window.

Latency: Directly proportional to the number of tool calls. Each call waits for the previous result.

Reliability: Good when the task is short. Degrades as chain length grows — each step is another chance for the model to reason incorrectly.

Complexity: Low. You can implement a working ReAct loop in under 100 lines of Python using any provider SDK.


Plan-Execute

Plan-Execute separates planning from execution. The model first produces a structured plan (a list of steps), then a separate executor runs those steps, optionally with a different model or set of tools.

# Phase 1: Planner
plan = planner_llm.complete(
    "Create a step-by-step plan to process this support ticket: {ticket}"
)
# Returns:
# [
#   {"step": 1, "action": "classify_ticket", "input": "..."},
#   {"step": 2, "action": "lookup_customer", "input": "..."},
#   {"step": 3, "action": "draft_response", "input": "..."},
# ]

# Phase 2: Executor
for step in plan.steps:
    result = executor.run(step)
    plan.record(step, result)

When it works well:

  • Tasks where the path is mostly predictable from the starting state
  • Long multi-step workflows where you want to audit or modify the plan before execution
  • Systems that need a human-in-the-loop review point between planning and acting
  • Workflows where some steps can run in parallel (the executor can parallelize)

When it breaks:

  • Tasks with high environmental uncertainty — the plan becomes stale after the first unexpected result
  • Short tasks where the planning overhead outweighs the benefit
  • Dynamic environments where step outputs change what subsequent steps should do

Token cost: Moderate. Planning is a single LLM call. Execution calls are focused and carry less context than ReAct traces.

Latency: Planning adds upfront latency. Execution can be fast if steps run in parallel.

Reliability: Higher than ReAct for predictable workflows. Lower for adaptive ones — the executor does not replan when it hits unexpected results unless you add a replanning loop.

Complexity: Medium. You need a plan schema, a planner prompt, an executor loop, and a decision about when to replan.


Tree-of-Thought

Tree-of-Thought (ToT) generates multiple reasoning branches and evaluates them before committing to a path. Instead of a single linear chain, the model explores several options, scores each, and picks the best continuation.

# Generate candidate next steps
candidates = [
    llm.complete(f"{state}
Option A:"),
    llm.complete(f"{state}
Option B:"),
    llm.complete(f"{state}
Option C:"),
]

# Score each candidate
scores = [evaluator.score(c) for c in candidates]

# Pick the best and continue from there
best = candidates[scores.index(max(scores))]

When it works well:

  • Tasks that resemble search problems — writing, code generation, mathematical reasoning
  • Cases where local optima are a real risk (picking the first plausible path leads to dead ends)
  • Offline batch tasks where you can afford multiple LLM calls per decision point
  • Quality-critical work where you are willing to pay for better outputs

When it breaks:

  • Latency-sensitive applications — branching multiplies your LLM calls
  • Tasks without a clear scoring function — you need a way to evaluate candidates
  • Most real-time conversational agents

Token cost: High. You are paying for multiple completions at each branch point.

Latency: High. Multiple LLM calls per step. Not suitable for interactive use.

Reliability: High for the task types it fits. The branching and evaluation naturally finds better paths.

Complexity: High. You need candidate generation, a scoring/evaluation mechanism, and a search strategy (breadth-first, depth-first, beam search).


Decision matrix

DimensionReActPlan-ExecuteTree-of-Thought
LatencyMedium (sequential)Low-Medium (parallel exec)High (multiple branches)
Token cost per taskHighMediumVery high
Reliability (short tasks)HighHighHigh
Reliability (long tasks)DegradesGoodGood
Parallelism supportNoYesYes (per branch)
Human review pointHardNaturalHard
Implementation effortLowMediumHigh
Good for real-timeYesYesNo
Good for quality-critical offline workNoSometimesYes

How to choose

Start with ReAct if:

  • The task has 6 or fewer tool calls
  • The path depends heavily on intermediate results
  • You are prototyping and want something running fast

Use Plan-Execute if:

  • The task is well-defined and the steps are mostly predictable
  • You want a human review point before execution
  • You need parallel step execution
  • Long-horizon multi-step tasks are the norm

Use Tree-of-Thought if:

  • Output quality is more important than latency or cost
  • The task resembles a search problem (many local optima)
  • You are running offline batch work
  • You have a reliable scoring function

Hybrid patterns are common in production. A Plan-Execute outer loop with a ReAct inner executor for individual steps is a practical middle ground. The planner breaks the task into chunks; each chunk runs a short ReAct loop.


Practical notes for production

  • Instrument every pattern the same way. Log the full trace — thoughts, tool calls, observations, scores — regardless of pattern. The patterns differ in structure but share the same debugging needs.
  • Token cost adds up faster than you expect. A Plan-Execute agent with a 10-step plan and 3 tool calls per step is 30+ LLM calls before counting retries. Model your cost before committing.
  • Reliability degrades with context window pressure. For ReAct especially, prune intermediate results or summarize early observations before they crowd out later reasoning.
  • The executor in Plan-Execute does not need to be the same model as the planner. Use a cheaper, faster model for execution steps that just need tool routing. Save your best model for planning and synthesis.