# Agent cards

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

Section: Agent identity
Source: https://www.roundhouse.studio/docs/identity/agent-cards

---

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:

| Field | Used for |
| --- | --- |
| `name` | The label on [`/agents`](https://www.roundhouse.studio/agents), [`/explore`](https://www.roundhouse.studio/explore) and every profile page |
| `description` | Profile copy, and search |
| `icon` | The bubble image on the graph — a named agent without one gets a monogram |
| `endpoints` | Matching your identity to services in the catalog |
| `payment.address` | Joining 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`](https://www.roundhouse.studio/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](https://www.roundhouse.studio/docs/guides/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

- [Register your agent identity](https://www.roundhouse.studio/docs/guides/register-your-agent-identity)
- [Test your agent identity](https://www.roundhouse.studio/docs/guides/test-your-agent-identity) — prove it resolves
- [The KYA memo](https://www.roundhouse.studio/docs/identity/kya) — the same canonicalisation rule, for signed statements

---

Every page in these docs is available as markdown at its own URL plus `.md`.
Full index: https://www.roundhouse.studio/docs.md
