↑ Contents Chapter 6 of 12

Chapter 6: Planning β€” One Step at a Time

Maya's Lisbon trip agent has gotten smarter. It can search flights, find hotels, even calculate budgets. But today she gave it a harder task: "Plan the whole trip β€” flights, hotel, and a 4-day itinerary β€” and make sure the total stays under €1,500." The agent froze. Well, not frozen β€” worse. It searched for flights, got a result, and then... just answered. "Here are some flights to Lisbon." That's it. It never searched for hotels. It never made an itinerary. It never checked the budget. It did one step and stopped. Maya stares at the screen. "It's like a cook who boils the pasta and then serves it plain. It forgot the sauce, the plate, the whole meal." TomΓ‘s nods. "It doesn't know how to plan. It can do one step, but it can't see the whole recipe. We need to teach it to think ahead β€” and to keep going until the meal is done."

Why This Matters

By the end of this chapter, you'll understand two patterns that turn a one-step agent into a multi-step planner: chain-of-thought (thinking out loud before acting) and ReAct (reasoning and acting in a loop). You'll build an agent that breaks a big task into steps, works through them, and β€” crucially β€” recovers when a step fails. This is the difference between an agent that does one thing and an agent that finishes the job.

The Problem: One-and-Done

Our agent loop from Chapter 3 has a hidden limitation. It works great when the task needs one or two tool calls. But give it a task that needs planning β€” "do A, then B, then C, then check the result" β€” and it often does A and stops. Why?

Because the LLM, without guidance, tends to answer the immediate question and consider itself done. It found flights. Job done, right? No β€” but the model doesn't naturally think "wait, the user asked for the whole trip, I've only done part of it." It needs to be told to think through the whole task first.

Without planning: one-and-done "Plan the trip" searches flights "Here are flights" stops. Done. No hotel. No itinerary. No budget check. The agent did one step and thought it was finished.
Without planning, the agent does the first step and stops. The task isn't done β€” but it thinks it is.

Chain-of-Thought: Think Before You Act

The first fix is simple and powerful: ask the LLM to think out loud before it acts. Instead of jumping straight to a tool call, it first writes out its reasoning: "The user wants a full trip. I need flights, a hotel, and an itinerary. Let me start with flights, then use the result to find a hotel, then build the itinerary, then check the budget."

This is called chain-of-thought, and it's the single most effective prompt technique for multi-step tasks. By forcing the LLM to articulate its plan before acting, you make it consider the whole task, not just the first move.

# The system prompt that unlocks planning SYSTEM_PROMPT = """You are a travel planning agent. Before taking any action, think step by step about what needs to be done. Consider the whole task, not just the first step. After each tool result, ask yourself: "Is the whole task done, or is there more to do?" Keep going until the entire task is complete."""
// One line in the system prompt. "Think step by step. Consider the whole task. Keep going until done."

That's it. The same agent loop, the same tools β€” but now the system prompt tells the LLM to plan ahead and keep going. Watch the difference:

