ra2a 0.5.0

A Rust implementation of the Agent2Agent (A2A) Protocol SDK
docs.rs failed to build ra2a-0.5.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: ra2a-0.4.0

ra2a

CI License Rust crates.io docs.rs

Comprehensive Rust SDK for the Agent2Agent (A2A) Protocol — client transport, server framework, streaming, gRPC, and multi-backend task storage.

ra2a implements the full A2A protocol specification (v0.3.0) with an idiomatic Rust API — Axum server middleware, reqwest-based client, SSE streaming, gRPC transport, push notifications, and pluggable SQL storage backends. For the upstream protocol specification, see google/A2A.

See Security before using in production.

Quick Start

Add ra2a to your project:

cargo add ra2a

Build an Agent (Server)

use async_trait::async_trait;
use ra2a::{
    error::Result,
    server::{A2AServerBuilder, AgentExecutor, ExecutionContext},
    types::{AgentCard, AgentCapabilities, AgentSkill, Message, Part, Task, TaskState, TaskStatus},
};

struct MyAgent { card: AgentCard }

#[async_trait]
impl AgentExecutor for MyAgent {
    async fn execute(&self, ctx: &ExecutionContext, message: &Message) -> Result<Task> {
        let reply = Message::agent(vec![Part::text("Hello from ra2a!")]);
        Ok(Task::new(&ctx.task_id, &ctx.context_id)
            .with_status(TaskStatus::with_message(TaskState::Completed, reply)))
    }

    async fn cancel(&self, ctx: &ExecutionContext, task_id: &str) -> Result<Task> {
        Ok(Task::new(task_id, &ctx.context_id)
            .with_status(TaskStatus::new(TaskState::Canceled)))
    }

    fn agent_card(&self) -> &AgentCard { &self.card }
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let card = AgentCard::builder("My Agent", "http://localhost:8080")
        .description("A minimal A2A agent")
        .version("1.0.0")
        .skill(AgentSkill::new("chat", "Chat", "General chat", vec![]))
        .build();

    A2AServerBuilder::new()
        .executor(MyAgent { card })
        .host("0.0.0.0")
        .port(8080)
        .cors(true)
        .build()
        .serve()
        .await
}

Talk to an Agent (Client)

use ra2a::client::{A2AClient, Client};

#[tokio::main]
async fn main() -> ra2a::Result<()> {
    let client = A2AClient::new("https://agent.example.com")?;

    // Discover agent capabilities
    let card = client.get_agent_card().await?;
    println!("Agent: {}{}", card.name, card.description.unwrap_or_default());

    // Send a message and stream responses
    let message = ra2a::types::Message::user_text("Hello!");
    let mut stream = client.send_message(message).await?;

    while let Some(event) = futures::StreamExt::next(&mut stream).await {
        println!("{:?}", event?);
    }
    Ok(())
}

Feature Flags

Feature flags keep compile-time dependencies minimal — enable only what you need:

Flag Default Description
client yes HTTP/JSON-RPC client, SSE streaming, card resolver, middleware
server yes Axum HTTP server, event queue, task lifecycle, REST + SSE endpoints
grpc gRPC transport via tonic/prost (requires protobuf)
telemetry OpenTelemetry tracing spans and metrics
postgresql PostgreSQL task store via sqlx
mysql MySQL task store via sqlx
sqlite SQLite task store via sqlx
sql All SQL backends (postgresql + mysql + sqlite)
full Everything (server + grpc + telemetry + sql)
# Server with PostgreSQL storage and telemetry
ra2a = { version = "0.4", features = ["server", "postgresql", "telemetry"] }

# Client only
ra2a = { version = "0.4", default-features = false, features = ["client"] }

# Everything
ra2a = { version = "0.4", features = ["full"] }

Design

Aspect Detail
Protocol version A2A v0.3.0
Transport HTTP/JSON-RPC + SSE streaming + gRPC
Server framework Axum with Tower middleware
Client reqwest + reqwest-eventsource (SSE)
Task storage In-memory (default), PostgreSQL, MySQL, SQLite
Authentication HMAC-SHA256 push notification verification
Serialization serde (JSON) + prost (protobuf)
Async runtime tokio
Linting pedantic + nursery (warn), correctness (deny)

Examples

Run the built-in examples to see ra2a in action:

# Start the server
cargo run --example server --features server

# In another terminal, run the client
cargo run --example client --features client

Security

See SECURITY.md for disclaimers, supported versions, and vulnerability reporting.

Acknowledgments

License

Licensed under either of:

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.