Web Adapter¶
The Web adapter provides FastAPI-based REST and WebSocket endpoints for external system integration with the multi-agent simulation core.
Features¶
REST API: Submit intents and retrieve observations via HTTP endpoints
WebSocket Streaming: Real-time observation streaming for responsive applications
Authentication & Authorization: Token-based authentication with per-agent/world permissions
Rate Limiting: Configurable rate limiting per tenant and agent
Error Handling: Structured error responses with detailed error information
Quick Start¶
1. Generate Authentication Token¶
uv run python -m gunn web generate-token --agent-id alice --world-id demo_world
This will output a token and configuration details:
Generated authentication token:
Token: bOQFLmqjEJyeyfoz7yyCqQf8Xu8W8xbHFgfOsRx6nu4
World ID: demo_world
Agent ID: alice
Permissions: submit_intent,get_observation,stream_observations
2. Start the Web Server¶
uv run python -m gunn web server \
--host 0.0.0.0 \
--port 8000 \
--auth-token "bOQFLmqjEJyeyfoz7yyCqQf8Xu8W8xbHFgfOsRx6nu4:demo_world:alice:submit_intent,get_observation,stream_observations"
3. Submit an Intent¶
curl -X POST "http://localhost:8000/worlds/demo_world/agents/alice/intents" \
-H "Authorization: Bearer bOQFLmqjEJyeyfoz7yyCqQf8Xu8W8xbHFgfOsRx6nu4" \
-H "Content-Type: application/json" \
-d '{
"kind": "Speak",
"payload": {"text": "Hello, world!"},
"priority": 1,
"context_seq": 0
}'
4. Get Observations¶
curl "http://localhost:8000/worlds/demo_world/agents/alice/observations?timeout=5" \
-H "Authorization: Bearer bOQFLmqjEJyeyfoz7yyCqQf8Xu8W8xbHFgfOsRx6nu4"
API Reference¶
REST Endpoints¶
Health Check¶
GET
/health
Returns server health status
Submit Intent¶
POST
/worlds/{world_id}/agents/{agent_id}/intents
Headers:
Authorization: Bearer <token>
Body: Intent JSON object
Returns: Request ID and status
Get Observation¶
GET
/worlds/{world_id}/agents/{agent_id}/observations
Headers:
Authorization: Bearer <token>
Query:
timeout
(optional, default 30s)Returns: Observation delta with patches
WebSocket Endpoints¶
Observation Streaming¶
WebSocket
/worlds/{world_id}/agents/{agent_id}/observations/stream?token=<token>
Streams real-time observation deltas as JSON messages
Authentication¶
The Web adapter uses Bearer token authentication. Each token is associated with:
World ID: Which simulation world the token can access
Agent ID: Which agent the token represents
Permissions: List of allowed operations
Expiration: Optional expiration timestamp
Permissions¶
submit_intent
: Submit intents for processingget_observation
: Retrieve observations via RESTstream_observations
: Stream observations via WebSocket
Configuration¶
Command Line Options¶
uv run python -m gunn web server --help
JSON Configuration File¶
{
"host": "0.0.0.0",
"port": 8000,
"workers": 1,
"log_level": "info",
"rate_limit_requests": 100,
"rate_limit_window": 60,
"auth_tokens": [
{
"token": "your-token-here",
"world_id": "demo_world",
"agent_id": "alice",
"permissions": ["submit_intent", "get_observation", "stream_observations"],
"expires_at": null
}
]
}
Use with: uv run python -m gunn web server --config config.json
Rate Limiting¶
Rate limiting is applied per world_id:agent_id
combination:
Default: 100 requests per 60-second window
Configurable: Via
--rate-limit-requests
and--rate-limit-window
Response: HTTP 429 when limit exceeded
Error Handling¶
The API returns structured error responses:
{
"error": "STALE_CONTEXT",
"message": "Context is stale: expected_seq=5, actual_seq=10, threshold=0",
"details": {
"expected_seq": 5,
"actual_seq": 10,
"threshold": 0
}
}
Error Types¶
STALE_CONTEXT
: Intent context is outdatedQUOTA_EXCEEDED
: Agent quota limits exceededBACKPRESSURE
: System under load, request deferredVALIDATION_ERROR
: Invalid request formatINTERNAL_ERROR
: Server error
Security Considerations¶
Token Management: Store tokens securely, rotate regularly
HTTPS: Use HTTPS in production environments
CORS: Configure CORS appropriately for your use case
Rate Limiting: Adjust limits based on expected load
Logging: Monitor authentication failures and rate limit violations
Integration Examples¶
Python Client¶
import asyncio
import httpx
import websockets
import json
async def submit_intent():
async with httpx.AsyncClient() as client:
response = await client.post(
"http://localhost:8000/worlds/demo_world/agents/alice/intents",
headers={"Authorization": "Bearer your-token-here"},
json={
"kind": "Speak",
"payload": {"text": "Hello!"},
"priority": 1,
"context_seq": 0
}
)
return response.json()
async def stream_observations():
uri = "ws://localhost:8000/worlds/demo_world/agents/alice/observations/stream?token=your-token-here"
async with websockets.connect(uri) as websocket:
async for message in websocket:
observation = json.loads(message)
print(f"Received observation: {observation}")
# Run examples
asyncio.run(submit_intent())
asyncio.run(stream_observations())
JavaScript Client¶
// Submit intent
async function submitIntent() {
const response = await fetch('http://localhost:8000/worlds/demo_world/agents/alice/intents', {
method: 'POST',
headers: {
'Authorization': 'Bearer your-token-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
kind: 'Speak',
payload: { text: 'Hello!' },
priority: 1,
context_seq: 0
})
});
return await response.json();
}
// Stream observations
function streamObservations() {
const ws = new WebSocket('ws://localhost:8000/worlds/demo_world/agents/alice/observations/stream?token=your-token-here');
ws.onmessage = (event) => {
const observation = JSON.parse(event.data);
console.log('Received observation:', observation);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
}
Monitoring¶
The Web adapter integrates with the core telemetry system:
Structured Logs: All requests logged with context
Metrics: Request counts, latencies, error rates
Tracing: OpenTelemetry integration (when configured)
Monitor these metrics for operational health:
Request rate and latency
Authentication failure rate
Rate limiting violations
WebSocket connection counts
Error rates by type
Troubleshooting¶
Common Issues¶
403 Forbidden: Check token validity and permissions
429 Too Many Requests: Rate limit exceeded, implement backoff
408 Request Timeout: No observations available, check agent registration
WebSocket Connection Failed: Verify token and network connectivity
Debug Mode¶
Enable debug logging:
uv run python -m gunn web server --log-level debug
This provides detailed request/response logging for troubleshooting.