Learn

A2A extensions: adding what the spec leaves out

How A2A extensions work: URIs, Agent Card declarations, activation with A2A-Extensions, metadata, versioning and limits, and published extensions to check.

An A2A extension is an addition to the protocol that is identified by a URI and defined in its own specification. An agent declares the extensions it supports in capabilities.extensions on its Agent Card, and a client turns one on for a request by naming its URI in the A2A-Extensions service parameter. Extension data travels in the metadata maps of core objects, keyed by the extension URI. Anyone can write one, and the core specification stays unchanged.

The specification points to extensions for the parts it leaves open. Section 7.6 lets an extension define in-band credential exchange for TASK_STATE_AUTH_REQUIRED, and section 7.6.4 names extensions as one place where the meaning of the resulting credential can be defined. Section 3.2.5 says extensions can strongly type metadata. This guide covers how extensions are identified, declared, activated and versioned, what they may not do, and which ones are published today.

Identify: the extension URI

The URI is the extension’s name and its version.

  • It should include a version, such as https://example.com/ext/citations/v1. A breaking change must get a new URI (section 4.6.3).
  • The extensions guide says the specification document should be hosted at that URI, and suggests a permanent identifier service such as w3id.org so the link doesn’t break.
  • Official extensions use the prefix https://a2a-protocol.org/extensions/. The governance document says these URIs are identifiers, and HTTP access to them is not expected.

The A2A project hosts official extensions in repositories named ext-{name} and experimental ones as experimental-ext-{name}, which need a maintainer’s sponsorship. Graduation to official status takes a reference implementation, documentation, evidence of adoption and a vote of the Technical Steering Committee. On 2026-09-26 the a2aproject organization had one extension repository, experimental-ext-oid4vp-auth, and no official ext- repositories.

Declare: capabilities.extensions

Each entry in capabilities.extensions is an AgentExtension:

Field Meaning
uri The extension’s identifier
description How this agent uses the extension
required If true, clients must understand and follow the extension
params Extension-specific configuration, defined by the extension

Illustrative: an agent that offers a citations extension and requires a signing extension.

{
  "capabilities": {
    "streaming": false,
    "extensions": [
      {
        "uri": "https://example.com/ext/citations/v1",
        "description": "Adds source citations to research artifacts",
        "required": false
      },
      {
        "uri": "https://example.com/ext/request-signing/v2",
        "description": "Every request must carry a detached signature from the calling agent",
        "required": true,
        "params": { "algorithms": ["ES256"] }
      }
    ]
  }
}

required: true is a hard dependency for every client, so use it sparingly. The extensions guide says not to mark data-only extensions as required, and to reserve the flag for extensions fundamental to the agent’s function or security, such as message signing. When a card marks an extension as required and the client doesn’t declare support, the agent must return ExtensionSupportRequiredError: -32008 in JSON-RPC, FAILED_PRECONDITION in gRPC, 400 Bad Request over HTTP (sections 3.3.4 and 5.4).

Activate: the A2A-Extensions header

Extensions are off by default, so a client that knows nothing about them gets the plain protocol. To turn some on, the client lists their URIs, comma-separated, in the A2A-Extensions service parameter. JSON-RPC and HTTP+JSON send it as an HTTP header, and gRPC sends it as the metadata key a2a-extensions. The agent activates the ones it supports and ignores the rest. Its response should repeat the header, listing the extensions it actually activated. Version 0.3 called the header X-A2A-Extensions.

Illustrative: a JSON-RPC request that activates the citations extension and carries its data.

POST /a2a/v1 HTTP/1.1
Host: agent.example.com
Content-Type: application/json
A2A-Version: 1.0
A2A-Extensions: https://example.com/ext/citations/v1

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": {
    "message": {
      "messageId": "msg-1",
      "role": "ROLE_USER",
      "parts": [{"text": "Summarize the 2026 freight rate outlook"}],
      "extensions": ["https://example.com/ext/citations/v1"],
      "metadata": {
        "https://example.com/ext/citations/v1": {"style": "short", "maxSources": 5}
      }
    }
  }
}

