# 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. ```listing 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}} | ```listing 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](#s-send-message) 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](#s-version-and-extension-headers) 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=True` to `create_jsonrpc_routes` and `create_rest_routes`, and add an `AgentInterface` with `protocolVersion` `0.3` to the card {{sdk src/a2a/server/routes/jsonrpc_routes.py}} {{sdk src/a2a/server/routes/rest_routes.py}}. The dispatcher routes by method name, so `message/send` reaches `JSONRPC03Adapter` before the version check {{sdk src/a2a/server/routes/jsonrpc_dispatcher.py}}. For gRPC it adds `CompatGrpcHandler` on the old package `a2a.v1` {{sdk src/a2a/compat/v0_3/grpc_handler.py}}. The client needs no switch: `ClientFactory` picks a compat transport for an interface below `1.0` {{sdk src/a2a/client/client_factory.py}}. - **a2a-js 1.3.0.** Set `legacyCompat: { enabled: true }` on each handler. It routes by `A2A-Version`, with an absent header as `0.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/a2av0` under 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-jsonrpc` or `multiversion-rest` reference module. Its `VersionRouter` sends `0.3` or 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 `MapA2AWithV03Compat` instead of `MapA2A`. It routes by `A2A-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 `taskStatusUpdate` and `taskArtifactUpdate`. The proto has `statusUpdate` and `artifactUpdate` ([conflict D9](#s-ref-sources)). [PR #2056](https://github.com/a2aproject/A2A/pull/2056) fixed it on main after v1.0.1, not yet released. - The guide added `Task.createdAt`, `Task.lastModified`, `configId`, and an artifact `index` that the proto lacks ([conflict D10](#s-ref-sources)). The same PR removed all but `index`. - Appendix A.2.2 calls the old flag `supportsExtendedAgentCard`. The guide and the SDK say `supportsAuthenticatedExtendedCard` ([conflict D40](#s-ref-sources)), and main has no fix. - The guide puts extensions at `agentCard.extensions`. The proto puts them at `capabilities.extensions` {{proto AgentCapabilities}}, as [extensions](#s-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](https://github.com/a2aproject/A2A/pull/1997)), which closes D34. It is the only entry in the pending 1.0.2 release ([PR #2072](https://github.com/a2aproject/A2A/pull/2072)). Documentation commits on main close D8, D9, D12, and D32, and part of D4, D5, D6, D10, and D23 ([the conflict register](#s-ref-sources)). Main also adds §7.6.4 on in-task authorization scope ([PR #2081](https://github.com/a2aproject/A2A/pull/2081)), which [security schemes](#s-security-schemes-and-in-task-authorization) 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](https://github.com/a2aproject/A2A/pull/1810)). `Task.history` is deprecated for a `timeline` of messages and statuses ([PR #2129](https://github.com/a2aproject/A2A/pull/2129)). None of this is released, and no 1.1 date is published. ```takeaways - 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