Prompting Agents to Plan Multi-Step Tasks

La Lakshmi Priya Updated 07 Nov 2026
9 min read ·Lesson 110 of 140

Why Agents Need Plans An agent that decides only one step at a time (Lesson 108) works well for short tasks. For longer tasks, step-by-step decisions can go wrong in predictable ways:

Missing prerequisites: the agent issues a refund before checking eligibility. Wasted steps: it searches for information it already has, or follows a path that cannot succeed. Losing the goal: after several tool results, it focuses on a detail and forgets part of the request. Unreviewable behavior: no one can see what the agent intends to do until it has done it. A plan is a short, structured list of the steps the agent intends to take, written before acting. Planning makes agent behavior more deliberate, more efficient, and, importantly, reviewable before any action happens.

This idea connects to earlier lessons: least-to-most prompting decomposes problems into subproblems (Lesson 49), task decomposition creates chains (Lesson 63), and Tree of Thoughts explores alternative plans (Lesson 47). Here, the plan guides an agent that uses tools.

Two Planning Styles Style How It Works Strengths Weaknesses Plan-then-execute Write a complete plan first, then carry out the steps Reviewable in advance; efficient; easy to enforce Rigid if early results change what is needed Interleaved (ReAct-style) Decide each step after seeing the previous result Adapts to new information Harder to predict and review; can wander The Practical Combination: Plan, Execute, Replan Most robust agents combine both:

  1. Write a plan
  2. Validate the plan (in code)
  3. Execute the next step
  4. Observe the result
  5. If the result changes what is needed → revise the plan (and validate again)
  6. Repeat until the plan's goal is met The plan provides direction and reviewability; replanning provides flexibility.

Prompting for a Plan The Planning Prompt Before taking any action, write a plan to achieve the goal in .

Available tools: {tool_list}

Return only JSON: a list of steps, each with:

  • "id": step number
  • "tool": the tool to use
  • "purpose": what this step finds out or does, in one sentence
  • "depends_on": ids of steps whose results this step needs ([] if none)
  • "needs_confirmation": true if the step changes data or contacts someone
  • "done_when": how you will know the step succeeded

Rules:

  • Use the fewest steps that achieve the goal; at most 6.
  • Check information before acting on it: lookups come before actions.
  • Do not plan steps for information you already have in .
  • If the goal cannot be achieved with the available tools, return [] and explain why in a separate "reason" field instead.

{goal}

{known_facts} Why Each Field Matters Field Purpose tool Makes the plan executable and checkable against available tools purpose States why the step exists, which supports review and later reflection (Lesson 112) depends_on Makes ordering explicit, so prerequisite checks can be enforced needs_confirmation Identifies steps that require approval before execution done_when A success criterion, so the agent knows when to move on, and code or reviewers can check progress Example Plan Goal: "A student asks for a refund for the Django REST APIs course."

[ {"id": 1, "tool": "get_enrollment", "purpose": "Find the purchase date and progress", "depends_on": [], "needs_confirmation": false, "done_when": "enrollment found or confirmed missing"}, {"id": 2, "tool": "search_docs", "purpose": "Find the refund rules", "depends_on": [], "needs_confirmation": false, "done_when": "refund rules retrieved"}, {"id": 3, "tool": "issue_refund", "purpose": "Refund if the rules allow it", "depends_on": [1, 2], "needs_confirmation": true, "done_when": "refund issued or declined"} ] Steps 1 and 2 do not depend on each other, so they could run in parallel. Step 3 depends on both, and is marked for confirmation.

Validating Plans in Code A plan is a proposal. Before executing it, check it against facts the model cannot change: which tools exist, which require confirmation, and whether the dependencies make sense.

from graphlib import CycleError, TopologicalSorter

AVAILABLE_TOOLS = {"get_enrollment", "search_docs", "issue_refund", "send_email"} CONFIRM_TOOLS = {"issue_refund", "send_email"}

