Skip to content
intermediate Phase 12 · Agent Loops and Planning

Planning Strategies for Agents

Compare ReAct, plan-then-execute, and hierarchical decomposition approaches.

55m
0 problems
Topic Progress 0%

The Plan That Was True When It Was Written

A refund-queue agent gets a task with an obvious shape:

user: For order 88213, check refund eligibility, issue the refund if eligible,
     then email the customer.

The first implementation asks the model for a plan up front and runs the steps in order. Step 1 returns: not eligible — the order shipped 40 days ago against a 30-day window. Steps 2 and 3 are now nonsense, but the executor runs them anyway: it refunds an ineligible order, then emails the customer to announce it.

Nothing crashed. The plan was true when it was written and false by the time it ran. That gap is the whole subject here: a plan is a prediction about observations you have not collected yet, and your strategy decides what happens when the prediction is wrong.

Three shapes dominate practice:

  • ReAct — reason and act one step at a time; the next action is chosen only after the previous observation arrives.
  • Plan-then-execute — draft the full step list first, then run it as written.
  • Hierarchical — a planner delegates subtasks to worker agents and merges what they report.

Each is correct under a different assumption about how predictable the observation stream is. The machinery that runs any of them already exists — The Core Agent Loop gives you think, act, observe, and a step cap. This topic decides what the think phase actually does with that cycle.

Three Ways to Order a Task

Pick the strategy by asking one question: how much of the plan can be correct before I see any data?

Strategy Shape Choose it when Breaks when
ReAct think → act → observe, one step per model call the next action depends on data you have not seen yet tasks need a global ordering of steps, and per-step model calls inflate latency
Plan-then-execute draft full step list, then run it in order structure is predictable and steps are mostly independent an early observation invalidates a later step, as with the refund eligibility check
Hierarchical planner hands subtasks to worker agents subtasks are independent and each is deep enough to need its own tool loop workers need each other's results mid-task, and merging partial reports loses context

ReAct never acts on stale information because it has no information until it acts. Every step costs a model call, so latency scales with step count, and there is no artifact to review before money moves.

Plan-then-execute buys the opposite trade: a reviewable step list, predictable cost, and the freedom to run independent steps concurrently. It converts a wrong assumption directly into a wrong action — the refund failure above is exactly this strategy without a verification step.

Hierarchical planning pushes detail down: the parent writes check eligibility → issue refund → notify customer and each line becomes a worker's own bounded loop with its own tools. The parent's plan stays valid because workers absorb the messy part. The risk moves to merging — a worker's finding that should change a sibling's work arrives too late — which is why workers should report back before the parent commits the next step.

The table settles what to run. The harder decision is what to do when the world contradicts the plan.

Executing a Plan and Replanning When It Fails

The two executors below take the same goal and the same first plan:

def run_fixed(plan, act):
    trace = []
    for step in plan:
        obs = act(step["tool"], step["args"])
        trace.append((step["name"], obs))
    return trace              # steps 2 and 3 still run after step 1 disproved them

def run_replan(goal, plan, act, ask, verify):
    done, i = [], 0
    while i < len(plan):
        step = plan[i]
        obs = act(step["tool"], step["args"])
        done.append((step["name"], obs))
        if not verify(step, obs):      # this observation invalidates what follows
            plan = plan[:i + 1] + ask.replan(goal, done)   # keep history, replace the tail
        i += 1
    return done

Executed against the refund request:

goal: check eligibility for order 88213, refund if eligible, email the customer
plan v1: [check_eligibility → issue_refund → email_customer]

run_fixed:
  check_eligibility → {"eligible": false, "shipped_days": 40}
  issue_refund      → REFUNDED 62.40          # a step the observation just killed
  email_customer    → "Your refund is on the way."

run_replan:
  check_eligibility → {"eligible": false, "shipped_days": 40}
  verify failed     → plan v2: [check_eligibility → flag_exception → email_customer]
  flag_exception    → {"case": "EX-2210", "owner": "policy-team"}
  email_customer    → "We could not refund order 88213 automatically."

plan[:i + 1] is the line to study: completed steps stay in the plan as evidence, and only the tail is replaced. Replanning from scratch discards observations the run already paid for, so the new plan repeats them and burns steps.

