livery_grpc_a2a

The Agent2Agent gRPC binding, built on livery_grpc for the wire and barrel_a2a for the protocol. Serve an A2A agent over gRPC, or talk to one.

It adds no transport and no protocol of its own. livery_grpc carries the gRPC framing; barrel_a2a owns the objects, the task lifecycle and the binding-neutral engine. This package is the adapter between them: a2a.proto messages in, barrel_a2a_server_core:call/4 out.

Why a separate package

A gRPC user should not take on an A2A implementation, and an A2A user should not take on gpb and a code generation step. barrel_a2a's decision record 0005 sets out the split and the two contracts it rests on: the binding-neutral barrel_a2a_server_core:call/4, and the barrel_a2a_client_transport behaviour for the client side.

Install

Add the package to your rebar.config:

{deps, [
{livery_grpc_a2a, "~> 0.1.0"}
]}.

It brings livery_grpc, livery and barrel_a2a with it. The modules use -moduledoc, so you need OTP 27 or later; CI runs OTP 28.

Serve an agent

{ok, Server} = barrel_a2a_server:start(Card, #{
handler => my_agent,
listen => false %% gRPC is the transport here
}),
{ok, _} = livery_grpc:start_server(#{
port => 50051,
services => [livery_grpc_a2a:service(Server)]
}).

Talk to an agent

{ok, Agent} = barrel_a2a_client:connect(<<"http://127.0.0.1:50051">>, #{
transports => [{<<"GRPC">>, livery_grpc_a2a_client}],
prefer => [grpc]
}),
{ok, {task, Task}} = barrel_a2a_client:send(Agent, <<"hello">>).

See the A2A guide, and the changelog for what each release carries.

Tests

rebar3 eunit # codec, including the schema vectors
rebar3 ct # everything below, skipping what is not installed
make interop # the reference SDKs: Python, Go and JavaScript
make check # the lot, plus dialyzer, xref, elvis and erlfmt

eunit runs 120 vendored schema vectors, one canonical instance of each A2A type, twice over: every vector round trips through to_pb and back with nothing lost or invented, and the JSON the codec writes is validated against the official A2A JSON Schema bundle that barrel_a2a ships in priv. The vectors live in test/schema_vectors; see its VENDORED.md for where they come from and how to update them.

ct starts a real agent, serves it over gRPC and drives it three ways: through barrel_a2a_client over the gRPC transport, through a raw livery_grpc_client, and through grpcurl against server reflection.

Interop drives the same agent from three independent SDKs over gRPC, none of which shares code with this one: a2a-python, a2a-go and @a2a-js/sdk, seven scenarios each. Every group skips when its toolchain is absent, so rebar3 ct never needs any of them. See test/interop/README.md.

docs/compliance.md maps every RPC, wire requirement and error rule to the test that proves it.

License

Apache 2.0.