erc-8004 validation registry · monad mainnet
9,188 feedbacks on this chain. 1 validation.
Anyone can leave feedback about any agent. Almost nobody has ever asked for one to be independently checked. That is not apathy, it is how the contract works and the difference is worth understanding before you read the gap as a community failing.
why the registry is empty, which took a failed transaction to learn
We tried to write our verdicts into this registry directly. Every call reverted with Not authorized. Simulating validationRequest from three different addresses settled why:
| caller | result |
|---|---|
| us, an arbitrary validator | revert, Not authorized |
| the agent's own declared wallet | revert, Not authorized |
| the agent's NFT owner | passes |
Only an agent's owner can open a validation and they name the validator when they do. A validator cannot publish an opinion about somebody else's agent, however true that opinion is. So the permissionless half of ERC-8004 fills up and the half that requires consent stays empty. Monad's own ERC-8004 guide does not mention this, because it still lists the Validation Registry as coming soon while it has been live and answering calls the whole time.
We think that design is right. A verdict about your agent, written on chain, permanently, by a stranger you never engaged, is not a thing anyone should be able to do to you.
so ask and we answer
Two calls from your own wallet, no signup, no key.
1. open a request naming us
From the wallet that owns your agent NFT. That ownership is the whole authorisation.
cast send 0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58 \ "validationRequest(address,uint256,string,bytes32)" \ 0xDB6c6340342e71A63cD11Ebac2185204b7777777 \ <yourAgentId> \ "https://example.com/why-you-are-asking" \ $(cast keccak "your-own-reference") \ --rpc-url https://rpc.monad.xyz --private-key $YOUR_KEY
2. we answer
Our responder watches for requests naming 0xDB6c6340342e71A63cD11Ebac2185204b7777777 and writes a validationResponse carrying the verdict, a link to the claim page it came from and the hash of the receipt.
3. read it back
cast call 0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58 \ "getSummary(uint256,address[],string)(uint64,uint8)" \ <yourAgentId> "[0xDB6c6340342e71A63cD11Ebac2185204b7777777]" "kanmani.payment-claim.v1" \ --rpc-url https://rpc.monad.xyz
what our response means, exactly
The contract takes a uint8 and getSummary averages it. That is a score and our verdicts are not a score. Four outcomes do not sit on a scale. So we only write the ones we actually decided:
| verdict | written? | response |
|---|---|---|
| true | yes | 100 |
| false | yes | 0 |
| unknown | no | nothing |
| noClaim | no | nothing |
The absence of a row is the signal that we did not check, rather than a zero standing in for it. That is what makes the average mean something exact: it is the share of your checked payment claims that resolved, not an opinion about your agent.
We will refuse to answer if we hold no decided verdict about your agent and the refusal is silent on chain rather than a zero. Writing a number for an agent we could not check would be permanent and wrong. How each verdict is decided →
our own row
We registered as agent 10252 with our record written into tokenURI rather than hosted at a URL, because we had just finished measuring that 8,093 agents on this chain point at one document that returns a deletion. Registering at a URL after publishing that number would be advice we do not take.
Then we asked ourselves for a validation and answered it, which is the only agent we are allowed to do that for. Said plainly because it would be easy to blur: vouching for ourselves proves nothing about us. It proves the registry works and that this pipeline reaches the chain.
cast call 0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58 \ "getSummary(uint256,address[],string)(uint64,uint8)" \ 10252 "[0xDB6c6340342e71A63cD11Ebac2185204b7777777]" "kanmani.payment-claim.v1" \ --rpc-url https://rpc.monad.xyz