πŸ€– AMCP v1.6 Agentic Capabilities: Orchestrator & Mesh Agents

Part 2: Orchestrator Agents, Mesh Agents & Real-World Use Cases


Orchestrator Agents

Definition

Orchestrator agents coordinate multiple agents and manage complex workflows. They decompose tasks, delegate to specialized agents, and aggregate results.

Architecture

User Request
    ↓
Orchestrator Agent
    β”œβ”€ Task Decomposition
    β”œβ”€ Agent Selection
    β”œβ”€ Delegation
    β”œβ”€ Result Aggregation
    └─ Response Generation
    ↓
Final Response

Implementation

@QuarkusMain
public class TravelPlannerOrchestrator extends OrchestratorAgent {
    
    @Inject
    WeatherChatAgent weatherAgent;
    
    @Inject
    StockAnalysisAgent stockAgent;
    
    @Inject
    LLMService llmService;
    
    @Override
    public void initialize(AgentContext context) {
        this.setSystemPrompt("""
            You are a travel planning orchestrator. Your job is to:
            1. Understand user travel requirements
            2. Delegate to specialized agents
            3. Aggregate information
            4. Provide comprehensive travel recommendations
        """);
        
        context.subscribe("travel-requests", this::handleTravelRequest);
    }
    
    private void handleTravelRequest(Message message) {
        String userRequest = message.getPayload();
        
        // Step 1: Parse user request
        TravelRequest request = parseRequest(userRequest);
        
        // Step 2: Decompose into sub-tasks
        List<Task> tasks = decomposeTasks(request);
        
        // Step 3: Delegate to specialized agents
        Map<String, String> results = new HashMap<>();
        
        for (Task task : tasks) {
            if (task.getType() == TaskType.WEATHER) {
                String weatherInfo = weatherAgent.getWeather(task.getLocation());
                results.put("weather", weatherInfo);
            }
            
            if (task.getType() == TaskType.MARKET) {
                String marketInfo = stockAgent.analyzeMarket(task.getSymbol());
                results.put("market", marketInfo);
            }
        }
        
        // Step 4: Aggregate results
        String aggregatedInfo = aggregateResults(results);
        
        // Step 5: Generate comprehensive response
        String response = llmService.chat(
            List.of(
                new Message("system", this.getSystemPrompt()),
                new Message("user", userRequest),
                new Message("context", aggregatedInfo)
            ),
            new ChatConfig()
                .model("gpt-4")
                .temperature(0.8)
                .maxTokens(1500)
        );
        
        this.publish("travel-response", response);
    }
    
    private List<Task> decomposeTasks(TravelRequest request) {
        List<Task> tasks = new ArrayList<>();
        tasks.add(new Task(TaskType.WEATHER, request.getDestination()));
        
        if (request.isBusinessTravel()) {
            tasks.add(new Task(TaskType.MARKET, request.getMarketSymbol()));
        }
        
        return tasks;
    }
    
    private String aggregateResults(Map<String, String> results) {
        StringBuilder sb = new StringBuilder();
        sb.append("Aggregated Information:\n");
        
        for (Map.Entry<String, String> entry : results.entrySet()) {
            sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
        }
        
        return sb.toString();
    }
}

CLI Example: Travel Planner Orchestrator

# Start Travel Planner
$ quarkus dev

# Send travel planning request
$ curl -X POST http://localhost:8080/travel \
  -H "Content-Type: application/json" \
  -d '{
    "request": "I want to travel to Barcelona next week for a business trip. What should I know?",
    "destination": "Barcelona",
    "businessTravel": true,
    "marketSymbol": "BBVA"
  }'

# Response:
# {
#   "response": "Great choice! Here's your Barcelona travel plan:\n\n
#     WEATHER:\n
#     Barcelona will have pleasant weather next week with temperatures around 18-20Β°C. 
#     Expect mostly sunny days with occasional clouds. Perfect for outdoor activities!\n\n
#     BUSINESS MARKET:\n
#     BBVA (Spanish banking) is showing strong performance. Consider visiting their 
#     headquarters in Madrid if time permits.\n\n
#     RECOMMENDATIONS:\n
#     1. Pack light clothing and sunscreen\n
#     2. Visit Sagrada Familia and Park GΓΌell\n
#     3. Try local tapas at La Boqueria Market\n
#     4. Network at business events in the Gothic Quarter",
#   "timestamp": "2025-11-11T08:10:00Z",
#   "agentsUsed": ["weather-agent", "market-agent"],
#   "executionTime": "2.5s"
# }

# Multi-city tour
$ curl -X POST http://localhost:8080/travel/multi-city \
  -H "Content-Type: application/json" \
  -d '{
    "request": "Plan a 2-week European tour",
    "destinations": ["Paris", "Barcelona", "Rome"],
    "duration": 14
  }'

