From 0.3 to 1.0
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.
Host: localhost:41241
Content-Type: application/json
A2A-Version: 1.0
{
"jsonrpc": "2.0",
"id": 3,
"method": "message/send",
…
}
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, because a major breaking change must come with migration guidance in a separate document. 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 |
| 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 |
| Roles | "user", "agent" | ROLE_USER, ROLE_AGENT |
| Part shape | TextPart, FilePart, DataPart, each with kind | one Part whose text, raw, url, or data member names the type |
| 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 |
| 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 |
| Extended card flag | supportsAuthenticatedExtendedCard | capabilities.extendedAgentCard |
| Card security | security | securityRequirements, each with a schemes map |
| Errors | RFC 9457 problem details | google.rpc.Status with ErrorInfo, plus -32008 and -32009 |
| Version header | none | A2A-Version: 1.0 on every request |
{
"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. SendMessage shows both modes.
The missing header
An agent must read an empty value as version 0.3. A 1.0-only interface must then answer VersionNotSupportedError, as the kit does.
The SDKs differ. JS and Java treat a missing header as 0.3 and reject it on every binding. Python does so on JSON-RPC and REST, and Rust on JSON-RPC only. Go never reads the header, and .NET accepts a missing one. 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.
- a2a-python 1.2.2. Pass
enable_v0_3_compat=Truetocreate_jsonrpc_routesandcreate_rest_routes, and add anAgentInterfacewithprotocolVersion0.3to the card. The dispatcher routes by method name, somessage/sendreachesJSONRPC03Adapterbefore the version check. For gRPC it addsCompatGrpcHandleron the old packagea2a.v1. The client needs no switch:ClientFactorypicks a compat transport for an interface below1.0. - a2a-js 1.3.0. Set
legacyCompat: { enabled: true }on each handler. It routes byA2A-Version, with an absent header as0.3. - 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. - a2a-java 1.4.0.Final. Add the
multiversion-jsonrpcormultiversion-restreference module. ItsVersionRoutersends0.3or an absent header to the 0.3 handler. - a2a-dotnet 1.0.0-preview2. Call
MapA2AWithV03Compatinstead ofMapA2A. It routes byA2A-Version. - a2a-rs 0.5.1. None.
Where the migration guide is wrong
The proto is normative, 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, 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.
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10