Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

On Ethereum’s agent registries: ERC-8004

ERC-8004, Trustless Agents, puts agents in three registries on EVM chains:

  • the Identity Registry, an ERC-721 whose token URI names an agent’s registration file;
  • the Reputation Registry, which keeps the feedback clients give an agent;
  • the Validation Registry, which keeps validators’ answers to requests to check an agent’s work.

sion agent erc8004 makes everything those registries take that is the agent’s, or its client’s, to write. It writes each call out as a transaction (chainId, to, data) for a wallet to send. It never sends one, never reads a chain, and needs no RPC provider.

The addresses are those of the reference deployment (erc-8004-contracts). On Ethereum, Optimism, Polygon, Base and Arbitrum One the Identity Registry is 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 and the Reputation Registry 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63. On Sepolia, Base Sepolia, Optimism Sepolia, Arbitrum Sepolia, Polygon Amoy, Linea Sepolia, BNB Smart Chain’s testnet, Avalanche Fuji and Hedera’s testnet they are 0x8004A818BFB912233c491871b3d84c89A494BD9e and 0x8004B663056A597Dffe9eCcC1965A193B7388713. On any other chain, --registry gives the address; none is guessed. No Validation Registry is listed as deployed yet, so validate takes its address.

The registration file

$ sion agent erc8004 card lead --description "Pays Acme's invoices." \
    --a2a https://lead.example/.well-known/agent-card.json --x402 \
    --agent-id 22 --chain 11155111 --out registration.json
wrote lead's registration file: registration.json

The file is the spec’s registration-v1. It holds the agent’s name and description and its services: the A2A card, the MCP server and the web page you name, and always its Siontology DID (did:sion:<chain>:<agent>). Its supportedTrust is reputation and crypto-economic. Both are what the DID leads to on Siontology: the agent’s record of what it was paid for and delivered, and the bonds behind its claims, which an adjudicator can rule against. Once the agent is registered, --agent-id adds its entry (eip155:<chain>:<registry>). --data-uri prints the file as a data: URI too, to keep it wholly on chain. check <file> reads any registration file and checks its type, its name and its entries.

The description is public. It is never taken from the operator’s instructions.

Registering, and binding the agent’s wallet

$ sion agent erc8004 register --uri https://lead.example/agent.json --chain 11155111
{
  "chainId": 11155111,
  "to": "0x8004A818BFB912233c491871b3d84c89A494BD9e",
  "data": "0xf2c298be…",
  "what": "registers an agent whose registration file is at https://lead.example/agent.json"
}

The owner sends register(agentURI) and becomes the token’s owner. The registry sets the agent’s wallet to the owner at first. To make another wallet the agent’s, that wallet signs an EIP-712 AgentWalletSet for the registry (domain ERC8004IdentityRegistry, version 1). wallet signs it with the key in EVM_PRIVATE_KEY, which is read from the environment and kept nowhere. Then it writes setAgentWallet for the owner to send:

$ EVM_PRIVATE_KEY=… sion agent erc8004 wallet 22 --owner 0x1111111111111111111111111111111111111111 --chain 11155111
0x2c7536E3605D9C16a7a3D7b1898e529396a65c23 signs that it is agent 22's wallet until 2026-11-07T08:38:33Z; 0x1111111111111111111111111111111111111111 sends this:
{
  "chainId": 11155111,
  "to": "0x8004A818BFB912233c491871b3d84c89A494BD9e",
  "data": "0x2d1ef5ae…",
  "what": "makes 0x2c7536E3605D9C16a7a3D7b1898e529396a65c23 agent 22's wallet"
}

The registry takes a signature good for at most five minutes by the chain’s clock. wallet signs for four unless told otherwise (--within), so a clock a little ahead of the chain’s does not push it past the limit, and the owner sends the call soon after.

Feedback and validation

A client gives feedback with feedback <agent> --value <decimal> --client <address>, and --tag1, --tag2 and --endpoint to say what it is about. The command writes the spec’s feedback file (--out) and the giveFeedback call, which names the file by its URI (--uri) and its Keccak digest. The value is a decimal: 99.77 is 9977 with two decimals. The registry refuses feedback from the agent’s own owner and its operators.

A validator answers a request with validate --request <digest> --response <0–100> --registry <address>. --found <file> names what it found by its Keccak digest, at --uri. On Siontology, a verifier who rebuilt and scored a release and attested it on its bond (Improving itself) can give the same answer on Ethereum, pointing at its attestation.

What was checked, and what was not

The EIP-712 digest and signature of AgentWalletSet, and the calls register, setAgentWallet, giveFeedback and validationResponse, match those that eth-account 0.13.4 and eth-abi compute from the same input. A signature wallet made through the binary recovers to its wallet there. The unit tests in crates/sion-cli/src/erc8004.rs hold those values. Nothing was sent to a chain, so no deployed registry has accepted these calls.