Thomas Piacentini
← Atelier

Chapitre

gRPC

Texte original · anglais

The gRPC binding is the proto itself: the eleven rpcs of A2AService in package lf.a2a.v1, carried over HTTP/2 with TLS, with the service parameters in metadata.

The planner reads three cards and finds only JSONRPC and HTTP+JSON interfaces, so no call in 19-planner.http uses gRPC. The kit is standard library only, and the standard library has no gRPC, so no capture in this manual shows a gRPC call. The reference SDK's sample agent lists a third interface, protocol_binding='GRPC' at a plain host and port {{sdk samples/hello_world_agent.py}}.

When you finish this section, you can read a GRPC interface, call A2AService from a generated stub, and read its errors and streams.

The service

The binding has four requirements: "gRPC over HTTP/2 with TLS", the normative definition in specification/a2a.proto, "Protocol Buffers version 3", and the A2AService service {{spec §10.1}}. The file declares package lf.a2a.v1, so the full service name is lf.a2a.v1.A2AService {{proto A2AService}}. Its eleven rpcs carry the same PascalCase names as the JSON-RPC methods, and operations by binding lists them with their messages.

Two rpcs return stream StreamResponse: SendStreamingMessage and SubscribeToTask {{proto A2AService}} {{spec §10.7}}. The other nine are unary, and none takes a client stream. Each rpc also carries the google.api.http annotation that defines its HTTP+JSON route, as HTTP+JSON shows:

the streaming send, as the proto defines ittextFull source
  // Sends a streaming message to an agent, allowing for real-time interaction and status updates.
  // Streaming version of `SendMessage`
  rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse) {
    option (google.api.http) = {
      post: "/message:stream"
      body: "*"
      additional_bindings: {
        post: "/{tenant}/message:stream"
        body: "*"
      }
    };
  }
The rpc with its HTTP annotation, complete. The additional_bindings block is the tenant route.
Original source
title: the streaming send, as the proto defines it
source: research/sources/a2a.proto
lang: text
note: The rpc with its HTTP annotation, complete. The additional_bindings block is the tenant route.
---
  // Sends a streaming message to an agent, allowing for real-time interaction and status updates.
  // Streaming version of `SendMessage`
  rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse) {
    option (google.api.http) = {
      post: "/message:stream"
      body: "*"
      additional_bindings: {
        post: "/{tenant}/message:stream"
        body: "*"
      }
    };
  }

A card names this binding with protocolBinding set to GRPC {{proto AgentInterface}}. At the tag the proto wants an absolute HTTPS URL for every interface, while a gRPC client dials a host and port (conflict D34). AgentCard fields notes the same gap. PR #1997 changed the comment on main to the form hostname:port, the one change queued for release 1.0.2, not yet released.

Metadata, errors, and streams

The two service parameters must travel as gRPC metadata {{spec §10.2}}. gRPC lowercases metadata keys, so the keys are a2a-version and a2a-extensions. A server should validate required service parameters, such as A2A-Version, from the metadata {{spec §10.2}}. The §10.2 sample sends a2a-version with the old example value 0.3 {{spec §10.2}}, so send 1.0 from a 1.0 client, as A2A-Version and A2A-Extensions explains.

An error is a google.rpc.Status with status.code, status.message, and status.details {{spec §10.6}}. For an A2A error, the details must include a google.rpc.ErrorInfo message {{spec §10.6}}. Its reason is the error name in upper snake case without Error, such as TASK_NOT_FOUND, and its domain is a2a-protocol.org {{spec §10.6}}. The table in errors gives the status of each error, and FAILED_PRECONDITION covers six of the nine, so read the reason.

A stream is a server-streaming rpc, and each message is one StreamResponse with one of task, message, status_update, or artifact_update {{spec §10.7}} {{proto StreamResponse}}. The stream ends when the rpc completes with its status, and the Go server returns OK when its event sequence ends {{sdk-go a2agrpc/v1/handler.go at v2.6.0}}. Figure follows one streaming call from the request to that end.

Fig. 5.2one SendStreamingMessage call over gRPCsequence
One rpc sends the request with its metadata, the server streams StreamResponse messages until the task ends, and the rpc status closes the stream.
One rpc sends the request with its metadata, the server streams StreamResponse messages until the task ends, and the rpc status closes the stream. Read top to bottom. The client sends one SendMessageRequest with a2a-version in its metadata, and each reply is one StreamResponse payload. Names are the proto's, because the kit has no gRPC capture, so no values are shown. From research/sources/a2a.proto.