The response would include A2A-Extensions: https://example.com/ext/citations/v1 if the agent activated it.

Carry data: metadata and the extensions list

Section 4.6.2 names two main extension points. A message can carry typed context from the client, or extra progress information when it is a status message. An artifact can carry typed information about the content it holds. In both, the object’s extensions field lists the URIs that apply, and its metadata map holds the data under a key equal to the URI. Tasks, status and artifact update events, and several requests also have metadata maps.

The extension’s own specification defines what goes inside that entry. The extensions guide says a specification should state at least:

  • The URI or URIs that identify it.
  • The schema and meaning of its params.
  • The schemas of any data exchanged between client and agent.
  • Any new request and response flows, endpoints or other logic.
  • Its dependencies on other extensions. Activating those is the client’s job.

What kind of extension are you writing?

The extensions guide lists four kinds.

Kind What it does Example from the guide
Data-only Adds structured information to the Agent Card without changing requests or responses Data about the agent’s GDPR compliance
Profile Adds structure and state rules to core messages, narrowing what is allowed Requiring every message to use data parts of one schema, or a generating-image sub-state under working
Method Adds new RPC methods, sometimes called extended skills A tasks/search method for task history
State machine Adds states or transitions to the task lifecycle Expressed through metadata, as below

Two limits apply to all of them. An extension must not change core data structures by adding fields or removing required ones; custom attributes go in metadata. And it must not add values to enum types. A new “state” therefore rides on an existing TASK_STATE_* value with a metadata annotation. That keeps core validation working for clients that ignore the extension.

Extension, skill, metadata or binding?

Not every addition needs an extension. The protocol offers four places to put something new, and they solve different problems.

You want to Use Why
Offer a new capability to callers, such as quoting freight A skill on the Agent Card Skills describe what the agent does; the core protocol already carries the request and the result
Pass a little context that only your own client and agent understand Plain metadata Metadata takes any JSON value; with no shared specification, only the two parties who agreed on it can read it
Define data, rules or methods that other implementers should read the same way An extension A URI, a published specification and Agent Card declaration let strangers negotiate it
Carry A2A over a different transport, such as WebSockets A custom protocol binding Bindings change the wire format and are declared in supportedInterfaces, with their own URI and governance tier

The test for an extension is interoperability. If two organizations that have never spoken need to agree on the meaning of a field, write it down as an extension with a versioned URI.

A worked outline

Illustrative: a delivery-window extension for logistics agents.

  1. Kind. A profile extension: it adds a typed field to messages and narrows what a quote artifact must contain.
  2. URI. https://example.com/ext/delivery-window/v1, with the specification published at that address.
  3. Params. The card entry lists the time zones the agent accepts, for example {"timeZones": ["America/Toronto"]}.
  4. Data. Client messages carry earliest and latest ISO 8601 timestamps under the URI key in metadata. Quote artifacts must answer with a window object under the same key.
  5. Required or not. Not required. Clients that don’t activate it still get quotes, just without a guaranteed window.
  6. Errors. Invalid timestamps are a validation failure, which maps to -32602 in JSON-RPC.
  7. Versions. Any breaking change, such as renaming earliest, ships as /v2, and agents may list both URIs during the transition.

Versioning and compatibility

If a client asks for an extension version the agent does not support, the agent should ignore it for that request and continue. If the agent marked that extension as required, it must return an error instead. Either way, it must not fall back to an older version on its own (section 4.6.3). Breaking changes to an official extension also need review by the Technical Steering Committee.

SDKs may implement extensions, and where they do, extensions must be off by default and need explicit opt-in. Extension support is not part of protocol conformance.

Security

The extensions guide gives three rules. Validate every field, parameter and method an extension adds, and treat extension data from another party as untrusted input. Mark an extension as required only when it is fundamental. And give any method an extension adds the same authentication and authorization checks as the core methods, so the extension never becomes a way around the agent’s security controls.

Published extensions you can check

These were verified against their repositories on 2026-09-26.

