This tutorial will guide you through building a production-ready multi-agent coordination system using the CoordinatorAgent. You'll learn how to create specialized agents, implement intelligent task routing, optimize load balancing, and monitor system performance.
By the end of this tutorial, you'll be able to:
- Create and register specialized worker agents
- Implement intelligent task delegation based on capabilities
- Monitor and optimize workload distribution
- Track agent performance metrics
- Build complex multi-stage workflows
- Handle edge cases and errors gracefully
- PHP 8.1 or higher
- Composer
- Claude API key (Anthropic)
- Basic understanding of object-oriented PHP
- Familiarity with agent concepts
- Getting Started
- Creating Your First Coordinator
- Registering Specialized Agents
- Task Delegation and Routing
- Load Balancing
- Performance Monitoring
- Building Complex Workflows
- Production Best Practices
First, ensure you have the claude-php-agent package installed:
composer require claude-php-agentCreate a simple script to test the CoordinatorAgent:
<?php
require_once 'vendor/autoload.php';
use ClaudeAgents\Agents\CoordinatorAgent;
use ClaudeAgents\Agents\WorkerAgent;
use ClaudePhp\ClaudePhp;
// Initialize the Claude client
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
// Create the coordinator
$coordinator = new CoordinatorAgent($client, [
'name' => 'tutorial_coordinator',
]);
echo "Coordinator agent ready!\n";The CoordinatorAgent acts as a smart task router that:
- Analyzes incoming tasks to determine what capabilities are needed
- Matches tasks to agents based on their registered capabilities
- Balances workload across agents with similar capabilities
- Tracks performance and provides analytics
use ClaudeAgents\Agents\CoordinatorAgent;
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp(apiKey: getenv('ANTHROPIC_API_KEY'));
$coordinator = new CoordinatorAgent($client, [
'name' => 'main_coordinator',
'model' => 'claude-sonnet-4-5',
'max_tokens' => 256,
]);Configuration Options:
name: Unique identifier for logging and trackingmodel: AI model used for task analysis (default: claude-sonnet-4-5)max_tokens: Token limit for requirement analysis (default: 256)logger: PSR-3 logger for debugging
echo "Coordinator: " . $coordinator->getName() . "\n";
echo "Registered agents: " . count($coordinator->getAgentIds()) . "\n";Worker agents are specialized components that handle specific types of tasks. Let's create several:
use ClaudeAgents\Agents\WorkerAgent;
// Software Developer Agent
$coderAgent = new WorkerAgent($client, [
'name' => 'software_developer',
'specialty' => 'software development, coding, algorithms, and implementation',
'system' => 'You are an expert software developer with deep knowledge of ' .
'algorithms, design patterns, and best practices. Write clean, ' .
'efficient, well-documented code.',
'model' => 'claude-sonnet-4-5',
'max_tokens' => 2048,
]);
// QA Engineer Agent
$testerAgent = new WorkerAgent($client, [
'name' => 'qa_engineer',
'specialty' => 'quality assurance, testing, test automation, and bug detection',
'system' => 'You are a QA expert specializing in comprehensive test coverage, ' .
'edge case detection, and test automation strategies.',
]);
// Technical Writer Agent
$writerAgent = new WorkerAgent($client, [
'name' => 'technical_writer',
'specialty' => 'technical documentation, API docs, user guides, and tutorials',
'system' => 'You are a technical writer who creates clear, comprehensive ' .
'documentation that developers love to read.',
]);
// DevOps Engineer Agent
$devopsAgent = new WorkerAgent($client, [
'name' => 'devops_engineer',
'specialty' => 'DevOps, CI/CD, infrastructure, Docker, Kubernetes, deployment',
'system' => 'You are a DevOps expert specializing in cloud infrastructure, ' .
'containerization, and automated deployment pipelines.',
]);The key to effective coordination is defining clear, specific capabilities:
// Register the software developer
$coordinator->registerAgent('coder', $coderAgent, [
'coding',
'programming',
'implementation',
'algorithms',
'software',
'development',
]);
// Register the QA engineer
$coordinator->registerAgent('tester', $testerAgent, [
'testing',
'qa',
'quality assurance',
'test cases',
'test automation',
'bug detection',
]);
// Register the technical writer
$coordinator->registerAgent('writer', $writerAgent, [
'documentation',
'writing',
'technical writing',
'api docs',
'tutorials',
'guides',
]);
// Register the DevOps engineer
$coordinator->registerAgent('devops', $devopsAgent, [
'devops',
'deployment',
'infrastructure',
'ci/cd',
'docker',
'kubernetes',
'cloud',
]);
echo "Registered " . count($coordinator->getAgentIds()) . " agents\n";Good capabilities are:
- Specific and descriptive
- Related to actual skills/domains
- Searchable (think of keywords someone would use)
// ✅ Good
['rest_api', 'graphql', 'database_design', 'sql', 'orm']
// ❌ Poor
['backend', 'stuff', 'things']When you delegate a task, the coordinator:
- Analyzes the task using AI to extract required capabilities
- Scores each agent based on matching capabilities
- Selects the best agent considering both match score and current workload
- Delegates the task to the selected agent
- Tracks the execution and updates metrics
$task = "Write a Python function to implement quicksort algorithm";
$result = $coordinator->run($task);
if ($result->isSuccess()) {
echo "Task completed!\n";
echo "Delegated to: " . $result->getMetadata()['delegated_to'] . "\n";
echo "Answer:\n" . $result->getAnswer() . "\n";
} else {
echo "Task failed: " . $result->getError() . "\n";
}$result = $coordinator->run($task);
// Check success
if ($result->isSuccess()) {
// Get the answer
$answer = $result->getAnswer();
// Get rich metadata
$metadata = $result->getMetadata();
// Who handled it?
$assignedTo = $metadata['delegated_to'];
// What capabilities were detected?
$requirements = $metadata['requirements'];
// How long did it take?
$duration = $metadata['duration'];
// Current workload distribution
$workload = $metadata['workload'];
// Performance of the assigned agent
$performance = $metadata['agent_performance'];
echo "Assigned to: {$assignedTo}\n";
echo "Requirements: " . implode(', ', $requirements) . "\n";
echo "Duration: {$duration}s\n";
echo "Agent has completed {$performance['total_tasks']} total tasks\n";
}$tasks = [
'Implement a binary search tree in PHP',
'Write unit tests for user authentication',
'Create API documentation for user endpoints',
'Set up Docker container for the application',
];
foreach ($tasks as $i => $task) {
echo "\n[Task " . ($i + 1) . "] {$task}\n";
echo str_repeat('-', 70) . "\n";
$result = $coordinator->run($task);
if ($result->isSuccess()) {
$metadata = $result->getMetadata();
echo "✓ Delegated to: {$metadata['delegated_to']}\n";
echo " Duration: " . round($metadata['duration'], 2) . "s\n";
echo " Result preview: " . substr($result->getAnswer(), 0, 100) . "...\n";
} else {
echo "✗ Failed: {$result->getError()}\n";
}
}When multiple agents can handle a task, the coordinator:
- Finds all agents with matching capabilities
- Scores them based on capability match
- Among equally-scored agents, selects the one with lowest workload
// Register two developers with identical capabilities
$dev1 = new WorkerAgent($client, [
'name' => 'dev_1',
'specialty' => 'software development',
'system' => 'You are a software developer.',
]);
$dev2 = new WorkerAgent($client, [
'name' => 'dev_2',
'specialty' => 'software development',
'system' => 'You are a software developer.',
]);
$coordinator->registerAgent('dev1', $dev1, ['coding', 'programming']);
$coordinator->registerAgent('dev2', $dev2, ['coding', 'programming']);
// Send multiple coding tasks
$codingTasks = [
'Implement a stack data structure',
'Create a hash map class',
'Write a merge sort function',
'Implement a linked list',
];
foreach ($codingTasks as $task) {
$result = $coordinator->run($task);
echo "Task: {$task}\n";
echo " → Assigned to: {$result->getMetadata()['delegated_to']}\n";
}
// Check workload distribution
echo "\nWorkload Distribution:\n";
$workload = $coordinator->getWorkload();
foreach ($workload as $agent => $count) {
echo " {$agent}: {$count} tasks\n";
}Expected output:
Task: Implement a stack data structure
→ Assigned to: dev1
Task: Create a hash map class
→ Assigned to: dev2
Task: Write a merge sort function
→ Assigned to: dev1
Task: Implement a linked list
→ Assigned to: dev2
Workload Distribution:
dev1: 2 tasks
dev2: 2 tasks
Create a visual representation of workload:
function visualizeWorkload(array $workload): void
{
$maxLoad = max($workload) ?: 1;
echo "\nWorkload Visualization:\n";
echo str_repeat('=', 70) . "\n";
foreach ($workload as $agent => $load) {
$percentage = ($load / $maxLoad) * 100;
$barLength = (int)($percentage / 3.33); // Scale to 30 chars max
$bar = str_repeat('█', $barLength);
printf(
"%-15s [%-30s] %2d tasks (%.1f%%)\n",
$agent,
$bar,
$load,
($load / array_sum($workload)) * 100
);
}
echo str_repeat('=', 70) . "\n";
}
// Usage
$workload = $coordinator->getWorkload();
visualizeWorkload($workload);The coordinator automatically tracks performance metrics for each agent:
$performance = $coordinator->getPerformance();
foreach ($performance as $agentId => $metrics) {
echo "\n{$agentId} Performance:\n";
echo " Total tasks: {$metrics['total_tasks']}\n";
echo " Successful: {$metrics['successful_tasks']}\n";
$successRate = $metrics['total_tasks'] > 0
? ($metrics['successful_tasks'] / $metrics['total_tasks']) * 100
: 0;
echo " Success rate: " . round($successRate, 1) . "%\n";
echo " Avg duration: " . round($metrics['average_duration'], 3) . "s\n";
}class PerformanceDashboard
{
public function __construct(private CoordinatorAgent $coordinator)
{
}
public function display(): void
{
$this->displayWorkload();
$this->displayPerformance();
$this->displayRecommendations();
}
private function displayWorkload(): void
{
echo "\n╔══════════════════════════════════════════════════════════╗\n";
echo "║ Workload Distribution ║\n";
echo "╚══════════════════════════════════════════════════════════╝\n";
$workload = $this->coordinator->getWorkload();
$total = array_sum($workload);
foreach ($workload as $agent => $count) {
$percentage = $total > 0 ? ($count / $total) * 100 : 0;
$bar = str_repeat('▓', (int)($percentage / 3));
printf(
" %-15s [%-30s] %3d (%.1f%%)\n",
$agent,
$bar,
$count,
$percentage
);
}
}
private function displayPerformance(): void
{
echo "\n╔══════════════════════════════════════════════════════════╗\n";
echo "║ Performance Metrics ║\n";
echo "╚══════════════════════════════════════════════════════════╝\n";
$performance = $this->coordinator->getPerformance();
foreach ($performance as $agentId => $metrics) {
if ($metrics['total_tasks'] === 0) continue;
$successRate = ($metrics['successful_tasks'] / $metrics['total_tasks']) * 100;
$status = $successRate >= 90 ? '✓' : ($successRate >= 70 ? '⚠' : '✗');
echo "\n {$status} {$agentId}:\n";
echo " Tasks: {$metrics['successful_tasks']}/{$metrics['total_tasks']} ";
echo "(" . round($successRate, 1) . "% success)\n";
echo " Avg duration: " . round($metrics['average_duration'], 3) . "s\n";
}
}
private function displayRecommendations(): void
{
echo "\n╔══════════════════════════════════════════════════════════╗\n";
echo "║ Recommendations ║\n";
echo "╚══════════════════════════════════════════════════════════╝\n";
$performance = $this->coordinator->getPerformance();
$workload = $this->coordinator->getWorkload();
// Check for overloaded agents
$avgWorkload = array_sum($workload) / count($workload);
foreach ($workload as $agent => $load) {
if ($load > $avgWorkload * 1.5) {
echo " ⚠ {$agent} is handling {$load} tasks (avg: " . round($avgWorkload, 1) . ")\n";
echo " Consider adding more agents with similar capabilities\n";
}
}
// Check for low success rates
foreach ($performance as $agentId => $metrics) {
if ($metrics['total_tasks'] === 0) continue;
$successRate = ($metrics['successful_tasks'] / $metrics['total_tasks']) * 100;
if ($successRate < 80) {
echo " ⚠ {$agentId} has low success rate: " . round($successRate, 1) . "%\n";
echo " Review agent configuration and capabilities\n";
}
}
// Check for slow agents
foreach ($performance as $agentId => $metrics) {
if ($metrics['average_duration'] > 30) {
echo " ⚠ {$agentId} has high avg duration: " . round($metrics['average_duration'], 1) . "s\n";
echo " Consider optimizing or adding parallel agents\n";
}
}
}
}
// Usage
$dashboard = new PerformanceDashboard($coordinator);
$dashboard->display();Create a complete project workflow with multiple stages:
class ProjectWorkflow
{
public function __construct(private CoordinatorAgent $coordinator)
{
}
public function execute(string $projectName, array $stages): array
{
echo "\n╔══════════════════════════════════════════════════════════╗\n";
echo "║ Project: {$projectName}\n";
echo "╚══════════════════════════════════════════════════════════╝\n";
$results = [];
$totalDuration = 0;
foreach ($stages as $stageName => $tasks) {
echo "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
echo " Stage: {$stageName}\n";
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
$stageResults = [];
$stageDuration = 0;
foreach ($tasks as $i => $task) {
$taskNum = $i + 1;
echo "\n[{$stageName}.{$taskNum}] {$task}\n";
$result = $this->coordinator->run($task);
if ($result->isSuccess()) {
$metadata = $result->getMetadata();
$duration = $metadata['duration'];
$stageDuration += $duration;
echo " ✓ Completed by: {$metadata['delegated_to']}\n";
echo " ⏱ Duration: " . round($duration, 2) . "s\n";
$stageResults[] = [
'task' => $task,
'success' => true,
'agent' => $metadata['delegated_to'],
'duration' => $duration,
];
} else {
echo " ✗ Failed: {$result->getError()}\n";
$stageResults[] = [
'task' => $task,
'success' => false,
'error' => $result->getError(),
];
}
}
$totalDuration += $stageDuration;
echo "\nStage completed in " . round($stageDuration, 2) . "s\n";
$results[$stageName] = [
'tasks' => $stageResults,
'duration' => $stageDuration,
'success_rate' => $this->calculateSuccessRate($stageResults),
];
}
$this->displaySummary($results, $totalDuration);
return $results;
}
private function calculateSuccessRate(array $results): float
{
$successful = count(array_filter($results, fn($r) => $r['success']));
return ($successful / count($results)) * 100;
}
private function displaySummary(array $results, float $totalDuration): void
{
echo "\n╔══════════════════════════════════════════════════════════╗\n";
echo "║ Project Summary ║\n";
echo "╚══════════════════════════════════════════════════════════╝\n";
foreach ($results as $stageName => $stageData) {
$successCount = count(array_filter($stageData['tasks'], fn($t) => $t['success']));
$totalCount = count($stageData['tasks']);
echo "\n {$stageName}:\n";
echo " Tasks: {$successCount}/{$totalCount} completed\n";
echo " Success rate: " . round($stageData['success_rate'], 1) . "%\n";
echo " Duration: " . round($stageData['duration'], 2) . "s\n";
}
echo "\n Total project duration: " . round($totalDuration, 2) . "s\n";
}
}
// Usage
$workflow = new ProjectWorkflow($coordinator);
$projectStages = [
'Planning & Design' => [
'Design the database schema for e-commerce platform',
'Create API endpoint specifications',
'Plan frontend component architecture',
],
'Implementation' => [
'Implement user authentication system',
'Create product catalog API endpoints',
'Build shopping cart functionality',
],
'Testing & QA' => [
'Write unit tests for authentication',
'Create integration tests for checkout flow',
'Perform security audit',
],
'Deployment' => [
'Create Docker containers for services',
'Set up CI/CD pipeline',
'Configure monitoring and alerts',
],
];
$results = $workflow->execute('E-Commerce Platform', $projectStages);class RobustCoordinator
{
public function __construct(
private CoordinatorAgent $coordinator,
private WorkerAgent $fallbackAgent
) {
}
public function runWithFallback(string $task, int $maxRetries = 3): AgentResult
{
$lastError = null;
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
try {
$result = $this->coordinator->run($task);
if ($result->isSuccess()) {
return $result;
}
$lastError = $result->getError();
if ($attempt < $maxRetries) {
echo "Attempt {$attempt} failed, retrying...\n";
sleep(1); // Brief delay before retry
}
} catch (\Exception $e) {
$lastError = $e->getMessage();
if ($attempt >= $maxRetries) {
break;
}
}
}
// Use fallback agent
echo "All retries failed, using fallback agent\n";
return $this->fallbackAgent->run($task);
}
}class MonitoredCoordinator
{
private array $metrics = [];
public function __construct(
private CoordinatorAgent $coordinator,
private float $slowThreshold = 30.0,
private float $lowSuccessThreshold = 0.8
) {
}
public function run(string $task): AgentResult
{
$start = microtime(true);
$result = $this->coordinator->run($task);
$duration = microtime(true) - $start;
$this->recordMetric($task, $result, $duration);
$this->checkThresholds();
return $result;
}
private function recordMetric(string $task, AgentResult $result, float $duration): void
{
$this->metrics[] = [
'task' => substr($task, 0, 50),
'success' => $result->isSuccess(),
'duration' => $duration,
'timestamp' => time(),
];
// Keep only last 100 metrics
if (count($this->metrics) > 100) {
array_shift($this->metrics);
}
}
private function checkThresholds(): void
{
if (empty($this->metrics)) return;
$recent = array_slice($this->metrics, -10);
// Check success rate
$successCount = count(array_filter($recent, fn($m) => $m['success']));
$successRate = $successCount / count($recent);
if ($successRate < $this->lowSuccessThreshold) {
$this->alert("Low success rate: " . round($successRate * 100, 1) . "%");
}
// Check average duration
$avgDuration = array_sum(array_column($recent, 'duration')) / count($recent);
if ($avgDuration > $this->slowThreshold) {
$this->alert("Slow performance: avg " . round($avgDuration, 1) . "s");
}
}
private function alert(string $message): void
{
error_log("[COORDINATOR ALERT] {$message}");
// Send to monitoring system, Slack, email, etc.
}
}class CapabilityManager
{
private const PRESETS = [
'backend' => [
'backend', 'api', 'rest', 'graphql', 'database',
'sql', 'orm', 'server', 'microservices'
],
'frontend' => [
'frontend', 'ui', 'ux', 'react', 'vue', 'angular',
'css', 'html', 'javascript', 'responsive'
],
'devops' => [
'devops', 'ci/cd', 'docker', 'kubernetes', 'terraform',
'deployment', 'infrastructure', 'monitoring', 'cloud'
],
'qa' => [
'testing', 'qa', 'test automation', 'selenium',
'unit tests', 'integration tests', 'e2e tests'
],
'security' => [
'security', 'penetration testing', 'vulnerability',
'authentication', 'authorization', 'encryption'
],
];
public static function getCapabilities(string $preset): array
{
return self::PRESETS[$preset] ?? [];
}
public static function merge(string ...$presets): array
{
$capabilities = [];
foreach ($presets as $preset) {
$capabilities = array_merge($capabilities, self::getCapabilities($preset));
}
return array_unique($capabilities);
}
}
// Usage
$coordinator->registerAgent(
'fullstack_dev',
$fullstackAgent,
CapabilityManager::merge('backend', 'frontend')
);use Psr\Log\LoggerInterface;
$coordinator = new CoordinatorAgent($client, [
'name' => 'production_coordinator',
'logger' => $logger, // PSR-3 logger
]);
// The coordinator will log:
// - Agent registrations
// - Task delegations
// - Requirement analysis failures
// - Performance issuesclass CoordinatorTester
{
public function __construct(private CoordinatorAgent $coordinator)
{
}
public function testConfiguration(): void
{
echo "Testing coordinator configuration...\n\n";
$testTasks = [
'Write a function' => 'coding',
'Create test cases' => 'testing',
'Write documentation' => 'documentation',
'Set up deployment' => 'devops',
];
foreach ($testTasks as $task => $expectedCapability) {
$result = $this->coordinator->run($task);
if ($result->isSuccess()) {
$agent = $result->getMetadata()['delegated_to'];
$capabilities = $this->coordinator->getAgentCapabilities($agent);
if (in_array($expectedCapability, $capabilities)) {
echo "✓ '{$task}' → {$agent} ✓\n";
} else {
echo "⚠ '{$task}' → {$agent} (unexpected)\n";
}
} else {
echo "✗ '{$task}' → FAILED: {$result->getError()}\n";
}
}
}
}
// Run tests
$tester = new CoordinatorTester($coordinator);
$tester->testConfiguration();You now have a comprehensive understanding of the CoordinatorAgent! You've learned:
✅ How to create and configure a coordinator
✅ Registering specialized agents with clear capabilities
✅ Intelligent task delegation and routing
✅ Load balancing across agents
✅ Performance monitoring and analytics
✅ Building complex multi-stage workflows
✅ Production best practices and error handling
- Review the CoordinatorAgent API Documentation
- Check out the examples directory for more code
- Explore multi-agent patterns
- Build your own custom agents
- Integrate with your existing systems
- CoordinatorAgent.md - Complete API reference
- coordinator_agent.php - Basic example
- advanced_coordinator.php - Advanced patterns
- Agent Selection Guide
Happy coordinating! 🎯