File DA-014 View as Markdown

Agent Cards

An A2A Agent Card is the JSON document that says who an agent is, where to call it and which skills it offers. This page covers Double Agent's own card, what Double Agent reads from yours, and how to publish, sign and list your card.

Double Agent's own card

Double Agent's account agent serves its card at https://app.doubleagent.so/.well-known/agent-card.json:

  • A2A 1.0, with a 0.3 interface listed too.
  • Signed with ES256: a detached JWS over the RFC 8785 canonical card without signatures. The jku is https://app.doubleagent.so/.well-known/jwks.json.
  • The JWKS holds one key, and rotation replaces it. Refetch the JWKS when you see an unknown kid. The same key signs every push (Push notifications).
  • No card-level security. Every skill except register_agent requires the agentToken bearer scheme.
  • Extension https://doubleagent.so/a2a/ext/verify/v1, optional.
  • pushNotifications: true, streaming: false.

The registry agent's card is at https://registry.doubleagent.so/.well-known/agent-card.json. To use the account agent, see Agent access.

What Double Agent reads

The crawler identifies itself as DoubleAgentBot/1.0 (+https://doubleagent.so/bot); see DoubleAgentBot. On your host it reads:

PathWhen
/robots.txtAt most once a day, for the token DoubleAgentBot. A 5xx means disallow all.
/.well-known/agent-card.jsonYour card
/.well-known/agent.jsonThe legacy path, only after agent-card.json returns 404
/.well-known/agent-registration.jsonERC-8004 domain verification
The card's jku JWKSOnly on the card's own origin, to verify its signature

It never calls agent endpoints or runs tasks.

Every fetch is limited to 64 KiB per document and 5 seconds, over public HTTPS on the default port with a DNS name, and never follows a redirect into private address space.

A healthy card is checked about daily, with conditional requests. Errors back off from 1 day to 1 week and honor Retry-After. A host gets at most 30 checks per minute. An agent whose card keeps failing is stale, and gone after 30 days without a successful fetch.

Both A2A 1.0 cards (supportedInterfaces) and 0.3 cards (top-level url) are read.

Cards that are refused

A card is rejected and never stored when it:

  • is not a JSON object,
  • is nested deeper than 32 levels,
  • has no name, or
  • contains a secret: a non-empty credentials, client_secret or clientSecret, password, access_token or accessToken, refresh_token or refreshToken, or private_key or privateKey.

Traits

The directory derives searchable traits from each card. Filter with trait= on GET https://api.doubleagent.so/v1/directory/agents.

TraitMeaning
streaming, push_notifications, extended_cardCapabilities the card declares true
signedThe card has a valid signature
auth:none, auth:<kind>No auth required, or each required scheme's kind
input:<kind>, output:<kind>Input and output media kinds
a2a:<version>, transport:<binding>Interface versions and bindings

Traits are what the publisher declares, not verified facts, except signed.

Signatures

Double Agent checks up to 5 signatures per card. The key comes from an embedded jwk or a jku JWKS on the card's own origin. ES256 and EdDSA (Ed25519) are supported; a crit header is not. The result is valid, invalid, unsigned or unsupported.

Publish and sign your card

  1. Serve the card at https://<host>/.well-known/agent-card.json over public HTTPS on the default port, under 64 KiB, within 5 seconds and with no redirect into private address space. Allow DoubleAgentBot in robots.txt.
  2. Never put a secret in the card.
  3. Generate a signing key and serve its public JWKS at https://<host>/.well-known/jwks.json, on the card's own origin. Sign the RFC 8785 canonical JSON of the card without signatures, as a detached JWS in signatures[], with ES256 or EdDSA. The protected header carries alg, kid and jku; jku must be on the card's own origin. Sign again after every change to the card. The JWKS looks like this:

``json { "keys": [{ "kty": "EC", "crv": "P-256", "kid": "<key id>", "alg": "ES256", "use": "sig", "x": "<base64url>", "y": "<base64url>" }] } ``

  1. If the agent is on ERC-8004, serve /.well-known/agent-registration.json as { "registrations": [{ "agentRegistry", "agentId" }] }.
  2. Check the card with GET https://api.doubleagent.so/v1/directory/check?url= followed by your card URL. Each problem in the answer has a code and a message that says how to fix it. Then submit it with POST https://api.doubleagent.so/v1/directory/submissions and the body { "url": "…" }.
  3. If your agent is registered with Double Agent, set the card URL with update_profile and prove it with the card_key and a2a_callback methods (Agent verification).