turul-a2a 0.1.17

A2A Protocol v1.0 server framework
Documentation

turul-a2a

A2A Protocol v1.0 server framework.

Provides the server side of the A2A Protocol: a typed AgentExecutor trait, HTTP + JSON-RPC transports, Server-Sent Events streaming, and a storage abstraction with four parity-proven backends.

Feature flags

Flag Purpose
in-memory Default. Volatile in-process storage.
sqlite SQLx SQLite backend with atomic task + event writes.
postgres SQLx PostgreSQL backend.
dynamodb AWS DynamoDB backend with TTL.
grpc Optional gRPC transport (tonic). HTTP-only deployments pay zero tonic weight.
compat-v03 Opt-in compatibility shim for a2a-sdk 0.3.x / Strands clients.

Storage wiring

Push delivery is strict opt-in at both levels:

  • Storage: InMemoryA2aStorage::new().with_push_dispatch_enabled(true) (and equivalents per backend) so atomic commits write the pending-dispatch marker.
  • Builder: .push_delivery_store(storage.clone()) to register the consumer.

.storage(storage) wires the framework's storage traits (task storage, event store, atomic store, push delivery store, cancellation supervisor) from a single backend. Cross-instance correctness for streaming and push delivery requires they all live on the same backend; the builder enforces this.

let storage = InMemoryA2aStorage::new(); // or SqliteA2aStorage, PostgresA2aStorage, DynamoDbA2aStorage
A2aServer::builder()
    .executor(MyAgent)
    .storage(storage)
    .build()?;

Durable event coordination

Task state and streaming events are written atomically via storage::A2aAtomicStore. The event store is the source of truth; the in-process broker is a local wake-up signal. Terminal replay and Last-Event-ID reconnection work across instances when all replicas share a backend (PostgreSQL, DynamoDB). Subscribers attached while a task is non-terminal receive replay of prior events and then live delivery; subscribing to an already-terminal task returns UnsupportedOperationError per A2A v1.0 §3.1.6 — use GetTask to retrieve the final state.

Multi-instance streaming

The in-process event broker provides local fanout for attached clients on the same instance only. Shared task storage solves request/response correctness across instances; cross-instance streaming coordination relies on the durable event store with monotonic IDs and replay semantics.

gRPC

A third transport alongside HTTP+JSON and JSON-RPC, behind the grpc feature. The default dependency tree does not include tonic.

cargo build -p turul-a2a --features grpc

# Example server + client
cargo run -p grpc-agent --bin grpc-agent
cargo run -p grpc-agent --bin grpc-client -- send "hello"
cargo run -p grpc-agent --bin grpc-client -- stream "hello"

All 11 lf.a2a.v1.A2AService RPCs are served via A2aServer::into_tonic_router() — the single public entry point, which always layers the same Tower auth stack as the HTTP path. Streaming consumes the same durable event store as SSE, with a2a-last-event-id ASCII metadata for resume. grpc-reflection and grpc-health are optional sub-features.

The client wrapper turul_a2a_client::grpc::A2aGrpcClient ships under the same feature flag. Not available under turul-a2a-aws-lambda (Lambda lacks persistent HTTP/2).

Examples

See examples/echo-agent, examples/auth-agent, and examples/grpc-agent in the repository for runnable end-to-end demos.

See the workspace README for the project overview and crate map.

License

Licensed under either MIT or Apache 2.0 at your option.