def validate_plan(plan: list[dict], max_steps: int = 6) -> tuple[list[str], list[int]]: """Return (problems, execution order). An empty problem list means the plan is valid.""" problems = [] ids = [step["id"] for step in plan] if len(plan) > max_steps: problems.append(f"plan has {len(plan)} steps; maximum is {max_steps}") if len(ids) != len(set(ids)): problems.append("duplicate step ids") for step in plan: if step["tool"] not in AVAILABLE_TOOLS: problems.append(f"step {step['id']}: unknown tool {step['tool']!r}") for dependency in step.get("depends_on", []): if dependency not in ids: problems.append(f"step {step['id']}: depends on missing step {dependency}") if step["tool"] in CONFIRM_TOOLS and not step.get("needs_confirmation"): problems.append(f"step {step['id']}: {step['tool']} must be marked needs_confirmation") if not step.get("done_when"): problems.append(f"step {step['id']}: no success criterion") try: graph = {step["id"]: set(step.get("depends_on", [])) for step in plan} order = list(TopologicalSorter(graph).static_order()) except CycleError: problems.append("steps depend on each other in a cycle") order = [] return problems, order

good_plan = [ {"id": 1, "tool": "get_enrollment", "purpose": "Find purchase date and progress", "depends_on": [], "done_when": "enrollment found or confirmed missing"}, {"id": 2, "tool": "search_docs", "purpose": "Find refund rules", "depends_on": [], "done_when": "refund rules retrieved"}, {"id": 3, "tool": "issue_refund", "purpose": "Refund if eligible", "depends_on": [1, 2], "needs_confirmation": True, "done_when": "refund issued or declined"}, ]

bad_plan = [ {"id": 1, "tool": "issue_refund", "purpose": "Refund", "depends_on": [2], "done_when": "done"}, {"id": 2, "tool": "check_bank", "purpose": "Check bank", "depends_on": [1]}, ]

print(validate_plan(good_plan)) print(validate_plan(bad_plan)) Output:

([], [1, 2, 3]) (['step 1: issue_refund must be marked needs_confirmation', "step 2: unknown tool 'check_bank'", 'step 2: no success criterion', 'steps depend on each other in a cycle'], []) Code Explanation Basic checks The number of steps is limited, step IDs must be unique, every tool must exist, and every dependency must refer to an existing step.

Confirmation check Any step using a tool in CONFIRM_TOOLS must be marked needs_confirmation. Code, not the model, decides which tools are sensitive.

Success criteria Every step needs a done_when, so progress can be checked.

Dependency order TopologicalSorter (Lesson 63) computes an order in which every step comes after the steps it depends on. In the bad plan, step 1 depends on step 2 and step 2 depends on step 1, a cycle that can never be executed. The sorter raises CycleError, which is reported as a problem.

What to Do With Problems Send the problems back to the model and ask for a corrected plan, as with any validation failure (Lesson 73). Limit the number of planning attempts, and hand over if no valid plan is produced.

Showing Plans to People For tasks with real consequences, the plan is the ideal moment for human review: nothing has happened yet, and the intended actions are visible.

Here's what I'll do:

  1. Look up your enrollment for the Django REST APIs course.
  2. Check the refund policy.
  3. If you're eligible, issue a refund of ₹4,999 to your original payment method (I'll ask you to confirm first). Converting the plan into plain language for the user, or for a staff member, builds trust and catches mistakes early. The plan's purpose fields make this conversion straightforward.

Replanning Plans are made with incomplete information. Results often change what is needed:

Observation Plan Change get_enrollment finds no enrollment Remove the refund step; add a step to ask the student for the correct email The refund policy says partial refunds need manager approval Replace issue_refund with a handover step A tool returns an error Add a retry or alternative step, or hand over (Lesson 113) The Replanning Prompt Here is the current plan in , the steps completed so far with their results in , and the goal in .

Decide:

  • "continue": the plan is still correct; name the next step id
  • "revise": the plan must change; return the revised remaining steps in the same JSON format
  • "done": the goal is achieved
  • "stop": the goal cannot be achieved; explain why

Return only JSON: {"decision": "...", "next_step": id or null, "revised_steps": [...] or [], "explanation": "one sentence"} Why Replanning Is Explicit Asking for an explicit decision after each result prevents two opposite failures: blindly following a plan that no longer fits, and abandoning a good plan because of one unexpected detail. Revised plans should go through validate_plan() again before execution.

When Not to Plan Planning adds a model call and some complexity. Skip it when:

