8004
Skill8 starsChanged 2 months agoApache-2.0View on GitHub
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.
- Installs packages
In this repository15 other files it gives its agents.
- bridgingSkill
- celo-composerSkill
- celo-defiSkill
- celo-rpcSkill
- celo-stablecoinsSkill
- contract-verificationSkill
- evm-foundrySkill
- evm-hardhatSkill
- evm-wallet-integrationSkill
- fee-abstractionSkill
- minipay-integrationSkill
- thirdwebSkill
- viemSkill
- wagmiSkill
- x402Skill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 103
Create an agent metadata JSON and host it (IPFS, HTTPS, etc.):
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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 viemABIs are available at
skills/8004/references/identity-registry-abi.jsonandskills/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, celoSepolia } from 'viem/chains';
import identityRegistryAbi from './references/identity-registry-abi.json';
import reputationRegistryAbi from './references/reputation-registry-abi.json';
// Celo Mainnet addresses
const IDENTITY_REGISTRY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';
const REPUTATION_REGISTRY = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63';
// Celo Sepolia Testnet addresses
// const IDENTITY_REGISTRY = '0x8004A818BFB912233c491871b3d84c89A494BD9e';
// const REPUTATION_REGISTRY = '0x8004B663056A597Dffe9eCcC1965A193B7388713';
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
// Register without URI (minimal)
const hash = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: [],
});
// Register with metadata URI
const hash = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: ['ipfs://QmYourAgentMetadata'],
});
// Register with URI + custom metadata key-value pairs
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') },
],
],
});
// Get agent ID from transaction receipt
const receipt = await publicClient.waitForTransactionReceipt({ hash });
const transferLog = receipt.logs.find(log => log.topics.length === 4); // Transfer event
const agentId = BigInt(transferLog.topics[3]); // tokenId is the 3rd indexed param
console.log('Agent registered with ID:', agentId);3. Read Agent Data
// Get agent metadata URI
const agentURI = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'tokenURI',
args: [agentId],
});
// Get agent wallet address
const agentWallet = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'getAgentWallet',
args: [agentId],
});
// Get agent owner (NFT holder)
const owner = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'ownerOf',
args: [agentId],
});
// Get custom metadata
const categoryBytes = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'getMetadata',
args: [agentId, 'category'],
});4. Update Agent
// Update agent URI
await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setAgentURI',
args: [agentId, 'ipfs://QmUpdatedMetadata'],
});
// Set custom metadata
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
valuefield isint128(supports negative scores).valueDecimalsmax 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, // agentId (uint256)
85n, // value (int128) — can be negative
0, // valueDecimals (uint8)
'starred', // tag1: category
'', // tag2: optional sub-category
'https://agent.example.com', // endpoint used
'ipfs://QmDetailedFeedback', // feedbackURI for details
feedbackHash, // keccak256 of feedback content
],
});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
// Revoke feedback at a specific index (1-indexed)
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'revokeFeedback',
args: [agentId, 1n], // feedbackIndex (uint64, 1-indexed)
});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, // address of feedback author
1n, // feedbackIndex
'ipfs://QmResponse', // responseURI
responseHash, // keccak256 of response content
],
});Query Reputation
// Get all clients who gave feedback
const clients = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getClients',
args: [agentId],
});
// Read a single feedback entry
const [value, valueDecimals, tag1, tag2, isRevoked] = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'readFeedback',
args: [agentId, clientAddress, 1n], // feedbackIndex (1-indexed)
});
// Read all feedback (pass clients array, filter by tags)
const allFeedback = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'readAllFeedback',
args: [
agentId,
clients, // clientAddresses — pass [] to auto-use all known clients
'', // tag1 filter ('' = all)
'', // tag2 filter ('' = all)
false, // includeRevoked
],
});
// Returns: { clients, feedbackIndexes, values, valueDecimals, tag1s, tag2s, revokedStatuses }
// Get aggregated summary (requires clientAddresses)
const [count, summaryValue, summaryValueDecimals] = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getSummary',
args: [
agentId,
clients, // clientAddresses (required, cannot be empty)
'', // tag1 filter
'', // tag2 filter
],
});
console.log(`Average: ${summaryValue} (${count} reviews, ${summaryValueDecimals} decimals)`);Trust Verification Workflow
async function verifyAndInteract(targetAgentId, minScore = 70n) {
// 1. Verify identity exists (reverts if not)
const owner = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'ownerOf',
args: [targetAgentId],
});
// 2. Get clients and check reputation
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}`);
}
}
// 3. Fetch agent metadata and find endpoint
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');
// 4. Interact with verified agent
const result = await interactWithAgent(endpoint.url);
// 5. Submit feedback
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) {
// 1. Verify trust via reputation
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');
}
}
// 2. Make paid request via x402
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
| Network | Chain ID | RPC Endpoint |
| Celo Mainnet | 42220 | https://forno.celo.org |
| Celo Sepolia | 11142220 | https://forno.celo-sepolia.celo-testnet.org |
Additional Resources
Related Skills
- x402 - Payment layer for AI agents
- celo-rpc - Celo blockchain interaction
- viem - TypeScript Ethereum library
Source of truth: Celopedia
These skills are focused, task-level references. For anything broader — verified contract addresses, ecosystem and protocol data, listing requirements, grants, governance, migration guides, or cross-cutting Celo questions — Celopedia is the canonical source and is kept current. Where this skill and Celopedia disagree, Celopedia wins.
npx skills add celo-org/celopedia-skillsDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

