Compare commits

..

1 Commits

Author SHA1 Message Date
HAL9000 ff2aae9eff docs: add configuration reference guide
- Create comprehensive Configuration Reference Guide in docs/guides/configuration-reference.md
- Document all environment variables organized by functional area (runtime, providers, storage, observability, etc.)
- Include configuration loading order, file locations, and best practices
- Add security considerations for secrets management, database, and API keys
- Provide troubleshooting guide for common configuration issues
- Include practical configuration examples for development, production, and Kubernetes deployments
- Update mkdocs.yml to include new Guides section with Configuration Reference link
2026-04-19 09:14:54 +00:00
5 changed files with 455 additions and 2302 deletions
-682
View File
@@ -1,682 +0,0 @@
# A2A Implementation Guide
## Overview
This guide provides comprehensive instructions for implementing the Agent-to-Agent (A2A) Protocol in CleverAgents applications. It covers both local (stdio) and remote (HTTP) transport mechanisms, integration with LangGraph Platform, and best practices for production deployments.
## A2A Implementation Overview
The A2A Protocol implementation consists of several key components:
1. **Protocol Handler**: Manages JSON-RPC 2.0 message parsing and routing
2. **Transport Layer**: Handles communication over stdio or HTTP
3. **Session Manager**: Manages agent sessions and lifecycle
4. **Plan Executor**: Executes and monitors plans
5. **Error Handler**: Manages error recovery and retry logic
### Architecture
```
┌─────────────────────────────────────────────────────────┐
│ Application Layer │
│ (Agent Logic, Skills, Tools) │
└──────────────────┬──────────────────────────────────────┘
┌──────────────────▼──────────────────────────────────────┐
│ A2A Protocol Handler │
│ (JSON-RPC 2.0 Parsing, Method Routing) │
└──────────────────┬──────────────────────────────────────┘
┌──────────────────▼──────────────────────────────────────┐
│ Session Manager │
│ (Session Lifecycle, Context Management) │
└──────────────────┬──────────────────────────────────────┘
┌──────────┴──────────┐
│ │
┌───────▼────────┐ ┌────────▼──────────┐
│ Stdio Transport│ │ HTTP Transport │
│ (Local Mode) │ │ (Server Mode) │
└────────────────┘ └───────────────────┘
```
## Stdio Transport (Local Mode)
Stdio transport is used for local, in-process agent communication.
### Implementation
#### Message Format
The stdio transport uses a length-prefixed message format:
```
<message_length_in_bytes>\n
<json_message>
```
#### Example Implementation (Python)
```python
import json
import sys
from typing import Dict, Any
class StdioTransport:
def __init__(self):
self.input_stream = sys.stdin.buffer
self.output_stream = sys.stdout.buffer
def send_message(self, message: Dict[str, Any]) -> None:
"""Send a message over stdio."""
json_str = json.dumps(message)
json_bytes = json_str.encode('utf-8')
length = len(json_bytes)
# Send length prefix
self.output_stream.write(f"{length}\n".encode('utf-8'))
# Send message
self.output_stream.write(json_bytes)
self.output_stream.flush()
def receive_message(self) -> Dict[str, Any]:
"""Receive a message over stdio."""
# Read length prefix
length_line = self.input_stream.readline().decode('utf-8').strip()
length = int(length_line)
# Read message
message_bytes = self.input_stream.read(length)
message_str = message_bytes.decode('utf-8')
return json.loads(message_str)
```
#### Example Implementation (JavaScript/Node.js)
```javascript
const readline = require('readline');
class StdioTransport {
constructor() {
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
this.buffer = '';
}
sendMessage(message) {
const jsonStr = JSON.stringify(message);
const jsonBytes = Buffer.from(jsonStr, 'utf-8');
const length = jsonBytes.length;
// Send length prefix and message
process.stdout.write(`${length}\n`);
process.stdout.write(jsonBytes);
}
async receiveMessage() {
return new Promise((resolve) => {
this.rl.once('line', (lengthLine) => {
const length = parseInt(lengthLine);
let data = '';
const onData = (chunk) => {
data += chunk.toString();
if (Buffer.byteLength(data, 'utf-8') >= length) {
process.stdin.removeListener('data', onData);
const message = JSON.parse(data.substring(0, length));
resolve(message);
}
};
process.stdin.on('data', onData);
});
});
}
}
```
### Local Mode Configuration
```yaml
# config.yaml
a2a:
transport: stdio
mode: local
session:
timeout: 3600
max_concurrent: 10
error_handling:
retry_attempts: 3
retry_backoff: exponential
retry_delay_ms: 1000
```
## HTTP Transport (Server Mode)
HTTP transport is used for remote, network-based agent communication.
### Implementation
#### Server Setup (Python/FastAPI)
```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import json
from typing import Dict, Any
app = FastAPI()
class JSONRPCRequest(BaseModel):
jsonrpc: str = "2.0"
method: str
params: Dict[str, Any] = {}
id: str
class JSONRPCResponse(BaseModel):
jsonrpc: str = "2.0"
result: Dict[str, Any] = None
error: Dict[str, Any] = None
id: str
class A2AServer:
def __init__(self):
self.sessions = {}
self.handlers = {
"_cleveragents/session/create": self.handle_session_create,
"_cleveragents/session/close": self.handle_session_close,
"_cleveragents/plan/create": self.handle_plan_create,
"_cleveragents/plan/execute": self.handle_plan_execute,
"_cleveragents/plan/status": self.handle_plan_status,
}
async def handle_rpc_call(self, request: JSONRPCRequest) -> JSONRPCResponse:
"""Handle a JSON-RPC 2.0 call."""
try:
handler = self.handlers.get(request.method)
if not handler:
return JSONRPCResponse(
id=request.id,
error={
"code": -32601,
"message": "Method not found"
}
)
result = await handler(request.params)
return JSONRPCResponse(
id=request.id,
result=result
)
except Exception as e:
return JSONRPCResponse(
id=request.id,
error={
"code": -32603,
"message": "Internal error",
"data": {"error": str(e)}
}
)
async def handle_session_create(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Create a new session."""
session_id = params.get("session_id")
agent_id = params.get("agent_id")
self.sessions[session_id] = {
"agent_id": agent_id,
"status": "active",
"created_at": "2024-04-19T10:30:00Z"
}
return {
"session_id": session_id,
"created_at": "2024-04-19T10:30:00Z",
"status": "active"
}
async def handle_session_close(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Close a session."""
session_id = params.get("session_id")
if session_id not in self.sessions:
raise ValueError(f"Session {session_id} not found")
del self.sessions[session_id]
return {
"session_id": session_id,
"closed_at": "2024-04-19T10:30:00Z",
"status": "closed"
}
async def handle_plan_create(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Create a new plan."""
plan_id = params.get("plan_id")
session_id = params.get("session_id")
return {
"plan_id": plan_id,
"session_id": session_id,
"status": "created",
"created_at": "2024-04-19T10:30:00Z"
}
async def handle_plan_execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Execute a plan."""
plan_id = params.get("plan_id")
return {
"plan_id": plan_id,
"execution_id": "exec_123",
"status": "executing",
"started_at": "2024-04-19T10:30:00Z"
}
async def handle_plan_status(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Get plan status."""
plan_id = params.get("plan_id")
return {
"plan_id": plan_id,
"status": "completed",
"progress": {
"total_steps": 2,
"completed_steps": 2,
"current_step": None
},
"result": {"status": "success"},
"error": None
}
# Initialize server
a2a_server = A2AServer()
@app.post("/rpc")
async def rpc_endpoint(request: JSONRPCRequest) -> JSONRPCResponse:
"""Main RPC endpoint."""
return await a2a_server.handle_rpc_call(request)
@app.post("/events")
async def events_endpoint(request: JSONRPCRequest) -> JSONRPCResponse:
"""Event notification endpoint."""
# Handle event notifications
return JSONRPCResponse(
id=request.id,
result={"status": "received"}
)
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {
"status": "healthy",
"timestamp": "2024-04-19T10:30:00Z",
"version": "1.0"
}
```
### Server Mode Configuration
```yaml
# config.yaml
a2a:
transport: http
mode: server
server:
host: 0.0.0.0
port: 8000
ssl:
enabled: true
cert_path: /etc/ssl/certs/server.crt
key_path: /etc/ssl/private/server.key
session:
timeout: 3600
max_concurrent: 100
error_handling:
retry_attempts: 3
retry_backoff: exponential
retry_delay_ms: 1000
```
## LangGraph Platform RemoteGraph Integration
The A2A Protocol integrates with LangGraph Platform's RemoteGraph for distributed graph execution.
### Integration Example
```python
from langgraph.graph import StateGraph
from langgraph.prebuilt import create_react_agent
from langgraph_sdk import RemoteGraph
import httpx
# Create a RemoteGraph client
client = RemoteGraph(
url="http://localhost:8000",
api_key="your-api-key"
)
# Define agent state
class AgentState(TypedDict):
messages: list
session_id: str
plan_id: str
# Create workflow
workflow = StateGraph(AgentState)
async def process_step(state: AgentState):
"""Process a workflow step."""
# Call remote agent via A2A Protocol
response = await client.invoke(
method="_cleveragents/skill/execute",
params={
"session_id": state["session_id"],
"skill_id": "process_data",
"skill_params": {"data": state["messages"]}
}
)
return {
"messages": state["messages"] + [response["result"]]
}
workflow.add_node("process", process_step)
workflow.set_entry_point("process")
# Compile and run
graph = workflow.compile()
result = await graph.ainvoke({
"messages": [],
"session_id": "sess_123",
"plan_id": "plan_456"
})
```
## Session Lifecycle Management
### Session States
```
┌─────────┐
│ Created │
└────┬────┘
┌─────────┐
│ Active │◄──────────┐
└────┬────┘ │
│ │
├─ Suspended ────┤
│ │
▼ │
┌─────────┐ │
│ Closing │───────────┘
└────┬────┘
┌─────────┐
│ Closed │
└─────────┘
```
### Session Management Code
```python
class SessionManager:
def __init__(self):
self.sessions = {}
async def create_session(self, session_id: str, agent_id: str) -> Dict[str, Any]:
"""Create a new session."""
session = {
"session_id": session_id,
"agent_id": agent_id,
"status": "active",
"created_at": datetime.now().isoformat(),
"context": {}
}
self.sessions[session_id] = session
return session
async def get_session(self, session_id: str) -> Dict[str, Any]:
"""Get session by ID."""
if session_id not in self.sessions:
raise ValueError(f"Session {session_id} not found")
return self.sessions[session_id]
async def update_session_context(self, session_id: str, context: Dict[str, Any]) -> None:
"""Update session context."""
session = await self.get_session(session_id)
session["context"].update(context)
async def close_session(self, session_id: str) -> Dict[str, Any]:
"""Close a session."""
session = await self.get_session(session_id)
session["status"] = "closed"
session["closed_at"] = datetime.now().isoformat()
return session
```
## Plan Lifecycle Management
### Plan States
```
┌─────────┐
│ Created │
└────┬────┘
┌──────────┐
│ Queued │
└────┬─────┘
┌──────────┐
│ Executing│◄──────────┐
└────┬─────┘ │
│ │
├─ Paused ────────┤
│ │
├─ Failed ────────┤
│ │
▼ │
┌──────────┐ │
│ Completed├───────────┘
└──────────┘
```
### Plan Execution Code
```python
class PlanExecutor:
def __init__(self):
self.plans = {}
self.executions = {}
async def create_plan(self, plan_id: str, plan_definition: Dict[str, Any]) -> Dict[str, Any]:
"""Create a new plan."""
plan = {
"plan_id": plan_id,
"definition": plan_definition,
"status": "created",
"created_at": datetime.now().isoformat()
}
self.plans[plan_id] = plan
return plan
async def execute_plan(self, plan_id: str, session_id: str) -> Dict[str, Any]:
"""Execute a plan."""
plan = self.plans[plan_id]
execution_id = f"exec_{uuid.uuid4()}"
execution = {
"execution_id": execution_id,
"plan_id": plan_id,
"session_id": session_id,
"status": "executing",
"started_at": datetime.now().isoformat(),
"progress": {
"total_steps": len(plan["definition"]["steps"]),
"completed_steps": 0,
"current_step": None
}
}
self.executions[execution_id] = execution
# Execute steps
for i, step in enumerate(plan["definition"]["steps"]):
execution["progress"]["current_step"] = step["id"]
# Execute step logic here
execution["progress"]["completed_steps"] = i + 1
execution["status"] = "completed"
execution["completed_at"] = datetime.now().isoformat()
return execution
async def get_plan_status(self, plan_id: str) -> Dict[str, Any]:
"""Get plan execution status."""
plan = self.plans[plan_id]
# Find latest execution
executions = [e for e in self.executions.values() if e["plan_id"] == plan_id]
if executions:
return executions[-1]
return {"status": "not_executed"}
```
## Error Recovery
### Retry Strategy
```python
import asyncio
from typing import Callable, Any
class RetryPolicy:
def __init__(self, max_attempts: int = 3, backoff_factor: float = 2.0):
self.max_attempts = max_attempts
self.backoff_factor = backoff_factor
async def execute_with_retry(self, func: Callable, *args, **kwargs) -> Any:
"""Execute a function with retry logic."""
last_exception = None
for attempt in range(self.max_attempts):
try:
return await func(*args, **kwargs)
except Exception as e:
last_exception = e
if attempt < self.max_attempts - 1:
delay = 1.0 * (self.backoff_factor ** attempt)
await asyncio.sleep(delay)
raise last_exception
```
### Circuit Breaker Pattern
```python
from enum import Enum
from datetime import datetime, timedelta
class CircuitState(Enum):
CLOSED = "closed"
OPEN = "open"
HALF_OPEN = "half_open"
class CircuitBreaker:
def __init__(self, failure_threshold: int = 5, timeout_seconds: int = 60):
self.failure_threshold = failure_threshold
self.timeout_seconds = timeout_seconds
self.state = CircuitState.CLOSED
self.failure_count = 0
self.last_failure_time = None
async def call(self, func: Callable, *args, **kwargs) -> Any:
"""Call a function with circuit breaker protection."""
if self.state == CircuitState.OPEN:
if datetime.now() - self.last_failure_time > timedelta(seconds=self.timeout_seconds):
self.state = CircuitState.HALF_OPEN
else:
raise Exception("Circuit breaker is open")
try:
result = await func(*args, **kwargs)
self.on_success()
return result
except Exception as e:
self.on_failure()
raise
def on_success(self):
"""Handle successful call."""
self.failure_count = 0
self.state = CircuitState.CLOSED
def on_failure(self):
"""Handle failed call."""
self.failure_count += 1
self.last_failure_time = datetime.now()
if self.failure_count >= self.failure_threshold:
self.state = CircuitState.OPEN
```
## Best Practices
### 1. Session Management
- Always create a session before executing plans
- Use unique session IDs for tracking
- Implement session timeout mechanisms
- Clean up sessions when done
### 2. Error Handling
- Implement comprehensive error handling
- Use appropriate error codes
- Provide detailed error messages
- Log all errors for debugging
### 3. Performance
- Use connection pooling for HTTP transport
- Implement request timeouts
- Monitor response times
- Optimize message serialization
### 4. Security
- Use TLS/SSL for HTTP transport
- Implement authentication and authorization
- Validate all inputs
- Sanitize error messages
### 5. Monitoring
- Log all RPC calls
- Track execution times
- Monitor error rates
- Implement health checks
### 6. Testing
- Unit test protocol handlers
- Integration test with real agents
- Load test with multiple concurrent sessions
- Test error recovery mechanisms
## Related Documentation
- [A2A Protocol Specification](../reference/a2a_protocol_spec.md)
- [A2A Server Deployment Guide](./a2a_server_deployment.md)
- [ADR-047: ACP Standard Adoption](../adr/ADR-047-acp-standard-adoption.md)
- [ADR-048: Server Application Architecture](../adr/ADR-048-server-application-architecture.md)
-749
View File
@@ -1,749 +0,0 @@
# A2A Server Deployment Guide
## Overview
This guide provides comprehensive instructions for deploying A2A servers in production environments. It covers Docker, Kubernetes, and Helm deployments, along with security, monitoring, and operational best practices.
## Server Deployment Overview
The A2A Server is a stateless HTTP service that implements the A2A Protocol. It can be deployed in various environments:
- **Single Container**: Simple deployments with Docker
- **Kubernetes Cluster**: Scalable deployments with automatic failover
- **Helm Charts**: Declarative infrastructure as code
- **Cloud Platforms**: AWS, GCP, Azure deployments
### Architecture
```
┌─────────────────────────────────────────────────────────┐
│ Load Balancer │
│ (Nginx, HAProxy, ALB) │
└──────────────────┬──────────────────────────────────────┘
┌──────────┼──────────┐
│ │ │
┌───────▼──┐ ┌────▼────┐ ┌───▼──────┐
│ A2A Pod 1│ │ A2A Pod2│ │ A2A Pod3 │
└──────────┘ └─────────┘ └──────────┘
│ │ │
└──────────┼──────────┘
┌──────────▼──────────┐
│ Persistent Storage │
│ (Redis, PostgreSQL) │
└─────────────────────┘
```
## Docker Deployment
### Dockerfile
```dockerfile
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
# Copy application
COPY . .
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Expose port
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Run application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```
### Docker Compose
```yaml
version: '3.8'
services:
a2a-server:
build: .
ports:
- "8000:8000"
environment:
- A2A_MODE=server
- A2A_TRANSPORT=http
- LOG_LEVEL=info
- REDIS_URL=redis://redis:6379
- DATABASE_URL=postgresql://user:password@postgres:5432/a2a
depends_on:
- redis
- postgres
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=a2a
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
redis_data:
postgres_data:
```
### Running Docker Deployment
```bash
# Build image
docker build -t cleveragents/a2a-server:latest .
# Run with Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f a2a-server
# Stop services
docker-compose down
```
## Kubernetes Deployment
### Deployment Manifest
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: a2a-server
namespace: cleveragents
labels:
app: a2a-server
version: v1
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: a2a-server
template:
metadata:
labels:
app: a2a-server
version: v1
spec:
serviceAccountName: a2a-server
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: a2a-server
image: cleveragents/a2a-server:latest
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8000
protocol: TCP
env:
- name: A2A_MODE
value: "server"
- name: A2A_TRANSPORT
value: "http"
- name: LOG_LEVEL
value: "info"
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: a2a-secrets
key: redis-url
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: a2a-secrets
key: database-url
- name: API_KEY
valueFrom:
secretKeyRef:
name: a2a-secrets
key: api-key
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/cache
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- a2a-server
topologyKey: kubernetes.io/hostname
```
### Service Manifest
```yaml
apiVersion: v1
kind: Service
metadata:
name: a2a-server
namespace: cleveragents
labels:
app: a2a-server
spec:
type: ClusterIP
ports:
- name: http
port: 8000
targetPort: http
protocol: TCP
selector:
app: a2a-server
```
### Ingress Manifest
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: a2a-server
namespace: cleveragents
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- a2a.example.com
secretName: a2a-tls
rules:
- host: a2a.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: a2a-server
port:
number: 8000
```
### Deploying to Kubernetes
```bash
# Create namespace
kubectl create namespace cleveragents
# Create secrets
kubectl create secret generic a2a-secrets \
--from-literal=redis-url=redis://redis:6379 \
--from-literal=database-url=postgresql://user:password@postgres:5432/a2a \
--from-literal=api-key=your-api-key \
-n cleveragents
# Apply manifests
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
# Check deployment status
kubectl get deployment a2a-server -n cleveragents
kubectl get pods -n cleveragents -l app=a2a-server
# View logs
kubectl logs -n cleveragents -l app=a2a-server -f
```
## Helm Configuration
### Helm Chart Structure
```
a2a-server-chart/
├── Chart.yaml
├── values.yaml
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── hpa.yaml
│ └── pdb.yaml
└── README.md
```
### Chart.yaml
```yaml
apiVersion: v2
name: a2a-server
description: A Helm chart for A2A Server
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- a2a
- cleveragents
- agent-communication
maintainers:
- name: CleverAgents
email: support@cleveragents.com
```
### values.yaml
```yaml
replicaCount: 3
image:
repository: cleveragents/a2a-server
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8000
targetPort: 8000
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: a2a.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: a2a-tls
hosts:
- a2a.example.com
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- a2a-server
topologyKey: kubernetes.io/hostname
config:
mode: server
transport: http
logLevel: info
sessionTimeout: 3600
maxConcurrentSessions: 100
secrets:
redisUrl: ""
databaseUrl: ""
apiKey: ""
```
### Installing Helm Chart
```bash
# Add Helm repository
helm repo add cleveragents https://charts.cleveragents.com
helm repo update
# Install chart
helm install a2a-server cleveragents/a2a-server \
--namespace cleveragents \
--create-namespace \
--values values.yaml
# Upgrade chart
helm upgrade a2a-server cleveragents/a2a-server \
--namespace cleveragents \
--values values.yaml
# Uninstall chart
helm uninstall a2a-server --namespace cleveragents
```
## Environment Variables
### Core Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `A2A_MODE` | `server` | Deployment mode (server, local) |
| `A2A_TRANSPORT` | `http` | Transport mechanism (http, stdio) |
| `A2A_HOST` | `0.0.0.0` | Server host address |
| `A2A_PORT` | `8000` | Server port |
| `LOG_LEVEL` | `info` | Logging level (debug, info, warning, error) |
### Session Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `SESSION_TIMEOUT` | `3600` | Session timeout in seconds |
| `MAX_CONCURRENT_SESSIONS` | `100` | Maximum concurrent sessions |
| `SESSION_STORAGE` | `redis` | Session storage backend |
### Database Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | - | Database connection URL |
| `DATABASE_POOL_SIZE` | `10` | Database connection pool size |
| `DATABASE_TIMEOUT` | `30` | Database timeout in seconds |
### Redis Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `REDIS_URL` | - | Redis connection URL |
| `REDIS_POOL_SIZE` | `10` | Redis connection pool size |
### Security Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `API_KEY` | - | API key for authentication |
| `TLS_ENABLED` | `true` | Enable TLS/SSL |
| `TLS_CERT_PATH` | - | Path to TLS certificate |
| `TLS_KEY_PATH` | - | Path to TLS private key |
## Security Configuration
### TLS/SSL Setup
```yaml
# config.yaml
server:
tls:
enabled: true
cert_path: /etc/ssl/certs/server.crt
key_path: /etc/ssl/private/server.key
min_version: "1.2"
cipher_suites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
```
### Authentication
```python
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthCredentials
security = HTTPBearer()
async def verify_api_key(credentials: HTTPAuthCredentials = Depends(security)):
"""Verify API key."""
if credentials.credentials != os.getenv("API_KEY"):
raise HTTPException(status_code=401, detail="Invalid API key")
return credentials.credentials
@app.post("/rpc")
async def rpc_endpoint(
request: JSONRPCRequest,
api_key: str = Depends(verify_api_key)
):
"""RPC endpoint with authentication."""
# Handle RPC call
pass
```
### RBAC Configuration
```yaml
# rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ServiceAccount
metadata:
name: a2a-server
namespace: cleveragents
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: a2a-server
namespace: cleveragents
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: a2a-server
namespace: cleveragents
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: a2a-server
subjects:
- kind: ServiceAccount
name: a2a-server
namespace: cleveragents
```
## Monitoring & Logging
### Prometheus Metrics
```python
from prometheus_client import Counter, Histogram, Gauge
# Define metrics
rpc_calls_total = Counter(
'a2a_rpc_calls_total',
'Total RPC calls',
['method', 'status']
)
rpc_call_duration = Histogram(
'a2a_rpc_call_duration_seconds',
'RPC call duration',
['method']
)
active_sessions = Gauge(
'a2a_active_sessions',
'Number of active sessions'
)
# Use metrics
@app.post("/rpc")
async def rpc_endpoint(request: JSONRPCRequest):
"""RPC endpoint with metrics."""
with rpc_call_duration.labels(method=request.method).time():
try:
result = await handle_rpc(request)
rpc_calls_total.labels(method=request.method, status='success').inc()
return result
except Exception as e:
rpc_calls_total.labels(method=request.method, status='error').inc()
raise
```
### Logging Configuration
```yaml
# logging.yaml
version: 1
disable_existing_loggers: false
formatters:
standard:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
json:
format: '{"timestamp": "%(asctime)s", "level": "%(levelname)s", "message": "%(message)s"}'
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: json
stream: ext://sys.stdout
file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: json
filename: /var/log/a2a-server.log
maxBytes: 10485760
backupCount: 10
loggers:
a2a:
level: DEBUG
handlers: [console, file]
root:
level: INFO
handlers: [console, file]
```
### ELK Stack Integration
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: cleveragents
data:
filebeat.yml: |
filebeat.inputs:
- type: container
paths:
- '/var/lib/docker/containers/*/*.log'
processors:
- add_kubernetes_metadata:
in_cluster: true
output.elasticsearch:
hosts: ["elasticsearch:9200"]
index: "a2a-server-%{+yyyy.MM.dd}"
```
## Operational Best Practices
### Health Checks
```bash
# Check server health
curl http://localhost:8000/health
# Check readiness
curl http://localhost:8000/ready
# Check liveness
curl http://localhost:8000/live
```
### Backup and Recovery
```bash
# Backup database
pg_dump -h postgres -U user a2a > backup.sql
# Restore database
psql -h postgres -U user a2a < backup.sql
# Backup Redis
redis-cli BGSAVE
# Restore Redis
redis-cli --pipe < dump.rdb
```
### Scaling
```bash
# Horizontal scaling with Kubernetes
kubectl scale deployment a2a-server --replicas=5 -n cleveragents
# Vertical scaling
kubectl set resources deployment a2a-server \
--limits=cpu=4,memory=4Gi \
--requests=cpu=2,memory=2Gi \
-n cleveragents
```
## Related Documentation
- [A2A Protocol Specification](../reference/a2a_protocol_spec.md)
- [A2A Implementation Guide](./a2a_implementation_guide.md)
- [ADR-048: Server Application Architecture](../adr/ADR-048-server-application-architecture.md)
+453
View File
@@ -0,0 +1,453 @@
# Configuration Reference Guide
This guide provides a comprehensive reference for configuring CleverAgents. Configuration is primarily managed through environment variables, with sensible defaults for most settings.
## Overview
CleverAgents uses a **Pydantic-based settings system** that reads configuration from environment variables with the `CLEVERAGENTS_` prefix. The configuration system is designed to be:
- **Environment-first**: All configuration comes from environment variables, making it ideal for containerized and cloud-native deployments
- **Hierarchical**: Settings are organized by functional area (runtime, providers, storage, observability, etc.)
- **Validated**: All configuration values are validated at startup with clear error messages
- **Sensible defaults**: Most settings have reasonable defaults suitable for development and production
### Configuration Loading Order
1. **Environment variables** (highest priority) — `CLEVERAGENTS_*` prefixed variables
2. **Provider-specific environment variables** — Native provider variables (e.g., `OPENAI_API_KEY`)
3. **Default values** — Hardcoded defaults in the settings schema
When a setting is not explicitly configured, the system falls back to the next level in the order above.
### Configuration File Locations
CleverAgents stores configuration and data in the following locations:
| Purpose | Default Location | Environment Variable |
|---------|------------------|----------------------|
| User data (sessions, personas, etc.) | `~/.cleveragents/` | `CLEVERAGENTS_DATA_DIR` |
| Database | `~/.cleveragents/cleveragents.db` | `CLEVERAGENTS_DATABASE_URL` |
| Logs | `./logs/` | `CLEVERAGENTS_LOG_DIR` |
| Storage (plans, resources, etc.) | `./data/` | `CLEVERAGENTS_STORAGE_BASE_PATH` |
| Vector store | `./.cleveragents/vector_store/` | `CLEVERAGENTS_VECTOR_STORE_PATH` |
## Environment Variables Reference
All environment variables are organized by functional area. Each entry includes:
- **Variable name** — The full `CLEVERAGENTS_*` environment variable name
- **Type** — The expected data type (string, integer, boolean, etc.)
- **Default** — The default value if not set
- **Description** — What the setting controls
- **Example** — A practical example value
### Runtime & Server Configuration
#### `CLEVERAGENTS_ENV`
- **Type:** String
- **Default:** `development`
- **Valid values:** `development`, `production`, `staging`, `test`
- **Description:** The runtime environment. Controls logging verbosity, debug features, and validation strictness.
- **Example:** `export CLEVERAGENTS_ENV=production`
#### `CLEVERAGENTS_DEBUG_ENABLED`
- **Type:** Boolean
- **Default:** `false`
- **Description:** Enable debug mode with verbose logging and additional runtime checks. Should never be enabled in production.
- **Example:** `export CLEVERAGENTS_DEBUG_ENABLED=true`
#### `CLEVERAGENTS_SERVER_HOST`
- **Type:** String (IP address)
- **Default:** `0.0.0.0`
- **Description:** The host address for the CleverAgents server to bind to.
- **Example:** `export CLEVERAGENTS_SERVER_HOST=127.0.0.1`
#### `CLEVERAGENTS_SERVER_PORT`
- **Type:** Integer
- **Default:** `8080`
- **Valid range:** 1-65535
- **Description:** The port for the CleverAgents server to listen on.
- **Example:** `export CLEVERAGENTS_SERVER_PORT=9000`
#### `CLEVERAGENTS_SERVER_RELOAD`
- **Type:** Boolean
- **Default:** `false`
- **Description:** Enable auto-reload on code changes (development only). Never use in production.
- **Example:** `export CLEVERAGENTS_SERVER_RELOAD=true`
#### `CLEVERAGENTS_SERVER_URL`
- **Type:** String (URL)
- **Default:** `None` (local mode)
- **Description:** URL of a remote CleverAgents server to connect to. When set, the CLI operates in server mode.
- **Example:** `export CLEVERAGENTS_SERVER_URL=https://cleveragents.example.com`
#### `CLEVERAGENTS_SERVER_TOKEN`
- **Type:** String
- **Default:** `None`
- **Description:** Authentication token for connecting to a remote CleverAgents server. Required when `CLEVERAGENTS_SERVER_URL` is set.
- **Example:** `export CLEVERAGENTS_SERVER_TOKEN=sk-1234567890abcdef`
### AI Provider Configuration
#### Provider API Keys
Each AI provider requires its API key to be configured. CleverAgents supports multiple providers simultaneously and automatically selects the best available one.
| Provider | Primary Variable | Fallback Variables | Example |
|----------|------------------|-------------------|---------|
| OpenAI | `OPENAI_API_KEY` | `CLEVERAGENTS_OPENAI_API_KEY` | `sk-proj-...` |
| Anthropic | `ANTHROPIC_API_KEY` | `CLEVERAGENTS_ANTHROPIC_API_KEY` | `sk-ant-...` |
| Google | `GOOGLE_API_KEY` | `GOOGLE_GENAI_API_KEY`, `CLEVERAGENTS_GOOGLE_API_KEY` | `AIza...` |
| Azure OpenAI | `AZURE_OPENAI_API_KEY` | `AZURE_API_KEY`, `CLEVERAGENTS_AZURE_API_KEY` | `...` |
| OpenRouter | `OPENROUTER_API_KEY` | `CLEVERAGENTS_OPENROUTER_API_KEY` | `sk-or-...` |
| Gemini | `GEMINI_API_KEY` | `GOOGLE_GEMINI_API_KEY`, `CLEVERAGENTS_GEMINI_API_KEY` | `AIza...` |
| Cohere | `COHERE_API_KEY` | `CLEVERAGENTS_COHERE_API_KEY` | `...` |
| Groq | `GROQ_API_KEY` | `CLEVERAGENTS_GROQ_API_KEY` | `gsk_...` |
| Together | `TOGETHER_API_KEY` | `CLEVERAGENTS_TOGETHER_API_KEY` | `...` |
| HuggingFace | `HF_TOKEN` | `HUGGINGFACEHUB_API_TOKEN`, `HUGGING_FACE_HUB_TOKEN` | `hf_...` |
| Perplexity | `PERPLEXITY_API_KEY` | `CLEVERAGENTS_PERPLEXITY_API_KEY` | `pplx-...` |
#### `CLEVERAGENTS_DEFAULT_PROVIDER`
- **Type:** String
- **Default:** `None` (auto-detect from configured providers)
- **Valid values:** `openai`, `anthropic`, `google`, `azure`, `openrouter`, `gemini`, `cohere`, `groq`, `together`, `huggingface`, `perplexity`
- **Description:** Pin the default AI provider. When not set, the system automatically selects the first available configured provider in the fallback order.
- **Example:** `export CLEVERAGENTS_DEFAULT_PROVIDER=anthropic`
#### `CLEVERAGENTS_DEFAULT_MODEL`
- **Type:** String
- **Default:** `None` (provider-specific default)
- **Description:** Pin the default model for the selected provider. When not set, each provider's published default is used (e.g., `gpt-4o` for OpenAI, `claude-sonnet-4-20250514` for Anthropic).
- **Example:** `export CLEVERAGENTS_DEFAULT_MODEL=gpt-4-turbo`
#### `CLEVERAGENTS_MOCK_PROVIDERS`
- **Type:** Boolean
- **Default:** `false`
- **Description:** Enable mock AI providers for testing. Must not be used in production. Useful for development and CI/CD pipelines.
- **Example:** `export CLEVERAGENTS_MOCK_PROVIDERS=true`
#### `CLEVERAGENTS_TESTING_USE_MOCK_AI`
- **Type:** Boolean
- **Default:** `false`
- **Description:** Force the in-repo mock provider for Behave/Robot test suites to prevent external API calls.
- **Example:** `export CLEVERAGENTS_TESTING_USE_MOCK_AI=true`
### Logging & Paths
#### `CLEVERAGENTS_LOG_LEVEL`
- **Type:** String
- **Default:** `INFO`
- **Valid values:** `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
- **Description:** The logging level for standard output and file logs.
- **Example:** `export CLEVERAGENTS_LOG_LEVEL=DEBUG`
#### `CLEVERAGENTS_LOG_DIR`
- **Type:** Path
- **Default:** `./logs/`
- **Description:** Directory where log files are written.
- **Example:** `export CLEVERAGENTS_LOG_DIR=/var/log/cleveragents`
#### `CLEVERAGENTS_DATA_DIR`
- **Type:** Path
- **Default:** `~/.cleveragents/`
- **Description:** Directory for user data, sessions, personas, and other persistent state.
- **Example:** `export CLEVERAGENTS_DATA_DIR=/data/cleveragents`
#### `CLEVERAGENTS_STORAGE_BASE_PATH`
- **Type:** Path
- **Default:** `./data/`
- **Description:** Base directory for plan storage, checkpoints, and other runtime data.
- **Example:** `export CLEVERAGENTS_STORAGE_BASE_PATH=/storage/cleveragents`
### Database & Persistence
#### `CLEVERAGENTS_DATABASE_URL`
- **Type:** String (database URL)
- **Default:** `sqlite:///$HOME/.cleveragents/cleveragents.db`
- **Supported formats:**
- SQLite: `sqlite:///path/to/database.db`
- PostgreSQL: `postgresql://user:password@host:port/database`
- MySQL: `mysql+pymysql://user:password@host:port/database`
- DuckDB: `duckdb:///path/to/database.duckdb`
- **Description:** The database URL for storing sessions, plans, and other persistent data.
- **Example:** `export CLEVERAGENTS_DATABASE_URL=postgresql://user:pass@localhost/cleveragents`
### Cost Controls & Budgets
#### `CLEVERAGENTS_SESSION_MAX_COST_USD`
- **Type:** Float
- **Default:** `None` (unlimited)
- **Valid range:** >= 0.0
- **Description:** Maximum USD spend per session across all plans. `None` means unlimited.
- **Example:** `export CLEVERAGENTS_SESSION_MAX_COST_USD=100.00`
#### `CLEVERAGENTS_ORG_MAX_COST_USD`
- **Type:** Float
- **Default:** `None` (unlimited)
- **Valid range:** >= 0.0
- **Description:** Maximum USD spend per organization across all sessions. `None` means unlimited.
- **Example:** `export CLEVERAGENTS_ORG_MAX_COST_USD=1000.00`
#### `CLEVERAGENTS_BUDGET_PER_PLAN`
- **Type:** Float
- **Default:** `None` (unlimited)
- **Valid range:** >= 0.0
- **Description:** Maximum USD spend per plan execution. `None` means unlimited.
- **Example:** `export CLEVERAGENTS_BUDGET_PER_PLAN=50.00`
#### `CLEVERAGENTS_BUDGET_PER_DAY`
- **Type:** Float
- **Default:** `None` (unlimited)
- **Valid range:** >= 0.0
- **Description:** Maximum USD spend per calendar day across all plans. `None` means unlimited.
- **Example:** `export CLEVERAGENTS_BUDGET_PER_DAY=500.00`
### Observability & Logging
#### LangSmith Tracing
#### `CLEVERAGENTS_LANGSMITH_ENABLED`
- **Type:** Boolean
- **Default:** `false`
- **Aliases:** `LANGCHAIN_TRACING_V2`, `LANGSMITH_TRACING_V2`
- **Description:** Enable LangSmith tracing for LangChain/LangGraph agents.
- **Example:** `export CLEVERAGENTS_LANGSMITH_ENABLED=true`
#### `CLEVERAGENTS_LANGSMITH_API_KEY`
- **Type:** String
- **Default:** `None`
- **Aliases:** `LANGSMITH_API_KEY`, `LANGCHAIN_API_KEY`
- **Description:** API key for LangSmith. Required when tracing is enabled.
- **Example:** `export CLEVERAGENTS_LANGSMITH_API_KEY=ls_...`
#### `CLEVERAGENTS_LANGSMITH_PROJECT`
- **Type:** String
- **Default:** `None`
- **Aliases:** `LANGSMITH_PROJECT`, `LANGCHAIN_PROJECT`
- **Description:** LangSmith project name. Required when tracing is enabled.
- **Example:** `export CLEVERAGENTS_LANGSMITH_PROJECT=my-project`
### Cleanup & Retention Policies
#### `CLEVERAGENTS_CLEANUP_SANDBOX_MAX_AGE_HOURS`
- **Type:** Integer
- **Default:** `48`
- **Valid range:** >= 1
- **Description:** Maximum age (in hours) before stale sandboxes are eligible for cleanup.
- **Example:** `export CLEVERAGENTS_CLEANUP_SANDBOX_MAX_AGE_HOURS=72`
#### `CLEVERAGENTS_CHECKPOINT_MAX`
- **Type:** Integer
- **Default:** `50`
- **Valid range:** >= 2
- **Description:** Maximum number of checkpoints to keep per plan. Oldest checkpoints are pruned first, but the first and most recent are always preserved.
- **Example:** `export CLEVERAGENTS_CHECKPOINT_MAX=100`
### Audit Logging
#### `CLEVERAGENTS_AUDIT_RETENTION_DAYS`
- **Type:** Integer
- **Default:** `0` (keep indefinitely)
- **Valid range:** >= 0
- **Description:** Days to retain audit log entries before pruning. `0` means keep indefinitely (spec default for compliance).
- **Example:** `export CLEVERAGENTS_AUDIT_RETENTION_DAYS=365`
#### `CLEVERAGENTS_AUDIT_ASYNC`
- **Type:** Boolean
- **Default:** `true`
- **Description:** When true, audit entries are written asynchronously via a write-behind queue on a background thread. Set to false for synchronous behavior (useful for debugging).
- **Example:** `export CLEVERAGENTS_AUDIT_ASYNC=false`
### Metrics & Observability
#### `CLEVERAGENTS_METRICS_ENABLED`
- **Type:** Boolean
- **Default:** `true`
- **Description:** Enable structured metric collection and emission.
- **Example:** `export CLEVERAGENTS_METRICS_ENABLED=false`
#### `CLEVERAGENTS_METRICS_EXPORT_PROMETHEUS`
- **Type:** Boolean
- **Default:** `false`
- **Description:** Enable Prometheus metrics export endpoint.
- **Example:** `export CLEVERAGENTS_METRICS_EXPORT_PROMETHEUS=true`
### Retry & Circuit Breaker Configuration
#### `CLEVERAGENTS_RETRY_MAX_ATTEMPTS`
- **Type:** Integer
- **Default:** `3`
- **Valid range:** 1-50
- **Description:** Default maximum retry attempts for service operations.
- **Example:** `export CLEVERAGENTS_RETRY_MAX_ATTEMPTS=5`
#### `CLEVERAGENTS_RETRY_BASE_DELAY`
- **Type:** Float
- **Default:** `1.0`
- **Valid range:** 0.0-300.0
- **Description:** Default base delay in seconds between retries.
- **Example:** `export CLEVERAGENTS_RETRY_BASE_DELAY=0.5`
#### `CLEVERAGENTS_RETRY_MAX_DELAY`
- **Type:** Float
- **Default:** `60.0`
- **Valid range:** 0.0-3600.0
- **Description:** Default maximum delay in seconds between retries.
- **Example:** `export CLEVERAGENTS_RETRY_MAX_DELAY=120.0`
#### `CLEVERAGENTS_RETRY_BACKOFF_STRATEGY`
- **Type:** String
- **Default:** `exponential`
- **Valid values:** `exponential`, `linear`, `fixed`, `jitter`, `none`
- **Description:** Default backoff strategy for retries.
- **Example:** `export CLEVERAGENTS_RETRY_BACKOFF_STRATEGY=linear`
### Security & Secrets
#### `CLEVERAGENTS_SHOW_SECRETS`
- **Type:** Boolean
- **Default:** `false`
- **Description:** When true, secrets are shown in CLI output and logs. Should never be enabled in production.
- **Example:** `export CLEVERAGENTS_SHOW_SECRETS=true`
### Automation & Output
#### `CLEVERAGENTS_AUTOMATION_PROFILE`
- **Type:** String
- **Default:** `` (empty, manual mode)
- **Valid values:** `manual`, `auto`, `full-auto` (or custom profile names)
- **Description:** Default automation profile name controlling plan execution behavior.
- **Example:** `export CLEVERAGENTS_AUTOMATION_PROFILE=auto`
#### `CLEVERAGENTS_FORMAT`
- **Type:** String
- **Default:** `None` (uses default format)
- **Valid values:** `json`, `markdown`, `text`, `yaml`
- **Description:** Default output format for CLI commands.
- **Example:** `export CLEVERAGENTS_FORMAT=json`
## Configuration Best Practices
### Development Environment
For local development, create a `.env` file in your project root:
```bash
# .env
CLEVERAGENTS_ENV=development
CLEVERAGENTS_DEBUG_ENABLED=true
CLEVERAGENTS_LOG_LEVEL=DEBUG
OPENAI_API_KEY=sk-proj-...
CLEVERAGENTS_DATABASE_URL=sqlite:///./dev.db
```
### Production Environment
For production deployments:
```bash
# Use strong, randomly generated secrets
export CLEVERAGENTS_ENV=production
export CLEVERAGENTS_DEBUG_ENABLED=false
export CLEVERAGENTS_LOG_LEVEL=WARNING
export CLEVERAGENTS_SHOW_SECRETS=false
# Use a production database
export CLEVERAGENTS_DATABASE_URL=postgresql://user:password@db.example.com/cleveragents
# Configure cost controls
export CLEVERAGENTS_SESSION_MAX_COST_USD=100
export CLEVERAGENTS_ORG_MAX_COST_USD=1000
# Enable observability
export CLEVERAGENTS_METRICS_ENABLED=true
export CLEVERAGENTS_LANGSMITH_ENABLED=true
export CLEVERAGENTS_LANGSMITH_API_KEY=ls_...
export CLEVERAGENTS_LANGSMITH_PROJECT=production
```
### Multi-Provider Setup
To support multiple AI providers with automatic fallback:
```bash
# Configure multiple providers
export OPENAI_API_KEY=sk-proj-...
export ANTHROPIC_API_KEY=sk-ant-...
export GOOGLE_API_KEY=AIza...
# Set primary provider (optional)
export CLEVERAGENTS_DEFAULT_PROVIDER=anthropic
```
## Security Considerations
### Secrets Management
1. **Never commit secrets** — Use environment variables or a secrets manager (Vault, AWS Secrets Manager, etc.)
2. **Use strong API keys** — Ensure all provider API keys are strong and rotated regularly
3. **Restrict access** — Limit who can view or modify configuration in your deployment
4. **Audit logging** — Enable audit logging to track configuration changes and API usage
5. **Redaction** — CleverAgents automatically redacts secrets in logs and output
### Database Security
- **Use encrypted connections** — Always use TLS/SSL for database connections
- **Strong credentials** — Use strong, randomly generated database passwords
- **Network isolation** — Restrict database access to authorized services only
### API Key Security
- **Rotate keys regularly** — Implement automated key rotation (e.g., monthly)
- **Use scoped keys** — If your provider supports it, use keys with minimal required permissions
- **Monitor usage** — Track API usage and set up alerts for unusual activity
## Troubleshooting Configuration Issues
### No AI Provider Configured
**Error:** `ValueError: No AI providers configured and mock_providers is disabled.`
**Solution:**
1. Set at least one provider API key: `export OPENAI_API_KEY=sk-proj-...`
2. Or enable mock providers for testing: `export CLEVERAGENTS_MOCK_PROVIDERS=true`
3. Verify the key is set: `echo $OPENAI_API_KEY`
### LangSmith Configuration Incomplete
**Error:** `LangSmith API key is required` or `LangSmith project name is required`
**Solution:**
1. Set both required variables:
```bash
export CLEVERAGENTS_LANGSMITH_API_KEY=ls_...
export CLEVERAGENTS_LANGSMITH_PROJECT=my-project
```
2. Or disable LangSmith: `export CLEVERAGENTS_LANGSMITH_ENABLED=false`
### Database Connection Failed
**Error:** `sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) could not connect to server`
**Solution:**
1. Verify the database URL: `echo $CLEVERAGENTS_DATABASE_URL`
2. Check database credentials and host
3. Ensure the database is running and accessible
### Configuration Not Taking Effect
**Problem:** Environment variable changes not reflected
**Solution:**
1. Verify the variable is set: `env | grep CLEVERAGENTS`
2. Restart the application (singleton settings are cached)
3. Check for typos in variable names (case-sensitive)
4. Ensure the variable is exported: `export CLEVERAGENTS_VAR=value`
## Related Documentation
- [Architecture Guide](../architecture.md) — System design and component overview
- [API Reference - Configuration](../api/config.md) — Detailed API documentation
- [Development Guide](../development/quality-automation.md) — Development setup and workflows
- [Specification](../specification.md) — Authoritative design documentation
- [FAQ](../faq.md) — Frequently asked questions
-871
View File
@@ -1,871 +0,0 @@
# A2A Protocol Specification
## Overview
The Agent-to-Agent (A2A) Protocol is a standardized communication protocol for inter-agent communication in the CleverAgents ecosystem. It enables agents to communicate with each other, coordinate on tasks, and manage distributed workflows.
The A2A Protocol is built on top of JSON-RPC 2.0 and extends it with CleverAgents-specific methods and semantics. It supports multiple transport mechanisms including stdio (for local/embedded mode) and HTTP (for server mode).
### Key Features
- **JSON-RPC 2.0 Compliant**: Uses the JSON-RPC 2.0 specification as the base protocol
- **Extensible**: Supports custom methods via the `_cleveragents/` namespace
- **Multi-Transport**: Works over stdio, HTTP, and other transport mechanisms
- **Bidirectional Communication**: Supports both request-response and notification patterns
- **Error Handling**: Comprehensive error codes and recovery mechanisms
- **Session Management**: Built-in session lifecycle management
- **Plan Coordination**: Support for distributed plan execution and coordination
## JSON-RPC 2.0 Foundation
The A2A Protocol is built on JSON-RPC 2.0, which defines:
### Request Format
```json
{
"jsonrpc": "2.0",
"method": "method_name",
"params": {},
"id": "request_id"
}
```
### Response Format
```json
{
"jsonrpc": "2.0",
"result": {},
"id": "request_id"
}
```
### Error Response Format
```json
{
"jsonrpc": "2.0",
"error": {
"code": -32600,
"message": "Invalid Request",
"data": {}
},
"id": "request_id"
}
```
### Notification Format (No Response Expected)
```json
{
"jsonrpc": "2.0",
"method": "method_name",
"params": {}
}
```
## CleverAgents Extension Methods
All CleverAgents-specific methods use the `_cleveragents/` namespace prefix to distinguish them from standard JSON-RPC methods.
### Session Management Methods
#### `_cleveragents/session/create`
Creates a new session for agent communication.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/session/create",
"params": {
"session_id": "string",
"agent_id": "string",
"context": {}
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"session_id": "string",
"created_at": "ISO8601_timestamp",
"status": "active"
},
"id": "request_id"
}
```
#### `_cleveragents/session/close`
Closes an existing session.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/session/close",
"params": {
"session_id": "string"
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"session_id": "string",
"closed_at": "ISO8601_timestamp",
"status": "closed"
},
"id": "request_id"
}
```
### Plan Management Methods
#### `_cleveragents/plan/create`
Creates a new plan for execution.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/plan/create",
"params": {
"session_id": "string",
"plan_id": "string",
"plan_definition": {},
"metadata": {}
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"plan_id": "string",
"session_id": "string",
"status": "created",
"created_at": "ISO8601_timestamp"
},
"id": "request_id"
}
```
#### `_cleveragents/plan/execute`
Executes a plan.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/plan/execute",
"params": {
"session_id": "string",
"plan_id": "string",
"execution_options": {}
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"plan_id": "string",
"execution_id": "string",
"status": "executing",
"started_at": "ISO8601_timestamp"
},
"id": "request_id"
}
```
#### `_cleveragents/plan/status`
Gets the status of a plan.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/plan/status",
"params": {
"session_id": "string",
"plan_id": "string"
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"plan_id": "string",
"status": "executing|completed|failed|cancelled",
"progress": {
"total_steps": 10,
"completed_steps": 5,
"current_step": "step_name"
},
"result": {},
"error": null
},
"id": "request_id"
}
```
### Agent Communication Methods
#### `_cleveragents/agent/call`
Calls another agent with a request.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/agent/call",
"params": {
"session_id": "string",
"target_agent_id": "string",
"method": "string",
"params": {},
"timeout": 30000
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"agent_id": "string",
"method": "string",
"result": {},
"execution_time_ms": 150
},
"id": "request_id"
}
```
#### `_cleveragents/agent/notify`
Sends a notification to another agent (no response expected).
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/agent/notify",
"params": {
"session_id": "string",
"target_agent_id": "string",
"event": "string",
"data": {}
}
}
```
### Skill Execution Methods
#### `_cleveragents/skill/execute`
Executes a skill.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/skill/execute",
"params": {
"session_id": "string",
"skill_id": "string",
"skill_params": {},
"timeout": 30000
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"skill_id": "string",
"status": "success|failed",
"output": {},
"execution_time_ms": 250
},
"id": "request_id"
}
```
### Context Management Methods
#### `_cleveragents/context/get`
Retrieves context information.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/context/get",
"params": {
"session_id": "string",
"context_key": "string"
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"context_key": "string",
"value": {},
"timestamp": "ISO8601_timestamp"
},
"id": "request_id"
}
```
#### `_cleveragents/context/set`
Sets context information.
**Request:**
```json
{
"jsonrpc": "2.0",
"method": "_cleveragents/context/set",
"params": {
"session_id": "string",
"context_key": "string",
"value": {},
"ttl": 3600
},
"id": "request_id"
}
```
**Response:**
```json
{
"jsonrpc": "2.0",
"result": {
"context_key": "string",
"status": "set",
"timestamp": "ISO8601_timestamp"
},
"id": "request_id"
}
```
## Message Types and Formats
### Message Envelope
All A2A messages follow a standard envelope format:
```json
{
"jsonrpc": "2.0",
"method": "method_name",
"params": {
"session_id": "string",
"request_id": "string",
"timestamp": "ISO8601_timestamp",
"version": "1.0"
},
"id": "unique_request_id"
}
```
### Common Parameter Types
#### Session Parameters
```json
{
"session_id": "string",
"agent_id": "string",
"context": {
"project_id": "string",
"environment": "string",
"metadata": {}
}
}
```
#### Plan Parameters
```json
{
"plan_id": "string",
"plan_definition": {
"name": "string",
"description": "string",
"steps": [
{
"id": "string",
"type": "string",
"action": "string",
"params": {}
}
]
}
}
```
#### Execution Parameters
```json
{
"execution_id": "string",
"plan_id": "string",
"status": "pending|executing|completed|failed|cancelled",
"progress": {
"total_steps": 10,
"completed_steps": 5,
"current_step": "string"
},
"result": {},
"error": {
"code": "string",
"message": "string",
"details": {}
}
}
```
## Transport Details
### Stdio Transport (Local Mode)
The stdio transport is used for local agent communication, typically for embedded or single-process scenarios.
**Characteristics:**
- Uses standard input/output streams
- Synchronous request-response pattern
- No network overhead
- Suitable for local testing and development
**Message Format:**
```
<message_length>\n
<json_message>
```
**Example:**
```
145
{"jsonrpc":"2.0","method":"_cleveragents/session/create","params":{"session_id":"sess_123"},"id":"req_1"}
```
### HTTP Transport (Server Mode)
The HTTP transport is used for remote agent communication over a network.
**Characteristics:**
- Uses HTTP/1.1 or HTTP/2
- RESTful endpoints
- Asynchronous support via webhooks
- Suitable for distributed systems
**Endpoints:**
#### POST /rpc
Main RPC endpoint for method calls.
**Request:**
```http
POST /rpc HTTP/1.1
Content-Type: application/json
```
**Response:**
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
#### POST /events
Event notification endpoint.
**Request:**
```http
POST /events HTTP/1.1
Content-Type: application/json
```
#### GET /health
Health check endpoint.
**Response:**
```http
HTTP/1.1 200 OK
Content-Type: application/json
```
### Transport Selection
The transport mechanism is selected based on the deployment mode:
- **Local Mode**: Uses stdio transport for direct process communication
- **Server Mode**: Uses HTTP transport for network communication
- **Hybrid Mode**: Can use both transports simultaneously
## Error Handling
### Standard JSON-RPC Error Codes
| Code | Message | Description |
|------|---------|-------------|
| -32700 | Parse error | Invalid JSON was received |
| -32600 | Invalid Request | The JSON sent is not a valid Request object |
| -32601 | Method not found | The method does not exist or is not available |
| -32602 | Invalid params | Invalid method parameter(s) |
| -32603 | Internal error | Internal JSON-RPC error |
| -32000 to -32099 | Server error | Reserved for implementation-defined server errors |
### CleverAgents-Specific Error Codes
| Code | Message | Description |
|------|---------|-------------|
| -32100 | Session not found | The specified session does not exist |
| -32101 | Plan not found | The specified plan does not exist |
| -32102 | Agent not found | The specified agent does not exist |
| -32103 | Skill execution failed | Skill execution failed with error |
| -32104 | Timeout | Request timed out |
| -32105 | Authorization failed | User is not authorized for this operation |
| -32106 | Resource exhausted | System resource limit exceeded |
| -32107 | Invalid state | Operation not valid in current state |
### Error Response Example
```json
{
"jsonrpc": "2.0",
"error": {
"code": -32100,
"message": "Session not found",
"data": {
"session_id": "sess_123",
"timestamp": "2024-04-19T10:30:00Z",
"request_id": "req_1"
}
},
"id": "req_1"
}
```
### Error Recovery
The A2A Protocol supports several error recovery mechanisms:
1. **Automatic Retry**: Failed requests can be automatically retried with exponential backoff
2. **Circuit Breaker**: Failing agents can be temporarily isolated to prevent cascading failures
3. **Fallback**: Alternative agents or skills can be used if primary ones fail
4. **Checkpoint/Restore**: Plan execution can be checkpointed and restored from failure points
## Protocol Examples
### Example 1: Creating and Executing a Plan
```json
// Step 1: Create a session
{
"jsonrpc": "2.0",
"method": "_cleveragents/session/create",
"params": {
"session_id": "sess_abc123",
"agent_id": "agent_main",
"context": {
"project_id": "proj_123",
"environment": "production"
}
},
"id": "req_1"
}
// Response
{
"jsonrpc": "2.0",
"result": {
"session_id": "sess_abc123",
"created_at": "2024-04-19T10:30:00Z",
"status": "active"
},
"id": "req_1"
}
// Step 2: Create a plan
{
"jsonrpc": "2.0",
"method": "_cleveragents/plan/create",
"params": {
"session_id": "sess_abc123",
"plan_id": "plan_xyz789",
"plan_definition": {
"name": "Deploy Application",
"steps": [
{
"id": "step_1",
"type": "skill",
"action": "build_application",
"params": {"version": "1.0"}
},
{
"id": "step_2",
"type": "skill",
"action": "deploy_application",
"params": {"environment": "production"}
}
]
}
},
"id": "req_2"
}
// Response
{
"jsonrpc": "2.0",
"result": {
"plan_id": "plan_xyz789",
"session_id": "sess_abc123",
"status": "created",
"created_at": "2024-04-19T10:30:05Z"
},
"id": "req_2"
}
// Step 3: Execute the plan
{
"jsonrpc": "2.0",
"method": "_cleveragents/plan/execute",
"params": {
"session_id": "sess_abc123",
"plan_id": "plan_xyz789",
"execution_options": {
"parallel": false,
"timeout": 3600000
}
},
"id": "req_3"
}
// Response
{
"jsonrpc": "2.0",
"result": {
"plan_id": "plan_xyz789",
"execution_id": "exec_123",
"status": "executing",
"started_at": "2024-04-19T10:30:10Z"
},
"id": "req_3"
}
// Step 4: Check plan status
{
"jsonrpc": "2.0",
"method": "_cleveragents/plan/status",
"params": {
"session_id": "sess_abc123",
"plan_id": "plan_xyz789"
},
"id": "req_4"
}
// Response
{
"jsonrpc": "2.0",
"result": {
"plan_id": "plan_xyz789",
"status": "completed",
"progress": {
"total_steps": 2,
"completed_steps": 2,
"current_step": null
},
"result": {
"deployment_id": "deploy_456",
"status": "success"
},
"error": null
},
"id": "req_4"
}
```
### Example 2: Agent-to-Agent Communication
```json
// Agent A calls Agent B
{
"jsonrpc": "2.0",
"method": "_cleveragents/agent/call",
"params": {
"session_id": "sess_abc123",
"target_agent_id": "agent_worker",
"method": "process_data",
"params": {
"data": [1, 2, 3, 4, 5],
"operation": "sum"
},
"timeout": 5000
},
"id": "req_5"
}
// Response from Agent B
{
"jsonrpc": "2.0",
"result": {
"agent_id": "agent_worker",
"method": "process_data",
"result": {
"sum": 15,
"count": 5,
"average": 3
},
"execution_time_ms": 125
},
"id": "req_5"
}
```
### Example 3: Skill Execution
```json
// Execute a skill
{
"jsonrpc": "2.0",
"method": "_cleveragents/skill/execute",
"params": {
"session_id": "sess_abc123",
"skill_id": "skill_email_sender",
"skill_params": {
"recipient": "user@example.com",
"subject": "Hello",
"body": "This is a test email"
},
"timeout": 10000
},
"id": "req_6"
}
// Response
{
"jsonrpc": "2.0",
"result": {
"skill_id": "skill_email_sender",
"status": "success",
"output": {
"message_id": "msg_789",
"sent_at": "2024-04-19T10:30:30Z"
},
"execution_time_ms": 450
},
"id": "req_6"
}
```
## Protocol Versioning
The A2A Protocol uses semantic versioning:
- **Major Version**: Breaking changes to the protocol
- **Minor Version**: Backward-compatible additions
- **Patch Version**: Bug fixes and non-breaking changes
Current version: **1.0.0**
## Security Considerations
### Authentication
All A2A communications should be authenticated using:
- API keys for HTTP transport
- Session tokens for long-lived connections
- TLS/SSL for encrypted communication
### Authorization
Authorization is enforced at multiple levels:
- Session-level: Who can access a session
- Plan-level: Who can execute a plan
- Skill-level: Who can execute a skill
- Agent-level: Who can call an agent
### Message Integrity
All messages should include:
- Request IDs for tracking
- Timestamps for audit trails
- Digital signatures for critical operations
## Related Documentation
- [A2A Implementation Guide](../guides/a2a_implementation_guide.md)
- [A2A Server Deployment Guide](../guides/a2a_server_deployment.md)
- [ADR-047: ACP Standard Adoption](../adr/ADR-047-acp-standard-adoption.md)
- [ADR-048: Server Application Architecture](../adr/ADR-048-server-application-architecture.md)
- [ADR-026: Agent Client Protocol](../adr/ADR-026-agent-client-protocol.md)
- TLS/SSL for encrypted communication
### Authorization
Authorization is enforced at multiple levels:
- Session-level: Who can access a session
- Plan-level: Who can execute a plan
- Skill-level: Who can execute a skill
- Agent-level: Who can call an agent
### Message Integrity
All messages should include:
- Request IDs for tracking
- Timestamps for audit trails
- Digital signatures for critical operations
## Related Documentation
- [A2A Implementation Guide](../guides/a2a_implementation_guide.md)
- [A2A Server Deployment Guide](../guides/a2a_server_deployment.md)
- [ADR-047: ACP Standard Adoption](../adr/ADR-047-acp-standard-adoption.md)
- [ADR-048: Server Application Architecture](../adr/ADR-048-server-application-architecture.md)
- [ADR-026: Agent Client Protocol](../adr/ADR-026-agent-client-protocol.md)
+2
View File
@@ -24,6 +24,8 @@ nav:
- AI Providers: api/providers.md
- TUI: api/tui.md
- ACMS / UKO: api/acms.md
- Guides:
- Configuration Reference: guides/configuration-reference.md
- Modules:
- Shell Safety: modules/shell-safety.md
- UKO Provenance Tracking: modules/uko-provenance.md