| name | 8004 |
| description | ERC-8004 Agent Trust Protocol for AI agent identity, reputation, and validation on Celo. Use when building AI agents that need identity registration, reputation tracking, or trust verification across organizational boundaries. |
| license | Apache-2.0 |
| metadata | {"author":"celo-org","version":"1.0.0"} |
ERC-8004: Agent Trust Protocol
ERC-8004 establishes trust infrastructure for autonomous AI agents, enabling them to discover, identify, and evaluate other agents across organizational boundaries.
When to Use
- Registering an AI agent's identity on-chain
- Building reputation systems for AI agents
- Verifying agent identity before interactions
- Querying agent reputation and feedback
- Implementing trust-based agent interactions
Core Concepts
The Three Registries
| Registry | Purpose | Key Functions |
|---|
| Identity Registry | Agent discovery via ERC-721 NFTs | register(), tokenURI(), getAgentWallet(), setMetadata(), getMetadata() |
| Reputation Registry | Feedback and attestations | giveFeedback(), revokeFeedback(), readFeedback(), readAllFeedback(), getSummary(), appendResponse(), getClients() |
| Validation Registry | Verification hooks | Custom validators |
Protocol Stack Position
Application Layer (Agent Apps, Marketplaces)
↓
Trust Layer (ERC-8004) ← This skill
↓
Payment Layer (x402)
↓
Communication Layer (A2A, MCP)
Installation
npm install viem
ABIs are available at skills/8004/references/identity-registry-abi.json and skills/8004/references/reputation-registry-abi.json.
Contract Addresses
Celo Mainnet (Chain ID: 42220)
| Contract | Address |
|---|
| Identity Registry | 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 |
| Reputation Registry | 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 |
Celo Sepolia Testnet (Chain ID: 11142220)
| Contract | Address |
|---|
| Identity Registry | 0x8004A818BFB912233c491871b3d84c89A494BD9e |
| Reputation Registry | 0x8004B663056A597Dffe9eCcC1965A193B7388713 |
Setup (viem)
import { createPublicClient, createWalletClient, http, getContract } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { celo, celoAlfajores } from 'viem/chains';
import identityRegistryAbi from './references/identity-registry-abi.json';
import reputationRegistryAbi from './references/reputation-registry-abi.json';
const IDENTITY_REGISTRY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';
const REPUTATION_REGISTRY = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63';
const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
const publicClient = createPublicClient({
chain: celo,
transport: http('https://forno.celo.org'),
});
const walletClient = createWalletClient({
account,
chain: celo,
transport: http('https://forno.celo.org'),
});
Agent Registration
1. Agent Metadata Format
Create an agent metadata JSON and host it (IPFS, HTTPS, etc.):
{
"type": "Agent",
"name": "My AI Agent",
"description": "Description of capabilities",
"image": "ipfs://Qm...",
"endpoints": [
{ "type": "a2a", "url": "https://example.com/.well-known/agent.json" },
{ "type": "mcp", "url": "https://example.com/mcp" },
{ "type": "wallet", "address": "0x...", "chainId": 42220 }
],
"supportedTrust": ["reputation", "validation", "tee"]
}
2. Register Agent On-Chain
const hash = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: [],
});
const hash = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: ['ipfs://QmYourAgentMetadata'],
});
const hash = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: [
'ipfs://QmYourAgentMetadata',
[
{ metadataKey: 'category', metadataValue: '0x' + Buffer.from('defi-trading').toString('hex') },
{ metadataKey: 'version', metadataValue: '0x' + Buffer.from('1.0.0').toString('hex') },
],
],
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });
const transferLog = receipt.logs.find(log => log.topics.length === 4);
const agentId = BigInt(transferLog.topics[3]);
console.log('Agent registered with ID:', agentId);
3. Read Agent Data
const agentURI = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'tokenURI',
args: [agentId],
});
const agentWallet = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'getAgentWallet',
args: [agentId],
});
const owner = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'ownerOf',
args: [agentId],
});
const categoryBytes = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'getMetadata',
args: [agentId, 'category'],
});
4. Update Agent
await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setAgentURI',
args: [agentId, 'ipfs://QmUpdatedMetadata'],
});
await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setMetadata',
args: [agentId, 'status', '0x' + Buffer.from('active').toString('hex')],
});
Reputation System
Give Feedback
Note: Self-feedback is blocked — the agent owner/operators cannot give feedback to their own agent. The value field is int128 (supports negative scores). valueDecimals max is 18.
import { keccak256, toBytes } from 'viem';
const feedbackContent = JSON.stringify({ quality: 'excellent', notes: 'Fast response' });
const feedbackHash = keccak256(toBytes(feedbackContent));
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'giveFeedback',
args: [
agentId,
85n,
0,
'starred',
'',
'https://agent.example.com',
'ipfs://QmDetailedFeedback',
feedbackHash,
],
});
Common Feedback Tags
| Tag | Measures | Example |
|---|
starred | Quality rating (0-100) | 87/100 |
uptime | Endpoint uptime % | 99.77% |
successRate | Task success rate % | 89% |
responseTime | Response time (ms) | 560ms |
reachable | Endpoint reachable | 1/0 |
Revoke Feedback
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'revokeFeedback',
args: [agentId, 1n],
});
Respond to Feedback
Agents (or anyone) can append responses to feedback entries:
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'appendResponse',
args: [
agentId,
clientAddress,
1n,
'ipfs://QmResponse',
responseHash,
],
});
Query Reputation
const clients = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getClients',
args: [agentId],
});
const [value, valueDecimals, tag1, tag2, isRevoked] = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'readFeedback',
args: [agentId, clientAddress, 1n],
});
const allFeedback = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'readAllFeedback',
args: [
agentId,
clients,
'',
'',
false,
],
});
const [count, summaryValue, summaryValueDecimals] = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getSummary',
args: [
agentId,
clients,
'',
'',
],
});
console.log(`Average: ${summaryValue} (${count} reviews, ${summaryValueDecimals} decimals)`);
Trust Verification Workflow
async function verifyAndInteract(targetAgentId, minScore = 70n) {
const owner = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'ownerOf',
args: [targetAgentId],
});
const clients = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getClients',
args: [targetAgentId],
});
if (clients.length > 0) {
const [count, summaryValue] = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getSummary',
args: [targetAgentId, clients, '', ''],
});
if (summaryValue < minScore) {
throw new Error(`Agent reputation ${summaryValue} below threshold ${minScore}`);
}
}
const agentURI = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'tokenURI',
args: [targetAgentId],
});
const agentData = await fetch(agentURI).then(r => r.json());
const endpoint = agentData.endpoints.find(e => e.type === 'a2a');
const result = await interactWithAgent(endpoint.url);
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'giveFeedback',
args: [
targetAgentId,
result.success ? 90n : 30n,
0,
result.success ? 'starred' : 'failed',
'',
endpoint.url,
'',
'0x0000000000000000000000000000000000000000000000000000000000000000',
],
});
return result;
}
Integration with x402 Payments
ERC-8004 and x402 work together for trustworthy paid agent interactions:
import { wrapFetchWithPayment } from 'thirdweb/x402';
async function payTrustedAgent(agentId, serviceUrl) {
const clients = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getClients',
args: [agentId],
});
if (clients.length > 0) {
const [count, summaryValue] = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getSummary',
args: [agentId, clients, '', ''],
});
if (summaryValue < 80n) {
throw new Error('Agent not trusted enough for payment');
}
}
const fetchWithPayment = wrapFetchWithPayment({
client,
account,
paymentOptions: { maxValue: "1000000" },
});
const response = await fetchWithPayment(serviceUrl);
return response.json();
}
Validation Registry
For high-stakes operations, use Validation Registry for additional verification:
| Model | Mechanism | Best For |
|---|
| Reputation-based | Client feedback | Low-stake, frequent |
| Crypto-economic | Stake + slashing | Medium-stake financial |
| zkML | Zero-knowledge proofs | Privacy-preserving |
| TEE Attestation | Hardware isolation | High-assurance |
Celo Network Reference
Additional Resources
Related Skills
- x402 - Payment layer for AI agents
- celo-rpc - Celo blockchain interaction
- viem - TypeScript Ethereum library