User: "Plan the whole trip β€” flights, hotel, itinerary β€” under €1,500." THINK (the LLM's internal reasoning, before any tool call) "The user wants a complete trip. I need to: 1. Find flights to Lisbon in October 2. Find a hotel for 4 nights 3. Build a day-by-day itinerary 4. Total the cost and check it's under €1,500 Let me start with flights." ACT search_flights(...) OBSERVE "Flights: €180 on Oct 12" THINK "Flights done. Now I need a hotel. Budget left: €1,320." ACT search_hotels(...) OBSERVE "Hotel: €120/night in Alfama" THINK "Hotel done. Now the itinerary. I should suggest activities." ACT (maybe calls a search_activities tool, or just drafts from knowledge) THINK "Now check the budget: €180 + (€120 Γ— 4) = €660. Under €1,500. Done!" Agent: "Here's your trip: flights €180, hotel €480, total €660..."
// Same loop, same tools. The system prompt made the agent plan and persist.
Note Chain-of-thought isn't a code change β€” it's a prompt change. "Think step by step" and "consider the whole task" are instructions that shift the LLM from reactive mode (answer the immediate question) to planning mode (work through the whole job). The loop doesn't change; the brain's behaviour does.

ReAct: Reason, Act, Observe β€” and Repeat

Chain-of-thought tells the agent to think before acting. ReAct (Reason + Act) is the full pattern: the agent reasons about what to do, acts by calling a tool, observes the result, and then reasons again about what to do next. Sound familiar? It should β€” it's the agent loop from Chapter 3, with explicit reasoning at each step.

ReAct: the loop with explicit reasoning REASON "I need flights first. Let me search." ACT call search_flights OBSERVE "€180 on Oct 12" REASON "Good. Now hotels."
ReAct = Reason β†’ Act β†’ Observe β†’ Reason again. It's our loop, with the reasoning made explicit.

The good news: our agent loop already is a ReAct loop. The LLM thinks (reasons), calls a tool (acts), sees the result (observes), and thinks again. The only addition is making the reasoning visible β€” asking the LLM to state its plan and its next step in words before each tool call.

# Enhanced system prompt for ReAct REACT_PROMPT = """You are a task-planning agent. For each step: 1. REASON: State what you're trying to achieve and why this step matters. 2. ACT: Call the appropriate tool. 3. After seeing the result, REASON again: Did this step succeed? Is the whole task done, or is there more to do? Keep going until the entire task is complete. If a step fails, reason about why and try a different approach. Don't stop until the task is truly done."""
// The ReAct pattern in a system prompt. Reason, act, observe, reason again. Repeat until done.

When Steps Fail: Recovery

Here's where planning gets real. Steps fail. The flight search returns nothing. The hotel API is down. The calculator gets a bad expression. A naive agent crashes or gives up. A planning agent reasons about the failure and tries something else.

THINK "I need flights. Let me search." ACT search_flights(dest="Lisbon", month="October", max_price=300) OBSERVE "No flights found under €300 in October." REASON (the key moment β€” what does the agent do with failure?) "No flights under €300. Options: 1. Try a higher price ceiling 2. Try November instead 3. Tell the user and ask Let me try €350 first β€” still leaves budget for hotel." ACT search_flights(dest="Lisbon", month="October", max_price=350) OBSERVE "Found: €320 on Oct 12" REASON "Success. €320 leaves €1,180 for hotel and activities. Continue."
// The agent hit a dead end, reasoned about alternatives, and tried a different approach. That's recovery.
Note Recovery isn't a separate feature β€” it's a consequence of the ReAct loop. When a tool returns an error or empty result, that goes back into the conversation as the observation. The LLM reads it, reasons about what went wrong, and decides what to try next. The loop is self-correcting by design β€” as long as you let the reasoning happen.
Sharpen your pencil

An agent is planning a research task: "Find the top 3 AI startups in Lisbon and summarise what each does." It calls a web_search tool and gets back zero results. Trace the ReAct loop: what does the agent REASON, what might it ACT differently, and what does it OBSERVE?

Think: what are the alternative actions? Different search terms? A broader query? Asking the user? The agent should reason about WHY the search failed before trying again.

Planning Ahead: The Plan-Then-Execute Pattern

For really complex tasks, you can take planning further: ask the LLM to produce a full plan upfront, then execute it step by step. This is called plan-then-execute, and it's useful when the task has many dependent steps.

Plan-then-execute: make the recipe, then cook PLAN LLM writes out all steps: 1. Search flights 2. Search hotels 3. Build itinerary... Execute step 1 Execute step 2 Execute step 3 Check Did each step succeed?
Plan the whole recipe first, then execute each step. If a step fails, replan.

The trade-off: a plan made upfront might be wrong if early results change what's possible. (What if there are no flights in October? The plan said "search hotels" next, but maybe the dates need to change.) Pure ReAct β€” reasoning at each step β€” is more flexible. Plan-then-execute is more structured. Most real agents blend both: make a rough plan, then adapt it as they go.

Geek Bits The ReAct pattern was introduced in a 2022 paper by Yao et al. The key insight was simple but powerful: LLMs reason better when they interleave reasoning with actions, rather than reasoning once and then acting, or acting without reasoning. The back-and-forth β€” think, do, see, think β€” is what makes the agent adaptive. Our loop from Chapter 3 is a ReAct loop; this chapter just makes the reasoning explicit.
There Are No Dumb Questions
Q: How do I know if my agent needs planning? Some tasks are one-step.
A: If the task can be done with one tool call, you don't need planning β€” the basic loop handles it. You need planning when the task has multiple steps that depend on each other, when the agent needs to decide the order, or when it might need to recover from failures. "What's 17 Γ— 24?" doesn't need planning. "Plan my trip" does.
Q: My agent keeps looping β€” it does the same thing over and over. Is that a planning problem?
A: That's usually a stopping problem, not a planning problem. The agent isn't deciding it's done. Check your system prompt: does it clearly say when to stop? Does it tell the agent to check whether the whole task is complete? Also check your max_turns β€” the safety net should catch runaway loops. We'll go deeper on this in Chapter 10 (Guardrails).
Q: Can the agent change its plan mid-task?
A: Yes β€” and it should. That's the whole point of ReAct. The agent makes a plan, starts executing, and if an observation changes things (no flights in October? prices higher than expected?), it reasons about the new situation and adjusts. A rigid plan that can't adapt is barely better than no plan.

Where People Come Unstuck

Mistake #1: No planning prompt

The agent does one step and stops. The fix is almost always the system prompt: tell it to think step by step, consider the whole task, and keep going until done. One line can transform a one-and-done agent into a multi-step planner.

Mistake #2: Stopping at the first failure

A tool returns an error, and the agent gives up β€” "I couldn't find flights, sorry." A planning agent reasons about the failure and tries an alternative. Make sure your system prompt tells the agent to recover, not just report. "If a step fails, try a different approach" is a line that saves hours of frustration.

Mistake #3: Overplanning

Not every task needs a 10-step plan. "What's the weather in Lisbon?" is one step. Forcing the agent to plan upfront for trivial tasks wastes tokens and time. Let the LLM decide β€” if you tell it to "plan when the task is complex, act directly when it's simple," it'll usually get the balance right.

Brain Power

Think about a research agent that answers: "Compare the battery life of the latest iPhone and Samsung Galaxy, and recommend which is better for someone who travels a lot."

Sketch the plan the agent should make. What steps? What tools might it need? Where might a step fail β€” and what would recovery look like? Would you use pure ReAct (reason at each step) or plan-then-execute (plan upfront)? Why?

There's no single right answer. The point is to start thinking in plans and recovery β€” the mental model this chapter is building.

Chapter Summary

  • Without planning, agents tend to do one step and stop β€” they answer the immediate question without considering the whole task.
  • Chain-of-thought is a prompt technique: ask the LLM to "think step by step" before acting. It's a prompt change, not a code change.
  • ReAct (Reason + Act) is the full pattern: reason about what to do, act by calling a tool, observe the result, reason again. Our agent loop is already a ReAct loop β€” we just make the reasoning explicit.
  • Recovery is a natural consequence of ReAct: when a tool fails, the error goes back as an observation, and the LLM reasons about what to try instead. The loop is self-correcting by design.
  • Plan-then-execute makes a full plan upfront, then executes step by step. More structured but less flexible. Most real agents blend planning with adaptive ReAct reasoning.
  • The system prompt is the lever: "think step by step, consider the whole task, keep going until done, recover from failures." One good prompt turns a one-step agent into a multi-step planner.
Chapter Challenge

The Research Agent. Take your agent loop and give it two tools: web_search(query) (fake it β€” return hardcoded results) and calculate(expression). Add the ReAct system prompt from this chapter.

Give it this task: "Find the population of Lisbon and Porto, then calculate which is larger and by how many people."

Watch the agent: plan the steps, search for both cities, calculate the difference, and report. Then break one of your fake search results β€” make it return "No results found" for Porto β€” and watch the agent recover. Does it try a different query? Does it tell you it couldn't find one? That's planning and recovery, working together.

← Previous Next β†’