The task needs only one or two tool calls, such as a single lookup. The task is a fixed sequence, which is better implemented as a prompt chain (Lesson 61). Each step depends entirely on the previous result in unpredictable ways, such as exploratory debugging, where interleaved ReAct with good limits may work better. Common Mistakes Mistake 1: Acting Without a Plan on Long Tasks What it is: Letting an agent decide each step from scratch for a task with many steps.

Why it happens: Step-by-step agents are simpler to build.

What it causes: Missed prerequisites, wasted calls, and forgotten parts of the goal.

How to fix it: Ask for a plan first for tasks with several steps or any action with consequences.

Mistake 2: Trusting Plans Without Validation What it is: Executing the model's plan as written.

Why it happens: Plans look reasonable.

What it causes: Calls to nonexistent tools, missing confirmations, and impossible orders.

How to fix it: Validate tools, dependencies, confirmations, and success criteria in code.

Mistake 3: Plans Without Success Criteria What it is: Steps that say what to do, but not how to know they worked.

Why it happens: The outcome seems obvious.

What it causes: Agents that move on after failed steps, or repeat successful ones.

How to fix it: Require a done_when for every step.

Mistake 4: Never Replanning What it is: Following the original plan even when results show it is wrong.

Why it happens: The plan is treated as fixed.

What it causes: Pointless or harmful actions, such as trying to refund a nonexistent enrollment.

How to fix it: Ask for an explicit continue, revise, done, or stop decision after each result.

Mistake 5: Planning Simple Tasks What it is: Requiring a plan for a single lookup.

Why it happens: Planning is applied everywhere once it is available.

What it causes: Extra cost and latency without benefit.

How to fix it: Use planning for multi-step or consequential tasks only.

Best Practices Plan before acting on multi-step tasks. Especially when actions have consequences.

Use a structured plan format. Tool, purpose, dependencies, confirmation, success criterion.

Validate plans in code. Tools, dependencies, cycles, confirmations, and limits.

Show plans to people for consequential tasks. Review before action is cheapest.

Replan explicitly after results. Continue, revise, done, or stop, with validation of revisions.

Keep plans short. The fewest steps that achieve the goal.

Try It Yourself Exercise 1: Generate and Validate Plans Write three goals for an enrollment agent: a refund request, a certificate request, and a course change request. Generate plans with the planning prompt, run validate_plan() on each, and send any problems back for a corrected plan.

Exercise 2: Plain-Language Plans Write a function that converts a validated plan into a numbered, plain-language message for a student, using each step's purpose and adding "I'll ask you to confirm first" for steps that need confirmation.

Exercise 3: Replanning Simulate a run of the refund plan where get_enrollment returns "No enrollment found". Use the replanning prompt, and check that the revised plan removes the refund step and adds an appropriate alternative. Validate the revised plan.

0 Comments

Reviewed before they appear

No comments yet.