# Response includes coordinated information from all agents

Test Case: Travel Planner Orchestrator

@QuarkusTest
public class TravelPlannerOrchestratorTest {
    
    @InjectMock
    WeatherChatAgent weatherAgent;
    
    @InjectMock
    StockAnalysisAgent stockAgent;
    
    @Test
    public void testTaskDecomposition() {
        TravelRequest request = new TravelRequest()
            .destination("Barcelona")
            .businessTravel(true);
        
        List<Task> tasks = orchestrator.decomposeTasks(request);
        
        assertThat(tasks)
            .hasSize(2)
            .extracting(Task::getType)
            .contains(TaskType.WEATHER, TaskType.MARKET);
    }
    
    @Test
    public void testAgentDelegation() {
        when(weatherAgent.getWeather("Barcelona"))
            .thenReturn("Sunny, 20Β°C");
        
        when(stockAgent.analyzeMarket("BBVA"))
            .thenReturn("Strong performance, +2.5%");
        
        String response = orchestrator.handleTravelRequest(
            "Plan my Barcelona trip"
        );
        
        assertThat(response)
            .contains("Sunny")
            .contains("BBVA")
            .contains("Barcelona");
    }
}

Mesh Agents

Definition

Mesh agents are distributed agents that form a mesh network for scalable, fault-tolerant communication. They can migrate between nodes and coordinate across the mesh.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Mesh Network (Kafka)            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                         β”‚
β”‚  Node 1          Node 2       Node 3   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚Agent│◄──────►│Agent│◄───►│Agentβ”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”˜  β”‚
β”‚    β”‚              β”‚            β”‚      β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                   β”‚                    β”‚
β”‚              Kafka Topics              β”‚
β”‚                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Implementation

@QuarkusMain
public class StockAnalysisMeshAgent extends MeshAgent {
    
    @Inject
    LLMService llmService;
    
    @Inject
    StockDataService stockDataService;
    
    @Inject
    KafkaProducer<String, String> producer;
    
    @Override
    public void initialize(AgentContext context) {
        this.setMeshConfig(new MeshConfig()
            .nodeId("stock-agent-" + UUID.randomUUID())
            .kafkaBrokers("localhost:9092")
            .topics("stock-analysis", "market-data")
        );
        
        context.subscribe("stock-analysis", this::analyzeStock);
        context.subscribe("market-data", this::processMarketData);
    }
    
    private void analyzeStock(Message message) {
        String stockSymbol = message.getPayload();
        
        StockData data = stockDataService.getStockData(stockSymbol);
        
        String analysis = llmService.chat(
            List.of(
                new Message("system", "You are a stock analyst. Analyze the stock data."),
                new Message("user", "Analyze " + stockSymbol + ": " + data.toString())
            ),
            new ChatConfig()
                .model("gpt-4")
                .temperature(0.5)
                .maxTokens(800)
        );
        
        producer.send("stock-analysis-results", 
            stockSymbol + ":" + analysis);
        
        if (this.getLoadFactor() > 0.8) {
            this.migrateToNode("stock-agent-2");
        }
    }
    
    private void processMarketData(Message message) {
        String marketData = message.getPayload();
        MarketAnalysis analysis = analyzeMarketTrends(marketData);
        producer.send("market-analysis-results", analysis.toJson());
    }
    
    private MarketAnalysis analyzeMarketTrends(String data) {
        return new MarketAnalysis();
    }
}

CLI Example: Stock Analysis Mesh Agent

# Start multiple mesh agents
$ quarkus dev -Dquarkus.http.port=8080 &
$ quarkus dev -Dquarkus.http.port=8081 &
$ quarkus dev -Dquarkus.http.port=8082 &

# Send stock analysis request to mesh
$ curl -X POST http://localhost:8080/analyze \
  -H "Content-Type: application/json" \
  -d '{"symbol": "AAPL", "action": "analyze"}'

# Response from any available agent in mesh
# {
#   "symbol": "AAPL",
#   "analysis": "Apple stock shows strong fundamentals with consistent revenue growth...",
#   "recommendation": "BUY",
#   "targetPrice": 195.50,
#   "confidence": 0.92,
#   "agentNode": "stock-agent-1",
#   "timestamp": "2025-11-11T08:15:00Z"
# }

# Monitor mesh network
$ curl http://localhost:8080/mesh/status

# Response:
# {
#   "nodes": 3,
#   "activeAgents": 5,
#   "topics": ["stock-analysis", "market-data"],
#   "throughput": "1000 msg/sec",
#   "latency": "45ms",
#   "health": "HEALTHY"
# }

# Trigger agent migration
$ curl -X POST http://localhost:8080/mesh/migrate \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "stock-agent-1",
    "targetNode": "stock-agent-3"
  }'

