docs / guide

view as .md

Agent-to-agent cards#

An agent card is metadata a service publishes to let other agents discover its authentication requirements and capabilities. Instead of a human reading a documentation page and configuring their client, an agent reads the card, sees what's needed, and acts — no human in the loop.

By the A2A convention, a resource publishes its card at /.well-known/agent.json, relative to its own base URL — the same well-known-path pattern RFC 9728 and Grantor's own discovery document use. Publish yours there so a consuming agent (or an off-the-shelf A2A client) can find it without being told the URL out of band; a consuming agent's first step is fetching https://<resource-host>/.well-known/agent.json.

When a Grantor-gated resource refuses a caller with a 401, the response funnel includes discovery — the URL where that specific resource publishes its deed requirements. An agent card is the inverse: a pre-flight contract, published before authentication is attempted, that tells an agent "if you want to call me, here is what I require." A card that declares securitySchemes with a Grantor deed requirement means: this resource authenticates with deeds; fetch this URL to learn what deed mode to mint, what the challenge endpoint is, and which chain and tenant gate this resource uses.

This is how off-the-shelf agents (Claude et al.) discover Grantor-gated resources without a human hand-wiring each one.

Fragment 1: Agent card deed declaration#

An agent card's securitySchemes field names the deed scheme and links to the resource's discovery document:

{
  "name": "Acme API",
  "description": "An example resource gated with Grantor deeds",
  "version": "1.0.0",
  "baseUrl": "https://api.example.com",
  "securitySchemes": {
    "grantor-deed": {
      "type": "http",
      "scheme": "Grantor-Deed",
      "description": "Grantor deed (zero-knowledge or wallet-signed)",
      "discovery": "/.well-known/grantor-deed",
      "learn": "https://chaingrantor.com/.well-known/grantor-onboard.json"
    }
  },
  "security": [
    { "grantor-deed": [] }
  ]
}

The discovery path is relative to this resource's baseUrl (so https://api.example.com/.well-known/grantor-deed in this example). The learn URL is stable and global — the same for every Grantor-gated resource anywhere, pointing at the onboarding manifest and its narrative twin, so an agent that has never interacted with Grantor before knows where to start.

Fragment 2: Consuming-agent recipe#

An agent fetches the card from /.well-known/agent.json, sees the grantor-deed scheme, and follows this recipe:

0. Fetch the agent card (if not already fetched):
   GET https://api.example.com/.well-known/agent.json
   → { "securitySchemes": { "grantor-deed": { "discovery": "/.well-known/grantor-deed", … } }, … }

1. Fetch the discovery document:
   GET https://api.example.com/.well-known/grantor-deed
   → { "tenant": 1, "audience": "api.example.com", "challenge_endpoint": "/auth/challenge", "modes": ["user-sig", "agent-zk"], "chain": { "id": 8453, "registry": "0x…" }, "origin_vouch": { … } }

2. Fetch a challenge from the endpoint named in the discovery document:
   GET https://api.example.com/auth/challenge
   → { "challenge": "abc123def…" }

3. Mint a deed. For agent-zk (fleet membership):
   - Verify the origin vouch against the origin you are talking to (https://api.example.com).
   - Build a Semaphore membership proof of this tenant's on-chain agent tree.
   - Mint the deed with the proof and the challenge.
   Result: { "mode": "agent-zk", "proof": "…", "challenge": "…", … }

4. Present the deed and challenge in separate headers:
   POST https://api.example.com/auth/token
   X-Grantor-Deed: <base64url-encoded deed JSON>
   X-Grantor-Challenge: abc123def…
   → { "access_token": "…" } (the resource's own session bearer)

The deed (X-Grantor-Deed header) and challenge are always separate — never read the challenge from inside the deed, which would let an attacker pick its own nonce and break the single-use property.

The learn URL (from the card) points an agent to the onboarding flow if it is not yet a tenant: it names the chain, funding, tier fees, and contract calls to become a tenant and enroll an agent key.

Bridge to RFC 9728#

This agent-card scheme serves the same discovery purpose as RFC 9728 OAuth 2.0 Protected Resource Metadata, which a resource also publishes at a well-known path (/.well-known/oauth-protected-resource) for off-the-shelf OAuth clients to discover. In that case, the client is shaped by the OAuth 2.0 spec and reads the metadata there. Here, the agent is shaped by the agent card and reads the discovery document — which is identical in both cases (same tenant, audience, challenge_endpoint, modes, chain, origin_vouch). An MCP-spec client that speaks OAuth 2.0 can use the RFC 9728 path; an agent following this pattern uses the agent card. Both point at the same document.

See also#

This page is also served as Markdown — agents should read that. The whole tree is indexed for machines in llms.txt.