Hi everyone, Shivam Goyal here! This blog series, based on Microsoft's AI Agents for Beginners repository, continues with a focus on the Planning Design Pattern. In previous posts (links at the end!), we've built a strong foundation in AI agent concepts. Now, we'll explore how to design agents that can effectively plan and orchestrate complex tasks, breaking them down into manageable subtasks and coordinating their execution.
Introduction to Planning Design
The Planning Design Pattern helps AI agents tackle complex goals by providing a structured approach to task decomposition and execution. This involves:
- Defining a clear overall goal.
- Breaking down the task into smaller, manageable subtasks.
- Leveraging structured output for easier processing.
- Using an event-driven approach for dynamic adaptation.
Defining Goals and Decomposing Tasks
A well-defined goal is crucial for effective agent planning. Consider the goal "Generate a 3-day travel itinerary." While seemingly simple, it requires refinement to ensure the agent understands the desired outcome (flights, hotels, activities, etc.).
Task Decomposition: We break down complex tasks into smaller, more manageable subtasks:
- Flight Booking
- Hotel Booking
- Car Rental
- Personalization
This allows specialized agents or processes to handle each subtask, improving modularity and enabling incremental enhancements (e.g., adding food recommendations later).
Structured Output for Seamless Communication
Structured output (like JSON) simplifies processing for other agents and services, especially in multi-agent systems. Here's how to define the structure for a travel plan:
class TravelSubTask(BaseModel):
task_details: str
assigned_agent: AgentEnum
class TravelPlan(BaseModel):
main_task: str
subtasks: List[TravelSubTask]
is_greeting: bool
Planning Agent with Multi-Agent Orchestration
A Semantic Router Agent can coordinate multiple specialized agents. It receives a user request, generates a structured plan, routes subtasks, and summarizes the outcome. Here's the core logic for creating the plan:
messages = [
SystemMessage(content="""You are a planner agent...""", source="system"),
UserMessage(content="Create a travel plan...", source="user"),
]
response = await client.create(messages=messages, extra_create_args={"response_format": TravelPlan})
This generates a structured plan like this:
{
"main_task": "Plan a family trip...",
"subtasks": [
{"assigned_agent": "flight_booking", "task_details": "Book flights..."},
// ... other subtasks
]
}
Iterative Planning and Adaptation
Iterative planning allows agents to adapt to changing requirements or unexpected data. Here's how to incorporate a previous plan for re-planning:
messages = [
// ... previous messages
AssistantMessage(content=f"Previous travel plan - {TravelPlan}", source="assistant")
]
# ... re-plan based on the previous plan
Summary
This post demonstrated how a planner agent can dynamically select and assign subtasks to specialized agents, generating structured plans for execution. We also touched upon iterative planning and adaptation. Explore the provided code examples and resources to deepen your understanding.
Further Resources and Learning
Catch up on the series:
- Part 1: Introduction to AI Agents
- Part 2: Exploring Agentic Frameworks
- Part 3: Agentic Design Principles
- Part 4: Tool Use Design Pattern
- Part 5: AI Agents: Mastering Agentic RAG
- Part 6: Building Trustworthy Agents
If you have any further questions or would like to connect for more discussion, feel free to reach out to me on the Microsoft AI Community Discord
Updated Apr 14, 2025
Version 1.0ShivamGoyal03
Iron Contributor
Joined December 03, 2023
Educator Developer Blog
Follow this blog board to get notified when there's new activity