Welcome to this comprehensive tutorial on using the PlanExecuteAgent! The plan-execute pattern is a powerful approach for handling complex, multi-step tasks by systematically breaking them down into manageable pieces.
- Introduction
- What is the Plan-Execute Pattern?
- Setup
- Tutorial 1: Your First Plan-Execute Agent
- Tutorial 2: Understanding the Execution Flow
- Tutorial 3: Adding Tools to Plans
- Tutorial 4: Adaptive Replanning
- Tutorial 5: Multi-Tool Coordination
- Tutorial 6: Complex Workflows
- Tutorial 7: Production Best Practices
- Common Patterns
- Troubleshooting
- Next Steps
This tutorial will teach you how to leverage the plan-execute pattern to solve complex tasks systematically. By the end, you'll be able to:
- Understand when and why to use plan-execute agents
- Create detailed execution plans automatically
- Coordinate multiple tools in sequence
- Handle adaptive replanning based on results
- Build production-ready planning systems
The plan-execute pattern separates task completion into distinct phases:
User: "Create a marketing report with sales analysis"
Agent: [Attempts everything at once] → Result
User: "Create a marketing report with sales analysis"
Agent:
Phase 1 - Planning:
1. Gather sales data for the period
2. Analyze trends and patterns
3. Create visualizations
4. Write executive summary
5. Compile final report
Phase 2 - Execution:
Execute Step 1 → Execute Step 2 → ... → Execute Step 5
Phase 3 - Synthesis:
Combine all results → Final comprehensive report
- Visibility: See exactly what steps will be taken
- Reliability: Systematic execution reduces errors
- Context: Each step gets results from previous steps
- Adaptability: Can revise plan based on results
- Debugging: Easy to identify where things went wrong
First, install the package and set up your API key:
composer require claude-php-agentSet your Anthropic API key:
export ANTHROPIC_API_KEY='your-api-key-here'Or create a .env file:
ANTHROPIC_API_KEY=your-api-key-hereLet's create a simple plan-execute agent to handle a multi-step task.
Create a file my_first_planner.php:
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudePhp\ClaudePhp;
// Initialize the Claude client
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
// Create a plan-execute agent
$agent = new PlanExecuteAgent($client);
// Define a multi-step task
$task = "Write a brief product announcement email for a new productivity app. " .
"Include: catchy subject line, brief intro, 3 key features, " .
"call-to-action, and closing.";
// Run the agent
$result = $agent->run($task);
// Check the results
if ($result->isSuccess()) {
echo "=== FINAL EMAIL ===\n";
echo $result->getAnswer() . "\n\n";
// View execution details
$metadata = $result->getMetadata();
echo "Execution Summary:\n";
echo "- Steps in plan: {$metadata['plan_steps']}\n";
echo "- Total iterations: {$result->getIterations()}\n";
$usage = $result->getTokenUsage();
echo "- Tokens used: {$usage['total']}\n";
} else {
echo "Error: " . $result->getError() . "\n";
}-
Planning: Agent creates a structured plan
1. Create a compelling subject line (under 50 characters) 2. Write an engaging opening paragraph 3. List and explain 3 key features 4. Write a clear call-to-action 5. Add a professional closing -
Execution: Each step is executed with context
- Step 1 creates the subject line
- Step 2 uses the subject line for context
- Step 3 builds on the intro
- And so on...
-
Synthesis: All pieces are assembled into the final email
php my_first_planner.phpYou'll see a complete email with all components, plus metadata about how it was created.
Let's examine what happens during each phase in detail.
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
$agent = new PlanExecuteAgent($client, [
'name' => 'detailed_planner',
]);
$task = "Create a simple 3-step morning routine guide for busy professionals.";
$result = $agent->run($task);
if ($result->isSuccess()) {
echo "=== FINAL GUIDE ===\n";
echo $result->getAnswer() . "\n\n";
// Detailed step breakdown
$metadata = $result->getMetadata();
echo "=== EXECUTION BREAKDOWN ===\n\n";
foreach ($metadata['step_results'] as $step) {
echo "Step {$step['step']}: {$step['description']}\n";
echo str_repeat('-', 70) . "\n";
echo $step['result'] . "\n";
echo str_repeat('=', 70) . "\n\n";
}
}$usage = $result->getTokenUsage();
echo "Token Analysis:\n";
echo "- Input tokens: {$usage['input']}\n";
echo "- Output tokens: {$usage['output']}\n";
echo "- Total: {$usage['total']}\n\n";
// Cost estimation (approximate rates)
$inputCost = ($usage['input'] / 1000) * 0.003;
$outputCost = ($usage['output'] / 1000) * 0.015;
$totalCost = $inputCost + $outputCost;
echo "Estimated Cost: $" . number_format($totalCost, 4) . "\n";Tools make plan-execute agents much more powerful by providing factual capabilities.
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudeAgents\Tools\Tool;
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
// Create a calculator tool
$calculator = Tool::create('calculator')
->description('Perform mathematical calculations')
->stringParam('expression', 'The math expression to evaluate')
->handler(function (array $input): string {
$expr = $input['expression'];
// Safe evaluation for basic math
$expr = preg_replace('/[^0-9+\-*\/\(\)\.\s]/', '', $expr);
try {
$result = eval("return {$expr};");
return "Result: " . number_format($result, 2);
} catch (\Throwable $e) {
return "Error: Invalid expression";
}
});
// Create a date tool
$dateInfo = Tool::create('date_info')
->description('Get current date and time information')
->stringParam('info_type', 'Type of info: date, time, day, month, year')
->handler(function (array $input): string {
$type = $input['info_type'] ?? 'date';
switch ($type) {
case 'date':
return date('Y-m-d');
case 'time':
return date('H:i:s');
case 'day':
return date('l'); // Monday, Tuesday, etc.
case 'month':
return date('F'); // January, February, etc.
case 'year':
return date('Y');
default:
return date('Y-m-d H:i:s');
}
});
// Create the agent with tools
$agent = new PlanExecuteAgent($client);
$agent->addTool($calculator);
$agent->addTool($dateInfo);
// Task that requires tools
$task = "Create a financial summary: Calculate quarterly revenue ($45,000 + $52,000 + $48,000), " .
"calculate average per month, and create a summary report with today's date.";
$result = $agent->run($task);
if ($result->isSuccess()) {
echo "=== FINANCIAL SUMMARY ===\n";
echo $result->getAnswer() . "\n";
}The agent's plan will include tool usage:
1. Use calculator to sum quarterly revenue
2. Use calculator to find monthly average
3. Use date_info to get current date
4. Compile summary report with all information
Enable the agent to revise its plan if steps don't go as expected.
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudeAgents\Tools\Tool;
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
// Create a tool that might "fail"
$dataFetch = Tool::create('fetch_sales_data')
->description('Fetch sales data from database')
->stringParam('month', 'Month to fetch data for')
->handler(function (array $input): string {
$month = $input['month'];
// Simulate data not being available for future months
$currentMonth = date('n');
$requestedMonth = date('n', strtotime($month));
if ($requestedMonth > $currentMonth) {
return "Error: Data not available for future months";
}
// Simulated data
return "Sales for {$month}: $" . rand(10000, 50000);
});
$agent = new PlanExecuteAgent($client, [
'allow_replan' => true, // Enable adaptive replanning
]);
$agent->addTool($dataFetch);
$task = "Analyze sales trends: Fetch data for the past 3 months and calculate growth rate.";
echo "Running with adaptive replanning enabled...\n\n";
$result = $agent->run($task);
if ($result->isSuccess()) {
echo "=== ANALYSIS RESULT ===\n";
echo $result->getAnswer() . "\n\n";
$metadata = $result->getMetadata();
// Check if replanning occurred
$originalSteps = $metadata['plan_steps'];
$actualSteps = count($metadata['step_results']);
if ($actualSteps != $originalSteps) {
echo "⚠️ Note: Plan was adapted during execution\n";
echo "Original plan had {$originalSteps} steps\n";
echo "Actually executed {$actualSteps} steps\n";
}
}- Agent executes a step
- If result contains failure indicators ("error", "unable", "failed")
- Agent creates a revised plan for remaining steps
- Continues with new plan
Original Plan:
1. Fetch January data
2. Fetch February data ← Fails
3. Calculate growth
After Replanning:
1. Fetch January data [completed]
2. Fetch February data [failed]
3. Use January data to estimate February ← New approach
4. Calculate estimated growth
Coordinate multiple tools in a complex workflow.
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudeAgents\Tools\Tool;
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
// Data collection tool
$collectData = Tool::create('collect_survey_data')
->description('Collect survey response data')
->stringParam('survey_id', 'Survey identifier')
->handler(function (array $input): string {
return "Survey responses: 150 total, 120 complete, 30 partial";
});
// Analysis tool
$analyze = Tool::create('analyze_responses')
->description('Analyze survey responses')
->stringParam('data', 'Data to analyze')
->handler(function (array $input): string {
return "Analysis: 85% satisfaction rate, top theme: product quality";
});
// Visualization tool
$visualize = Tool::create('create_chart')
->description('Create data visualization')
->stringParam('chart_type', 'Type of chart: bar, pie, line')
->stringParam('data', 'Data to visualize')
->handler(function (array $input): string {
$type = $input['chart_type'];
return "Created {$type} chart: chart_image_url.png";
});
// Report generation tool
$generateReport = Tool::create('generate_pdf')
->description('Generate PDF report')
->stringParam('content', 'Report content')
->handler(function (array $input): string {
return "PDF generated: survey_report_2024.pdf";
});
// Create agent with all tools
$agent = new PlanExecuteAgent($client, [
'name' => 'survey_analyzer',
'max_tokens' => 4096,
]);
$agent->addTool($collectData)
->addTool($analyze)
->addTool($visualize)
->addTool($generateReport);
$task = "Complete survey analysis workflow: " .
"1) Collect data from survey_2024_q4, " .
"2) Analyze responses for key insights, " .
"3) Create bar chart of satisfaction ratings, " .
"4) Generate PDF report with findings and chart.";
echo "Running multi-tool workflow...\n\n";
$result = $agent->run($task);
if ($result->isSuccess()) {
echo "=== WORKFLOW COMPLETE ===\n";
echo $result->getAnswer() . "\n\n";
// Show tool usage
$metadata = $result->getMetadata();
echo "=== EXECUTION STEPS ===\n";
foreach ($metadata['step_results'] as $step) {
echo "• Step {$step['step']}: {$step['description']}\n";
}
}Plan Created:
1. Use collect_survey_data tool to gather responses
2. Use analyze_responses tool to identify insights
3. Use create_chart tool to visualize satisfaction
4. Use generate_pdf tool to compile final report
Execution:
Step 1: collect_survey_data(survey_2024_q4) → "150 responses..."
Step 2: analyze_responses(previous data) → "85% satisfaction..."
Step 3: create_chart(bar, satisfaction data) → "Created bar chart..."
Step 4: generate_pdf(all content) → "PDF generated..."
Synthesis: "Survey analysis complete. Key findings: ..."
Handle sophisticated multi-phase projects.
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudePhp\ClaudePhp;
use Psr\Log\LoggerInterface;
// Simple console logger
class ConsoleLogger implements LoggerInterface
{
public function log($level, $message, array $context = []): void
{
echo "[{$level}] {$message}\n";
}
public function emergency($message, array $context = []): void
{ $this->log('EMERGENCY', $message, $context); }
public function alert($message, array $context = []): void
{ $this->log('ALERT', $message, $context); }
public function critical($message, array $context = []): void
{ $this->log('CRITICAL', $message, $context); }
public function error($message, array $context = []): void
{ $this->log('ERROR', $message, $context); }
public function warning($message, array $context = []): void
{ $this->log('WARNING', $message, $context); }
public function notice($message, array $context = []): void
{ $this->log('NOTICE', $message, $context); }
public function info($message, array $context = []): void
{ $this->log('INFO', $message, $context); }
public function debug($message, array $context = []): void
{ $this->log('DEBUG', $message, $context); }
}
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
$agent = new PlanExecuteAgent($client, [
'name' => 'project_planner',
'max_tokens' => 4096,
'allow_replan' => true,
'logger' => new ConsoleLogger(),
]);
$task = "Create a comprehensive launch plan for a new mobile app. " .
"Include: market research summary, target audience personas (2-3), " .
"marketing channel strategy, launch timeline (12 weeks), " .
"success metrics, and risk mitigation strategies.";
echo "Creating comprehensive project plan...\n";
echo str_repeat('=', 70) . "\n\n";
$result = $agent->run($task);
if ($result->isSuccess()) {
echo "\n" . str_repeat('=', 70) . "\n";
echo "=== LAUNCH PLAN ===\n";
echo str_repeat('=', 70) . "\n\n";
echo $result->getAnswer() . "\n\n";
// Detailed metrics
$metadata = $result->getMetadata();
$usage = $result->getTokenUsage();
echo str_repeat('=', 70) . "\n";
echo "=== EXECUTION METRICS ===\n";
echo str_repeat('=', 70) . "\n";
echo "Plan Steps: {$metadata['plan_steps']}\n";
echo "Iterations: {$result->getIterations()}\n";
echo "Tokens: {$usage['total']} ({$usage['input']} in, {$usage['output']} out)\n";
echo "Est. Cost: $" . number_format(
($usage['input'] * 0.003 + $usage['output'] * 0.015) / 1000,
4
) . "\n";
}The agent will create a detailed multi-section document:
- Market Research Summary
- Target Audience Personas
- Marketing Channel Strategy
- 12-Week Launch Timeline
- Success Metrics
- Risk Mitigation
Each section builds on previous ones for coherence.
Build robust, production-ready plan-execute systems.
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\PlanExecuteAgent;
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
class ProductionPlanner
{
private PlanExecuteAgent $agent;
private array $stats = [
'total_runs' => 0,
'successful' => 0,
'failed' => 0,
'total_tokens' => 0,
];
public function __construct(ClaudePhp $client)
{
$this->agent = new PlanExecuteAgent($client, [
'name' => 'production_planner',
'max_tokens' => 4096,
'allow_replan' => true,
]);
}
public function executeTask(string $task, int $retries = 3): ?string
{
$this->stats['total_runs']++;
$attempt = 0;
$lastError = null;
while ($attempt < $retries) {
try {
$result = $this->agent->run($task);
if ($result->isSuccess()) {
$this->stats['successful']++;
$usage = $result->getTokenUsage();
$this->stats['total_tokens'] += $usage['total'];
return $result->getAnswer();
}
$lastError = $result->getError();
$attempt++;
if ($attempt < $retries) {
// Exponential backoff
sleep(pow(2, $attempt));
}
} catch (\Throwable $e) {
$lastError = $e->getMessage();
$attempt++;
if ($attempt < $retries) {
sleep(pow(2, $attempt));
}
}
}
$this->stats['failed']++;
error_log("Task failed after {$retries} attempts: {$lastError}");
return null;
}
public function getStats(): array
{
return $this->stats;
}
}
// Usage
$planner = new ProductionPlanner($client);
$tasks = [
"Create a product feature comparison table",
"Write a technical blog post outline",
"Generate FAQ content for customer support",
];
echo "Processing tasks in production mode...\n\n";
foreach ($tasks as $i => $task) {
echo "Task " . ($i + 1) . ": " . substr($task, 0, 50) . "...\n";
$result = $planner->executeTask($task);
if ($result) {
echo "✅ Success\n";
echo substr($result, 0, 100) . "...\n\n";
} else {
echo "❌ Failed\n\n";
}
}
// Show statistics
$stats = $planner->getStats();
echo str_repeat('=', 70) . "\n";
echo "=== SESSION STATISTICS ===\n";
echo "Total tasks: {$stats['total_runs']}\n";
echo "Successful: {$stats['successful']}\n";
echo "Failed: {$stats['failed']}\n";
echo "Total tokens: {$stats['total_tokens']}\n";
echo "Success rate: " . round(($stats['successful'] / $stats['total_runs']) * 100, 1) . "%\n";class PlanExecuteMonitor
{
private array $executions = [];
public function trackExecution(string $taskId, AgentResult $result): void
{
$metadata = $result->getMetadata();
$usage = $result->getTokenUsage();
$this->executions[] = [
'task_id' => $taskId,
'success' => $result->isSuccess(),
'plan_steps' => $metadata['plan_steps'] ?? 0,
'actual_steps' => count($metadata['step_results'] ?? []),
'iterations' => $result->getIterations(),
'tokens' => $usage['total'],
'cost' => ($usage['input'] * 0.003 + $usage['output'] * 0.015) / 1000,
'timestamp' => time(),
];
}
public function generateReport(): string
{
$total = count($this->executions);
$successful = count(array_filter($this->executions, fn($e) => $e['success']));
$avgTokens = array_sum(array_column($this->executions, 'tokens')) / $total;
$totalCost = array_sum(array_column($this->executions, 'cost'));
return "Plan-Execute Report\n" .
"Total executions: {$total}\n" .
"Success rate: " . round(($successful / $total) * 100, 1) . "%\n" .
"Avg tokens per task: " . round($avgTokens) . "\n" .
"Total cost: $" . number_format($totalCost, 4) . "\n";
}
}$agent = new PlanExecuteAgent($client);
$task = "Research topic: 'Benefits of microservices architecture'. " .
"Create: 1) Key benefits list, 2) Common challenges, " .
"3) Best practices, 4) Executive summary.";
$result = $agent->run($task);$agent = new PlanExecuteAgent($client, [
'tools' => [$fetchTool, $transformTool, $analyzeTool, $exportTool],
]);
$task = "Execute data pipeline: fetch user data, transform to standard format, " .
"analyze for insights, export results to CSV.";
$result = $agent->run($task);$task = "Create blog post: Topic 'Getting Started with PHP 8.3'. " .
"1) Outline with 5 sections, 2) Write intro, " .
"3) Write each section, 4) Add code examples, " .
"5) Write conclusion with CTAs.";
$result = $agent->run($task);$task = "Generate monthly report: 1) Collect metrics, " .
"2) Calculate trends vs last month, 3) Identify top 5 insights, " .
"4) Create executive summary, 5) List recommendations.";
$result = $agent->run($task);Solution: Provide more specific task descriptions:
// ❌ Too vague
$task = "Make a report about sales";
// ✅ Specific
$task = "Create sales report with: 1) Q4 revenue summary, " .
"2) Month-over-month comparison, 3) Top 5 products, " .
"4) Regional breakdown, 5) Forecasts for Q1.";Solution: Enable replanning and trust the synthesis phase:
$agent = new PlanExecuteAgent($client, [
'allow_replan' => true, // Let agent adapt
'max_tokens' => 4096, // Allow detailed synthesis
]);Solution: Optimize configuration:
$agent = new PlanExecuteAgent($client, [
'max_tokens' => 1024, // Shorter responses
'allow_replan' => false, // No replanning overhead
]);
// Break large tasks into smaller ones
$result1 = $agent->run("Part 1: Create outline");
$result2 = $agent->run("Part 2: Write sections based on: " . $result1->getAnswer());Solution: Plan-execute involves multiple API calls. For speed:
// Use regular Agent for simple tasks
$simpleAgent = Agent::create($client);
// Use PlanExecuteAgent only for complex multi-step tasks
if ($isComplex) {
$result = $planExecuteAgent->run($task);
} else {
$result = $simpleAgent->run($task);
}-
Combine with other agents:
// Use CoT for planning, Plan-Execute for execution $planExecute->run("Using chain-of-thought, create detailed plan for: " . $task);
-
Create specialized planners:
class ContentPlanner extends PlanExecuteAgent { /* ... */ } class DataPipeline extends PlanExecuteAgent { /* ... */ }
-
Build workflow libraries:
class WorkflowLibrary { public static function contentCreation(): string { /* ... */ } public static function dataAnalysis(): string { /* ... */ } public static function reportGeneration(): string { /* ... */ } }
- Read the PlanExecuteAgent Documentation
- Explore the Complete Example
- Check out the Agent Selection Guide
- Blog Post Generator: Plan and create complete blog posts with research
- Event Planner: Create comprehensive event plans with timelines
- Data Pipeline: Build multi-step data processing workflows
- Report System: Generate complex analytical reports
You now have a comprehensive understanding of the PlanExecuteAgent! The plan-execute pattern is perfect for:
- ✅ Complex multi-step tasks
- ✅ Sequential tool coordination
- ✅ Tasks requiring visible planning
- ✅ Workflows needing adaptation
Start building systematic, reliable task completion systems today!
This tutorial is part of the claude-php-agent package and is licensed under the MIT License.