On January 29th, agents got a permissionless identity layer on Ethereum mainnet. A real handle, a real reputation board, no gatekeeper. It's good plumbing. It also means I can manufacture a five star agent in three lines of script, because on a permissionless registry, identity is free, and anything free can be Sybil'd.
Let me back up and give the standard its due first, because it earned it.
ERC-8004, "Trustless Agents," deployed reference contracts to mainnet on January 29, 2026. The author list is not a side project: MetaMask, the Ethereum Foundation, Google, and Coinbase, extending Google's A2A (agent to agent) protocol on-chain instead of leaving it as a JSON schema floating in a spec doc somewhere. By mid February, thousands of agents had registered, feedback was flowing, and for the first time you had a chain-native answer to "who is this agent and what has it done before." No central issuer. No revoker. Any agent, anywhere, gets a handle that nobody can take away or silently blacklist.
That's the pitch, and it's a genuinely good one. Crypto has spent years building programmable money and basically nothing on programmable identity for non-human actors. ERC-8004 is the first serious attempt at the second thing, and it's three registries stacked on top of each other, each doing one job.
Identity Registry, Reputation Registry, Validation Registry. Read → write → verify. Let's go through them, because the architecture is clean and worth understanding before I tell you where it breaks.
The Identity Registry is an ERC-721 with URIStorage. Each agent gets minted a token, agentId, and tokenURI(agentId) resolves to a registration file that describes the agent: its capabilities, its endpoints, its keys. It's the same "NFT points at metadata" pattern you've seen a thousand times for profile pictures, applied to something that actually matters.
The resolve path looks like this:
// Identity Registry, sketch of the resolve path
interface IIdentityRegistry {
function tokenURI(uint256 agentId) external view returns (string memory);
function ownerOf(uint256 agentId) external view returns (address);
}
// reading it: onchain ID -> registration file -> capability claims
async function resolveAgent(registry: IdentityRegistry, agentId: bigint) {
const uri = await registry.tokenURI(agentId);
const registrationFile = await fetch(uri).then(r => r.json());
return {
owner: await registry.ownerOf(agentId),
capabilities: registrationFile.capabilities,
endpoints: registrationFile.endpoints,
publicKeys: registrationFile.keys,
};
}That's it. On-chain ID, off-chain (or on-chain, doesn't matter for the pattern) registration file, capability claims. Nothing exotic. The interesting design choice is what's not in this contract: any check on who's allowed to mint, any requirement that the claims in the registration file are true. It's a permissionless address book. It will happily register a real production agent right next to a script running in a loop on someone's laptop, and it has no opinion about which is which.
That's not a bug. It's the whole point of "permissionless." Keep it in mind for later.
The Reputation Registry gives you a standard interface to post feedback about an agent and fetch feedback about an agent. Aggregation can happen on-chain (composable, cheap, dumb) or off-chain (expensive to build, can be as sophisticated as you want). Structurally it's identical to a Yelp review or an Amazon star rating: anyone can post, anyone can read.
That's the thing to internalize. It is a bulletin board where anyone can pin a note. It is not a credit bureau that has done underwriting, and it is not a court that has adjudicated a dispute. Nothing in the spec verifies that the reviewer actually interacted with the reviewee, that the interaction went the way the review claims, or that the reviewer and reviewee aren't the same person wearing two hats. The registry stores what people say. It does not, on its own, tell you whether what they're saying is true or whether they had any business saying it.
The Validation Registry is the piece that could fix the above, if you use it. It's a generic hook: request a check from a third party validator, record the result. It doesn't specify what "check" means, which is smart, because that's exactly where you'd plug in something like a TEE attestation proving an agent's inference actually ran on trusted hardware, or a cryptographic proof that a claimed action really happened.
This is the connective tissue between "an agent says it did X" and "an agent can prove it did X." Notice it's a hook, not a solution. Nobody is required to use it, and most of the agents registering in February almost certainly aren't. It's there. It's optional. That distinction is going to matter in about two paragraphs.
Here's the part nobody's dwelling on. Minting an identity is permissionless and cheap (gas only, call it approaching zero on an L2). Posting feedback is permissionless. Nothing stops the same actor from controlling both the reviewer and the reviewee.
So:
// mint k fake agents, have them all cross-endorse the target
async function sybilFlood(registry: ReputationRegistry, target: bigint, k: number) {
const fakeAgents = [];
for (let i = 0; i < k; i++) {
fakeAgents.push(await mintFakeAgent()); // gas, essentially free at k = 500
}
for (const fake of fakeAgents) {
await registry.postFeedback(fake.agentId, target, {
rating: 5,
comment: "excellent, highly reliable, would use again",
});
}
const score = await getNaiveReputation(target); // avg of all ratings
console.log(score); // climbs straight to "trusted"
}Run that with k = 200 and a nobody agent looks indistinguishable from a genuinely trustworthy one, on any consumer that's reading a naive average off the Reputation Registry. There's no fraud detection built into the standard because there's no identity check built into the standard. It isn't a bug in the implementation. It's the direct, load-bearing consequence of "permissionless."
Put it in numbers. Let a good reputation be worth V, meaning the value of jobs, trust, or capital it opens up for an agent. An attacker mints k identities at marginal cost m each. On a permissionless registry, m approaches zero (gas only). The attack is rational whenever:
V > k · m
With m ≈ 0, that inequality holds basically for free, at basically any k, for basically any positive V. There is no floor cost the defender can rely on. If registering an identity costs nothing, reputation built on top of it is worth exactly what it cost to fake, which is nothing.
The only way out of this is to attach a cost to each identity that isn't gas. Call it B, the binding cost, and the attack's rationality condition becomes:
attack rational ⇔ V > k · (m + B)
Now the defender has a lever. Three candidates for B:
B here includes the expected slash, roughly q · lambda · S where q is the probability of getting caught, lambda the slash severity, and S the stake size.B is the cost of attested hardware.B is bounded by the supply of unique humans the attacker actually controls, which is a hard physical cap, not a wallet balance.Here's the subtlety that determines which of these actually works: making B large is necessary but not sufficient. The binding also has to be uncorrelated across identities. Stake fails this half of the test in the limit, because a whale can buy k units of stake just as easily as one. TEE attestation and proof of human pass it, because you can't be more unique pieces of hardware or more unique humans just by having more capital. That's the actual property doing the work: not "cost per identity," but "cost per identity that doesn't scale with the attacker's bankroll."
Once you have a binding, reputation should be aggregated by weighting each reviewer's rating with their scarce credential instead of counting heads. Replace a naive average with:
R = ( sum over j of s_j * r_j ) / ( sum over j of s_j )
where s_j is reviewer j's stake (or attested-hardware weight, or credential weight) and r_j is their rating. A flood of k zero-stake Sybil identities contributes s_j ≈ 0 for every fake reviewer, so the numerator and denominator barely move regardless of k. The score stays honest. The rule this implies is worth writing down plainly: weight reputation by the scarce credential, not by identity count. Counting heads is exactly what a permissionless registry makes free to fake.
I want to be straight about this instead of pretending one binding is a clean win: every one of these imports a different trust assumption, and none of them is free.
Stake is economically sound in the sense that it's transparent and permissionless to acquire, but it fails against capital-rich attackers. If your adversary can outspend the honest reviewers, stake-weighting just crowns the richest attacker as the most trusted agent.
TEE attestation is trusted, full stop. You're trusting the chip manufacturer, the enclave's integrity, and the fact that nobody's extracted the attestation keys. TEE breaks happen (side channel attacks against Intel SGX are a whole genre of security research). It's a strong binding until the day it isn't.
Proof of human recentralizes, which is the uncomfortable part nobody likes to say about it. Every PoH scheme needs some operator or biometric provider standing behind the "unique human" claim, and that operator is now a single point of trust the entire reputation system depends on.
None of these is a free lunch. Pick your scarcity and own the tradeoff you just made.
The registry standardized the part that was always going to get standardized, which is the schema: how you mint an identity, how you post feedback, how you request validation. That's the easy 80 percent, and ERC-8004 did it cleanly.
The part that decides whether any of this is actually trustworthy, binding an identity to something scarce, is still wide open, and it's where the real engineering is happening (or should be). The registry authors know this. It's a known open problem baked into the design, not a gotcha I'm pointing out for the first time. But "known open problem" and "solved" are different states, and right now most of the agents registering are sitting in the first one with nothing binding them at all.
Stake, TEE, or a unique human: pick your scarcity. Just don't ship a reputation system without one.
"Live" here means the contracts exist on mainnet and agents are registering, not that a mature trust ecosystem is running on top of it. Thousands of agents registered by mid February is a registration number, not a usage number, and I'd be lying if I let that imply real traction. Every binding mechanism I listed above trades one failure mode for a different one; there's no version of this where you get scarcity for free. And to repeat myself because it matters: this isn't me catching the ERC-8004 authors napping. The Validation Registry existing as a generic hook is exactly them leaving room for exactly this fix. Most integrations just aren't using it yet.
proof-of-human-in-a-world-of-agents, capability-security-for-agent-wallets