OpenA2A/specs
did:opena2a0.3 (draft)Registered in the W3C DID Extensions registry (PR #717 merged 2026-07-04)

Decentralized Identifier Method

A W3C DID method where did:opena2a:<type>:<id> resolves over HTTPS to a DID Document, so any verifier can fetch an agent's public key and trust endpoints.

The question it answers

“What is this agent called, and how do I look it up?”

If you know one thing already

It’s like DNS + a certificate authority's directory.

Why it exists

Before you can trust an agent, you have to be able to name it , and look that name up. On the web, a domain name resolves through DNS to an address, and a certificate ties that name to a key. Agents need the same thing: a stable, globally-unique identifier that anyone can resolve to a public key and a set of trust endpoints.

did:opena2a is that identifier. It is a W3C Decentralized Identifier method. A DID like did:opena2a:agent:acme/billing resolves, over plain HTTP, to a DID Documentcontaining the subject's verification key and service endpoints for trust lookup, signed proofs, and badges. Today the reference resolver returns the registry's signing key for every DID, not the agent's own key.

The identifier, decoded

Every did:opena2a identifier has three parts after the method prefix: a resource type, a resource id, and an optional fragment pointing at a key or endpoint.

did-method-opena2a.md, syntaxabnf
opena2a-did   = "did:opena2a:" resource-type ":" resource-id [ "#" fragment ]
resource-type = lowercase letters and "_"      ; agent, mcp_server, authority, ...
resource-id   = unreserved chars + ":" + "/" + "@"   ; case-preserving
fragment      = "#key-1", "#trust-lookup", ...

# Example identifiers
did:opena2a:registry:opena2a.org
did:opena2a:authority:gov.uk
did:opena2a:agent:acme/billing-agent#key-1
did:opena2a:mcp_server:@modelcontextprotocol/server-filesystem
Note

Why the id is case-preserving

The resource id is never lowercased, because scoped package names like @modelcontextprotocol/server-filesystem are case-sensitive. The method prefix and type, however, are always lowercase.

Registered resource types

registry
An OpenA2A Registry instance, the trust root itself.
authority
A naming authority (usually a domain) recognized as a root or delegated trust anchor.
publisher
A vetted publisher of one or more catalogued resources.
agent
An autonomous agent (A2A or otherwise).
mcp_server
A Model Context Protocol server.
ai_tool / llm / skill
A catalogued AI tool, large language model, or reusable agent skill.

What resolution returns

Resolving a DID returns a JSON-LD DID Document conforming to W3C DID Core. The key fields: a verificationMethodholding the Registry's Ed25519 public key, and service endpoints for trust queries.

DID Document (abridged)json
{
  "@context": ["https://www.w3.org/ns/did/v1", ".../ed25519-2020/v1"],
  "id": "did:opena2a:mcp_server:@modelcontextprotocol/server-filesystem",
  "verificationMethod": [{
    "id": "...#registry-key",
    "type": "Ed25519VerificationKey2020",
    "controller": "did:opena2a:registry:opena2a.org",
    "publicKeyMultibase": "z6Mk..."
  }],
  "service": [
    { "type": "TrustLookup", "serviceEndpoint": "https://api.oa2a.org/api/v1/trust/query?..." },
    { "type": "TrustProof",  "serviceEndpoint": "https://api.oa2a.org/api/v1/trust/proof?..." },
    { "type": "TrustBadge",  "serviceEndpoint": "https://api.oa2a.org/badge/..." }
  ],
  "created": "2026-02-15T19:24:01Z",
  "updated": "2026-05-14T08:11:33Z"
}
Key idea

The controller is the Registry

Notice the controller is did:opena2a:registry:opena2a.org, not the subject. The Registry holds the key that signs statements about every resource it names. That single fact defines the trust model below.

How resolution works

Read (resolve) is a single HTTP GET against a Registry you choose to trust. For signature verification, a consumer also consults the Registry's /.well-known/opena2a document for the full set of currently-valid keys (so a rotated key still verifies).

Resolving did:opena2a:agent:acme/billing
Consumerverifier
Registryresolver you trust
GET /api/v1/did/did:opena2a:agent:acme/billing
↻ look up resource by type + id
200 · DID Document (application/did+ld+json)

Cache-Control: max-age=300

GET /.well-known/opena2a (valid keys)
publicKeys[], verify signatures against any
request response↻ local / internal step

The honest trust model

did:opena2a is deliberately registry-mediated, not fully decentralized like did:key or a ledger method. The spec states the trade plainly:

“A verifier trusts a registry's assertions about a did:opena2a subject exactly as much as it trusts the registry that issued the DID, and it pins that registry (Section 6.1).”

In return for that trust, resolution yields far more than a key: a live trust score, signed proofs, scan history and badge endpoints. The spec is candid about the cost, a single reference Registry is a point of failure, and lists the mitigations: 5-minute cache headers, a signed offline trust bundle, key rotation with overlap windows, and federation (multiple registries resolving the same method).

If you know DNS and CAs

The web
did:opena2a
Domain name
→
Resource idagent:acme/billing
DNS resolver
→
Registry resolverGET /api/v1/did/…
CA root key
→
Registry signing keycontrols every DID Document
Key rotation + overlap
→
/.well-known/opena2a publicKeys[]old + new both valid
A directory you query, signed by an authority you choose to trust.

How it applies to agents

  • It gives every agent, tool, MCP server and authority one canonical name the rest of the stack can point at.
  • It is the identifier substrate beneath AIP, ATX and ATP, they all name their subjects with did:opena2a.
  • Because the controller key is the Registry's, verifying any signature about a subject reduces to verifying a Registry signature, one key to reason about, rotated transparently.