verify is a small predicate, not a second model — obs.get("eligible") is not False, a schema check, a status code. It runs after every step because any observation can invalidate any later step.

How it goes wrong:

  • Blind execution. The fixed executor above: a disproved step still runs, and the cost lands on the customer.
  • Replan thrash. Rewriting the plan after every step means no plan is ever executed to completion. Replan only when verify fails.
  • A stale plan handed to workers. Hierarchical runs re-dispatch subtasks from a plan the parent has already replaced.
  • Never replanning. Following a dead plan because the team agreed on it is the same bug as blind execution, one decision later.

Replanning is also a budget question — each revision is another model call against your per-task allowance, so bound it alongside the loop caps in Stopping Conditions and Budgets. Once the plan runs, the next topic grades what it produced: Reflection and Self-Critique.

Quiz

1. A task's next action depends on results you have not retrieved yet. Which strategy fits best?

Question 1 options

2. The refund agent executed issue_refund after check_eligibility returned eligible: false. What failed?

Question 2 options

3. In run_replan, why does the new plan start with plan[:i + 1] rather than a fresh list?

Question 3 options

4. What is the main risk of hierarchical planning?

Question 4 options

Flashcards

Question

What question picks between ReAct, plan-then-execute, and hierarchical planning?

Answer

How much of the plan can be correct before you see any data? ReAct: none of it needs to be. Plan-then-execute: all of it. Hierarchical: the decomposition, while workers absorb the detail.

Question

When does plan-then-execute outperform ReAct?

Answer

When structure is predictable and steps are independent: you get a reviewable plan, predictable cost, and concurrent execution instead of one model call per step.

Question

What is the replan trigger in iterative replanning?

Answer

A verify predicate that fails after a step — the observation contradicts a later step's assumption. Replanning on every step causes thrash and no plan ever completes.

Question

How much of a plan does a replan replace?

Answer

Only the tail after the failed step: plan[:i + 1] keeps completed steps as evidence so already-paid-for observations are not recomputed.

Question

What does hierarchical planning delegate, and what must the parent still do?

Answer

Each subtask becomes a worker's own bounded tool loop; the parent keeps ordering, merges reports, and should re-dispatch when a report invalidates a sibling's work.

Revision Notes

Key Takeaways

  • 1. A plan predicts observations you have not collected; strategy choice decides what happens when that prediction is wrong
  • 2. ReAct never acts on stale data; plan-then-execute trades that safety for reviewability, cost predictability, and concurrency
  • 3. Replan only when a verify predicate fails, and keep completed steps so their observations are not recomputed
  • 4. Hierarchical planning moves detail into workers but moves risk into merging their reports

Interview Tips

  • • State the decision rule — predictability of the observation stream — before comparing the three strategies
  • • Walk the refund example end to end: where verify fires, what the new plan keeps, what it drops
  • • Name the difference between replanning (reactive, verify-triggered) and re-planning on a schedule (thrash)
  • • Say how you bound replan revisions, since each revision is another model call

Cheat Sheet

Planning Strategies — Cheat Sheet

Decision rule: how much of the plan can be correct before any data is seen?

Strategy Shape Wins Fails
ReAct think→act→observe per step exploratory tasks, data-dependent next action no upfront artifact; latency scales with steps
Plan-then-execute draft list, run in order predictable structure, independent steps early observation disproves a later step
Hierarchical planner → worker agents → merge deep independent subtasks cross-subtask findings arrive at merge time

Replanning loop

while i < len(plan):
    obs = act(plan[i]["tool"], plan[i]["args"])
    done.append((plan[i]["name"], obs))
    if not verify(plan[i], obs):                 # observation breaks the tail
        plan = plan[:i + 1] + ask.replan(goal, done)
    i += 1

Rules

  • verify = cheap predicate (field check, status code), run after every step
  • Replace the tail only — completed steps are paid-for evidence
  • Replan on verify failure, never on a timer or every step
  • Cap revisions: each one is a model call against the task budget

Failure modes: blind execution · replan thrash · stale plan handed to workers · never replanning a dead plan

Continue Learning

Before You Start

  • No prerequisites listed.

Related Reading