Version 1.0 renames every operation, changes every enum value, flattens the card and the parts, and rejects a request without
A2A-Version, so a 0.3 client needs a compatibility layer.
The kit's error scenario sends two requests that a 0.3 client would send today. One omits A2A-Version and gets VersionNotSupportedError. The other calls message/send and gets MethodNotFoundError. When you finish this section, you can map a 0.3 request to its 1.0 form, and turn on the 0.3 layer in the reference SDK.
POST /a2a/jsonrpc HTTP/1.1
Host: localhost:41241
Content-Type: application/json
A2A-Version: 1.0
{
"jsonrpc": "2.0",
"id": 3,
"method": "message/send",
…
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32601,
"message": "Method not found"
}
}Original source
title: a 0.3 method name on a 1.0 endpoint
source: capture/out/11-errors.http
lang: http
note: The third record of the error scenario. The message in the params is cut.
---
POST /a2a/jsonrpc HTTP/1.1
Host: localhost:41241
Content-Type: application/json
A2A-Version: 1.0
{
"jsonrpc": "2.0",
"id": 3,
"method": "message/send",
…
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32601,
"message": "Method not found"
}
}Before and after
The project's migration guide lists the changes {{docs whats-new-v1}}, because a major breaking change must come with migration guidance in a separate document {{spec §1.4}}. The table keeps the changes that reach code.
| Area | 0.3 | 1.0 |
|---|---|---|
| Method names | message/send, tasks/get, tasks/resubscribe |
SendMessage, GetTask, SubscribeToTask, the same PascalCase name on every binding {{spec §9.1}} |
| Push config methods | tasks/pushNotificationConfig/set, and /get, /list, /delete |
CreateTaskPushNotificationConfig, and Get, List (plural Configs), Delete |
| Extended card | agent/getAuthenticatedExtendedCard, REST GET /v1/card |
GetExtendedAgentCard, REST GET /extendedAgentCard, no /v1 prefix |
| Task states | "working", "input-required" |
TASK_STATE_WORKING, TASK_STATE_INPUT_REQUIRED {{proto TaskState}} |
| Roles | "user", "agent" |
ROLE_USER, ROLE_AGENT {{proto Role}} |
| Part shape | TextPart, FilePart, DataPart, each with kind |
one Part whose text, raw, url, or data member names the type {{proto Part}} |
| File fields | file.mimeType, file.name, file.fileWithUri |
mediaType, filename, url, flat on the part |
| Stream frames | "kind": "status-update" |
a statusUpdate or artifactUpdate member {{proto StreamResponse}} |
| End of a stream | final: true on the last status update |
the binding closes the stream |
| Card endpoint | url, protocolVersion, preferredTransport, additionalInterfaces |
supportedInterfaces[], each with url, protocolBinding, protocolVersion {{proto AgentInterface}} |
| Extended card flag | supportsAuthenticatedExtendedCard |
capabilities.extendedAgentCard |
| Card security | security |
securityRequirements, each with a schemes map {{proto AgentCard}} |
| Errors | RFC 9457 problem details | google.rpc.Status with ErrorInfo, plus -32008 and -32009 {{spec §5.4}} |
| Version header | none | A2A-Version: 1.0 on every request {{spec §3.6.1}} |
{
"protocolVersion": "0.3",
"url": "https://agent.example.com/a2a",
"preferredTransport": "JSONRPC",
"supportsAuthenticatedExtendedCard": true,
"additionalInterfaces": [...]
}Original source
title: the five card fields that moved
source: research/sources/docs.md
lang: json
note: The 0.3 card example from the migration guide. The first four fields became supportedInterfaces, and the fifth became capabilities.extendedAgentCard.
---
{
"protocolVersion": "0.3",
"url": "https://agent.example.com/a2a",
"preferredTransport": "JSONRPC",
"supportsAuthenticatedExtendedCard": true,
"additionalInterfaces": [...]
}The guide misses one change. The 0.3 flag blocking was false by default, so a send returned at once. Its replacement returnImmediately is also false by default, so a send now waits {{proto SendMessageConfiguration}} {{spec §3.2.2}}. SendMessage shows both modes.
The missing header
An agent must read an empty value as version 0.3 {{spec §3.6.2}}. A 1.0-only interface must then answer VersionNotSupportedError {{spec §5.4}}, as the kit does.
The SDKs differ. JS and Java treat a missing header as 0.3 and reject it on every binding {{sdk-js src/server/version.ts at v1.3.0}} {{sdk-java server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java at v1.4.0.Final}}. Python does so on JSON-RPC and REST {{sdk src/a2a/utils/version_validator.py}}, and Rust on JSON-RPC only {{sdk-rust a2a-server/src/jsonrpc.rs at a2a-server-lf-v0.5.1}}. Go never reads the header, and .NET accepts a missing one {{sdk-go a2a/svcparams.go at v2.6.0}} {{sdk-dotnet src/A2A.AspNetCore/A2AJsonRpcProcessor.cs at v1.0.0-preview2}}. The version header has the full table.
The 0.3 layer in each SDK
During the overlap period, a server can accept both the old and the current forms of a request message {{spec §A.2}}.
- a2a-python 1.2.2. Pass
enable_v0_3_compat=Truetocreate_jsonrpc_routesandcreate_rest_routes, and add anAgentInterfacewithprotocolVersion0.3to the card {{sdk src/a2a/server/routes/jsonrpc_routes.py}} {{sdk src/a2a/server/routes/rest_routes.py}}. The dispatcher routes by method name, somessage/sendreachesJSONRPC03Adapterbefore the version check {{sdk src/a2a/server/routes/jsonrpc_dispatcher.py}}. For gRPC it addsCompatGrpcHandleron the old packagea2a.v1{{sdk src/a2a/compat/v0_3/grpc_handler.py}}. The client needs no switch:ClientFactorypicks a compat transport for an interface below1.0{{sdk src/a2a/client/client_factory.py}}. - a2a-js 1.3.0. Set
legacyCompat: { enabled: true }on each handler. It routes byA2A-Version, with an absent header as0.3{{sdk-js src/server/express/json_rpc_handler.ts at v1.3.0}}. - a2a-go 2.6.0. Mount a second handler from
a2acompat/a2av0under its own URL and advertise a second interface. It routes by URL, never by header {{sdk-go a2acompat/a2av0/jsonrpc_server.go at v2.6.0}}. - a2a-java 1.4.0.Final. Add the
multiversion-jsonrpcormultiversion-restreference module. ItsVersionRoutersends0.3or an absent header to the 0.3 handler {{sdk-java docs/content/dev/compatibility.md at v1.4.0.Final}}. - a2a-dotnet 1.0.0-preview2. Call
MapA2AWithV03Compatinstead ofMapA2A. It routes byA2A-Version{{sdk-dotnet src/A2A.V0_3Compat/V03ServerCompatEndpointExtensions.cs at v1.0.0-preview2}}. - a2a-rs 0.5.1. None {{sdk-rust a2a-client/src/factory.rs at a2a-server-lf-v0.5.1}}.
Where the migration guide is wrong
The proto is normative {{spec §1.4}}, so follow it where the guide names a field or a value the proto lacks.
- The guide named the stream members
taskStatusUpdateandtaskArtifactUpdate. The proto hasstatusUpdateandartifactUpdate(conflict D9). PR #2056 fixed it on main after v1.0.1, not yet released. - The guide added
Task.createdAt,Task.lastModified,configId, and an artifactindexthat the proto lacks (conflict D10). The same PR removed all butindex. - Appendix A.2.2 calls the old flag
supportsExtendedAgentCard. The guide and the SDK saysupportsAuthenticatedExtendedCard(conflict D40), and main has no fix. - The guide puts extensions at
agentCard.extensions. The proto puts them atcapabilities.extensions{{proto AgentCapabilities}}, as extensions explains.
After v1.0.1
No tag newer than v1.0.1 exists. Main has one proto change since the tag: the gRPC url comment, now hostname:port (PR #1997), which closes D34. It is the only entry in the pending 1.0.2 release (PR #2072). Documentation commits on main close D8, D9, D12, and D32, and part of D4, D5, D6, D10, and D23 (the conflict register). Main also adds §7.6.4 on in-task authorization scope (PR #2081), which security schemes quotes.
Branch dev-1.1 changes the task record. Task.generation counts every state change, and GetTaskRequest.currentGeneration lets a client wait for the next one. SendMessageConfiguration.ifGenerationMatch makes a send conditional, and a stale value gets TaskGenerationMismatchError, -32010 (PR #1810). Task.history is deprecated for a timeline of messages and statuses (PR #2129). None of this is released, and no 1.1 date is published.
Original source
- Send `A2A-Version: 1.0` on every request, and set `returnImmediately` where a 0.3 client relied on `blocking: false`.
- Turn on the SDK's 0.3 layer and add a `0.3` interface to the card while old clients remain.
- Follow the proto where the migration guide names a field the proto lacks.
- Treat `generation` and `timeline` as unreleased until a tag carries them.Sources: spec §1.4, §3.2.2, §3.6.1, §3.6.2, §5.4, §9.1, §A.2 (research/sources/specification.md); proto TaskState, Role, Part, StreamResponse, AgentInterface, AgentCard, AgentCapabilities, SendMessageConfiguration (research/sources/a2a.proto); docs/whats-new-v1.md at v1.0.1 (research/sources/docs.md); sdk src/a2a/utils/version_validator.py, src/a2a/server/routes/jsonrpc_routes.py, src/a2a/server/routes/rest_routes.py, src/a2a/server/routes/jsonrpc_dispatcher.py, src/a2a/compat/v0_3/grpc_handler.py, src/a2a/client/client_factory.py at a2a-python 1.2.2; sdk-js src/server/version.ts, src/server/express/json_rpc_handler.ts at v1.3.0; sdk-go a2a/svcparams.go, a2acompat/a2av0/jsonrpc_server.go at v2.6.0; sdk-java server-common/src/main/java/org/a2aproject/sdk/server/version/A2AVersionValidator.java, docs/content/dev/compatibility.md at v1.4.0.Final; sdk-dotnet src/A2A.AspNetCore/A2AJsonRpcProcessor.cs, src/A2A.V0_3Compat/V03ServerCompatEndpointExtensions.cs at v1.0.0-preview2; sdk-rust a2a-server/src/jsonrpc.rs, a2a-client/src/factory.rs at a2a-server-lf-v0.5.1; capture/out/11-errors.http; capture/a2a_ref.py; a2aproject/A2A pull requests #1810, #1997, #2056, #2072, #2081, #2129, main at 679ab3a and branch dev-1.1 at db39eb5