adk-server
HTTP server and A2A v1.0.0 protocol for Rust Agent Development Kit (ADK-Rust) agents.
Overview
adk-server provides HTTP infrastructure for the Rust Agent Development Kit (ADK-Rust):
- REST API - Standard HTTP endpoints for agent interaction
- A2A Protocol - Agent-to-Agent v1.0.0 communication (JSON-RPC 2.0, all 11 operations)
- SSE Streaming - Server-Sent Events for real-time responses
- Runtime UI - Built-in responsive interface for agent and team execution
- RemoteA2aAgent - Connect to remote agents as sub-agents
- Auth Bridge - Flow authenticated identity from HTTP headers into agent execution
- Artifacts - Binary artifact storage and retrieval per session
- Debug/Tracing - Trace inspection and graph visualization endpoints
- YAML Agent Config (feature:
yaml-agent) - Declarative agent definitions with:AgentConfigLoader— load agents from YAML filesHotReloadWatcher— filesystem watching with debounce- Environment variable interpolation (
${VAR}and${VAR:-default}) - Plugin, session, and memory backend configuration in YAML
- Round-trip serialization (
serialize_definition())
Installation
[]
= "2.1.0"
Or use the meta-crate:
[]
= { = "2.1.0", = ["server"] }
Quick Start
Basic Server
use ;
use Arc;
let config = new;
let app = create_app;
let listener = bind.await?;
serve.await?;
Security Configuration
Configure CORS, timeouts, and other security settings:
use ;
use Duration;
// Development mode (permissive CORS, detailed errors)
let config = new
.with_security;
// Production mode (restricted CORS, sanitized errors)
let config = new
.with_security;
// Or configure individual settings
let config = new
.with_allowed_origins
.with_request_timeout
.with_max_body_size // 5MB
.with_error_details;
Optional Services
let config = new
.with_artifact_service
.with_memory_service
.with_span_exporter
.with_request_context;
Runner Configuration Passthrough
ServerConfig can now forward runner-level compaction and prompt-cache settings:
let config = new
.with_compaction
.with_context_cache;
This applies to both the standard SSE runtime endpoints and the A2A runtime controller.
A2A v1.0.0 Server
use create_app_with_a2a;
let app = create_app_with_a2a;
ServerBuilder — Custom Routes
ServerBuilder lets you register custom Axum controllers alongside the built-in
routes. Custom routes share the same middleware stack (auth, CORS, tracing,
timeout, security headers).
use ;
use ;
let app = new
// Routes nested under /api — get auth middleware automatically
.add_api_routes
// Root-level routes — CORS/tracing/security headers, but no auth middleware
.add_root_routes
// Enable A2A protocol
.with_a2a
.build;
let listener = bind.await?;
serve.await?;
| Method | Description |
|---|---|
ServerBuilder::new(config) |
Create a builder from a ServerConfig |
.add_api_routes(router) |
Add routes nested under /api with auth middleware |
.add_root_routes(router) |
Add routes at the root level (no auth middleware) |
.with_a2a(base_url) |
Enable A2A protocol endpoints |
.enable_shutdown_endpoint() |
Enable POST /api/shutdown for graceful shutdown |
.build() |
Build the final axum::Router with all middleware |
.build_with_shutdown() |
Build and return a ShutdownHandle for graceful shutdown |
See examples/server_builder/ for a complete working example.
Graceful Shutdown Endpoint
Enable POST /api/shutdown for clean process termination (e.g., from an Electron shell):
use ;
let = new
.enable_shutdown_endpoint
.build_with_shutdown;
let listener = bind.await?;
serve
.with_graceful_shutdown
.await?;
When POST /api/shutdown is called, the server:
- Stops accepting new connections
- Completes in-flight requests
- Flushes pending writes (SQLite WAL, etc.)
- Exits with code 0
The ShutdownHandle::signal() also responds to Ctrl+C and SIGTERM, combining all shutdown triggers into one future.
// Exposes: // GET /.well-known/agent-card.json - Agent card with capabilities // POST /jsonrpc - JSON-RPC endpoint (all 11 v1 operations) // REST routes for all operations // A2A-Version header negotiation
The A2A v1.0.0 implementation includes: RFC 3339 timestamps, capabilities declaration, message ID idempotency, push notification authentication, INPUT_REQUIRED multi-turn flow, input validation, `application/a2a+json` Content-Type, and Task-as-first-SSE-event. See [A2A docs](../docs/official_docs/deployment/a2a.md) for details.
### Remote Agent Client
```rust
use adk_server::RemoteA2aAgent;
let remote = RemoteA2aAgent::builder("weather_agent")
.description("Remote weather service")
.agent_url("http://weather-service:8080")
.build()?;
// Use as sub-agent
let coordinator = LlmAgentBuilder::new("coordinator")
.sub_agent(Arc::new(remote))
.build()?;
Auth Bridge
Flow authenticated identity from HTTP requests into agent execution:
use ;
use RequestContext;
use async_trait;
;
let config = new
.with_request_context;
When configured, the extracted RequestContext flows into InvocationContext, making scopes available to tools via ToolContext::user_scopes(). Session and artifact endpoints enforce user_id authorization against the authenticated identity.
Background Runs and Cron (feature: background)
Runs a workflow without holding the request open, and schedules one on a cron expression. Neither is compiled unless the feature is on.
use ;
use Arc;
// Runs are held in memory. Attach persistence so a restart can still see them.
let store = new
.with_persistence
.with_retention;
// At startup, report what the last stop interrupted.
for run_id in store.restore.await?
| Endpoint | Method | Purpose |
|---|---|---|
/runs |
POST | Start a run, returning its id immediately |
/runs/{id} |
GET | Read a run's status and result |
/runs/{id} |
DELETE | Cancel a run |
/cron |
POST / GET / PATCH / DELETE | Manage scheduled jobs |
Cron jobs take a concurrency policy — skip, allow or queue — for what happens
when the previous run is still going.
What survives a restart. With a RunPersistence attached, run records do. A run
that was still going cannot still be going, so restore returns it as Failed with
a reason and gives it a live cancellation token. The graph state behind it is
separate: a checkpointed adk-graph thread can still be resumed by its id.
Finished runs are bounded by default — the newest 1000 — because a store that keeps
every finished run forever is a leak that only appears after weeks.
RunRetention::unlimited() opts out. A run still in flight is never discarded.
FileRunPersistence writes one JSON file and is enough for a single node. A
deployment across several needs a shared store; implement RunPersistence for one.
API Endpoints
Health
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check with component status |
Apps
| Endpoint | Method | Description |
|---|---|---|
/api/apps |
GET | List available agents |
/api/list-apps |
GET | adk-go compatible app listing |
Sessions
| Endpoint | Method | Description |
|---|---|---|
/api/sessions |
POST | Create session |
/api/sessions/{app_name}/{user_id}/{session_id} |
GET, DELETE | Get or delete session |
/api/apps/{app_name}/users/{user_id}/sessions |
GET, POST | List or create sessions |
/api/apps/{app_name}/users/{user_id}/sessions/{session_id} |
GET, POST, DELETE | Get, create, or delete session |
Runtime
| Endpoint | Method | Description |
|---|---|---|
/api/run/{app_name}/{user_id}/{session_id} |
POST | Run agent with SSE |
/api/run_sse |
POST | adk-go compatible SSE runtime |
Artifacts
| Endpoint | Method | Description |
|---|---|---|
/api/sessions/{app_name}/{user_id}/{session_id}/artifacts |
GET | List artifacts for a session |
/api/sessions/{app_name}/{user_id}/{session_id}/artifacts/{artifact_name} |
GET | Get a specific artifact |
Debug and Tracing
| Endpoint | Method | Description |
|---|---|---|
/api/debug/trace/{event_id} |
GET | Get trace by event ID (admin only when auth configured) |
/api/debug/trace/session/{session_id} |
GET | Get all spans for a session |
/api/debug/graph/{app_name}/{user_id}/{session_id}/{event_id} |
GET | Get graph visualization |
/api/apps/{app_name}/users/{user_id}/sessions/{session_id}/events/{event_id} |
GET | Get event data |
/api/apps/{app_name}/users/{user_id}/sessions/{session_id}/events/{event_id}/graph |
GET | Get graph (path-style) |
/api/apps/{app_name}/eval_sets |
GET | Get evaluation sets (stub) |
UI Protocol
| Endpoint | Method | Description |
|---|---|---|
/api/ui/capabilities |
GET | Supported UI protocols plus capability metadata (versions, features, implementationTier, specTrack, summary, limitations) |
/api/ui/agents/{name} |
GET | Agent capabilities, hierarchy, and exact portable team topology |
/api/ui/initialize |
POST | Additive MCP Apps host-bridge initialize helper (direct body or JSON-RPC-like envelope) |
/api/ui/message |
POST | Additive MCP Apps host-bridge message helper |
/api/ui/update-model-context |
POST | Additive MCP Apps host-bridge model-context helper |
/api/ui/notifications/poll |
POST | Poll queued MCP Apps host-bridge notifications |
/api/ui/notifications/resources-list-changed |
POST | Queue an MCP Apps resource-list-changed notification |
/api/ui/notifications/tools-list-changed |
POST | Queue an MCP Apps tool-list-changed notification |
/api/ui/resources |
GET | List MCP UI resources (ui:// entries) |
/api/ui/resources/read?uri=... |
GET | Read a registered MCP UI resource |
/api/ui/resources/register |
POST | Register an MCP UI resource (validated ui:// + mime/meta) |
Runtime endpoints support protocol negotiation via:
- request body field
uiProtocol/ui_protocol - header
x-adk-ui-protocol(takes precedence) - request body field
uiTransport/ui_transport - header
x-adk-ui-transport(takes precedence)
Supported runtime profile values: adk_ui (default), a2ui, ag_ui, mcp_apps.
Current support is intentionally tiered:
a2uiis a draft-aligned hybrid subset exposed through protocol-aware UI tool payloads.ag_uiis a hybrid subset: the default stream remains the generic ADK wrapper, but clients can opt intoprotocol_nativetransport plus AG-UI run input fields on/api/run_sse.mcp_appsis a compatibility subset withui://resource registration plus additiveinitialize/message/update-model-contextbridge helpers, notification polling, list-changed host flows, and runtime request fields, not a full browserpostMessagehost bridge yet.
Runtime transport values:
legacy_wrapper(default) preserves the existing generic ADK SSE envelope.protocol_nativeis currently available forag_uionly.
Use /api/ui/capabilities instead of assuming full upstream protocol parity.
For MCP Apps tool responses, adk-server::ui_types now exposes a canonical additive helper:
McpUiBridgeSnapshotfor typed host/app bridge state that can be promoted into tool responsesMcpUiToolResultfor the shared tool-result envelopeMcpUiToolResultBridgefor typed bridge metadata (protocolVersion,structuredContent,hostInfo,hostCapabilities,hostContext,appInfo,appCapabilities,initialized)
Use McpUiBridgeSnapshot::build_tool_result(...) as the preferred constructor path when promoting framework bridge state into an MCP Apps tool response. resourceUri and inline html fallbacks remain available for compatibility-oriented hosts.
For embedded-host mappings, the additive HTTP bridge corresponds to MCP Apps host/app methods as follows:
ui/initialize->/api/ui/initializeui/message->/api/ui/messageui/update-model-context->/api/ui/update-model-contextnotifications/resources/list_changed->/api/ui/notifications/resources-list-changednotifications/tools/list_changed->/api/ui/notifications/tools-list-changed- queued host notifications ->
/api/ui/notifications/poll
A2A Endpoints
| Endpoint | Method | Description |
|---|---|---|
/.well-known/agent.json |
GET | A2A agent card |
/a2a |
POST | A2A JSON-RPC |
/a2a/stream |
POST | A2A streaming |
Web UI
The ADK-Rust-owned interface uses the Studio Next visual language while staying focused on execution. It displays Markdown-formatted conversations and multimodal attachments, streaming tool activity, handoffs, animated exact team delegation/handoff topology, realtime transcripts and completed audio, event timelines, dedicated telemetry spans, session and shared state, artifacts, prior sessions, configured runtime services, A2A discovery, and negotiated UI and MCP Apps protocols. It is responsive, keyboard accessible, supports system/light/dark themes, and has no external font or asset dependency. The ADK Runtime brand links to adk-rust.com.
See examples/advanced_agents/ for one OpenAI-backed server
demonstrating ambient scheduling, realtime voice, A2A, MCP discovery/tasks, and telemetry.
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Redirect to /ui/ |
/ui/ |
GET | Built-in agent and team runtime interface |
/ui/assets/config/runtime-config.json |
GET | Runtime configuration |
/ui/{*path} |
GET | Static UI assets |
Security
The server applies the following security layers automatically:
- CORS (configurable allowed origins)
- Request body size limits (default 10MB)
- Request timeouts (default 30s)
X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=block- Request ID tracking via
x-request-idheader - User ID authorization on session/artifact/debug endpoints when auth is configured
Features
- Axum-based async HTTP server
- CORS support with configurable origins
- Embedded web UI assets
- Multi-agent routing via
AgentLoader - Health checks with component status
- OpenTelemetry trace integration
- Auth middleware bridge for identity propagation
- Artifact storage and retrieval
- A2A v1.0.0 protocol with JSON-RPC 2.0 (all 11 operations, idempotency, multi-turn, push auth)
Related Crates
- adk-rust - Meta-crate with all components
- adk-runner - Execution runtime
- adk-cli - CLI launcher
- adk-telemetry - OpenTelemetry integration
- adk-artifact - Artifact storage
- adk-auth - Authentication (JWT bridge)
- adk-ui - UI protocol support
License
Apache-2.0
Part of ADK-Rust
This crate is part of the ADK-Rust framework for building AI agents in Rust.