AI Agents for Beginners - 7. Planning Design Pattern
How to build planning agents that decompose complex goals into structured subtasks, route work to specialized agents, and iteratively re-plan based on real-world feedback.
June 9, 2026
AI Agents for Beginners - 7. Planning Design Pattern
This post is a summary based on Lesson 07 of Microsoft's AI Agents for Beginners course.
Defining the Overall Goal and Breaking Down a Task
Complex real-world tasks are difficult to resolve in a single step.
AI agents require clear goals to guide their planning and actions. For example, a goal like "Generate a 3-day travel itinerary" may seem simple, but creating a comprehensive itinerary that covers flights, accommodations, and activity recommendations requires concrete decomposition.
AI agents require clear goals to guide their planning and actions. For example, a goal like "Generate a 3-day travel itinerary" may seem simple, but creating a comprehensive itinerary that covers flights, accommodations, and activity recommendations requires concrete decomposition.
The more specific the goal, the better the agent (and its collaborators) can focus on the right outcome.
Planning Design Pattern OverviewMermaidflowchart TD Goal["Overall Goal\n'Generate a 3-day travel itinerary'"] --> Decompose["Task Decomposition\nDecompose into Subtasks"] Decompose --> T1["Flight Booking"] Decompose --> T2["Hotel Booking"] Decompose --> T3["Car Rental"] Decompose --> T4["Activities Booking"] T1 & T2 & T3 & T4 --> Plan["Structured Plan\n(JSON output)"] Plan --> Route["Route to\nSpecialized Agents"] Route --> Result["Cohesive Final\nItinerary"]
Three core elements of the Planning Pattern:
| Element | Description |
|---|---|
| Goal Setting | Clearly defines what the agent must achieve. The more specific, the better the result |
| Task Decomposition | Breaks down complex tasks into independent subtasks and delegates them to specialized agents |
| Structured Output | The LLM generates a plan in JSON format, making it easy for downstream agents to parse and process |
Task Decomposition
A goal like "Generate a 3-day travel itinerary" appears simple, but in reality, it breaks down into several specialized domains.
Each subtask is handled by a dedicated agent or process, and thanks to the modular architecture, it can be expanded incrementally later by adding things like Food Recommendations or Local Activity Suggestions.
Each subtask is handled by a dedicated agent or process, and thanks to the modular architecture, it can be expanded incrementally later by adding things like Food Recommendations or Local Activity Suggestions.
Travel Itinerary Task DecompositionMermaidflowchart LR Main["Plan a family trip\nSingapore → Melbourne"] Main --> F["FlightBooking\nRound-trip flight booking"] Main --> H["HotelBooking\nFamily-friendly hotel"] Main --> C["CarRental\nCar rental for a family of 4"] Main --> A["ActivitiesBooking\nFamily activities"] Main --> D["DestinationInfo\nMelbourne travel info"]
Structured output
For downstream systems to process the plan generated by an LLM, structured output is required.
Defining the response schema with a Pydantic model provides type safety and automatic validation:
Defining the response schema with a Pydantic model provides type safety and automatic validation:
planning_agent.pypython
Example output of the code above:
planning_output.jsonjson
Structured Output FlowMermaidflowchart TD User["User Request\n'Plan a family trip Singapore → Melbourne'"] --> Planner["Planner Agent\n(system_prompt + user_message)"] Planner --> LLM["LLM\nGenerate plan based on Pydantic schema"] LLM --> JSON["TravelPlan JSON\nmain_task + subtasks[]"] JSON --> V1["assigned_agent:\nflight_booking"] JSON --> V2["assigned_agent:\nhotel_booking"] JSON --> V3["assigned_agent:\ncar_rental"] JSON --> V4["assigned_agent:\nactivities_booking"] JSON --> V5["assigned_agent:\ndestination_info"]
Planning Agent with Multi-Agent Orchestration
The Planning Agent routes tasks to specialized agents based on the generated plan.
| Scenario | Routing Method |
|---|---|
| Single Task | Delivered directly to the corresponding dedicated agent |
| Multiple Tasks | Multiple agents collaborate via GroupChatManager |
Planning Agent with Multi-Agent OrchestrationMermaidflowchart TD User["User\n'Plan a family trip Singapore → Melbourne'"] --> Planner["Planner Agent\nGenerate plan based on system_prompt"] Planner --> LLM["LLM\nGenerate TravelPlan JSON"] Route{Number of subtasks} Route -->|"Single task"| Direct["Deliver directly to dedicated agent"] Route -->|"Multiple tasks"| GCM["GroupChatManager\nCoordinate multi-agent collaboration"] GCM --> FA["FlightAgent"] GCM --> HA["HotelAgent"] GCM --> CA["CarRentalAgent"] GCM --> AA["ActivitiesAgent"] GCM --> DA["DestInfoAgent"] FA & HA & CA & AA & DA --> GCM GCM --> Summary["Aggregate and summarize results"] Direct --> Summary Summary --> User
GroupChatManager aggregates results from multiple agents to deliver a cohesive response to the end user.Iterative Planning
Some tasks cannot be completed with a single round of planning.
There are cases where the results of a subtask affect subsequent steps, or where user feedback requires re-planning.
There are cases where the results of a subtask affect subsequent steps, or where user feedback requires re-planning.
For example:
- Unexpected data format encountered during flight booking → Change strategy and proceed with hotel booking
- User requests "prefer an earlier flight" → Triggers partial re-planning
iterative_planning.pypython
Iterative Planning LoopMermaidflowchart TD Start["User Request"] --> Plan["Initial Plan\n(TravelPlan JSON)"] Plan --> Execute["Execute Subtasks\n(Specialized Agents)"] Execute --> Check{Review results} Check -->|"Success"| Next["Next Subtask\nor Final Response"] Check -->|"Failure / Change needed"| Replan["Re-plan\n(context: Previous TravelPlan)"] Replan --> Execute Next --> Done["Final Travel Itinerary"]
Passing the previous plan via the
context parameter allows the LLM to generate a revised plan based on prior results.Summary
Lesson 07 SummaryMermaidflowchart LR Root["Planning\nDesign Pattern"] Root --> Goal["Goal Setting"] Root --> Decomp["Task\nDecomposition"] Root --> Struct["Structured\nOutput"] Root --> Orch["Multi-Agent\nOrchestration"] Root --> Iter["Iterative\nPlanning"] Goal --> G1["Clear goal definition"] Goal --> G2["More specific = better results"] Decomp --> D1["Decompose into subtasks"] Decomp --> D2["Assign dedicated agents"] Struct --> S1["Pydantic schema"] Struct --> S2["Generate JSON plan"] Orch --> O1["Single → Direct routing"] Orch --> O2["Multiple → GroupChatManager"] Iter --> I1["Re-plan upon failure"] Iter --> I2["Pass previous plan via context"]
- The Planning Design Pattern decomposes complex goals into manageable subtasks and delegates them to specialized agents.
- Defining Structured Output with Pydantic models enables type-safe parsing of LLM responses for immediate processing by downstream agents.
- Multi-Agent Orchestration routes single or multiple tasks to appropriate agents and coordinates collaboration via
GroupChatManager. - Iterative Re-planning responds to unexpected outcomes or user feedback, dynamically adapting plans to real-world constraints.