What A2A v1.0 changed in the Agent Card
A2A v1.0 is not a cosmetic renumbering. The transport section of the Agent Card was restructured, which means a v0.x card does not degrade gracefully — it stops describing anything a v1.0 client can address, while still parsing as perfectly good JSON.
Why this one is not a renumbering
Most of what changed in the
A2A specification is a rename you could
handle with sed. The official
what's new in v1.0 page lists
the whole set; two changes to the card are not mechanical:
four separate top-level fields that described how to reach an agent were
replaced by a single ordered array, and the security fields changed shape. That
is why a v0.x card fails silently rather than loudly: a v1.0 client looks for
supportedInterfaces, does not find it, and concludes your agent has no
reachable interface.
The protocol began as a launch at Google and v1.0 shipped on March 12, 2026, with a technical steering committee of representatives from AWS, Cisco, Google, IBM Research, Microsoft, Salesforce, SAP and ServiceNow. The direction of travel is fewer implicit assumptions and more things stated per endpoint instead of per agent.
supportedInterfaces: four fields collapsed into one
In v0.x, reaching an agent meant assembling information from four places:
{
"url": "https://agents.example.com/a2a",
"preferredTransport": "JSONRPC",
"additionalInterfaces": [
{ "url": "https://agents.example.com/grpc", "transport": "GRPC" }
],
"protocolVersion": "0.3.0"
}
The primary endpoint lived in one field, its transport in another, alternatives in a third, and the protocol version applied to all of them at once — which was never quite true. v1.0 states everything per endpoint:
{
"supportedInterfaces": [
{ "url": "https://agents.example.com/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0" },
{ "url": "https://agents.example.com/grpc",
"protocolBinding": "GRPC",
"protocolVersion": "1.0" }
]
}
Three consequences worth internalising:
- Order carries meaning.
preferredTransportdisappeared because position replaced it — the first entry is the preferred interface. Reordering the array is a behavioural change. - Every entry needs all three keys.
url,protocolBindingandprotocolVersion. A partially specified entry is an error, not a fallback. - The vocabulary changed too.
transportbecameprotocolBinding, with core valuesJSONRPC,GRPCandHTTP+JSON. Custom bindings should be identified by a URI so they cannot collide with future core values.
The renames
| v0.x | v1.0 | Note |
|---|---|---|
supportsAuthenticatedExtendedCard | capabilities.extendedAgentCard | Moved inside capabilities, where the other feature flags live |
additionalInterfaces[].transport | supportedInterfaces[].protocolBinding | "Binding" because it names the protocol mapping, not the network transport |
security | securityRequirements | New name and a new shape — see below |
agent/getAuthenticatedExtendedCard | GetExtendedAgentCard | The operation was renamed along with the flag |
Security requirements changed shape
The securitySchemes map survives, but each scheme is now wrapped in a key that
names its type, and the top-level security list became
securityRequirements with a different entry shape. The easiest way to miss it
is that a v1.0 client does not read the old field at all: it sees no
requirements and treats the agent as open.
"securitySchemes": {
"partner-oauth": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "https://sso.example.com/oauth2/token",
"scopes": { "agents.invoke": "Send tasks" }
}
}
}
},
"security": [{ "partner-oauth": ["agents.invoke"] }]
"securitySchemes": {
"partner-oauth": {
"oauth2SecurityScheme": {
"flows": {
"clientCredentials": {
"tokenUrl": "https://sso.example.com/oauth2/token",
"scopes": { "agents.invoke": "Send tasks" }
}
}
}
}
},
"securityRequirements": [
{ "schemes": { "partner-oauth": { "list": ["agents.invoke"] } } }
]
The wrapper keys are apiKeySecurityScheme, httpAuthSecurityScheme,
oauth2SecurityScheme, openIdConnectSecurityScheme and mtlsSecurityScheme;
exactly one per scheme. An OAuth scheme now declares exactly one flow, and the
implicit and password flows are deprecated in favour of authorization code
with PKCE, client credentials, or the new device code flow.
What disappeared
capabilities.stateTransitionHistory is gone. It was a boolean claiming an
agent could report the history of a task's state changes, and it is not part of
the v1.0 AgentCapabilities message. A v1.0 validator flags it as not part of
the specification.
If your agent really does expose task history, declare it as an extension
instead — that is what capabilities.extensions exists for, and an extension
carries a URI you can point at documentation:
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extensions": [
{
"uri": "https://northwind.example.com/a2a/ext/task-history/v1",
"description": "Exposes the full state-transition history of a task.",
"required": false
}
]
}
What did not change
Two things that circulate as "v1.0 changes" are not:
- Skill tags were already required.
tagsis required on every skill in the v0.2.5 and v0.3.0 JSON schemas, and v1.0 keeps it that way. It still breaks cards because nothing fails until a router or validator checks, but a migration does not newly demand it. - provider.organization is not a rename. The provider object has always been
{ organization, url }, both required. If a card saysprovider.name, it was never valid, in any version.
{ "id": "reconcile-payment-batch",
"name": "Reconcile a payment batch",
"description": "Given a bank statement export, match each line to an open
invoice and report exceptions with reasons.",
"tags": ["finance", "invoices", "reconciliation"] }
The discovery path
The standard discovery path is /.well-known/agent-card.json. A2A registers it
as a RFC 8615 well-known URI, it has
been the recommended location since v0.3, and v1.0 keeps it unchanged. The
older /.well-known/agent.json belongs to A2A v0.2 and earlier. The response is
plain JSON; the specification does not require a special media type for the
card.
GET /.well-known/agent-card.json -> 200 application/json GET /.well-known/agent.json -> 308 Location: /.well-known/agent-card.json
The spec also asks servers to send a Cache-Control header with a max-age and
an ETag, so clients can revalidate cheaply.
A card, before and after
{
"name": "Invoice Reconciliation Agent",
"description": "Matches payments to invoices.",
"version": "3.1.0",
"url": "https://agents.northwind.example.com/a2a",
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0",
"supportsAuthenticatedExtendedCard": false,
"provider": { "organization": "Northwind Finance",
"url": "https://northwind.example.com" },
"capabilities": { "streaming": true,
"stateTransitionHistory": true },
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["application/json"],
"skills": [
{ "id": "reconcile", "name": "Reconcile",
"description": "Matches payments.",
"tags": ["finance"] }
]
}
{
"name": "Invoice Reconciliation Agent",
"description": "Matches incoming payments against open invoices, flags
partial and duplicate payments, and drafts follow-ups
for anything it cannot reconcile.",
"version": "3.1.0",
"supportedInterfaces": [
{ "url": "https://agents.northwind.example.com/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0" }
],
"provider": { "organization": "Northwind Finance",
"url": "https://northwind.example.com" },
"capabilities": {
"streaming": true,
"pushNotifications": false,
"extendedAgentCard": false
},
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["application/json"],
"skills": [
{ "id": "reconcile-payment-batch",
"name": "Reconcile a payment batch",
"description": "Given a bank statement export, match each line to an
open invoice and report exceptions with reasons.",
"tags": ["finance", "invoices", "reconciliation"] }
]
}
Strictly, nothing here is new information: the transport fields became one
array, the extended-card flag moved, and stateTransitionHistory is gone. The
v1.0 card above also takes the chance to describe the agent properly, because a
description and tags are what a stranger's router actually reads.
Migrating without stranding existing clients
A2A v0.3 and v1.0 clients fetch the same path, so the discovery URL cannot tell them apart; the card itself has to serve both. If nobody is integrated with you yet, publish the v1.0 card and move on. If you have live v0.3 callers, you have three options, in increasing order of effort:
- Cut over. Replace the card with the v1.0 shape on a scheduled date and tell integrators. Honest, simple, and fine when you know who your callers are.
- Serve a transitional card. Include
supportedInterfacesand retain the legacy top-levelurl,preferredTransportandprotocolVersion, so v1.0 clients read the array and v0.3 clients read the fields. The v1.0 release explicitly allows one card to advertise both generations. - List a versioned interface per generation. Put one entry with
"protocolVersion": "1.0"and another with"0.3"insupportedInterfaces, at the same URL or different ones. The spec lets an agent expose several interfaces for one binding with different versions, and clients pick the first entry they support.
Migration checklist
- Replace
url,preferredTransportandadditionalInterfaceswith one orderedsupportedInterfaces[], preferred entry first. - Give every interface entry all three of
url,protocolBindingandprotocolVersion; renametransporttoprotocolBinding. - Set top-level
versionto your agent's build — not the protocol version you just moved. - Move
supportsAuthenticatedExtendedCardtocapabilities.extendedAgentCard. - Rewrite
securityassecurityRequirements, and wrap every entry ofsecuritySchemesin its type key (for exampleoauth2SecurityScheme). - Delete
capabilities.stateTransitionHistory, or re-model it undercapabilities.extensions. - Check every skill has non-empty
tags, using the words a searcher would use. - Serve the card at
/.well-known/agent-card.jsonas JSON with aCache-Controlheader, and add/.well-known/agent.jsononly if you still support A2A v0.2 clients. - Run the card through the validator, then check the live domain with the well-known URL checker.
The schema reference documents every v1.0 field with its type, requirement level and the mistake most often made with it — useful as the target state while you work through the list above.
Frequently asked questions
Will a v0.x Agent Card still work with v1.0 clients?
Only if it also carries the v1.0 shape. A client that implements only v1.0 looks for supportedInterfaces to find your endpoint; a v0.x card has a top-level url instead, so that client finds no addressable interface. The card parses as JSON and conveys nothing actionable, which is worse than a hard failure because it looks fine. The v1.0 release lets one card advertise both generations, so keep the legacy fields next to supportedInterfaces while v0.3 clients are still calling you.
Where did protocolVersion go?
Into each entry of supportedInterfaces. The protocol version is now a property of an endpoint rather than of the whole agent, which is what lets one agent expose a v1.0 interface and a differently versioned interface alongside it. The top-level version field means your agent build.
Do I have to serve both /.well-known/agent.json and agent-card.json?
No. agent-card.json has been the discovery path since v0.3 and v1.0 keeps it, so every client you are likely to meet fetches it. Only clients from A2A v0.2 or earlier look at agent.json. Serve it as an alias or a 308 redirect if you still support those; otherwise skip it.
Did skill tags or provider.organization change in v1.0?
No. Both were already required in the v0.2.5 and v0.3.0 JSON schemas: every skill needs tags, and a provider needs organization and url. There is no provider.name field to rename. They still trip up migrations because nothing enforced them until a router or validator started checking.
What happened to stateTransitionHistory?
It was removed from capabilities in v1.0. If your agent genuinely exposes task state history, model it as an extension under capabilities.extensions rather than reintroducing the old boolean — a v1.0 validator flags the field as unrecognised.
Is A2A still a Google project?
It began at Google, was donated to the Linux Foundation in 2025, and joined the Linux Foundation's Agentic AI Foundation (AAIF) in August 2026. The v1.0 specification is developed in the open, with a technical steering committee that includes AWS, Cisco, Google, IBM Research, Microsoft, Salesforce, SAP and ServiceNow. Practically, that means the specification is versioned and published independently, which is exactly why pinning a protocol version in each interface entry matters.
References
- A2A protocol specification (a2aproject/A2A)github.com/a2aproject/A2A
- What's new in A2A v1.0a2a-protocol.org/latest/whats-new-v1/
- A2A: a new era of agent interoperability — Google Developers Blogdevelopers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
- RFC 8615 — Well-Known Uniform Resource Identifierswww.rfc-editor.org/rfc/rfc8615
Related tool: Agent Card Validator
Read more guides
Next step
Find out which v0.x fields your card still carries.
The validator detects every pre-1.0 field, names its v1.0 replacement, and reports the rest of the card against the current specification.