# vapora-a2a **Agent-to-Agent (A2A) Protocol Server** - Production-ready implementation of the A2A specification for VAPORA. ## Features - ✅ **Full A2A Protocol Compliance** - JSON-RPC 2.0, Agent Card discovery - ✅ **SurrealDB Persistence** - Tasks survive restarts, production-ready storage - ✅ **NATS Async Coordination** - Real-time task completion via message queue - ✅ **Prometheus Metrics** - Full observability with `/metrics` endpoint - ✅ **Type-Safe** - Rust compile-time guarantees for protocol correctness - ✅ **Integration Tests** - 5 comprehensive end-to-end tests ## Architecture ``` ┌─────────────────────────────────────────────────┐ │ A2A HTTP Server (Axum) │ │ /.well-known/agent.json | /a2a | /metrics │ └────────────────┬────────────────────────────────┘ │ ┌───────┴────────┐ │ │ ┌────▼─────┐ ┌──────▼────────┐ │ Bridge │ │ TaskManager │ │ (NATS) │ │ (SurrealDB) │ └────┬─────┘ └──────┬────────┘ │ │ │ ┌──────▼────────┐ └────────►│ AgentCoord │ └───────────────┘ ``` ### Components 1. **CoordinatorBridge** - Maps A2A tasks to internal agent coordination - NATS subscribers for TaskCompleted/TaskFailed events - DashMap for async result delivery via oneshot channels - Graceful degradation if NATS unavailable 2. **TaskManager** - Persistent task storage and lifecycle - SurrealDB integration with Surreal - Parameterized queries for security - Tasks survive server restarts 3. **Server** - HTTP endpoints (Axum) - `GET /.well-known/agent.json` - Agent discovery - `POST /a2a` - Task dispatch - `GET /a2a/tasks/{task_id}` - Status query - `GET /health` - Health check - `GET /metrics` - Prometheus metrics ## Quick Start ### Prerequisites ```bash # Start SurrealDB docker run -d -p 8000:8000 \ surrealdb/surrealdb:latest \ start --bind 0.0.0.0:8000 # Start NATS (optional, graceful degradation) docker run -d -p 4222:4222 nats:latest # Run migration surrealdb import --conn ws://localhost:8000 \ --user root --pass root \ migrations/007_a2a_tasks_schema.surql ``` ### Run Server ```bash cargo run --bin vapora-a2a -- \ --host 127.0.0.1 \ --port 8003 \ --version 1.0.0 ``` Server will start on `http://127.0.0.1:8003` ### Using the Client ```rust use vapora_a2a_client::{A2aClient, RetryPolicy}; #[tokio::main] async fn main() { let client = A2aClient::new("http://localhost:8003"); // Discover agent capabilities let agent_card = client.discover_agent().await?; println!("Agent: {} v{}", agent_card.name, agent_card.version); // Dispatch task let task_id = client.dispatch_task( "task-123".to_string(), "Write hello world function".to_string(), Some("In Rust".to_string()), Some("developer".to_string()), ).await?; // Poll for completion loop { let status = client.get_task_status(&task_id).await?; match status.state.as_str() { "completed" => { println!("Result: {:?}", status.result); break; } "failed" => { eprintln!("Error: {:?}", status.error); break; } _ => tokio::time::sleep(Duration::from_millis(500)).await, } } } ``` ## Configuration ### Environment Variables ```bash # SurrealDB SURREAL_URL=ws://localhost:8000 SURREAL_USER=root SURREAL_PASS=root # NATS (optional) NATS_URL=nats://localhost:4222 # Server A2A_HOST=0.0.0.0 A2A_PORT=8003 A2A_VERSION=1.0.0 ``` ### CLI Arguments ```bash vapora-a2a \ --host 0.0.0.0 \ --port 8003 \ --version 1.0.0 ``` ## Metrics Exposed at `http://localhost:8003/metrics` in Prometheus text format: - `vapora_a2a_tasks_total{status="waiting|working|completed|failed"}` - Task counts - `vapora_a2a_task_duration_seconds{status="completed|failed"}` - Task execution time - `vapora_a2a_nats_messages_total{subject,result}` - NATS message handling - `vapora_a2a_db_operations_total{operation,result}` - Database operations - `vapora_a2a_coordinator_assignments_total{skill,result}` - Coordinator assignments ## Testing ### Unit Tests ```bash cargo test -p vapora-a2a --lib ``` ### Integration Tests Require SurrealDB + NATS running: ```bash # Start dependencies docker compose up -d surrealdb nats # Run tests cargo test -p vapora-a2a --test integration_test -- --ignored # Tests: # 1. Task persistence after restart # 2. NATS completion updates DB # 3. Task state transitions # 4. Task failure handling # 5. End-to-end dispatch with timeout ``` ## Protocol Compliance Implements [A2A Protocol Specification](https://a2a-spec.dev): - ✅ Agent Card (`/.well-known/agent.json`) - ✅ Task dispatch (`POST /a2a`) - ✅ Status query (`GET /a2a/tasks/{id}`) - ✅ JSON-RPC 2.0 envelope - ✅ Task lifecycle (waiting → working → completed|failed) - ✅ Artifact support - ✅ Error handling ## Production Deployment See [ADR-0001](../../docs/architecture/adr/0001-a2a-protocol-implementation.md) and [ADR-0002](../../docs/architecture/adr/0002-kubernetes-deployment-strategy.md). ### Kubernetes ```bash kubectl apply -k kubernetes/overlays/prod/ ``` ### Docker ```bash docker build -t vapora-a2a:latest -f Dockerfile . docker run -p 8003:8003 \ -e SURREAL_URL=ws://surrealdb:8000 \ -e NATS_URL=nats://nats:4222 \ vapora-a2a:latest ``` ## Troubleshooting ### Tasks not persisting Check SurrealDB connection: ```bash # Verify connection curl http://localhost:8000/health # Check migration applied surrealdb sql --conn ws://localhost:8000 \ --user root --pass root --ns test --db main \ "SELECT * FROM a2a_tasks LIMIT 1;" ``` ### Tasks not completing Check NATS connection: ```bash # Subscribe to completion events nats sub "vapora.tasks.completed" # Server will log warnings if NATS unavailable ``` ### Metrics not showing ```bash # Check metrics endpoint curl http://localhost:8003/metrics | grep vapora_a2a ``` ## Related Crates - **vapora-a2a-client** - Client library for calling A2A servers - **vapora-agents** - Agent coordinator and registry - **vapora-backend** - Main VAPORA REST API ## License MIT OR Apache-2.0