# Response:
# {
#   "status": "MIGRATING",
#   "agentId": "stock-agent-1",
#   "sourceNode": "stock-agent-1",
#   "targetNode": "stock-agent-3",
#   "statePreserved": true,
#   "estimatedTime": "500ms"
# }

Test Case: Stock Analysis Mesh Agent

@QuarkusTest
public class StockAnalysisMeshAgentTest {
    
    @InjectMock
    StockDataService stockDataService;
    
    @InjectMock
    LLMService llmService;
    
    @Test
    public void testStockAnalysis() {
        StockData data = new StockData()
            .symbol("AAPL")
            .price(195.50)
            .change(2.5);
        
        when(stockDataService.getStockData("AAPL"))
            .thenReturn(data);
        
        when(llmService.chat(any(), any()))
            .thenReturn("Apple shows strong fundamentals...");
        
        String analysis = meshAgent.analyzeStock("AAPL");
        
        assertThat(analysis)
            .contains("Apple")
            .contains("fundamentals");
    }
    
    @Test
    public void testMeshCommunication() {
        meshAgent.analyzeStock("AAPL");
        verify(producer).send("stock-analysis-results", any());
    }
    
    @Test
    public void testAgentMigration() {
        meshAgent.setLoadFactor(0.9);
        meshAgent.analyzeStock("AAPL");
        verify(meshAgent).migrateToNode("stock-agent-2");
    }
}

Real-World Use Cases

1. Weather Agent System

# Query weather for multiple cities
$ for city in Paris London Berlin Tokyo; do
    curl -X POST http://localhost:8080/chat \
      -H "Content-Type: application/json" \
      -d "{\"message\": \"Weather in $city\"}"
  done

# Multi-turn conversation
$ curl -X POST http://localhost:8080/chat \
  -d '{"message": "Which city has the best weather?"}'

2. Stock Trading System

# Analyze portfolio
$ curl -X POST http://localhost:8080/analyze-portfolio \
  -H "Content-Type: application/json" \
  -d '{
    "symbols": ["AAPL", "MSFT", "GOOGL", "TSLA"],
    "action": "analyze"
  }'

# Get recommendations
$ curl -X POST http://localhost:8080/recommendations \
  -H "Content-Type: application/json" \
  -d '{
    "portfolio": ["AAPL", "MSFT", "GOOGL"],
    "riskTolerance": "medium"
  }'

3. Travel Planning System

# Plan multi-city tour
$ curl -X POST http://localhost:8080/travel/multi-city \
  -H "Content-Type: application/json" \
  -d '{
    "cities": ["Paris", "Barcelona", "Rome"],
    "duration": 14,
    "interests": ["culture", "food", "history"]
  }'

# Get daily itinerary
$ curl -X POST http://localhost:8080/travel/itinerary \
  -H "Content-Type: application/json" \
  -d '{
    "city": "Paris",
    "day": 1,
    "interests": ["museums", "food"]
  }'

Performance Benchmarks

Chat Agent Performance

OpenAI GPT-4:
- Latency: 800-1200ms
- Throughput: 100 req/sec
- Cost: $0.03/1K tokens

Local Llama 2:
- Latency: 400-600ms
- Throughput: 500 req/sec
- Cost: Free (on-premise)

Hybrid:
- Latency: 300-400ms (fallback)
- Throughput: 1000 req/sec
- Cost: 60-80% savings

Mesh Agent Performance

Single Node:
- Throughput: 1000 msg/sec
- Latency: 45ms
- Memory: 200MB

3-Node Mesh:
- Throughput: 3000 msg/sec
- Latency: 50ms
- Memory: 600MB

5-Node Mesh:
- Throughput: 5000 msg/sec
- Latency: 55ms
- Memory: 1GB

Best Practices

1. Orchestrator Design

// Always implement timeout handling
String response = llmService.chat(messages, 
    config.timeout(Duration.ofSeconds(30)));

// Implement fallback strategies
try {
    return primaryAgent.process(task);
} catch (Exception e) {
    return fallbackAgent.process(task);
}

// Monitor agent health
if (!agent.isHealthy()) {
    removeFromPool(agent);
}

2. Mesh Deployment

# Use container orchestration
kubectl apply -f amcp-agents.yaml

# Monitor mesh health
kubectl logs -f deployment/amcp-agents

# Scale agents
kubectl scale deployment amcp-agents --replicas=5

# Monitor performance
kubectl top pods

3. LLM Cost Optimization

// Track costs
if (costTracker.getDailySpend() > threshold) {
    switchToLocalLLM();
}

// Use caching
String cached = cache.get(query);
if (cached != null) return cached;

// Batch requests
List<String> responses = llmService.batchChat(queries);

Conclusion

AMCP v1.6 provides powerful agentic capabilities:

Combined with LLM integration (OpenAI or local), AMCP enables building intelligent, autonomous systems.


Resources