# klieo-a2a
Durable A2A v1.0 protocol layer atop klieo-bus traits.
Part of the [klieo](https://crates.io/crates/klieo) Rust agent framework.
## Quickstart — laptop-dev
```toml
[dependencies]
klieo-a2a = { version = "3", features = ["test-fixtures"] }
```
```rust
use std::sync::Arc;
use klieo_a2a::{A2aDispatcher, handler::EchoHandler};
# fn run() {
let dispatcher = A2aDispatcher::local(Arc::new(EchoHandler::default()));
# let _ = dispatcher; }
```
`A2aDispatcher::local(handler)` bakes in `AllowAnonymous` + a fresh
in-process `MemoryBus` pubsub. Gated behind the `test-fixtures`
feature (CWE-1188): production builds without the feature cannot reach
the permissive authenticator. For production wire your own
`Authenticator` via `A2aDispatcher::builder()` (see HTTP/SSE section
below).
## Cargo features
| `http` | off | HTTP/SSE transport per A2A v1.0 §9.4.2 (single `POST /a2a` endpoint). See HTTP/SSE section below. |
| `conformance` | off | Exposes `pub mod conformance` — the conformance test suite + harness `cargo-klieo` consumes. |
| `test-fixtures` | off | Exposes `EchoHandler` (no-auth in-mem) for the conformance suite. Activates `klieo-auth-common/test-fixtures` so `AllowAnonymous` is reachable. **Never** in production. |
## Status
`3.x` — stable. See [`docs/SEMVER.md`](https://github.com/mohrimic/klieo/blob/main/docs/SEMVER.md).
## HTTP/SSE transport
`klieo-a2a` ships an HTTP/SSE transport behind the `http`
cargo feature. Single `POST /a2a` endpoint per A2A v1.0
§9.4.2 with JSON-or-SSE response negotiation based on
JSON-RPC method.
```toml
[dependencies]
klieo-a2a = { version = "3", features = ["http"] }
klieo-auth-common = "3"
```
```rust
use klieo_auth_common::AllowAnonymous;
use klieo_a2a::handler::EchoHandler;
use klieo_a2a::http::A2aHttpServer;
use klieo_a2a::task_store::A2aTaskStore;
use klieo_a2a::A2aDispatcher;
use std::sync::Arc;
use tokio_util::sync::CancellationToken;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let dispatcher = Arc::new(
A2aDispatcher::builder()
.handler(Arc::new(my_handler()))
.authenticator(Arc::new(AllowAnonymous))
.with_in_process_pubsub()
.build()?,
);
let kv = my_kv_store();
let task_store = Arc::new(
A2aTaskStore::new(kv, klieo_a2a::task_store::DEFAULT_BUCKET.into())
.with_event_sink(dispatcher.event_sink()),
);
let cancel = CancellationToken::new();
let server = Arc::new(A2aHttpServer::new(dispatcher, task_store, cancel));
server.serve_http("127.0.0.1:8080".parse()?).await?;
Ok(())
}
```
**Streaming methods.** `SendStreamingMessage` and
`SubscribeToTask` return `text/event-stream`; all other
methods return `application/json`.
**Security boundary.** The HTTP layer adds no authentication
beyond what the configured `Authenticator` enforces on the
JSON-RPC payload. Bind `127.0.0.1` and front with an
auth-enforcing reverse proxy for any non-localhost
deployment. Plain HTTP only — terminate TLS at the proxy.
See [`docs/adr/adr-013-a2a-http-sse-transport.md`](../../docs/adr/adr-013-a2a-http-sse-transport.md)
for the design rationale and out-of-scope items.
## License
MIT — see [`LICENSE`](https://github.com/mohrimic/klieo/blob/main/LICENSE).