What A2A v1.0 changed in the Agent Card

9 min read
A2A v0.xA2A v1.0urlsupportedInterfaces[0].urlpreferredTransportsupportedInterfaces[] orderadditionalInterfacessupportedInterfaces[]protocolVersionsupportedInterfaces[].protocolVersionsupportsAuthenticatedExtendedCardcapabilities.extendedAgentCardsecuritysecurityRequirements (new shape)capabilities.stateTransitionHistoryremoved in v1.0
Four top-level transport fields collapsed into one ordered array, and the security shapes were rewritten. Everything else is a rename or a removal.

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:

v0.x
{
  "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:

v1.0
{
  "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. preferredTransport disappeared 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, protocolBinding and protocolVersion. A partially specified entry is an error, not a fallback.
  • The vocabulary changed too. transport became protocolBinding, with core values JSONRPC, GRPC and HTTP+JSON. Custom bindings should be identified by a URI so they cannot collide with future core values.

The renames

v0.xv1.0Note
supportsAuthenticatedExtendedCardcapabilities.extendedAgentCardMoved inside capabilities, where the other feature flags live
additionalInterfaces[].transportsupportedInterfaces[].protocolBinding"Binding" because it names the protocol mapping, not the network transport
securitysecurityRequirementsNew name and a new shape — see below
agent/getAuthenticatedExtendedCardGetExtendedAgentCardThe 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.

v0.x — type-tagged scheme, scopes as a bare array
"securitySchemes": {
  "partner-oauth": {
    "type": "oauth2",
    "flows": {
      "clientCredentials": {
        "tokenUrl": "https://sso.example.com/oauth2/token",
        "scopes": { "agents.invoke": "Send tasks" }
      }
    }
  }
},
"security": [{ "partner-oauth": ["agents.invoke"] }]
v1.0 — wrapped scheme, schemes/list requirement
"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:

Modelling a removed capability as an extension
"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. tags is 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 says provider.name, it was never valid, in any version.
Per skill — valid in v0.3 and v1.0
{ "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.

Serve the standard path, optionally alias the old one
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

v0.3
{
  "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"] }
  ]
}
v1.0
{
  "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:

  1. 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.
  2. Serve a transitional card. Include supportedInterfaces and retain the legacy top-level url, preferredTransport and protocolVersion, 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.
  3. List a versioned interface per generation. Put one entry with "protocolVersion": "1.0" and another with "0.3" in supportedInterfaces, 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

  1. Replace url, preferredTransport and additionalInterfaces with one ordered supportedInterfaces[], preferred entry first.
  2. Give every interface entry all three of url, protocolBinding and protocolVersion; rename transport to protocolBinding.
  3. Set top-level version to your agent's build — not the protocol version you just moved.
  4. Move supportsAuthenticatedExtendedCard to capabilities.extendedAgentCard.
  5. Rewrite security as securityRequirements, and wrap every entry of securitySchemes in its type key (for example oauth2SecurityScheme).
  6. Delete capabilities.stateTransitionHistory, or re-model it under capabilities.extensions.
  7. Check every skill has non-empty tags, using the words a searcher would use.
  8. Serve the card at /.well-known/agent-card.json as JSON with a Cache-Control header, and add /.well-known/agent.json only if you still support A2A v0.2 clients.
  9. 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

  1. A2A protocol specification (a2aproject/A2A)github.com/a2aproject/A2A
  2. What's new in A2A v1.0a2a-protocol.org/latest/whats-new-v1/
  3. A2A: a new era of agent interoperability — Google Developers Blogdevelopers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
  4. RFC 8615 — Well-Known Uniform Resource Identifierswww.rfc-editor.org/rfc/rfc8615

Related tool: Agent Card Validator

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.