Rust SDK for the Agent2Agent (A2A) Protocol with full v0.3.0 spec Client/Server, gRPC transport, and pluggable task storage
ra2a is a Rust SDK for the Agent2Agent (A2A) Protocol, maintained by community developer qntx. A2A is an open standard hosted by the Linux Foundation for interoperable communication between AI Agents, complementary to MCP (agent-to-tool).
Project Nature#
Unofficial A2A Protocol SDK (community implementation); official A2A SDKs are Python/JavaScript/Java/C#/.NET/Golang.
Core Capabilities#
- Full implementation of 11 JSON-RPC methods in A2A v0.3.0 spec
- Event-driven server:
AgentExecutor → EventQueue → RequestHandlerpipeline - Composable Axum handlers (
a2a_router), user controls routing, listener, TLS, and middleware - Transport-agnostic client with
CallInterceptormiddleware and automatic streaming fallback - gRPC transport support (via tonic/prost)
- Push Notification configuration with HMAC-SHA256 verification
- Pluggable SQL task storage (PostgreSQL/MySQL/SQLite)
Component Structure#
| Crate | Description |
|---|---|
ra2a | Main SDK — Client, Server, Types, gRPC, task storage |
ra2a-ext | Extension package — ExtensionActivator, MetadataPropagator interceptors (WIP) |
JSON-RPC Method Support#
| Method | Description |
|---|---|
message/send | Send message, receive Task or Message |
message/stream | Send message, receive SSE event stream |
tasks/get | Get task by ID (optional history) |
tasks/list | List tasks with pagination/filtering |
tasks/cancel | Request task cancellation |
tasks/resubscribe | Reconnect to in-progress task event stream |
tasks/pushNotificationConfig/* | Push Notification Webhook CRUD |
agent/getAuthenticatedExtendedCard | Get authenticated extended Agent Card |
Feature Flags#
| Feature | Default | Description |
|---|---|---|
client | yes | HTTP/JSON-RPC client, SSE streaming, card resolver, interceptors |
server | yes | Composable Axum handlers, event queue, task lifecycle, SSE streaming |
grpc | — | gRPC transport (requires protobuf compiler) |
telemetry | — | OpenTelemetry tracing spans and metrics |
postgresql / mysql / sqlite | — | SQL task storage (via sqlx) |
full | — | All features |
Security Model#
Supports 5 security schemes aligned with OpenAPI 3.0:
| Scheme | Description |
|---|---|
| API Key | Static key in Header/Query/Cookie |
| HTTP Auth | Bearer token or Basic authentication |
| OAuth 2.0 | Authorization code, Client credentials, Device code, Implicit flows |
| OpenID Connect | OIDC discovery-based authentication |
| Mutual TLS | Client certificate authentication |
Layered Architecture#
| Layer | Key types | Role |
|---|---|---|
| Server | AgentExecutor, EventQueue, DefaultRequestHandler | Event-driven Agent execution; composable Axum handlers |
| Client | Client, Transport, CallInterceptor | Transport-agnostic client with middleware |
| Types | AgentCard, Task, Message, Event | A2A v0.3.0 type definitions |
| Storage | TaskStore, PushConfigStore | Pluggable persistence |
| gRPC | GrpcTransport, GrpcServiceImpl | Alternative transport (tonic/prost) |
Task Lifecycle#
9 states, terminal states are Completed / Failed / Canceled / Rejected:
Submitted → Working → Completed
→ Failed
→ Canceled
→ Rejected
Input Required ←→ Working
Auth Required ←→ Working
Unknown (initial/query state)
Agent Discovery#
Agents publish AgentCard at /.well-known/agent-card.json, describing identity, capabilities, skills, transport, and security requirements.
Installation#
# Basic installation (client + server enabled by default)
ra2a = "0.8"
# Client only
ra2a = { version = "0.8", default-features = false, features = ["client"] }
# With PostgreSQL and telemetry
ra2a = { version = "0.8", features = ["server", "postgresql", "telemetry"] }
# Full features
ra2a = { version = "0.8", features = ["full"] }
Server Example#
use ra2a::{
server::{AgentExecutor, Event, EventQueue, RequestContext, ServerState, a2a_router},
types::{AgentCard, Message, Part, Task, TaskState, TaskStatus},
};
struct EchoAgent;
impl AgentExecutor for EchoAgent {
fn execute<'a>(
&'a self, ctx: &'a RequestContext, queue: &'a EventQueue,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(async move {
let input = ctx.message.as_ref()
.and_then(ra2a::Message::text_content)
.unwrap_or_default();
let mut task = Task::new(&ctx.task_id, &ctx.context_id);
task.status = TaskStatus::with_message(
TaskState::Completed,
Message::agent(vec![Part::text(format!("Echo: {input}"))]),
);
queue.send(Event::Task(task))?;
Ok(())
})
}
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let card = AgentCard::new("Echo Agent", "http://localhost:8080");
let state = ServerState::from_executor(EchoAgent, card);
let app = axum::Router::new().merge(a2a_router(state));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?;
axum::serve(listener, app).await
}
Client Example#
use ra2a::{
client::Client,
types::{Message, MessageSendParams, Part, SendMessageResult},
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_url("http://localhost:8080")?;
let msg = Message::user(vec![Part::text("Hello!")]);
let result = client.send_message(&MessageSendParams::new(msg)).await?;
Ok(())
}
Use Cases#
- Building A2A-compatible Rust Agent servers
- Implementing A2A clients to connect remote Agents
- High-performance memory-safe Agent-to-Agent communication infrastructure
- Task orchestration and state management in multi-Agent collaboration systems
Pending Information#
| Item | Status | Notes |
|---|---|---|
| v1.0 protocol support | Pending | README states v1.0 not yet officially released, will follow up after release |
| Independent security audit | Not conducted | README explicitly states no independent audit |
| ra2a-ext completeness | WIP | README marks ra2a-ext as Work In Progress |
| docs.rs latest build | Failed | docs.rs shows 0.8.0 build failed, latest successful build is 0.4.0 |