JSON-RPC vs gRPC for A2A: two bindings for one protocol
A2A's JSON-RPC binding sends JSON over HTTP with SSE streaming. Its gRPC binding sends Protocol Buffers over HTTP/2. How the two compare and when to offer both.
The JSON-RPC binding is for carrying A2A as JSON-RPC 2.0 requests over ordinary HTTPS, with Server-Sent Events for streaming, so any HTTP client can talk to an agent. The gRPC binding is for carrying A2A as strongly typed Protocol Buffers messages over HTTP/2, with generated clients and server-streaming RPCs, for teams already running gRPC.
Both carry the same protocol. Section 5.1 of the A2A specification requires every binding an agent offers to provide the same operations, equivalent results, consistently mapped errors and the same authentication schemes. The choice between them is about infrastructure and clients. It never changes what an agent can do.
Status as of September 26, 2026. JSON-RPC and gRPC are two of the three standard bindings in A2A 1.0, alongside HTTP+JSON. A2A is a Linux Foundation project; its latest release, v1.0.1, shipped on May 28, 2026. JSON-RPC 2.0 is a small specification from the informal JSON-RPC Working Group, dated 2010-03-26 and last updated 2013-01-04. gRPC is an incubating project of the Cloud Native Computing Foundation, accepted on February 16, 2017.
What the JSON-RPC binding is for
JSON-RPC 2.0 is a transport-agnostic remote procedure call format. A request is a JSON object with jsonrpc, method, params and id. A response carries the same id and either a result or an error with a numeric code, a message and optional data. The specification reserves -32700 to -32603 for parse, request, method, parameter and internal errors, and -32000 to -32099 for implementation-defined server errors.
Section 9 of the A2A specification fixes the rest:
- Transport. JSON-RPC 2.0 over HTTP(S), with
application/jsonfor requests and responses. - Method names. PascalCase, matching the gRPC service:
SendMessage,GetTask,CancelTaskand so on. A2A 0.3 used names such asmessage/send. - Service parameters.
A2A-Version,A2A-Extensionsand credentials travel as HTTP headers. - Streaming.
SendStreamingMessageandSubscribeToTaskanswer withtext/event-stream. Each event’sdatais a complete JSON-RPC response with the request’sidand aStreamResponseinresult. - Errors. A2A errors use codes
-32001to-32009, such as-32001for a missing task. Thedatafield is an array of objects, each with an@typekey, typicallygoogle.rpc.ErrorInfo.
A task-not-found error in this binding, as the specification shows it:
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32001,
"message": "Task not found",
"data": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "TASK_NOT_FOUND",
"domain": "a2a-protocol.org",
"metadata": { "taskId": "nonexistent-task-id", "timestamp": "2025-11-09T10:30:00.000Z" }
}
]
}
}
Everything is readable JSON over HTTPS. You can send a request with curl, inspect it in any proxy, and serve it from platforms that handle plain HTTP requests, including serverless runtimes.
What the gRPC binding is for
gRPC is a remote procedure call framework. Services are defined in Protocol Buffers, clients and servers are generated from the definition, and calls run over HTTP/2. It supports four kinds of method (unary, server streaming, client streaming and bidirectional streaming), deadlines, per-call metadata, and a fixed set of status codes from OK to UNAUTHENTICATED.
Section 10 of the A2A specification sets these requirements:
- Transport. gRPC over HTTP/2 with TLS.
- Definition. The normative
a2a.proto, packagelf.a2a.v1, Protocol Buffers version 3. Servers implement theA2AServiceservice. - Service parameters. Sent as gRPC metadata, which gRPC lowercases, so
A2A-Versionarrives asa2a-version. - Streaming. Server-streaming RPCs that return
StreamResponsemessages. - Errors. A
google.rpc.Statuswith a gRPC status code, such asNOT_FOUNDfor a missing task orFAILED_PRECONDITIONfor a task that cannot be canceled. A2A errors must include agoogle.rpc.ErrorInfodetail withreason(for exampleTASK_NOT_FOUND) anddomainset toa2a-protocol.org.
An excerpt of the service definition, with the HTTP annotations removed:
service A2AService {
rpc SendMessage(SendMessageRequest) returns (SendMessageResponse);
rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse);
rpc GetTask(GetTaskRequest) returns (Task);
rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse);
}
The gRPC binding gives you typed stubs in every gRPC language, binary encoding, and the interceptors, deadlines and load balancing your gRPC stack already provides. A2A uses only unary and server-streaming methods.
Side by side
| JSON-RPC binding | gRPC binding | |
|---|---|---|
| Purpose | Carry A2A as JSON-RPC 2.0 over plain HTTPS | Carry A2A as typed Protocol Buffers RPCs |
| Layer | A2A protocol binding (specification section 9) | A2A protocol binding (specification section 10) |
| Who talks to whom | Any HTTP client and an A2A server | A gRPC client, usually generated from a2a.proto, and an A2A server |
| Transport | HTTP(S) with application/json; SSE for streaming |
HTTP/2 with TLS; server-streaming RPCs |
| Discovery | Agent Card entry with protocolBinding JSONRPC and an HTTPS URL |
Agent Card entry with protocolBinding GRPC; the proto gives the address as host:port |
| Auth | Schemes from the Agent Card, sent as HTTP headers | The same schemes, sent as gRPC metadata |
| State | Tasks and contexts defined by A2A; each HTTP request stands alone | The same tasks and contexts; streams are server-streaming calls |
| Governance and status | Part of A2A 1.0 (Linux Foundation); JSON-RPC 2.0 last updated 2013 | Part of A2A 1.0 (Linux Foundation); gRPC is a CNCF incubating project |
A few details differ in ways that matter to implementers:
| JSON-RPC binding | gRPC binding | |
|---|---|---|
| Encoding | JSON with camelCase fields and ProtoJSON enum strings such as TASK_STATE_COMPLETED |
Binary Protocol Buffers |
| Error shape | JSON-RPC error object, A2A code, data array |
google.rpc.Status, gRPC code, details list |
| Tooling | Any HTTP client, curl, standard proxies |
Generated stubs; gRPC-aware proxies and tools |
| Browsers | Possible with an HTTP client that reads the response stream | Needs gRPC-Web and a proxy such as Envoy; gRPC-Web supports unary and server streaming only |
When to use the JSON-RPC binding
Offer JSON-RPC when you want the widest reach: outside agents from unknown vendors, simple scripts, and platforms that serve plain HTTP. It is the easiest binding to debug by hand, and it runs anywhere an HTTPS endpoint runs. If you publish one binding for the public internet, this is the lowest barrier for callers.
When to use the gRPC binding
Offer gRPC when your agents and clients already live in a gRPC environment: internal service meshes, polyglot teams that rely on generated code, and calls where binary encoding and HTTP/2 connection reuse matter. Check that every hop between client and agent, including load balancers and gateways, passes HTTP/2 end to end.
Using both
An agent may declare several interfaces in supportedInterfaces, in preference order. Clients must pick the first entry they support and use that entry’s URL. A common pattern is JSON-RPC for external callers and gRPC for internal ones, both backed by the same task store.
Keep them identical in behaviour. Section 5.1 requires the same operations, results, error meanings and authentication across bindings, so test each operation against both, including refusals such as UnsupportedOperationError and VersionNotSupportedError. Push notifications are not part of this choice: webhook calls always use plain HTTP and the JSON payloads of the HTTP+JSON binding, whichever binding created the task.
Common misconceptions
“A gRPC agent speaks a different protocol.” It speaks the same A2A operations with the same data model. Only the encoding, error envelope and streaming mechanism change.
“The JSON-RPC binding still uses message/send.” That was A2A 0.3. Version 1.0 uses PascalCase names such as SendMessage, and a request without an A2A-Version header is treated as 0.3.
“A gRPC interface URL starts with https://.” The proto describes the gRPC address as host:port, for example grpc.example.com:443. The specification’s sample Agent Card uses an HTTPS-style URL for its gRPC entry, a known inconsistency; follow the proto and make sure your clients accept what you publish.
“JSON-RPC batches and notifications work in A2A.” JSON-RPC 2.0 defines both. A2A’s binding section describes neither, so do not assume an agent accepts them.
Questions
- Does a client need to support both bindings?
- No. A client may use any binding the agent declares in supportedInterfaces, and should prefer earlier entries. Supporting more than one lets a client fall back when its first choice is unavailable, which the specification recommends.
- Do the two bindings behave differently?
- They must not. Section 5.1 requires every binding an agent offers to provide the same operations, semantically equivalent results, consistent error mapping and the same authentication schemes.
Sources
- A2A Protocol Specification, sections 5 (binding requirements), 9 (JSON-RPC binding) and 10 (gRPC binding) (accessed )
- A2A protocol definition (a2a.proto): package lf.a2a.v1, A2AService, AgentInterface (accessed )
- A2A releases on GitHub (v1.0.1, May 28, 2026) (accessed )
- JSON-RPC 2.0 Specification (origin date 2010-03-26, updated 2013-01-04) (accessed )
- gRPC: Core concepts, architecture and lifecycle (accessed )
- gRPC: Status codes and their use in gRPC (accessed )
- gRPC-Web README (proxy requirement, streaming support) (accessed )
- CNCF project page: gRPC (incubating, accepted February 16, 2017) (accessed )