Agentic AI Performance
Performance optimization strategies for building high-performance AI agents with PHP MCP SDK.
Overview
This guide covers performance considerations specific to agentic AI systems, including optimization techniques for agent reasoning, tool execution, and multi-agent coordination.
Agent Performance Fundamentals
Response Time Optimization
php
<?php
// src/AgenticAI/Performance/ResponseOptimizer.php
class ResponseOptimizer
{
private CacheManager $cache;
private array $optimizationStrategies = [];
public function __construct(CacheManager $cache)
{
$this->cache = $cache;
$this->initializeStrategies();
}
private function initializeStrategies(): void
{
$this->optimizationStrategies = [
'cache_responses' => true,
'parallel_execution' => true,
'lazy_loading' => true,
'response_compression' => true,
'streaming_responses' => false,
];
}
public function optimizeAgentResponse(string $agentId, string $query, callable $responseGenerator): array
{
$startTime = microtime(true);
// Try cache first
if ($this->optimizationStrategies['cache_responses']) {
$cacheKey = $this->generateCacheKey($agentId, $query);
$cachedResponse = $this->cache->get($cacheKey);
if ($cachedResponse !== null) {
return [
'response' => $cachedResponse,
'cached' => true,
'execution_time' => microtime(true) - $startTime,
];
}
}
// Generate response with optimizations
$response = $this->executeWithOptimizations($responseGenerator);
// Cache the response
if ($this->optimizationStrategies['cache_responses']) {
$this->cache->set($cacheKey, $response, 3600); // Cache for 1 hour
}
return [
'response' => $response,
'cached' => false,
'execution_time' => microtime(true) - $startTime,
];
}
private function executeWithOptimizations(callable $responseGenerator): array
{
if ($this->optimizationStrategies['parallel_execution']) {
return $this->executeInParallel($responseGenerator);
}
return $responseGenerator();
}
private function executeInParallel(callable $responseGenerator): array
{
// Implement parallel execution using ReactPHP or similar
$promises = [];
// Break down the response generation into parallel tasks
$tasks = $this->identifyParallelTasks($responseGenerator);
foreach ($tasks as $task) {
$promises[] = $this->executeAsync($task);
}
// Wait for all tasks to complete
$results = Promise::all($promises)->wait();
// Combine results
return $this->combineResults($results);
}
private function generateCacheKey(string $agentId, string $query): string
{
return "agent_response:{$agentId}:" . hash('sha256', $query);
}
}
Memory-Efficient Agent Processing
php
<?php
// src/AgenticAI/Performance/MemoryEfficientAgent.php
class MemoryEfficientAgent
{
private array $contextWindow = [];
private int $maxContextSize;
private array $compressionStrategies = [];
public function __construct(int $maxContextSize = 1000)
{
$this->maxContextSize = $maxContextSize;
$this->initializeCompressionStrategies();
}
private function initializeCompressionStrategies(): void
{
$this->compressionStrategies = [
'summarization' => new ContextSummarizer(),
'pruning' => new ContextPruner(),
'compression' => new ContextCompressor(),
];
}
public function processWithMemoryManagement(array $input, array $context = []): array
{
$startMemory = memory_get_usage(true);
try {
// Manage context window
$optimizedContext = $this->manageContextWindow($context);
// Process with optimized context
$result = $this->processInput($input, $optimizedContext);
// Update context window
$this->updateContextWindow($input, $result);
return [
'result' => $result,
'memory_used' => memory_get_usage(true) - $startMemory,
'context_size' => count($optimizedContext),
];
} finally {
// Force garbage collection
if (function_exists('gc_collect_cycles')) {
gc_collect_cycles();
}
}
}
private function manageContextWindow(array $context): array
{
if (count($context) <= $this->maxContextSize) {
return $context;
}
// Apply compression strategies
$compressed = $context;
foreach ($this->compressionStrategies as $strategy) {
if (count($compressed) <= $this->maxContextSize) {
break;
}
$compressed = $strategy->compress($compressed, $this->maxContextSize);
}
return $compressed;
}
private function processInput(array $input, array $context): array
{
// Implement efficient processing logic
// This would typically involve AI model inference
return [
'processed_input' => $input,
'context_used' => count($context),
'processing_time' => microtime(true),
];
}
private function updateContextWindow(array $input, array $result): void
{
$this->contextWindow[] = [
'input' => $input,
'result' => $result,
'timestamp' => time(),
];
// Maintain window size
while (count($this->contextWindow) > $this->maxContextSize) {
array_shift($this->contextWindow);
}
}
public function getMemoryStats(): array
{
return [
'context_window_size' => count($this->contextWindow),
'max_context_size' => $this->maxContextSize,
'memory_usage' => memory_get_usage(true),
'peak_memory' => memory_get_peak_usage(true),
];
}
}
class ContextSummarizer
{
public function compress(array $context, int $targetSize): array
{
if (count($context) <= $targetSize) {
return $context;
}
// Group similar contexts and summarize
$groups = $this->groupSimilarContexts($context);
$summarized = [];
foreach ($groups as $group) {
if (count($group) > 1) {
$summarized[] = $this->summarizeGroup($group);
} else {
$summarized[] = $group[0];
}
}
return array_slice($summarized, -$targetSize);
}
private function groupSimilarContexts(array $context): array
{
// Simple grouping by similarity (could use more sophisticated methods)
$groups = [];
foreach ($context as $item) {
$found = false;
foreach ($groups as &$group) {
if ($this->isSimilar($item, $group[0])) {
$group[] = $item;
$found = true;
break;
}
}
if (!$found) {
$groups[] = [$item];
}
}
return $groups;
}
private function isSimilar(array $item1, array $item2): bool
{
// Simple similarity check (could be enhanced)
$text1 = json_encode($item1);
$text2 = json_encode($item2);
similar_text($text1, $text2, $percent);
return $percent > 70; // 70% similarity threshold
}
private function summarizeGroup(array $group): array
{
// Create a summary of the group
return [
'type' => 'summary',
'original_count' => count($group),
'summary' => 'Summarized ' . count($group) . ' similar items',
'timestamp' => time(),
];
}
}
Tool Execution Performance
Parallel Tool Execution
php
<?php
// src/AgenticAI/Performance/ParallelToolExecutor.php
class ParallelToolExecutor
{
private array $tools = [];
private int $maxConcurrency;
private EventLoop $eventLoop;
public function __construct(int $maxConcurrency = 10)
{
$this->maxConcurrency = $maxConcurrency;
$this->eventLoop = Factory::create();
}
public function registerTool(string $name, callable $tool): void
{
$this->tools[$name] = $tool;
}
public function executeToolsInParallel(array $toolCalls): array
{
$promises = [];
$semaphore = new Semaphore($this->maxConcurrency);
foreach ($toolCalls as $index => $toolCall) {
$promises[$index] = $semaphore->acquire()->then(function () use ($toolCall, $semaphore) {
return $this->executeToolAsync($toolCall)->always(function () use ($semaphore) {
$semaphore->release();
});
});
}
return Promise::all($promises)->wait();
}
private function executeToolAsync(array $toolCall): Promise
{
return new Promise(function ($resolve, $reject) use ($toolCall) {
$toolName = $toolCall['name'];
$parameters = $toolCall['parameters'] ?? [];
if (!isset($this->tools[$toolName])) {
$reject(new InvalidArgumentException("Tool '{$toolName}' not found"));
return;
}
try {
$startTime = microtime(true);
$result = ($this->tools[$toolName])($parameters);
$executionTime = microtime(true) - $startTime;
$resolve([
'tool' => $toolName,
'result' => $result,
'execution_time' => $executionTime,
'success' => true,
]);
} catch (Exception $e) {
$resolve([
'tool' => $toolName,
'error' => $e->getMessage(),
'execution_time' => microtime(true) - $startTime,
'success' => false,
]);
}
});
}
public function executeBatchWithPriority(array $toolCalls, array $priorities = []): array
{
// Sort by priority
usort($toolCalls, function ($a, $b) use ($priorities) {
$priorityA = $priorities[$a['name']] ?? 0;
$priorityB = $priorities[$b['name']] ?? 0;
return $priorityB <=> $priorityA; // Higher priority first
});
return $this->executeToolsInParallel($toolCalls);
}
public function getExecutionStats(): array
{
return [
'registered_tools' => count($this->tools),
'max_concurrency' => $this->maxConcurrency,
'memory_usage' => memory_get_usage(true),
];
}
}
class Semaphore
{
private int $permits;
private array $waitingQueue = [];
public function __construct(int $permits)
{
$this->permits = $permits;
}
public function acquire(): Promise
{
if ($this->permits > 0) {
$this->permits--;
return Promise::resolve();
}
return new Promise(function ($resolve) {
$this->waitingQueue[] = $resolve;
});
}
public function release(): void
{
if (!empty($this->waitingQueue)) {
$resolve = array_shift($this->waitingQueue);
$resolve();
} else {
$this->permits++;
}
}
}
Tool Result Caching
php
<?php
// src/AgenticAI/Performance/ToolResultCache.php
class ToolResultCache
{
private CacheInterface $cache;
private array $cacheStrategies = [];
private array $cacheTtls = [];
public function __construct(CacheInterface $cache)
{
$this->cache = $cache;
$this->initializeDefaultStrategies();
}
private function initializeDefaultStrategies(): void
{
$this->cacheStrategies = [
'deterministic' => true, // Cache deterministic tools
'expensive' => true, // Cache expensive operations
'frequent' => true, // Cache frequently used tools
];
$this->cacheTtls = [
'default' => 3600, // 1 hour
'expensive' => 86400, // 24 hours
'frequent' => 1800, // 30 minutes
];
}
public function setCachingStrategy(string $toolName, array $strategy): void
{
$this->cacheStrategies[$toolName] = $strategy;
}
public function setCacheTtl(string $toolName, int $ttl): void
{
$this->cacheTtls[$toolName] = $ttl;
}
public function executeWithCache(string $toolName, array $parameters, callable $toolFunction): array
{
if (!$this->shouldCache($toolName, $parameters)) {
return $this->executeDirectly($toolFunction, $parameters);
}
$cacheKey = $this->generateCacheKey($toolName, $parameters);
$cachedResult = $this->cache->get($cacheKey);
if ($cachedResult !== null) {
return [
'result' => $cachedResult['result'],
'cached' => true,
'cache_hit' => true,
'execution_time' => 0,
'original_execution_time' => $cachedResult['execution_time'],
];
}
// Execute and cache
$result = $this->executeDirectly($toolFunction, $parameters);
if ($result['success']) {
$ttl = $this->getCacheTtl($toolName);
$this->cache->set($cacheKey, [
'result' => $result['result'],
'execution_time' => $result['execution_time'],
'timestamp' => time(),
], $ttl);
}
$result['cached'] = true;
$result['cache_hit'] = false;
return $result;
}
private function shouldCache(string $toolName, array $parameters): bool
{
$strategy = $this->cacheStrategies[$toolName] ?? $this->cacheStrategies;
// Check if tool is deterministic
if (isset($strategy['deterministic']) && !$strategy['deterministic']) {
return false;
}
// Check if parameters contain non-cacheable data
if ($this->containsNonCacheableData($parameters)) {
return false;
}
return true;
}
private function containsNonCacheableData(array $parameters): bool
{
$nonCacheableKeys = ['timestamp', 'random', 'nonce', 'current_time'];
foreach ($parameters as $key => $value) {
if (in_array(strtolower($key), $nonCacheableKeys)) {
return true;
}
if (is_array($value) && $this->containsNonCacheableData($value)) {
return true;
}
}
return false;
}
private function generateCacheKey(string $toolName, array $parameters): string
{
// Sort parameters for consistent cache keys
ksort($parameters);
return "tool_cache:{$toolName}:" . hash('sha256', json_encode($parameters));
}
private function getCacheTtl(string $toolName): int
{
return $this->cacheTtls[$toolName] ?? $this->cacheTtls['default'];
}
private function executeDirectly(callable $toolFunction, array $parameters): array
{
$startTime = microtime(true);
try {
$result = $toolFunction($parameters);
return [
'result' => $result,
'success' => true,
'execution_time' => microtime(true) - $startTime,
];
} catch (Exception $e) {
return [
'error' => $e->getMessage(),
'success' => false,
'execution_time' => microtime(true) - $startTime,
];
}
}
public function invalidateToolCache(string $toolName): bool
{
$pattern = "tool_cache:{$toolName}:*";
// This would need to be implemented based on your cache backend
// For Redis: $this->cache->deletePattern($pattern);
return true;
}
public function getCacheStats(): array
{
return [
'cache_strategies' => count($this->cacheStrategies),
'configured_ttls' => count($this->cacheTtls),
'memory_usage' => memory_get_usage(true),
];
}
}
Multi-Agent Performance
Agent Coordination Optimization
php
<?php
// src/AgenticAI/Performance/AgentCoordinator.php
class AgentCoordinator
{
private array $agents = [];
private array $taskQueue = [];
private array $completedTasks = [];
private int $maxConcurrentAgents;
public function __construct(int $maxConcurrentAgents = 5)
{
$this->maxConcurrentAgents = $maxConcurrentAgents;
}
public function registerAgent(string $agentId, AgentInterface $agent, array $capabilities = []): void
{
$this->agents[$agentId] = [
'agent' => $agent,
'capabilities' => $capabilities,
'status' => 'idle',
'current_task' => null,
'performance_stats' => [
'tasks_completed' => 0,
'average_execution_time' => 0,
'error_rate' => 0,
],
];
}
public function distributeTasks(array $tasks): array
{
$startTime = microtime(true);
// Analyze tasks and assign to optimal agents
$assignments = $this->optimizeTaskAssignment($tasks);
// Execute tasks in parallel
$results = $this->executeTasksInParallel($assignments);
// Update performance statistics
$this->updatePerformanceStats($results);
return [
'results' => $results,
'execution_time' => microtime(true) - $startTime,
'task_count' => count($tasks),
'agent_utilization' => $this->calculateAgentUtilization(),
];
}
private function optimizeTaskAssignment(array $tasks): array
{
$assignments = [];
foreach ($tasks as $task) {
$bestAgent = $this->findBestAgentForTask($task);
if ($bestAgent) {
$assignments[] = [
'agent_id' => $bestAgent,
'task' => $task,
'priority' => $task['priority'] ?? 0,
];
}
}
// Sort by priority
usort($assignments, fn($a, $b) => $b['priority'] <=> $a['priority']);
return $assignments;
}
private function findBestAgentForTask(array $task): ?string
{
$requiredCapabilities = $task['required_capabilities'] ?? [];
$candidates = [];
foreach ($this->agents as $agentId => $agentData) {
if ($agentData['status'] === 'busy') {
continue;
}
// Check if agent has required capabilities
$hasCapabilities = true;
foreach ($requiredCapabilities as $capability) {
if (!in_array($capability, $agentData['capabilities'])) {
$hasCapabilities = false;
break;
}
}
if ($hasCapabilities) {
$candidates[$agentId] = $this->calculateAgentScore($agentId, $task);
}
}
if (empty($candidates)) {
return null;
}
// Return agent with highest score
arsort($candidates);
return array_key_first($candidates);
}
private function calculateAgentScore(string $agentId, array $task): float
{
$agentData = $this->agents[$agentId];
$stats = $agentData['performance_stats'];
$score = 100; // Base score
// Factor in performance metrics
$score += (1 - $stats['error_rate']) * 50; // Lower error rate = higher score
$score -= $stats['average_execution_time']; // Faster execution = higher score
$score += $stats['tasks_completed'] * 0.1; // Experience bonus
// Factor in task complexity
$complexity = $task['complexity'] ?? 1;
$score -= $complexity * 10;
return $score;
}
private function executeTasksInParallel(array $assignments): array
{
$promises = [];
$activeAgents = 0;
foreach ($assignments as $assignment) {
if ($activeAgents >= $this->maxConcurrentAgents) {
// Wait for an agent to become available
Promise::race($promises)->wait();
$activeAgents--;
}
$promises[] = $this->executeTaskAsync($assignment);
$activeAgents++;
}
// Wait for all tasks to complete
return Promise::all($promises)->wait();
}
private function executeTaskAsync(array $assignment): Promise
{
return new Promise(function ($resolve) use ($assignment) {
$agentId = $assignment['agent_id'];
$task = $assignment['task'];
$this->agents[$agentId]['status'] = 'busy';
$this->agents[$agentId]['current_task'] = $task;
$startTime = microtime(true);
try {
$agent = $this->agents[$agentId]['agent'];
$result = $agent->executeTask($task);
$executionTime = microtime(true) - $startTime;
$resolve([
'agent_id' => $agentId,
'task_id' => $task['id'] ?? uniqid(),
'result' => $result,
'execution_time' => $executionTime,
'success' => true,
]);
} catch (Exception $e) {
$resolve([
'agent_id' => $agentId,
'task_id' => $task['id'] ?? uniqid(),
'error' => $e->getMessage(),
'execution_time' => microtime(true) - $startTime,
'success' => false,
]);
} finally {
$this->agents[$agentId]['status'] = 'idle';
$this->agents[$agentId]['current_task'] = null;
}
});
}
private function updatePerformanceStats(array $results): void
{
foreach ($results as $result) {
$agentId = $result['agent_id'];
$stats = &$this->agents[$agentId]['performance_stats'];
$stats['tasks_completed']++;
// Update average execution time
$currentAvg = $stats['average_execution_time'];
$newTime = $result['execution_time'];
$count = $stats['tasks_completed'];
$stats['average_execution_time'] = (($currentAvg * ($count - 1)) + $newTime) / $count;
// Update error rate
if (!$result['success']) {
$errorCount = $stats['error_rate'] * ($count - 1) + 1;
$stats['error_rate'] = $errorCount / $count;
} else {
$errorCount = $stats['error_rate'] * ($count - 1);
$stats['error_rate'] = $errorCount / $count;
}
}
}
private function calculateAgentUtilization(): array
{
$utilization = [];
foreach ($this->agents as $agentId => $agentData) {
$stats = $agentData['performance_stats'];
$utilization[$agentId] = [
'status' => $agentData['status'],
'tasks_completed' => $stats['tasks_completed'],
'average_execution_time' => $stats['average_execution_time'],
'error_rate' => $stats['error_rate'] * 100, // Convert to percentage
];
}
return $utilization;
}
public function getPerformanceReport(): array
{
return [
'total_agents' => count($this->agents),
'active_agents' => count(array_filter($this->agents, fn($a) => $a['status'] === 'busy')),
'agent_utilization' => $this->calculateAgentUtilization(),
'system_performance' => [
'memory_usage' => memory_get_usage(true),
'peak_memory' => memory_get_peak_usage(true),
],
];
}
}
interface AgentInterface
{
public function executeTask(array $task): array;
public function getCapabilities(): array;
public function getStatus(): string;
}
Performance Monitoring
AI-Specific Metrics
php
<?php
// src/AgenticAI/Performance/AiMetricsCollector.php
class AiMetricsCollector
{
private PrometheusMetrics $metrics;
private array $customMetrics = [];
public function __construct(PrometheusMetrics $metrics)
{
$this->metrics = $metrics;
$this->registerAiMetrics();
}
private function registerAiMetrics(): void
{
// Agent-specific metrics
$this->metrics->registerCounter(
'ai_agent_requests_total',
'Total number of agent requests',
['agent_id', 'status']
);
$this->metrics->registerHistogram(
'ai_agent_response_time_seconds',
'Agent response time in seconds',
['agent_id'],
[0.1, 0.5, 1, 2, 5, 10, 30]
);
$this->metrics->registerGauge(
'ai_agent_memory_usage_bytes',
'Agent memory usage in bytes',
['agent_id']
);
// Tool execution metrics
$this->metrics->registerCounter(
'ai_tool_executions_total',
'Total number of tool executions',
['tool_name', 'agent_id', 'status']
);
$this->metrics->registerHistogram(
'ai_tool_execution_time_seconds',
'Tool execution time in seconds',
['tool_name'],
[0.01, 0.1, 0.5, 1, 2, 5]
);
// Context management metrics
$this->metrics->registerGauge(
'ai_context_window_size',
'Current context window size',
['agent_id']
);
$this->metrics->registerCounter(
'ai_context_compressions_total',
'Total number of context compressions',
['agent_id', 'strategy']
);
}
public function recordAgentRequest(string $agentId, float $responseTime, bool $success): void
{
$status = $success ? 'success' : 'error';
$this->metrics->incrementCounter('ai_agent_requests_total', [$agentId, $status]);
$this->metrics->recordHistogram('ai_agent_response_time_seconds', $responseTime, [$agentId]);
// Record memory usage
$memoryUsage = memory_get_usage(true);
$this->metrics->setGauge('ai_agent_memory_usage_bytes', $memoryUsage, [$agentId]);
}
public function recordToolExecution(string $toolName, string $agentId, float $executionTime, bool $success): void
{
$status = $success ? 'success' : 'error';
$this->metrics->incrementCounter('ai_tool_executions_total', [$toolName, $agentId, $status]);
$this->metrics->recordHistogram('ai_tool_execution_time_seconds', $executionTime, [$toolName]);
}
public function recordContextMetrics(string $agentId, int $contextSize, string $compressionStrategy = null): void
{
$this->metrics->setGauge('ai_context_window_size', $contextSize, [$agentId]);
if ($compressionStrategy) {
$this->metrics->incrementCounter('ai_context_compressions_total', [$agentId, $compressionStrategy]);
}
}
public function recordCustomMetric(string $name, $value, array $labels = []): void
{
$this->customMetrics[$name] = [
'value' => $value,
'labels' => $labels,
'timestamp' => time(),
];
}
public function getPerformanceInsights(): array
{
return [
'top_performing_agents' => $this->getTopPerformingAgents(),
'slowest_tools' => $this->getSlowestTools(),
'memory_usage_trends' => $this->getMemoryUsageTrends(),
'error_patterns' => $this->getErrorPatterns(),
];
}
private function getTopPerformingAgents(): array
{
// This would query the metrics backend to get top performing agents
// For now, return mock data
return [
'agent_1' => ['avg_response_time' => 0.5, 'success_rate' => 98.5],
'agent_2' => ['avg_response_time' => 0.7, 'success_rate' => 97.2],
'agent_3' => ['avg_response_time' => 0.9, 'success_rate' => 96.8],
];
}
private function getSlowestTools(): array
{
return [
'database_query' => ['avg_time' => 2.3, 'executions' => 1250],
'api_call' => ['avg_time' => 1.8, 'executions' => 890],
'file_processing' => ['avg_time' => 1.2, 'executions' => 456],
];
}
private function getMemoryUsageTrends(): array
{
return [
'current_usage' => memory_get_usage(true),
'peak_usage' => memory_get_peak_usage(true),
'trend' => 'increasing', // This would be calculated from historical data
];
}
private function getErrorPatterns(): array
{
return [
'timeout_errors' => 15,
'authentication_errors' => 8,
'validation_errors' => 23,
'system_errors' => 4,
];
}
}
Performance Best Practices
1. Response Optimization
- Implement intelligent caching strategies
- Use parallel processing where possible
- Optimize context window management
- Implement response streaming for long operations
2. Memory Management
- Monitor and limit memory usage
- Implement context compression
- Use garbage collection strategically
- Pool resources where possible
3. Tool Execution
- Cache deterministic tool results
- Execute tools in parallel when possible
- Implement timeout and retry mechanisms
- Monitor tool performance metrics
4. Multi-Agent Coordination
- Optimize task assignment algorithms
- Balance agent workloads
- Implement efficient communication patterns
- Monitor system-wide performance
Next Steps
- Security - AI security considerations
- Multi-Agent Systems - Advanced coordination patterns
- Best Practices - General AI development guidelines
Optimize your AI agents for maximum performance! ⚡