Extension URI Notes
OID4VP In-Task Authorization, v1 draft (a2aproject/experimental-ext-oid4vp-auth) https://github.com/a2aproject/experimental-ext-oid4vp-auth/tree/main/v1 Experimental. Uses 1.0 shapes. An agent in TASK_STATE_AUTH_REQUIRED puts an OpenID for Verifiable Presentations authorization request in metadata under the extension URI. params.oid4vpVersions lists supported OID4VP versions; declared with required: false
x402 Payments Extension v0.2 (google-agentic-commerce/a2a-x402) https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2 Recommends required: true. Written against 0.3: kind fields, lowercase states, X-A2A-Extensions. Uses input-required for “payment required” and metadata keys such as x402.payment.status
x402 Payments Extension v0.1 https://github.com/google-a2a/a2a-x402/v0.1 Earlier version. The google-a2a/a2a-x402 repository now redirects to google-agentic-commerce/a2a-x402
AP2 A2A extension, from AP2 v0.1.0 https://github.com/google-agentic-commerce/ap2/tree/v0.1 params.roles lists the agent’s AP2 roles: merchant, shopper, credentials-provider or payment-processor. Merchants should mark it required. Carries v0.1 Intent, Cart and Payment Mandates
AP2, current samples https://github.com/google-agentic-commerce/ap2/v1 AP2 v0.2 (2026-04-28) replaced Intent and Cart Mandates with Checkout and Payment Mandates. Its docs have no separate A2A extension page; the Python samples on main declare this URI

Two lessons come out of this table. First, published extensions track different A2A versions, so check which shapes and header name an extension expects before you implement it. Second, the keying style varies: OID4VP nests its data under the extension URI as the specification describes, while x402 uses dotted keys of its own. The x402 v0.2 embedded flow also nests its payment request inside an AP2 CartMandate, a v0.1 object that AP2 v0.2 has since replaced. The A2A extensions page also lists sample extensions in the a2aproject/a2a-samples repository: Secure Passport, Timestamp, Traceability and Agent Gateway Protocol.

Where Emissar Mandate fits

Section 7.6.4 leaves the scope, format, validity and revocation of an in-task credential to implementations, credential issuers or extensions. Emissar’s Mandate module is a proposal for that gap: a scoped, revocable credential bound to one agent, stating what it may do for a specific person or company. It is intended to be carried as an A2A extension. Its status is Spec in progress, and its specification has not been published yet. The multi-turn tasks guide covers what TASK_STATE_AUTH_REQUIRED defines today.

Questions

Do I need permission to publish an A2A extension?
No. Anyone can define, publish and implement one. The governance process of tiers, sponsorship and TSC votes applies only to extensions hosted in the a2aproject GitHub organization.
What happens if a client asks for an extension the agent doesn't support?
The agent ignores it and carries on without it. The exception is an extension the agent itself marks as required: a client that doesn't activate that one gets ExtensionSupportRequiredError (-32008).
Can an extension add a new task state?
It cannot add a value to the TaskState enum or any other enum. The extensions guide says to use existing values and put the extra meaning in metadata, for example a sub-state carried alongside TASK_STATE_WORKING.

Sources

  1. A2A Protocol Specification (sections 3.2.5, 3.2.6, 3.3.4, 4.6, 7.6 and 14.2.2) (accessed )
  2. A2A protocol definition (a2a.proto): AgentExtension, AgentCapabilities, Message, Artifact (accessed )
  3. Extensions in A2A (A2A documentation) (accessed )
  4. A2A Extension and Protocol Binding Governance (accessed )
  5. A2A v0.3.0 extensions guide (X-A2A-Extensions header) (accessed )
  6. a2aproject organization repositories on GitHub (accessed )
  7. OID4VP In-Task Authorization Extension, v1 draft (a2aproject, experimental) (accessed )
  8. A2A x402 Payments Extension v0.2 specification (accessed )
  9. A2A x402 Payments Extension v0.1 specification (accessed )
  10. AP2 v0.1.0: A2A extension document (accessed )
  11. AP2 changelog (v0.2.0, 2026-04-28) (accessed )
  12. AP2 specification (current, Checkout and Payment Mandates) (accessed )
  13. AP2 Python samples: A2A extension URI constant (accessed )
  14. Emissar: Mandate module (accessed )