This protocol proposes to use blockchains to discover, choose, and interact with agents across organizational boundaries without pre-existing trust, thus enabling open-ended agent economies.
Trust models are pluggable and tiered, with security proportional to value at risk, from low-stake tasks like ordering pizza to high-stake tasks like medical diagnosis. Developers can choose from three trust models: reputation systems using client feedback, validation via stake-secured re-execution, zkML proofs, or TEE oracles.
Motivation
MCP allows servers to list and offer their capabilities (prompts, resources, tools, and completions), while A2A handles agent authentication, skills advertisement via AgentCards, direct messaging, and complete task-lifecycle orchestration. However, these agent communication protocols don’t inherently cover agent discovery and trust.
To foster an open, cross-organizational agent economy, we need mechanisms for discovering and trusting agents in untrusted settings. This ERC addresses this need through three lightweight registries, which can be deployed on any L2 or on Mainnet as per-chain singletons:
Identity Registry - A minimal on-chain handle based on ERC-721 with URIStorage extension that resolves to an agent’s registration file, providing every agent with a portable, censorship-resistant identifier.
Reputation Registry - A standard interface for posting and fetching feedback signals. Scoring and aggregation occur both on-chain (for composability) and off-chain (for sophisticated algorithms), enabling an ecosystem of specialized services for agent scoring, auditor networks, and insurance pools.
Validation Registry - Generic hooks for requesting and recording independent validators checks (e.g. stakers re-running the job, zkML verifiers, TEE oracles, trusted judges).
Payments are orthogonal to this protocol and not covered here. However, examples are provided showing how x402 payment proofs can enrich feedback signals.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Identity Registry
The Identity Registry uses ERC-721 with the URIStorage extension for agent registration, making all agents immediately browsable and transferable with NFTs-compliant apps. Each agent is uniquely identified globally by:
namespace:eip155 for EVM chains
chainId: The blockchain network identifier
identityRegistry: The address where the ERC-721 registry contract is deployed
agentId: The ERC-721 tokenId assigned incrementally by the registry
Throughout this document, tokenId in ERC-721 is referred to as agentId. The owner of the ERC-721 token is the owner of the agent and can transfer ownership or delegate management (e.g., updating the registration file) to operators, as supported by ERC721URIStorage.
Token URI and Agent Registration File
The tokenURI MUST resolve to the agent registration file. It MAY use any URI scheme such as ipfs:// (e.g., ipfs://cid) or https:// (e.g., https://domain.com/agent3.json). When the registration data changes, it can be updated with _setTokenURI() as per ERC721URIStorage.
The registration file MUST have the following structure:
{"type":"https://eips.ethereum.org/EIPS/eip-8004#registration-v1","name":"myAgentName","description":"A natural language description of the Agent, which MAY include what it does, how it works, pricing, and interaction methods","image":"https://example.com/agentimage.png","endpoints":[{"name":"A2A","endpoint":"https://agent.example/.well-known/agent-card.json","version":"0.3.0"},{"name":"MCP","endpoint":"https://mcp.agent.eth/","capabilities":{},// OPTIONAL, as per MCP spec"version":"2025-06-18"},{"name":"OASF","endpoint":"ipfs://{cid}","version":"0.7"// https://github.com/agntcy/oasf/tree/v0.7.0},{"name":"ENS","endpoint":"vitalik.eth","version":"v1"},{"name":"DID","endpoint":"did:method:foobar","version":"v1"},{"name":"agentWallet","endpoint":"eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"}],"registrations":[{"agentId":22,"agentRegistry":"eip155:1:{identityRegistry}"}],"supportedTrust":["reputation","crypto-economic","tee-attestation"]}
The type, name, description, and image fields at the top SHOULD ensure compatibility with ERC-721 apps. The number and type of endpoints are fully customizable, allowing developers to add as many as they wish. The version field in endpoints is a SHOULD, not a MUST.
Agents MAY advertise their endpoints, which point to an A2A agent card, an MCP endpoint, an ENS agent name, DIDs, or the agent’s wallets on any chain (even chains where the agent is not registered).
Agents SHOULD have at least one registration (multiple are possible), and all fields in the registration are mandatory.
The supportedTrust field is OPTIONAL. If absent or empty, this ERC is used only for discovery, not for trust.
Onchain metadata
The registry extends ERC-721 by adding getMetadata(uint256 agentId, string key) and setMetadata(uint256 agentId, string key, bytes value) functions for optional extra on-chain agent metadata.
Examples of keys are “agentWallet” or “agentName”.
When metadata is set, the following event is emitted:
New agents can be minted by calling one of these functions:
structMetadataEntry{stringkey;bytesvalue;}functionregister(stringtokenURI,MetadataEntry[]calldatametadata)returns(uint256agentId)functionregister(stringtokenURI)returns(uint256agentId)// tokenURI is added later with _setTokenURI()functionregister()returns(uint256agentId)
This emits one Transfer event, one MetadataSet event for each metadata entry, if any, and
As an agent accepts a task, it’s expected to sign a feedbackAuth to authorize the clientAddress (human or agent) to give feedback. The feedback consists of a score (0-100), tag1 and tag2 (left to developers’ discretion to provide maximum on-chain composability and filtering), a file uri pointing to an off-chain JSON containing additional information, and its KECCAK-256 file hash to guarantee integrity. We suggest using IPFS or equivalent services to make feedback easily indexed by subgraphs or similar technologies. For IPFS uris, the hash is not required.
All fields except the score are OPTIONAL, so the off-chain file is not required and can be omitted.
Giving Feedback
New feedback can be added by any clientAddress calling:
The agentId must be a validly registered agent. The score MUST be between 0 and 100. tag1, tag2, and uri are OPTIONAL.
feedbackAuth is a tuple with the structure (agentId, clientAddress, indexLimit, expiry, chainId, identityRegistry, signerAddress) signed using EIP-191 or ERC-1271 (if clientAddress is a smart contract). The signerAddress field identifies the agent owner or operator who signed.
Verification succeeds only if: agentId, clientAddress, chainId and identityRegistry are correct, blocktime < expiry and indexLimit is greater than the last index of feedback received by that client for that agentId. While in most cases indexLimit is simply lastIndex + 1, it can be much higher. This allows agentId to pre-authorize multiple feedback submissions, useful for agent watch tower use cases.
The feedback fields, except fileuri and filehash, are stored in the contract storage along with the feedbackIndex (the number of feedback submissions that clientAddress has given to agentId). This exposes reputation signals to any smart contract, enabling on-chain composability.
When the feedback is given by an agent (i.e., the client is an agent), the agent SHOULD use the address set in the on-chain optional walletAddress metadata as the clientAddress, to facilitate reputation aggregation.
functiongetSummary(uint256agentId,address[]calldataclientAddresses,bytes32tag1,bytes32tag2)externalviewreturns(uint64count,uint8averageScore)//agentId is the only mandatory parameter; others are optional filters.//Without filtering by clientAddresses, results are subject to Sybil/spam attacks. See Security Considerations for detailsfunctionreadFeedback(uint256agentId,addressclientAddress,uint64index)externalviewreturns(uint8score,bytes32tag1,bytes32tag2,boolisRevoked)functionreadAllFeedback(uint256agentId,address[]calldataclientAddresses,bytes32tag1,bytes32tag2,boolincludeRevoked)externalviewreturns(address[]memoryclientAddresses,uint8[]memoryscores,bytes32[]memorytag1s,bytes32[]memorytag2s,bool[]memoryrevokedStatuses)//agentId is the only mandatory parameter; others are optional filters. Revoked feedback are omitted.functiongetResponseCount(uint256agentId,addressclientAddress,uint64feedbackIndex,address[]responders)externalviewreturns(uint64)//agentId is the only mandatory parameter; others are optional filters.functiongetClients(uint256agentId)externalviewreturns(address[]memory)functiongetLastIndex(uint256agentId,addressclientAddress)externalviewreturns(uint64)
We expect reputation systems around reviewers/clientAddresses to emerge. While simple filtering by reviewer (useful to mitigate spam) and by tag are enabled on-chain, more complex reputation aggregation will happen off-chain.
Off-Chain Feedback File Structure
The OPTIONAL file at the URI could look like:
{//MUST FIELDS"agentRegistry":"eip155:1:{identityRegistry}","agentId":22,"clientAddress":"eip155:1:{clientAddress}","createdAt":"2025-09-23T12:00:00Z","feedbackAuth":"...","score":100,//MAY FIELDS"tag1":"foo","tag2":"bar","skill":"as-defined-by-A2A","context":"as-defined-by-A2A","task":"as-defined-by-A2A","capability":"tools",// As per MCP: "prompts", "resources", "tools" or "completions""name":"Put the name of the MCP tool you liked!",// As per MCP: the name of the prompt, resource or tool"proof_of_payment":{"fromAddress":"0x00...","toAddress":"0x00...","chainId":"1","txHash":"0x00..."},// this can be used for x402 proof of payment// Other fields" ... ":{" ... "}// MAY}
Validation Registry
This registry enables agents to request verification of their work and allows validator smart contracts to provide responses that can be tracked on-chain. Validator smart contracts could use, for example, stake-secured inference re-execution, zkML verifiers or TEE oracles to validate or reject requests.
When the Validation Registry is deployed, the identityRegistry address is passed to the constructor and is visible by calling getIdentityRegistry(), as described above.
This function MUST be called by the owner or operator of agentId. The requestUri points to off-chain data containing all information needed for the validator to validate, including inputs and outputs needed for the verification. The requestHash is a commitment to this data, which is OPTIONAL if requestUri is a content addressable storage uri (e.g. IPFS). All other fields are mandatory.
Only requestHash and response are mandatory; responseUri, responseHash and tag are optional. This function MUST be called by the validatorAddress specified in the original request. The response is a value between 0 and 100, which can be used as binary (0 for failed, 100 for passed) or with intermediate values for validations with a spectrum of outcomes. The optional responseUri points to off-chain evidence or audit of the validation, responseHash is its commitment (in case the resource is not on IPFS), while tag allows for custom categorization or additional data.
validationResponse() can be called multiple times for the same requestHash, enabling use cases like progressive validation states (e.g., “soft finality” and “hard finality” using tag) or updates to validation status.
Upon successful execution, a ValidationResponse event is emitted with all function parameters:
The contract stores requestHash, validatorAddress, agentId, response, lastUpdate, and tag in its memory for on-chain querying and composability.
Read Functions
functiongetValidationStatus(bytes32requestHash)externalviewreturns(addressvalidatorAddress,uint256agentId,uint8response,bytes32tag,uint256lastUpdate)functiongetSummary(uint256agentId,address[]calldatavalidatorAddresses,bytes32tag)externalviewreturns(uint64count,uint8avgResponse)//Returns aggregated validation statistics for an agent. agentId is the only mandatory parameter; validatorAddresses and tag are optional filtersfunctiongetAgentValidations(uint256agentId)externalviewreturns(bytes32[]memoryrequestHashes)functiongetValidatorRequests(addressvalidatorAddress)externalviewreturns(bytes32[]memoryrequestHashes)
Incentives and slashing related to validation are managed by the specific validation protocol and are outside the scope of this registry.
Rationale
Agent communication protocols: MCP and A2A are popular, and other protocols could emerge. For this reason, this protocol links from the blockchain to a flexible registration file including a list where endpoints can be added at will, combining AI primitives (MCP, A2A) and Web3 primitives such as wallet addresses, DIDs, and ENS names.
Feedback: The protocol combines the leverage of nomenclature already established by A2A (such as tasks and skills) and MCP (such as tools and prompts) with complete flexibility in the feedback signal structure.
Gas Sponsorship: Since clients don’t need to be registered anymore, any application can implement frictionless feedback leveraging EIP-7702.
Indexing: Since feedback data is saved on-chain and we suggest using IPFS for full data, it’s easy to leverage subgraphs to create indexers and improve UX.
Deployment: We expect the registries to be deployed with singletons per chain. Note that an agent registered and receiving feedback on chain A can still operate and transact on other chains. Agents can also be registered on multiple chains if desired.
Test Cases
This protocol enables:
Crawling all agents starting from a logically centralized endpoint and discover agent information (name, image, services), capabilities, communication endpoints (MCP, A2A, others), ENS names, wallet addresses and which trust models they support (reputation, validation, TEE attestation)
Building agent explorers and marketplaces using any ERC-721 compatible application to browse, transfer, and manage agents
Building reputation systems with on-chain aggregation (average scores for smart contract composability) or sophisticated off-chain analysis. All reputation signals are public good.
Discovering which agents support stake-secured or zkML validation and how to request it through a standardized interface
Security Considerations
Pre-authorization for feedback only partially mitigates spam, as Sybil attacks are still possible, inflating the reputation of fake agents. The protocol’s contribution is to make signals public and use the same schema. We expect many players to build reputation systems, for example, trusting or giving reputation to reviewers (and therefore filtering by reviewer, as the protocol already enables).
On-chain pointers and hashes cannot be deleted, ensuring audit trail integrity
Validator incentives and slashing are managed by specific validation protocols
While this ERC cryptographically ensures the registration file corresponds to the on-chain agent, it cannot cryptographically guarantee that advertised capabilities are functional and non-malicious. The three trust models (reputation, validation, and TEE attestation) are designed to support this verification need