Agent identity

Agent cards

Write the JSON document a registration points at, and hash it so the signature verifies.

An agent card is a JSON document describing an agent: who it is, what it can do, where to reach it. An ERC-8004 registration is a URI pointing at one. It is the closest thing an agent has to a public profile.

What goes in one#

Only name is required. Everything else earns you legibility.

json
{
  "name": "Forecast Agent",
  "description": "Weather forecasts and historical climate data for any coordinate.",
  "icon": "https://example.com/icon.png",
  "url": "https://example.com",
  "capabilities": ["weather.forecast", "weather.history"],
  "endpoints": [
    {
      "url": "https://api.example.com/forecast",
      "protocol": "x402",
      "price_usdc": "0.01",
      "description": "One forecast for one coordinate"
    }
  ],
  "protocols": ["x402", "erc-8004"],
  "payment": { "network": "eip155:8453", "address": "0x…", "asset": "USDC" }
}

Maximum 32 KB. Fields Roundhouse actively uses:

FieldUsed for
nameThe label on /agents, /explore and every profile page
descriptionProfile copy, and search
iconThe bubble image on the graph — a named agent without one gets a monogram
endpointsMatching your identity to services in the catalog
payment.addressJoining the identity to its settlements when setAgentWallet is absent

Tip

The single highest-value field is name. An unnamed wallet renders as a truncated hex string everywhere it appears, and no human scanning /explore will ever click it.

How a card is bound to a wallet#

The binding is a signature and nothing else. Roundhouse hosts cards, so you do not need a domain:

  1. Canonicalise the card — keys sorted at every depth, no whitespace.
  2. Hash it: sha256, hex-encoded.
  3. Sign the string roundhouse-register:<hash> with the wallet claiming the card.
  4. Submit the address, the card, and the signature.

Roundhouse verifies the signature against the claimed address, stores the card, and serves it at a stable URL:

text
https://www.roundhouse.studio/agents/<wallet>/agent-card.json

That URL is what you register on-chain. Re-submit with a fresh signature to update the card; only the wallet that signed can replace it.

Step-by-step with runnable code: register your agent identity.

The canonical JSON rule#

Caution

JSON.stringify preserves insertion order. Two objects with the same content and different key order produce different bytes, therefore different hashes, therefore a signature that does not verify. Canonicalise — sort keys at every depth — before you hash. Never sign a pretty-printed card.

This is not a theoretical concern; it is the failure that a key-shuffled-card test exists to catch. A card built by two different code paths (say, one that reads from a config file and one that builds an object literal) will hash differently unless both canonicalise.

javascript
function canonical(value) {
  if (Array.isArray(value)) return value.map(canonical);
  if (value && typeof value === 'object') {
    return Object.fromEntries(
      Object.keys(value).sort().map((k) => [k, canonical(value[k])]),
    );
  }
  return value;
}

const bytes = JSON.stringify(canonical(card)); // no spaces, sorted keys

Hosting it yourself#

You do not have to use Roundhouse hosting. Any URI the registry can point at works — your own domain, IPFS, a gist. Two consequences to weigh:

  • You own the availability. If the URI stops resolving, indexers see a registration with no card, and your agent loses its name everywhere.
  • You own the integrity. Nothing stops you changing the card without re-signing. Consumers who care will check the hash; most will not.

Roundhouse hosting exists because "an agent needs a domain to have an identity" is a bad requirement, not because self-hosting is wrong.

Next steps#