Original SVG

Original source
id: fig-grpc-call
kind: sequence
title: one SendStreamingMessage call over gRPC
claim: One rpc sends the request with its metadata, the server streams StreamResponse messages until the task ends, and the rpc status closes the stream.
caption: Read top to bottom. The client sends one SendMessageRequest with a2a-version in its metadata, and each reply is one StreamResponse payload. Names are the proto's, because the kit has no gRPC capture, so no values are shown. From research/sources/a2a.proto.

SDK support

SDK gRPC server gRPC client How to enable it
a2a-python 1.2.2 GrpcHandler {{sdk src/a2a/server/request_handlers/grpc_handler.py}} GrpcTransport {{sdk src/a2a/client/transports/grpc.py}} pip install a2a-sdk[grpc], register the handler as the servicer, and list GRPC in the client factory {{sdk src/a2a/client/client_factory.py}}
a2a-js 1.3.0 grpcService, Node only {{sdk-js src/server/grpc/grpc_service.ts at v1.3.0}} GrpcTransport add GrpcTransportFactory, which the default factory omits {{sdk-js src/client/factory.ts at v1.3.0}}
a2a-go 2.6.0 a2agrpc/v1.NewHandler {{sdk-go a2agrpc/v1/handler.go at v2.6.0}} a2agrpc/v1.WithGRPCTransport add the transport option, which the default client omits {{sdk-go a2aclient/factory.go at v2.6.0}}
a2a-java 1.4.0.Final transport/grpc and the Quarkus reference/grpc server client/transport/grpc add the Maven modules {{sdk-java README.md at v1.4.0.Final}}
a2a-dotnet 1.0.0-preview2 none, only the name constant {{sdk-dotnet src/A2A/Client/ProtocolBindingNames.cs at v1.0.0-preview2}} none A2A.Grpc.AspNetCore and A2A.Grpc exist on main, not yet released
a2a-rs, a2a-grpc 0.3.9 GrpcHandler in the a2a-grpc crate GrpcTransport in the same crate register it yourself, because the client factory lists JSON-RPC and HTTP+JSON only {{sdk-rust a2a-client/src/factory.rs at a2a-server-lf-v0.5.1}}

The servers differ on the version check: the Python, Go, and Rust gRPC servers never read a2a-version, as the table in A2A-Version and A2A-Extensions shows.

One custom binding exists in the project today, SLIMRPC: Protocol Buffers RPC over SLIM instead of HTTP/2. A card names it https://a2a-protocol.org/bindings/experimental-slimrpc/v1, and its repository marks it experimental. A custom binding should have a URI as its identifier {{spec §5.8}}, and the project's guide gives the rules for one {{docs custom-protocol-bindings}}.

Original source
- Generate the stub from `specification/a2a.proto`, package `lf.a2a.v1`, and keep its rpc names.
- Send `a2a-version` and `a2a-extensions` as lowercase metadata keys on every call.
- Read `ErrorInfo.reason` from `status.details`, because `FAILED_PRECONDITION` covers six A2A errors.
- Register the gRPC transport yourself in the JS, Go, and Rust client factories.

Sources: spec §5.8, §10, §10.1, §10.2, §10.6, §10.7 (research/sources/specification.md); proto A2AService, AgentInterface, StreamResponse (research/sources/a2a.proto); docs custom-protocol-bindings (research/sources/docs.md); sdk samples/hello_world_agent.py, src/a2a/server/request_handlers/grpc_handler.py, src/a2a/client/transports/grpc.py, src/a2a/client/client_factory.py (a2a-python 1.2.2); sdk-go a2agrpc/v1/handler.go, a2aclient/factory.go at v2.6.0; sdk-js src/server/grpc/grpc_service.ts, src/client/factory.ts at v1.3.0; sdk-java README.md at v1.4.0.Final; sdk-dotnet src/A2A/Client/ProtocolBindingNames.cs at v1.0.0-preview2; sdk-rust a2a-client/src/factory.rs at a2a-server-lf-v0.5.1; capture/out/01-agent-cards.http, 19-planner.http; capture/README.md

Code et livrables 1
Ce que vous en retenez

Enregistré dans votre carnet sur cet appareil.

Sources et limites

Les repères de lecture sont déclaratifs. Les résultats de tests sont enregistrés séparément ; ils valent pour les cas exécutés.

AI Engineering from Scratch · 3f9715c · MIT

Télécharger ce fichier ↓