See how AI agents use planning to handle complex, multi-step tasks. Learn task decomposition, sequential execution, and error handling through a complete example of booking meetings and sending summaries.

This article is part of the free-to-read AI Agent Handbook
Example: Planning with Our Assistant
You've learned how to break down tasks and implement plan-and-execute patterns. Now let's see these concepts in action with a realistic scenario that brings together everything our assistant has learned so far.
A Complex Request
Imagine you send this message to your personal assistant:
1Book a meeting next week with Alice to discuss the Q4 marketing campaign.
2Send her a summary of what we accomplished in Q3 before the meeting.1Book a meeting next week with Alice to discuss the Q4 marketing campaign.
2Send her a summary of what we accomplished in Q3 before the meeting.This isn't a simple, single-step task. It requires coordination across multiple systems, retrieving historical information, and executing several actions in the right order. Let's watch our assistant plan and execute this request step by step.
The Planning Phase
When our assistant receives this request, it doesn't immediately start booking meetings or sending emails. Instead, it enters a planning phase where it breaks down the goal into manageable subtasks.
Here's how the assistant might decompose this request:
1## Using Claude Sonnet 4.5 for its superior planning capabilities
2import anthropic
3
4client = anthropic.Anthropic(api_key="ANTHROPIC_API_KEY")
5
6user_request = """
7Book a meeting next week with Alice to discuss the Q4 marketing campaign.
8Send her a summary of what we accomplished in Q3 before the meeting.
9"""
10
11planning_prompt = f"""You are a personal assistant. Break down this request into a numbered list of specific steps:
12
13Request: {user_request}
14
15List each step as a clear action. Consider what information you need and what order makes sense."""
16
17response = client.messages.create(
18 model="claude-sonnet-4.5",
19 max_tokens=1024,
20 messages=[{"role": "user", "content": planning_prompt}]
21)
22
23print(response.content[0].text)1## Using Claude Sonnet 4.5 for its superior planning capabilities
2import anthropic
3
4client = anthropic.Anthropic(api_key="ANTHROPIC_API_KEY")
5
6user_request = """
7Book a meeting next week with Alice to discuss the Q4 marketing campaign.
8Send her a summary of what we accomplished in Q3 before the meeting.
9"""
10
11planning_prompt = f"""You are a personal assistant. Break down this request into a numbered list of specific steps:
12
13Request: {user_request}
14
15List each step as a clear action. Consider what information you need and what order makes sense."""
16
17response = client.messages.create(
18 model="claude-sonnet-4.5",
19 max_tokens=1024,
20 messages=[{"role": "user", "content": planning_prompt}]
21)
22
23print(response.content[0].text)The assistant generates this plan:
1To complete this request, I'll need to:
2
31. Check Alice's calendar availability for next week
42. Check your calendar for the same period
53. Identify overlapping time slots
64. Retrieve your Q3 marketing notes and accomplishments
75. Create a concise summary of Q3 work
86. Send the summary email to Alice
97. Schedule the meeting once a time is confirmed
108. Provide you with confirmation of both actions
11
12I notice there are dependencies here. I should send the summary before
13scheduling the meeting so Alice has context when she receives the invite.
14I also need to find availability before I can schedule anything.1To complete this request, I'll need to:
2
31. Check Alice's calendar availability for next week
42. Check your calendar for the same period
53. Identify overlapping time slots
64. Retrieve your Q3 marketing notes and accomplishments
75. Create a concise summary of Q3 work
86. Send the summary email to Alice
97. Schedule the meeting once a time is confirmed
108. Provide you with confirmation of both actions
11
12I notice there are dependencies here. I should send the summary before
13scheduling the meeting so Alice has context when she receives the invite.
14I also need to find availability before I can schedule anything.Notice how the assistant has identified dependencies on its own. You can't schedule a meeting before checking availability, and you should send the summary before the meeting gets scheduled so Alice has context when she accepts. This kind of dependency awareness is what makes planning valuable.
Executing the Plan
Now our assistant moves through each step, using the tools and capabilities we've built in previous chapters.
Step 1-3: Finding a Meeting Time
1## Example (Claude Sonnet 4.5)
2## Simulating calendar tool calls
3
4def check_calendar(person, start_date, end_date):
5 """Tool to check calendar availability"""
6 # In reality, this would call Google Calendar API or similar
7 if person == "Alice":
8 return {
9 "available_slots": [
10 "2025-11-17 14:00-15:00",
11 "2025-11-18 10:00-11:00",
12 "2025-11-19 15:00-16:00"
13 ]
14 }
15 else: # User's calendar
16 return {
17 "available_slots": [
18 "2025-11-17 14:00-15:00",
19 "2025-11-18 10:00-11:00",
20 "2025-11-20 09:00-10:00"
21 ]
22 }
23
24## Agent executes steps 1-3
25alice_availability = check_calendar("Alice", "2025-11-17", "2025-11-23")
26user_availability = check_calendar("User", "2025-11-17", "2025-11-23")
27
28## Find overlapping slots
29alice_slots = set(alice_availability["available_slots"])
30user_slots = set(user_availability["available_slots"])
31common_slots = alice_slots.intersection(user_slots)
32
33print(f"Available times for both: {list(common_slots)}")
34## Output: ['2025-11-17 14:00-15:00', '2025-11-18 10:00-11:00']1## Example (Claude Sonnet 4.5)
2## Simulating calendar tool calls
3
4def check_calendar(person, start_date, end_date):
5 """Tool to check calendar availability"""
6 # In reality, this would call Google Calendar API or similar
7 if person == "Alice":
8 return {
9 "available_slots": [
10 "2025-11-17 14:00-15:00",
11 "2025-11-18 10:00-11:00",
12 "2025-11-19 15:00-16:00"
13 ]
14 }
15 else: # User's calendar
16 return {
17 "available_slots": [
18 "2025-11-17 14:00-15:00",
19 "2025-11-18 10:00-11:00",
20 "2025-11-20 09:00-10:00"
21 ]
22 }
23
24## Agent executes steps 1-3
25alice_availability = check_calendar("Alice", "2025-11-17", "2025-11-23")
26user_availability = check_calendar("User", "2025-11-17", "2025-11-23")
27
28## Find overlapping slots
29alice_slots = set(alice_availability["available_slots"])
30user_slots = set(user_availability["available_slots"])
31common_slots = alice_slots.intersection(user_slots)
32
33print(f"Available times for both: {list(common_slots)}")
34## Output: ['2025-11-17 14:00-15:00', '2025-11-18 10:00-11:00']The assistant has now completed the first three steps of its plan. It found two possible meeting times.
Step 4-5: Retrieving and Summarizing Q3 Work
Next, the assistant needs to gather information about Q3 marketing activities. This is where memory and retrieval come in.
1## Example (Claude Sonnet 4.5)
2## Using the memory system from Chapter 6
3
4def retrieve_project_notes(project_name, time_period):
5 """Retrieve notes from long-term memory"""
6 # This would query a vector database or document store
7 return {
8 "notes": [
9 "Launched new social media campaign in July - 50K impressions",
10 "Redesigned email templates - open rate increased 15%",
11 "Partnered with 3 influencers for product reviews",
12 "A/B tested landing pages - version B performed 22% better",
13 "Ran webinar series - 500 attendees total"
14 ],
15 "documents": ["Q3_campaign_metrics.pdf", "social_media_report.xlsx"]
16 }
17
18## Agent executes step 4
19q3_data = retrieve_project_notes("marketing", "Q3 2025")
20
21## Agent executes step 5: summarize the findings
22summary_prompt = f"""Summarize these Q3 marketing accomplishments in a brief, professional email format:
23
24{q3_data['notes']}
25
26Keep it concise but highlight key metrics."""
27
28response = client.messages.create(
29 model="claude-sonnet-4.5",
30 max_tokens=512,
31 messages=[{"role": "user", "content": summary_prompt}]
32)
33
34summary = response.content[0].text
35print(summary)1## Example (Claude Sonnet 4.5)
2## Using the memory system from Chapter 6
3
4def retrieve_project_notes(project_name, time_period):
5 """Retrieve notes from long-term memory"""
6 # This would query a vector database or document store
7 return {
8 "notes": [
9 "Launched new social media campaign in July - 50K impressions",
10 "Redesigned email templates - open rate increased 15%",
11 "Partnered with 3 influencers for product reviews",
12 "A/B tested landing pages - version B performed 22% better",
13 "Ran webinar series - 500 attendees total"
14 ],
15 "documents": ["Q3_campaign_metrics.pdf", "social_media_report.xlsx"]
16 }
17
18## Agent executes step 4
19q3_data = retrieve_project_notes("marketing", "Q3 2025")
20
21## Agent executes step 5: summarize the findings
22summary_prompt = f"""Summarize these Q3 marketing accomplishments in a brief, professional email format:
23
24{q3_data['notes']}
25
26Keep it concise but highlight key metrics."""
27
28response = client.messages.create(
29 model="claude-sonnet-4.5",
30 max_tokens=512,
31 messages=[{"role": "user", "content": summary_prompt}]
32)
33
34summary = response.content[0].text
35print(summary)The assistant generates a summary:
1Hi Alice,
2
3Here's a quick overview of our Q3 marketing accomplishments:
4
5- Social Media: Launched new campaign reaching 50K impressions
6- Email Marketing: Redesigned templates with 15% improvement in open rates
7- Influencer Partnerships: Collaborated with 3 influencers for product reviews
8- Website Optimization: A/B testing showed 22% better performance on new landing page
9- Webinar Series: Hosted events with 500 total attendees
10
11Looking forward to discussing Q4 plans!1Hi Alice,
2
3Here's a quick overview of our Q3 marketing accomplishments:
4
5- Social Media: Launched new campaign reaching 50K impressions
6- Email Marketing: Redesigned templates with 15% improvement in open rates
7- Influencer Partnerships: Collaborated with 3 influencers for product reviews
8- Website Optimization: A/B testing showed 22% better performance on new landing page
9- Webinar Series: Hosted events with 500 total attendees
10
11Looking forward to discussing Q4 plans!Step 6: Sending the Summary
1## Example (Claude Sonnet 4.5)
2def send_email(to, subject, body):
3 """Tool to send email"""
4 # Would use SendGrid, Gmail API, or similar
5 print(f"Sending email to {to}")
6 print(f"Subject: {subject}")
7 print(f"Body: {body}")
8 return {"status": "sent", "message_id": "msg_12345"}
9
10## Agent executes step 6
11email_result = send_email(
12 to="alice@company.com",
13 subject="Q3 Marketing Summary - Ahead of Our Q4 Planning Meeting",
14 body=summary
15)
16
17print(f"Email status: {email_result['status']}")1## Example (Claude Sonnet 4.5)
2def send_email(to, subject, body):
3 """Tool to send email"""
4 # Would use SendGrid, Gmail API, or similar
5 print(f"Sending email to {to}")
6 print(f"Subject: {subject}")
7 print(f"Body: {body}")
8 return {"status": "sent", "message_id": "msg_12345"}
9
10## Agent executes step 6
11email_result = send_email(
12 to="alice@company.com",
13 subject="Q3 Marketing Summary - Ahead of Our Q4 Planning Meeting",
14 body=summary
15)
16
17print(f"Email status: {email_result['status']}")Step 7-8: Scheduling and Confirming
1## Example (Claude Sonnet 4.5)
2def schedule_meeting(attendees, time_slot, subject, description):
3 """Tool to create calendar event"""
4 # Would use Google Calendar API or similar
5 return {
6 "event_id": "evt_67890",
7 "status": "scheduled",
8 "time": time_slot,
9 "attendees": attendees
10 }
11
12## Agent executes step 7
13## Choose the first available slot
14chosen_time = list(common_slots)[0]
15
16meeting_result = schedule_meeting(
17 attendees=["alice@company.com", "user@company.com"],
18 time_slot=chosen_time,
19 subject="Q4 Marketing Campaign Planning",
20 description="Discuss Q4 marketing strategy and campaign plans"
21)
22
23## Agent executes step 8: Confirm with user
24confirmation_message = f"""
25Task completed! Here's what I did:
26
27✓ Found available time: {chosen_time}
28✓ Retrieved and summarized Q3 marketing accomplishments
29✓ Sent summary to Alice at alice@company.com
30✓ Scheduled meeting: "Q4 Marketing Campaign Planning"
31
32The meeting is confirmed for {chosen_time}. Alice has received the Q3 summary in advance.
33"""
34
35print(confirmation_message)1## Example (Claude Sonnet 4.5)
2def schedule_meeting(attendees, time_slot, subject, description):
3 """Tool to create calendar event"""
4 # Would use Google Calendar API or similar
5 return {
6 "event_id": "evt_67890",
7 "status": "scheduled",
8 "time": time_slot,
9 "attendees": attendees
10 }
11
12## Agent executes step 7
13## Choose the first available slot
14chosen_time = list(common_slots)[0]
15
16meeting_result = schedule_meeting(
17 attendees=["alice@company.com", "user@company.com"],
18 time_slot=chosen_time,
19 subject="Q4 Marketing Campaign Planning",
20 description="Discuss Q4 marketing strategy and campaign plans"
21)
22
23## Agent executes step 8: Confirm with user
24confirmation_message = f"""
25Task completed! Here's what I did:
26
27✓ Found available time: {chosen_time}
28✓ Retrieved and summarized Q3 marketing accomplishments
29✓ Sent summary to Alice at alice@company.com
30✓ Scheduled meeting: "Q4 Marketing Campaign Planning"
31
32The meeting is confirmed for {chosen_time}. Alice has received the Q3 summary in advance.
33"""
34
35print(confirmation_message)What Made This Work
Let's unpack what just happened. Our assistant successfully handled a complex, multi-step request by combining several capabilities:
Planning: The assistant didn't just react to the request. It thought ahead, identified dependencies, and created a logical sequence of actions.
Tool Use: Multiple tools came into play - calendar APIs for checking availability, a memory system for retrieving past work, and email services for communication. The assistant knew which tool to use at each step.
Memory and Retrieval: The assistant pulled relevant information from its long-term memory about Q3 marketing activities. Without this capability, it couldn't have generated an accurate summary.
Reasoning: When finding a meeting time, the assistant had to reason about overlapping availability. It understood that both parties need to be free at the same time.
State Management: Throughout execution, the assistant maintained state about what it had accomplished, what remained to be done, and what information it had gathered. This prevented it from repeating steps or losing track of progress.
Handling Complications
Real-world scenarios rarely go perfectly. Let's see how our assistant handles a complication.
Suppose when the assistant tries to retrieve Q3 notes, the memory system returns incomplete information:
1## Example (Claude Sonnet 4.5)
2## Simulating incomplete data retrieval
3
4q3_data_incomplete = retrieve_project_notes("marketing", "Q3 2025")
5
6if len(q3_data_incomplete["notes"]) < 3:
7 # Assistant recognizes insufficient information
8 replanning_prompt = """
9 I was asked to summarize Q3 marketing work, but I only found limited notes.
10 What should I do?
11
12 Options:
13 A) Send what I have
14 B) Ask the user for more information
15 C) Search additional sources
16 D) Indicate in the summary that information is incomplete
17
18 Consider: The summary will be sent to Alice before a meeting.
19 """
20
21 response = client.messages.create(
22 model="claude-sonnet-4.5",
23 max_tokens=256,
24 messages=[{"role": "user", "content": replanning_prompt}]
25 )
26
27 print(response.content[0].text)1## Example (Claude Sonnet 4.5)
2## Simulating incomplete data retrieval
3
4q3_data_incomplete = retrieve_project_notes("marketing", "Q3 2025")
5
6if len(q3_data_incomplete["notes"]) < 3:
7 # Assistant recognizes insufficient information
8 replanning_prompt = """
9 I was asked to summarize Q3 marketing work, but I only found limited notes.
10 What should I do?
11
12 Options:
13 A) Send what I have
14 B) Ask the user for more information
15 C) Search additional sources
16 D) Indicate in the summary that information is incomplete
17
18 Consider: The summary will be sent to Alice before a meeting.
19 """
20
21 response = client.messages.create(
22 model="claude-sonnet-4.5",
23 max_tokens=256,
24 messages=[{"role": "user", "content": replanning_prompt}]
25 )
26
27 print(response.content[0].text)A well-designed assistant might respond:
1I should ask the user for more information (Option B). Sending incomplete
2information to Alice could make us look unprepared for the meeting. I'll
3pause execution and request additional details from the user.1I should ask the user for more information (Option B). Sending incomplete
2information to Alice could make us look unprepared for the meeting. I'll
3pause execution and request additional details from the user.This demonstrates adaptive planning. When the original plan hits an obstacle, the assistant can recognize the problem and adjust its approach.
Bringing It All Together
This example shows how planning transforms our assistant from a simple question-answering tool into something that can handle real work. The key elements that made this possible:
Task Decomposition: Breaking "book a meeting and send a summary" into eight concrete steps made the complex request manageable. Without decomposition, the assistant might have tried to do everything at once or missed important steps.
Sequential Execution: Following the plan in order, with each step building on the previous ones, ensured nothing was forgotten or done out of sequence. The assistant knew to check calendars before scheduling and to send the summary before creating the meeting invite.
Tool Orchestration: The assistant coordinated multiple tools (calendar, memory, email) to accomplish different parts of the task. Each tool served a specific purpose, and the assistant knew when to invoke each one.
Contextual Awareness: Throughout execution, the assistant maintained awareness of the overall goal and how each step contributed to it. This prevented it from getting lost in the details or forgetting why it was performing certain actions.
Graceful Handling: When problems arise, the assistant can recognize them and adapt rather than blindly continuing. This makes the difference between a brittle system that breaks easily and a robust one that handles real-world messiness.
Design Considerations
As you build planning capabilities into your own agents, consider these trade-offs:
Plan Detail vs. Flexibility: Highly detailed plans are easier to execute but harder to adapt when things change. More abstract plans are flexible but require more reasoning at each step. For our assistant, we chose medium-detail plans that specify what to do but allow some flexibility in how.
Upfront Planning vs. Incremental Planning: Should the agent plan everything before starting, or plan a few steps and then replan? Upfront planning works well for predictable tasks. Incremental planning handles uncertainty better but adds overhead. Our example used upfront planning because meeting scheduling is fairly predictable.
Error Recovery Strategies: When a step fails, should the agent retry, skip it, ask for help, or abort entirely? The right choice depends on the consequences of failure. For our assistant, we chose to ask for help when critical information is missing, since sending incomplete information could damage professional relationships.
You now have an assistant that doesn't just respond to requests but actively works to accomplish goals. In the next chapter, we'll explore how multiple agents can work together, enabling even more sophisticated capabilities through collaboration and specialization.
Glossary
Task Decomposition: The process of breaking down a complex goal into smaller, manageable subtasks that can be executed sequentially or in parallel.
Tool Orchestration: Coordinating multiple different tools or APIs to accomplish various parts of a larger task, ensuring they work together effectively.
Sequential Execution: Performing planned steps in a specific order, where each step may depend on the results of previous steps.
Adaptive Planning: The ability to recognize when a plan isn't working and adjust the approach, either by replanning or by asking for additional information.
State Management: Maintaining awareness of what has been accomplished, what remains to be done, and what information has been gathered during task execution.
Quiz
Ready to test your understanding? Take this quick quiz to reinforce what you've learned about planning in AI agents.
Reference

About the author: Michael Brenndoerfer
All opinions expressed here are my own and do not reflect the views of my employer.
Michael currently works as an Associate Director of Data Science at EQT Partners in Singapore, where he drives AI and data initiatives across private capital investments.
With over a decade of experience spanning private equity, management consulting, and software engineering, he specializes in building and scaling analytics capabilities from the ground up. He has published research in leading AI conferences and holds expertise in machine learning, natural language processing, and value creation through data.
Related Content

Scaling Up without Breaking the Bank: AI Agent Performance & Cost Optimization at Scale
Learn how to scale AI agents from single users to thousands while maintaining performance and controlling costs. Covers horizontal scaling, load balancing, monitoring, cost controls, and prompt optimization strategies.

Managing and Reducing AI Agent Costs: Complete Guide to Cost Optimization Strategies
Learn how to dramatically reduce AI agent API costs without sacrificing capability. Covers model selection, caching, batching, prompt optimization, and budget controls with practical Python examples.

Speeding Up AI Agents: Performance Optimization Techniques for Faster Response Times
Learn practical techniques to make AI agents respond faster, including model selection strategies, response caching, streaming, parallel execution, and prompt optimization for reduced latency.
Stay updated
Get notified when I publish new articles on data and AI, private equity, technology, and more.

