6.2

Extensions

An extension is a URI that a card declares, a client activates per request with A2A-Extensions, and both sides carry as metadata keyed by that URI.

The three cards in 01-agent-cards.http declare no extension, so the planner sends plain requests. A reviewer that returned a citation with each finding would need data the core protocol lacks, and an extension adds it under a URI. When you finish this section, you can read an extension declaration, activate one on a request, and handle a missing required one.

AgentExtension in the card

Extension: an addition to the protocol, identified by a URI and defined by its own specification. An agent declares each one as an AgentExtension in capabilities.extensions, with four optional fields.

  • uri, the unique URI of the extension.
  • description, how this agent uses it.
  • required, true when the client must understand the extension and follow its rules.
  • params, the configuration parameters of the extension, as a JSON object.

Section 4.6.1 puts the array on the AgentCard itself, and the migration guide reads agentCard.extensions. The proto puts it under capabilities, so read capabilities.extensions.

two optional extensions on the §4.6.1 sample cardjsonFull log
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "extensions": [
      {
        "uri": "https://standards.org/extensions/citations/v1",
        "description": "Provides citation formatting and source verification",
        "required": false
      },
      {
        "uri": "https://example.com/extensions/geolocation/v1",
        "description": "Location-based search capabilities",
        "required": false
      }
    ]
  },
The sample card, cut to its capabilities. The same sample sends protocolVersion 0.3 and has a trailing comma (conflict D24).

Activating an extension on a request

The client lists the URIs it wants in the A2A-Extensions service parameter. A2A-Version and A2A-Extensions says how that parameter travels in each binding.

Message.extensions lists the URIs of the extensions that are present in the message or that added to it. The payload sits in metadata under the same URI as key. The specification shows that keying by example only. Artifact.extensions works the same way.

the §4.6.1 request: the header names the extension, and metadata carries its datahttpFull log
POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token
A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

{
  "message": {
    "role": "ROLE_USER",
    "parts": [{"text": "Find restaurants near me"}],
    "extensions": ["https://example.com/extensions/geolocation/v1"],
    "metadata": {
      "https://example.com/extensions/geolocation/v1": {
        "latitude": 37.7749,
        "longitude": -122.4194
      }
    }
  }
}
The HTTP sample under the card in §4.6.1. It omits the REQUIRED messageId (conflict D23).

The guide adds a third step: the response should carry the A2A-Extensions header with every extension that the server activated for that request. The specification has no such rule, and the SDKs differ. The a2a-js server echoes the header on all three bindings. The a2a-go and a2a-java servers echo it only as gRPC response metadata. The a2a-python, a2a-dotnet, and a2a-rs servers never write it. Figure 6.2 shows the exchange.

Fig. 6.2activating an extension, and the error when a required one is missingsequence
Activating an extension, and the error when a required one is missing A sequence with two lifelines: a client and the Research Assistant Agent from the sample card in section 4.6.1 of the specification. The client fetches the card and reads two extensions under capabilities.extensions: https://standards.org/extensions/citations/v1 and https://example.com/extensions/geolocation/v1. It sends a message with the A2A-Extensions header naming the geolocation extension and with latitude and longitude in metadata under that URI. The agent answers 200 and echoes the header, which the extensions guide recommends and the SDKs do differently. A second message without the header gets ExtensionSupportRequiredError, code -32008, when the card marks the extension required. client A2A client Research Assistant Agent the §4.6.1 sample card 1 GET /.well-known/agent-card.json the client reads capabilities.extensions 2 card: capabilities.extensions citations/v1 and geolocation/v1 3 POST /message:send A2A-Extensions: geolocation/v1 metadata keyed by the URI: latitude, longitude 4 200 OK, A2A-Extensions echoed the guide says SHOULD, and SDKs differ 5 POST /message:send, no A2A-Extensions when the card marks the extension required 6 ExtensionSupportRequiredError -32008, HTTP 400, FAILED_PRECONDITION
The card lists the extension, the request names it in A2A-Extensions and keys its data by the URI, and a missing required extension answers -32008. Read top to bottom. Steps 1 to 4 follow the §4.6.1 sample card and request, and the activation steps of the extensions guide. Steps 5 and 6 show the §3.3.4 rule for a card that marks an extension required, which the sample does not. The kit declares no extension, so no capture is shown. URIs are shortened to their last two path segments.

Required extensions and versions

A card can mark an extension required: true. When the client does not declare that extension, the agent must return ExtensionSupportRequiredError: -32008, HTTP 400, or gRPC FAILED_PRECONDITION, as errors tables. Only a2a-java has the check built in. The reference SDK only exposes the requested URIs as requested_extensions and never raises the error.

An extension should put its version in its URI, and a breaking change must get a new URI. An agent ignores an unknown version of an optional extension and returns an error for a required one. It must not switch to an older version of the extension by itself.

Kinds, governance, and what exists

The extensions guide names four kinds. Data-only extensions add structured data to the card. Profile extensions narrow the values that core messages carry. Method extensions add RPC methods. State machine extensions add states, which task and task state rejects (conflict D29).

Two tiers govern extensions in the a2aproject organization: official ones in ext-{name} repositories under the URI prefix https://a2a-protocol.org/extensions/, and experimental ones in experimental-ext-{name}. For SDKs, extensions must be off by default and need an explicit opt-in. A conformant implementation does not have to support extensions.

On 2026-10-06 the organization had no ext- repository, so no official extension exists. One experimental extension exists: experimental-ext-oid4vp-auth, for in-task authorization with OpenID for Verifiable Presentations. Its agent moves the task to TASK_STATE_AUTH_REQUIRED and puts an authorization request in metadata under the extension URI, for a wallet to answer. It builds on in-task authorization, and its README allows breaking changes. The four example extensions that the guide lists are samples in a2a-samples, outside the tiers: timestamp, traceability, secure-passport, and agp.

A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10