A2A-Version and A2A-Extensions
Two service parameters travel as HTTP headers or gRPC metadata on every request, and a missing A2A-Version means 0.3, which a 1.0 agent must refuse.
The kit sends test-runner a SendMessage with only Host and Content-Type headers, as a client that forgot the version would. The agent answers -32009 and reports the request as 0.3 (no header), in exchange 2 of 11-errors.http. Every other request in the captures carries A2A-Version: 1.0.
When you finish this section, you can set both headers in any binding and predict what each SDK does without a version.
Service parameters
Service parameter: an entry in a key-value map that carries context or parameters that apply to every operation. The keys are case-insensitive strings, and the values are case-sensitive strings. The specification defines two, A2A-Version and A2A-Extensions, and reserves the prefix a2a- for its own. Each binding says how they travel: as HTTP request headers in JSON-RPC and HTTP+JSON, and as metadata keys in gRPC. A custom binding must document how it carries service parameters.
The IANA templates for both headers cite section 3.2.5 of the specification. That is the metadata section, where the parameters are §3.2.6 (conflict D17). Issue #2305 tracks it, still open.
A2A-Version
A version is Major.Minor, such as 1.0, and requests, responses, and Agent Cards should not carry a patch number. A client must send the A2A-Version header with every request, and a 1.0 client sends 1.0. A server has two duties: process the request with the semantics of that version, and return VersionNotSupportedError when the interface does not support it. The empty case has a fixed meaning: an agent must read an empty value as version 0.3. So a client that forgets the header gets 0.3 semantics from an agent that still serves 0.3, and this error from one that does not:
Host: localhost:41241
Content-Type: application/json
…
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32009,
"message": "Protocol version not supported",
…
"requested": "0.3 (no header)",
"supported": "1.0"VersionNotSupportedError is -32009 in JSON-RPC, 400 in HTTP+JSON, and FAILED_PRECONDITION in gRPC, with the reason VERSION_NOT_SUPPORTED, as errors lists. The version to send comes from the card: each supportedInterfaces entry declares its own protocolVersion. An agent can expose several interfaces on the same transport with different versions, as AgentCard fields shows.
Three samples in the specification send A2A-Version: 0.3, and the gRPC sample in §10.2 sends the same value as metadata. Never copy a sample's value into a 1.0 client (conflict D39). §3.6.1 also allows a client to send A2A-Version as a request parameter instead of a header. Yet both JSON bindings require the header (conflict D31). The reference SDK reads only the header, and the kit reads both, so send the header.
What each SDK does without the header
| Implementation | Missing or empty header | Accepted values | Where it checks |
|---|---|---|---|
kit, a2a_ref.py | refused as 0.3 (no header) | exactly 1.0, from the header or the query parameter | JSON-RPC and HTTP+JSON |
| a2a-python 1.2.2 | read as 0.3, then refused | 1, 1.0, 1.0.0, and 1.5, because only the major must be 1 | JSON-RPC and HTTP+JSON, never gRPC |
| a2a-js 1.3.0 | read as 0.3, refused unless the card lists it | only the strings the card declares for that binding, so 1.0.0 is refused | all three bindings |
| a2a-java 1.4.0.Final | read as 0.3, then refused | the same major, in major.minor form, so 1 is refused | all three, with gRPC UNIMPLEMENTED instead of FAILED_PRECONDITION |
| a2a-go 2.6.0 | accepted | anything, because no server code reads the header | nowhere |
| a2a-dotnet 1.0.0-preview2 | accepted as 1.0 | 1.0 or 0.3, with 0.3 processed as 1.0 | JSON-RPC only |
| a2a-rs, a2a-server 0.5.1 | read as 0.3, then refused | major 1 | JSON-RPC only |
Every client in the list sends 1.0 on each call, and the Python and JS clients send it on the card fetch too. So send the literal string 1.0, never a patch number, and never rely on a server to refuse a missing header.
A2A-Extensions
A2A-Extensions is a comma-separated list of the extension URIs that the client wants for the request. It is one header field in both JSON bindings and one metadata entry in gRPC. §4.6.1 also allows JSON-RPC request parameters as the mechanism, while §9.2 requires the header, so send the header (conflict D30). The reference SDK's with_a2a_extensions helper joins the URIs with commas on the client, and its server reads them into the call context. What the server does with them, the payload keyed by URI, and ExtensionSupportRequiredError are in extensions.
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10