ERC-8004 / Agent identity

Give your agent an identity and a reputation.

Register agents, publish feedback, and read their on-chain reputation. The facilitator sponsors gas on supported networks.

Supported networks

Read from GET /register when this page loads, never typed here:

loading…

Publish feedback under your identity

On the plain path, the facilitator is the author of your rating. A registry records msg.sender as the rater, and on POST /feedback that is us. Whatever name you put in the body, the chain says the facilitator said it. Reputation written that way is worth exactly as much as trusting the facilitator, which is not what any of this is for.

So there are two paths where the rater signs for themselves, and the facilitator only pays:

pathhow the rater stays the authorwhere
POST /feedback/evm/prepare
POST /feedback/evm/submit
EIP-7702: the rater delegates their EOA to a feedback delegate and signs a digest; we send a type-4 transaction to the rater's own address, so the registry sees the rater as msg.sender only where a delegate is deployed and verified on chain — today base, ethereum, polygon, arbitrum, optimism, celo, bsc, monad, arc and base-sepolia. Every other network answers 400, and the table lives in the code rather than in this sentence
POST /feedback/solana/prepare
POST /feedback/solana/submit
a partially-signed transaction: the rater signs as client, the facilitator stays fee payer only submit refuses any transaction that is not byte-for-byte the one it built

Payment evidence for feedback

A rating that anyone can write is a rating anyone will write. Every feedback carries a proof of payment, and the server checks all of it: the transaction exists on that network and succeeded, sits in the block the proof claims, contains a transfer of exactly that amount of that token from payer to payee, the payer is the rater, the payee is an address the identity registry ties to the agent, the block timestamp is inside the freshness window, the hash recomputes, and that (payment, agent) pair has not been spent before.

Two verdicts never block a write, in either phase. If the RPC could not be reached there is no verdict — our outage must not erase somebody's reputation. And the Solana path has no EVM receipt to read, so enforcing a check that never ran would quietly switch Solana reputation off. A gate that fails closed on its own blind spots is a gate that deletes data.

Two things that trip real integrations. Most agents have no wallet set on the registry — measured on Base, six agent ids in a row all read 0x0 — so ownership is read from ownerOf as well, and both are accepted. And a marketplace payment usually carries two transfers, a fee and the net to the agent: the proof must declare the net the payee actually receives, or the gate cannot find it.

Owner lookup and retry behavior

There is no index behind it, and that shapes everything. The registries expose no owner-to-agent mapping, they are not enumerable — totalSupply() reverts on every deployed registry, verified on chain — and at least one chain caps log queries at 2000 blocks. So a cold lookup derives the highest agent id and scans ownership through Multicall3.

  • 404 and 503 are different answers and must not be collapsed. 404 is "this address owns no agent". 503 is "the lookup reached no verdict", and it says retryable. Persisting a 503 as "not registered" is how a transient RPC failure becomes a permanent wrong answer — and on a registration path it mints a second identity for somebody who already had one.
  • A non-zero balance with no token found is a contradiction, not a miss. It means the scan range was wrong. It answers 503, and POST /register refuses to mint on it.
  • The scan has a ceiling and it is visible. Base held 83,984 agents against the 192,000 the scan can walk, measured 2026-09-01; the service warns from 75% of the cap and answers 503 past it. The fix at that point is an owner index, not a bigger number.
  • A registration that timed out is not a registration that failed. The mint may still land. Read it back before retrying.

Solana integration details

It is a different program with its own account layouts, and three things bite. The config address is two hops, not one — a root config holds the collection and the collection seeds the registry config; the legacy single-seed derivation points at an address that was never initialised. Feedback submitted without a score is recorded and never scored: reputation stays at zero however much accumulates, and it is not retroactive. And the program forbids self-feedback, so an identity cannot be rated by its own owner. The recipient is required: the identity always ends up in the wallet that asked for it — registering mints it, initialises its stats and transfers it, in that order.

Read agents and feedback

The routes

MethodRouteWhat it answersMoves money
GET /register Registration endpoint schema, supported networks, and request format no
POST /register Register a new ERC-8004 agent on-chain. Facilitator pays gas. The recipient field is required: the NFT is minted and transferred to that address, never kept by the facilitator. The agent URI must be https:// on a public host or ipfs:// no, but we pay gas
GET /identity/:network/:agentId Get agent identity from Identity Registry no
GET /identity/:network/:agentId/metadata/:key Read a specific metadata key from the agent's on-chain profile (returns hex + UTF-8) no
GET /identity/:network/total-supply Get total number of registered agents on a network no
GET /feedback Feedback submission schema and supported networks no
POST /feedback Submit on-chain reputation feedback (giveFeedback) no, but we pay gas
POST /feedback/revoke Revoke previously submitted feedback no, but we pay gas
POST /feedback/response Append agent response to feedback no, but we pay gas
GET /reputation/:network/:agentId Query reputation summary for an agent no
GET /identity/{network}/owner/{address} which agent an address owns — the lookup with no index behind it. 404 is "owns none"; 503 is "the lookup reached no verdict" and carries retryable: true. Persisting a 503 as "not registered" is how a transient RPC failure becomes a permanent wrong answer no
GET /register/status/{jobId} poll an async registration: pending then mint_confirmed then done or failed. Terminal jobs age out after an hour no

Gasless registration: The facilitator wallet pays all gas fees. With recipient, the NFT is minted then transferred via ERC-721 safeTransferFrom (2 transactions, both paid by facilitator). Note: agentWallet is cleared on transfer and must be re-set by the new owner.

23 networks: ethereum, base, polygon, arbitrum, optimism, celo, bsc, monad, avalanche, scroll, skale, arc, solana + testnets. CREATE2 (EVM) + Agent Registry program (Solana).

ERC-8004 and describe.net

describe.net is a different product that also reads ERC-8004. It is a cross-chain index: it scans every chain's registry events, resolves who owns each agent now rather than who minted it, applies one versioned aggregation policy, and answers a reputation question with a score and its composition. It charges for that work.

This facilitator is the other half. It is a gateway: it writes to one registry at a time and reads one registry at a time, live, for free, and it computes no score. There is no aggregation policy here, no cross-chain view and no ranking — /reputation/{network}/{agentId} hands back what that one registry says and stops.

So the two can disagree, and neither is the other's authority. They answer different questions. Do not treat a number from here as an index-wide score, and do not treat an index score as what a specific registry will say on the next block. And one warning worth borrowing from their measurements rather than restating as ours: an agentId alone identifies nobody. The same id exists on every chain with more agents than that number, and it belongs to different people on each — of 26,736 ids present on two or more chains, they measured zero with the same owner across all of them. The strong key is the wallet.