Prompt Engineering
Prompt Engineering Introduction How Large Language Models Respond to Prompts Prompting Basics Elements of an Effective Prompt Writing Clear Instructions for AI Models Adding Context to a Prompt Providing Input Data in Prompts Using Output Indicators and Response Formats Prompt Formatting: Questions, Instructions, and Templates General Tips for Designing Better Prompts Common Prompt Engineering Mistakes Iterative Prompt Design and Refinement Understanding Instruction, Context, Input, and Output How Specificity and Conciseness Affect Prompt Quality Breaking Large Tasks into Smaller Prompting Tasks Zero-Shot Prompting Zero-Shot Prompting Examples for Everyday Tasks Zero-Shot Text Classification Zero-Shot Question Answering Zero-Shot Summarization Zero-Shot Translation Zero-Shot Prompting for Information Extraction When to Use Zero-Shot Prompting Limitations of Zero-Shot Prompting Improving Weak Zero-Shot Prompts Few-Shot Prompting One-Shot Prompting vs Few-Shot Prompting Choosing Good Examples for Few-Shot Prompts Formatting Examples in Few-Shot Prompts Few-Shot Classification with Examples Few-Shot Prompting for Structured Output Few-Shot Prompting Zero-Shot vs Few-Shot Prompting Role Prompting and Persona Instructions Instruction-Based Prompting Task-Oriented Prompt Templates Using Delimiters to Separate Prompt Sections Prompt Templates with Variables Chain-of-Thought Prompting Zero-Shot Chain-of-Thought Prompting Few-Shot Chain-of-Thought Prompting Automatic Chain-of-Thought (Auto-CoT) When Chain-of-Thought Prompting Helps Limitations of Chain-of-Thought Prompting Self-Consistency Prompting Comparing Chain-of-Thought and Self-Consistency Tree of Thoughts (ToT) Prompting Exploring Multiple Solutions with Tree of Thoughts Least-to-Most Prompting Complexity-Based Prompting Maieutic Prompting Self-Consistency: Sampling Multiple Reasoning Paths Self-Consistency for Arithmetic and Logic Tasks Tree of Thoughts: Search, Evaluation, and Backtracking Meta Prompting Generate Knowledge Prompting Directional Stimulus Prompting Program-Aided Language Models (PAL) React: Reasoning and Acting with Language Models Reflexion: Improving Agents Through Feedback Prompt Chaining Designing Multi-Step Prompt Chains Decomposing Complex Tasks into Prompt Chains Automatic Prompt Engineer (APE) Active-Prompt: Selecting Useful Reasoning Examples Optimizing Prompts Systematically Prompt Iteration and Versioning Building Reusable Prompt Libraries Testing Prompt Variants Prompt Chaining Fundamentals Passing Outputs Between Prompt Steps Prompt Chains for Summarization and Extraction Validating Intermediate Results in a Prompt Chain Debugging a Multi-Step Prompt Workflow Graph Prompting Multimodal Chain-of-Thought Prompting Automatic Reasoning and Tool-Use (ART) Prompting for Tool Selection and Use Combining Prompting Techniques for Complex Tasks Prompts for Text Summarization Prompts for Information Extraction Prompts for Text Classification Prompts for Question Answering Prompts for Sentiment Analysis Prompts for Rewriting and Editing Prompts for Translation and Localization Prompts for Brainstorming and Creative Writing Prompts for Generating Structured Data Prompts for Explaining Technical Concepts Prompts for Generating and Reviewing Code Prompting for Code Generation Prompting for Code Explanation Prompting for Debugging and Error Analysis Prompting for Unit Test Generation Prompting for SQL Query Generation Prompting for API Documentation Prompting for Technical Documentation Using Prompting to Extract Requirements Creating JSON-Style Structured Responses with Prompts Designing Prompts for Repeatable Developer Workflows Retrieval-Augmented Generation (RAG) How Prompt Engineering Supports RAG Writing Prompts That Use Retrieved Context Grounding Answers in Provided Documents Handling Missing Information in RAG Prompts Reducing Unsupported Claims in Context-Based Answers Prompt Engineering for AI Agents ReAct Prompting for Tool-Using Agents Writing Tool Instructions for AI Agents Prompting Agents to Plan Multi-Step Tasks Prompting Agents to Observe Tool Results Using Feedback and Reflection in Agent Workflows Prompting for Agent Error Recovery How to Evaluate Prompt Quality Creating Test Cases for Prompts Comparing Prompt Outputs with a Rubric Evaluating Accuracy, Relevance, and Completeness Regression Testing for Prompt Changes Building a Prompt Evaluation Dataset Common Causes of Inconsistent Prompt Outputs Prompt Injection: Introduction and Examples Recognizing Prompt Injection Attempts Prompt Leaking and Instruction Disclosure Risks Jailbreaking: Understanding Adversarial Prompts Writing Safer Prompts for Untrusted Inputs Reducing Hallucinations with Clear Instructions and Context Prompt Safety: Limitations and Best Practices Build a Zero-Shot Sentiment Classifier Project Goal Build a Few-Shot Text Classification Prompt Build a Prompt-Based Text Summarizer Project Goal Build a Structured Information Extraction Prompt Build a Prompt Template for Blog Outlines Build a Prompt-Based SQL Assistant Build a Code Explanation Prompt Workflow Build a Multi-Step Research and Summarization Workflow Build a Prompt Comparison and Evaluation Pipeline Build a Prompt-Chaining Workflow for Document Analysis Build a RAG Prompt for Question Answering over Documents Build a Tool-Using ReAct Assistant Create a Reusable Prompt Library for a Web Application
Ask about this post
AI Ask about this post

Ask questions about Prompting Agents to Plan Multi-Step Tasks and get answers drawn from it.

Signed-in readers only.