Claimed vs Verified: What ERC-8004 Agent Identity Evidence Actually Proves Before an x402 Payment
What ERC-8004 agent identity evidence proves: on-chain getAgentWallet, ENS/DID/email linkage claimed vs verified, and .well-known ownership, before an x402 payment.
An ERC-8004 registration answers one question: did someone mint an agent identity? It doesn't answer the question an agent about to sign an x402 payment actually has: is the party behind this endpoint who they say they are? Those are different claims with different evidence, and a scoring system that blurs them hands out trust it hasn't earned.
This post describes how ContextIQ's Policy Check and ERC-8004 Inspector keep them apart. Every identity signal is labelled verified or claimed, and endpoint ownership is checked against the domain itself. If you're new to the standard, start with What Is ERC-8004?.
The Problem: Registration Is Cheap
Minting an agent ID on the ERC-8004 Identity Registry costs gas and nothing else. The registration file the token points to is self-authored: the registrant chooses the name, the services, and whether to list an ENS name, a DID, or an email address. Anyone can list research-agent.eth without owning it.
So an identity check that only asks "is there a registration, a wallet and a filled-in metadata file?" mostly measures effort to look legitimate. It rewards all of it whether or not any of it was independently checked.
The fix isn't to distrust everything. It's to record, for each signal, who vouches for it.
Three Kinds of Evidence
1. Agent wallet: authoritative, read from the chain
The payment wallet comes from the Identity Registry's getAgentWallet(agentId), not from the registration file. The EIP states that agentWallet is reserved, can't be set through setMetadata(), and is automatically cleared when the agent NFT is transferred, so the new owner must re-verify it.
That last property matters: a wallet that was valid for the previous owner can't silently carry over. The Inspector reports exactly what the call returned:
agentWalletEvidence.status | Meaning |
|---|---|
verified | getAgentWallet returned a non-zero address (isAuthoritative: true) |
zero_address | The call succeeded and returned 0x000… — no wallet set, or cleared by a transfer |
missing | The call reverted |
unknown | The RPC request itself failed, so the chain was never actually asked (isAuthoritative: false) |
The unknown case is the one that's easy to get wrong. Treating a failed RPC call as "no wallet" would penalize an agent for an infrastructure hiccup.
2. Human linkage: declared is not verified
Registration files commonly declare ENS, DID, email and web entries under services (older files used endpoints; both are read). ContextIQ parses these and reports them as:
{
"humanLinkage": {
"status": "claimed",
"confidence": "medium",
"sources": [
{ "type": "ENS", "value": "research-agent.eth", "verification": "declared", "weight": "weak" },
{ "type": "DID", "value": "did:web:research-agent.example", "verification": "declared", "weight": "weak" }
],
"summary": "Agent declares ENS and DID, but no external proof-of-human signal was verified."
}
}
The rules are deliberately strict:
- ENS, DID, email and web values are claimed linkage. We don't resolve the ENS name or the DID document, so they stay
declared. - Confidence is
lowfor one declared type andmediumfor two or more. It never reacheshighfrom self-declared data. externally_verifiedis reserved for evidence that is actually checked: a World ID or Self proof, an Icebreaker credential, or an EAS attestation. No verifier exists yet, so nothing emits that status today. The type is in the response so the shape won't change when one ships.- Malformed values (an "ENS" entry that isn't a
.ethname, a "DID" without adid:prefix) are ignored rather than counted.
3. Endpoint ownership: the domain vouches for the agent
The ERC-8004 spec defines an endpoint domain verification file. A domain that serves an agent's endpoint publishes https://{endpoint-domain}/.well-known/agent-registration.json:
{
"registrations": [
{
"agentId": 22,
"agentRegistry": "eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432"
}
]
}
Only whoever controls the domain can serve that file, so a matching entry ties the on-chain agent to the party operating the endpoint. Policy Check fetches it from the endpoint's own origin (SSRF-guarded) and returns one of four results:
endpointOwnershipEvidence.status | When |
|---|---|
verified | The file lists this agentId on this registry |
mismatch | The file lists other agents on this registry but not this one |
unverified | No file, unreadable file, redirect to another domain, or the agent appears only on a different chain |
not_checked | No endpoint to check |
Two details are worth stating. A missing or unreachable file is unverified, never mismatch: a domain that doesn't publish the file isn't contradicting anything. And a redirect to a different domain is ignored, since otherwise a third party could vouch for the endpoint. A tokenURI hosted on the same domain is noted as corroboration but doesn't count as verification, because the registrant can point the URI anywhere.
How the Evidence Feeds the Decision
Policy Check combines two kinds of input into one pre-payment decision: checks on the x402 endpoint's 402 challenge, and, when you supply an agentId, the evidence about the agent behind it. Each check is reported by name in the reasons list, so a decision can be traced to what produced it.
A few properties are worth stating:
- Verified evidence counts for more than claimed evidence. A self-declared ENS name or email is credited far less than an on-chain read or a domain-published registration, and unverified proof-of-human signals earn nothing.
- Hard failures still block. A malformed challenge, an unreachable endpoint, or an agent ID that isn't registered blocks the payment regardless of how strong the identity evidence is.
- Weak identity behind a valid payment is a warning, not a block. Whether an unproven agent is acceptable is the caller's judgment, so Policy Check says "look closer" rather than deciding for them.
- An ownership mismatch is surfaced as a warning. If the endpoint's domain vouches for a different agent than the one you supplied, the agent ID and the endpoint may not belong together. That is a strong signal rather than proof of fraud.
- No
agentIdmeans identity isn't evaluated. The response saysnot_evaluatedinstead of substituting a default agent, and only the payment checks run.
The weighting behind these checks is not published and may change between releases. Treat the decision and the per-check reasons as the interface, and apply your own policy on top.
What Changes in the API Response
The request is untouched: { "endpoint", "agentId"?, "network"? }. The response gains fields, and reasons keeps its shape.
{
"decision": "allow",
"rubricVersion": 2,
"trustEvidence": {
"agentWallet": { "status": "verified" },
"humanLinkage": { "status": "claimed", "confidence": "medium" },
"endpointOwnership": { "status": "unverified" }
}
}
trustEvidencesummarizes each dimension, and readsnot_evaluatedwhen noagentIdwas supplied.reasonsgains checks for human linkage and endpoint ownership, andagent_wallet_setis nowagent_wallet_verified.rubricVersionrecords which scoring version produced a result, so a stored decision can be read against the right one.- The ERC-8004 Inspector response adds
agentWalletEvidence,humanLinkage,endpointOwnershipEvidenceandtrustEvidenceSummary.
In the UI, each signal carries one of these labels: Verified, Claimed, Unverified, Missing or Mismatch, plus Not evaluated when nothing was checked. "Claimed" is a different color from "Verified" on purpose.
What This Doesn't Prove
- Ownership isn't personhood. A verified
.well-knownfile shows the endpoint's operator registered the agent. It says nothing about whether that operator is a person, a company, or a bot. - ENS and DID aren't resolved. Claimed means claimed. Resolving and verifying them, and checking EAS, Icebreaker, World ID or Self proofs, is where
externally_verifiedwould come from. - DNS races remain. The runtime resolves DNS itself, so a record could change between the safety check and the fetch. Checks and redirect re-validation reduce this but can't pin the IP.
- It's a signal, not a verdict. ERC-8004 is a draft standard, and strong evidence means the identity is better supported, not that a payment is safe.
To see these fields for a real agent, look one up in the ERC-8004 Inspector, or run the combined check with an agent ID and an x402 endpoint in Policy Check. For what to verify on the payment side of the decision, see the x402 payment checklist.
Follow Trango Compute on LinkedIn
We post updates on new tools, context engineering patterns, and LLM cost research.