Build with ERC-8004 Trustless Agents - on-chain agent identity, reputation, validation, and discovery on EVM chains. Use when registering AI agents on-chain,...
---
name: erc-8004
description: Build with ERC-8004 Trustless Agents - on-chain agent identity, reputation, validation, and discovery on EVM chains. Use when registering AI agents on-chain, building agent reputation systems, searching/discovering agents, working with the Agent0 SDK (agent0-sdk), or implementing the ERC-8004 standard. Triggers on ERC-8004, Agent0, agent identity, agent registry, agent reputation, trustless agents, agent discovery.
metadata:
version: "0.2.2"
openclaw:
homepage: https://github.com/tenequm/skills/tree/main/skills/erc-8004
emoji: "🤝"
primaryEnv: PRIVATE_KEY
envVars:
- name: RPC_URL
required: false
description: EVM JSON-RPC endpoint for the registry chain.
- name: PRIVATE_KEY
required: false
description: Signer key for on-chain registration. Use throwaway/testnet keys.
- name: PINATA_JWT
required: false
description: JWT for IPFS pinning via Pinata.
---
# ERC-8004: Trustless Agents
ERC-8004 is a Draft EIP for discovering, choosing, and interacting with AI agents across organizational boundaries without pre-existing trust. It defines three on-chain registries deployed as per-chain singletons on any EVM chain.
**Authors:** Marco De Rossi (MetaMask), Davide Crapis (EF), Jordan Ellis (Google), Erik Reppel (Coinbase)
**Full spec:** [references/spec.md](references/spec.md)
## When to Use This Skill
- Registering AI agents on-chain (ERC-721 identity)
- Building or querying agent reputation/feedback systems
- Searching and discovering agents by capabilities, trust models, or endpoints
- Working with the Agent0 TypeScript SDK (`agent0-sdk`)
- Implementing ERC-8004 smart contract integrations
- Setting up agent wallets, MCP/A2A endpoints, or OASF taxonomies
## Core Architecture
Three lightweight registries, each deployed as a UUPS-upgradeable singleton:
| Registry | Purpose | Contract |
|----------|---------|----------|
| **Identity** | ERC-721 NFTs for agent identities + registration files | `IdentityRegistryUpgradeable` |
| **Reputation** | Signed fixed-point feedback signals + off-chain detail files | `ReputationRegistryUpgradeable` |
| **Validation** | Third-party validator attestations (stake, zkML, TEE) | `ValidationRegistryUpgradeable` |
**Agent identity** = `agentRegistry` (string `eip155:{chainId}:{contractAddress}`) + `agentId` (ERC-721 tokenId).
Each agent's `agentURI` points to a JSON registration file (IPFS or HTTPS) advertising name, description, endpoints (MCP, A2A, ENS, DID, wallet), OASF skills/domains, trust models, and x402 support.
**See:** [references/contracts.md](references/contracts.md) for full contract interfaces and addresses.
## Quick Start with Agent0 SDK (TypeScript)
```bash
npm install agent0-sdk
```
### Register an Agent
`RPC_URL`, `PRIVATE_KEY`, and `PINATA_JWT` are declared in this skill's `metadata.openclaw.envVars`. Use throwaway/testnet keys for development; reach for a hardware wallet or scoped signer for any mainnet activity.
```typescript
import { SDK } from 'agent0-sdk';
const sdk = new SDK({
chainId: 84532, // Base Sepolia
rpcUrl: process.env.RPC_URL,
privateKey: process.env.PRIVATE_KEY,
ipfs: 'pinata',
pinataJwt: process.env.PINATA_JWT,
});
const agent = sdk.createAgent(
'MyAgent',
'An AI agent that analyzes crypto markets',
'https://example.com/agent-image.png'
);
// Configure endpoints and capabilities
await agent.setMCP('https://mcp.example.com', '2025-06-18', true); // auto-fetches tools
await agent.setA2A('https://example.com/.well-known/agent-card.json', '0.3.0', true);
agent.setENS('myagent.eth');
agent.setActive(true);
agent.setX402Support(true);
agent.setTrust(true, false, false); // reputation only
// Add OASF taxonomy
agent.addSkill('natural_language_processing/natural_language_generation/summarization', true);
agent.addDomain('finance_and_business/investment_services', true);
// Register on-chain (mints NFT + uploads to IPFS).
// Sends a real transaction signed with PRIVATE_KEY - confirm chainId, signer, and balance before running.
const tx = await agent.registerIPFS();
const { result } = await tx.waitConfirmed();
console.log(`Registered: ${result.agentId}`); // e.g. "84532:42"
```
### Search for Agents
```typescript
const sdk = new SDK({ chainId: 84532, rpcUrl: process.env.RPC_URL });
// Search by capabilities
const agents = await sdk.searchAgents({
hasMCP: true,
active: true,
x402support: true,
mcpTools: ['financial_analyzer'],
supportedTrust: ['reputation'],
});
// Get a specific agent
const agent = await sdk.getAgent('84532:42');
// Semantic search
const results = await sdk.searchAgents(
{ keyword: 'crypto market analysis' },
{ sort: ['semanticScore:desc'] }
);
```
### Give Feedback
```typescript
// Prepare optional off-chain feedback file
const feedbackFile = await sdk.prepareFeedbackFile({
text: 'Accurate market analysis',
capability: 'tools',
name: 'financial_analyzer',
proofOfPayment: { txHash: '0x...', chainId: '8453', fromAddress: '0x...', toAddress: '0x...' },
});
// Submit feedback (value=85 out of 100). On-chain tx; same caveats as `registerIPFS()` above.
const tx = await sdk.giveFeedback('84532:42', 85, 'starred', '', '', feedbackFile);
await tx.waitConfirmed();
// Read reputation summary
const summary = await sdk.getReputationSummary('84532:42');
console.log(`Average: ${summary.averageValue}, Count: ${summary.count}`);
```
**See:** [references/sdk-typescript.md](references/sdk-typescript.md) for full SDK API reference.
## Registration File Format
Every agent's `agentURI` resolves to this JSON structure:
```json
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "MyAgent",
"description": "What it does, pricing, interaction methods",
"image": "https://example.com/agent.png",
"services": [
{ "name": "MCP", "endpoint": "https://mcp.example.com", "version": "2025-06-18", "mcpTools": ["tool1"] },
{ "name": "A2A", "endpoint": "https://example.com/.well-known/agent-card.json", "version": "0.3.0" },
{ "name": "OASF", "endpoint": "https://github.com/agntcy/oasf/", "version": "v0.8.0",
"skills": ["natural_language_processing/summarization"],
"domains": ["finance_and_business/investment_services"] },
{ "name": "ENS", "endpoint": "myagent.eth", "version": "v1" },
{ "name": "agentWallet", "endpoint": "eip155:8453:0x..." }
],
"registrations": [
{ "agentId": 42, "agentRegistry": "eip155:84532:0x8004A818BFB912233c491871b3d84c89A494BD9e" }
],
"supportedTrust": ["reputation", "crypto-economic", "tee-attestation"],
"active": true,
"x402Support": true
}
```
The `registrations` field creates a bidirectional cryptographic link: the NFT points to this file, and this file points back to the NFT. This enables endpoint domain verification via `/.well-known/agent-registration.json`.
**See:** [references/registration.md](references/registration.md) for best practices (Four Golden Rules) and complete field reference.
## Contract Addresses
All registries deploy to deterministic vanity addresses via CREATE2 (SAFE Singleton Factory):
### Mainnet (Ethereum, Base, Polygon, Arbitrum, Optimism, etc.)
| Registry | Address |
|----------|---------|
| Identity | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` |
| Reputation | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` |
| Validation | `0x8004Cb1BF31DAf7788923b405b754f57acEB4272` |
### Testnet (Sepolia, Base Sepolia, etc.)
| Registry | Address |
|----------|---------|
| Identity | `0x8004A818BFB912233c491871b3d84c89A494BD9e` |
| Reputation | `0x8004B663056A597Dffe9eCcC1965A193B7388713` |
| Validation | `0x8004Cb1BF31DAf7788923b405b754f57acEB4272` |
Same proxy addresses on: Ethereum, Base, Arbitrum, Avalanche, Celo, Gnosis, Linea, Mantle, MegaETH, Optimism, Polygon, Scroll, Taiko, Monad, BSC + testnets.
## Reputation System
Feedback uses signed fixed-point numbers: `value` (int128) + `valueDecimals` (uint8, 0-18).
| tag1 | Measures | Example | value | valueDecimals |
|------|----------|---------|-------|---------------|
| `starred` | Quality 0-100 | 87/100 | 87 | 0 |
| `reachable` | Endpoint up (binary) | true | 1 | 0 |
| `uptime` | Uptime % | 99.77% | 9977 | 2 |
| `successRate` | Success % | 89% | 89 | 0 |
| `responseTime` | Latency ms | 560ms | 560 | 0 |
Anti-Sybil: `getSummary()` requires a non-empty `clientAddresses` array (caller must supply trusted reviewer list). Self-feedback is rejected (agent owner/operators cannot submit feedback on their own agent).
**See:** [references/reputation.md](references/reputation.md) for full feedback system, off-chain file format, and aggregation details.
## OASF Taxonomy (v0.8.0)
Open Agentic Schema Framework provides standardized skills (136) and domains (204) for agent classification.
**Top-level skill categories:** `natural_language_processing`, `images_computer_vision`, `audio`, `analytical_skills`, `multi_modal`, `agent_orchestration`, `advanced_reasoning_planning`, `data_engineering`, `security_privacy`, `evaluation_monitoring`, `devops_mlops`, `governance_compliance`, `tool_interaction`, `retrieval_augmented_generation`, `tabular_text`
**Top-level domain categories:** `technology`, `finance_and_business`, `healthcare`, `legal`, `education`, `life_science`, `agriculture`, `energy`, `environmental_science`, `government`, `manufacturing`, `transportation`, and more.
Use slash-separated paths: `agent.addSkill('natural_language_processing/natural_language_generation/summarization', true)`.
## Key Concepts
| Term | Meaning |
|------|---------|
| `agentRegistry` | `eip155:{chainId}:{contractAddress}` - globally unique registry identifier |
| `agentId` | ERC-721 tokenId - numeric on-chain identifier (format in SDK: `"chainId:tokenId"`) |
| `agentURI` | URI (IPFS/HTTPS) pointing to agent registration file |
| `agentWallet` | Reserved on-chain metadata key for verified payment address (EIP-712/ERC-1271) |
| `feedbackIndex` | 1-indexed counter of feedback a clientAddress has given to an agentId |
| `supportedTrust` | Array: `"reputation"`, `"crypto-economic"`, `"tee-attestation"` |
| `x402Support` | Boolean flag for Coinbase x402 HTTP payment protocol support |
| OASF | Open Agentic Schema Framework - standardized agent skills/domains taxonomy |
| MCP | Model Context Protocol - tools, prompts, resources, completions |
| A2A | Agent2Agent - authentication, skills via AgentCards, task orchestration |
## Reference Index
| Reference | Content |
|-----------|---------|
| [spec.md](references/spec.md) | Complete ERC-8004 specification (EIP text) |
| [contracts.md](references/contracts.md) | Smart contract interfaces, storage layout, deployment |
| [sdk-typescript.md](references/sdk-typescript.md) | Agent0 TypeScript SDK full API |
| [registration.md](references/registration.md) | Registration file format, Four Golden Rules, domain verification |
| [reputation.md](references/reputation.md) | Feedback system, off-chain files, value encoding, aggregation |
| [search-discovery.md](references/search-discovery.md) | Agent search, subgraph queries, multi-chain discovery |
| [oasf-taxonomy.md](references/oasf-taxonomy.md) | Complete OASF v0.8.0 taxonomy: all 136 skills and 204 domains with slugs |
## Official Resources
- EIP Discussion: https://ethereum-magicians.org/t/erc-8004-trustless-agents/25098
- Contracts: https://github.com/erc-8004/erc-8004-contracts
- Best Practices: https://github.com/erc-8004/best-practices
- SDK Docs: https://sdk.ag0.xyz
- SDK Docs Source: https://github.com/agent0lab/agent0-sdk-docs
- TypeScript SDK: https://github.com/agent0lab/agent0-ts
- Python SDK: https://github.com/agent0lab/agent0-py
- Subgraph: https://github.com/agent0lab/subgraph
- OASF: https://github.com/agntcy/oasf
don't have the plugin yet? install it then click "run inline in claude" again.
ERC-8004 is a draft EIP for discovering, choosing, and interacting with AI agents across organizational boundaries without pre-existing trust. It defines three on-chain registries deployed as per-chain singletons on any EVM chain.
Authors: Marco De Rossi (MetaMask), Davide Crapis (EF), Jordan Ellis (Google), Erik Reppel (Coinbase)
Full spec: references/spec.md
Register AI agents on-chain with verifiable identity (ERC-721 NFTs), build and query reputation systems, discover agents by capability or trust model, and integrate with the Agent0 TypeScript SDK for trustless agent interaction. Use this skill when you need cryptographic proof of agent identity, want to award or read reputation signals from multiple validators, implement ERC-8004 smart contract integrations, or set up agent wallets, MCP/A2A endpoints, or OASF taxonomies across EVM chains.
Environment Variables (see metadata.openclaw.envVars):
RPC_URL (optional): JSON-RPC endpoint for the registry chain. If absent, SDK uses public fallback endpoints (may have rate limits). Recommendation: use Alchemy or Infura for production.PRIVATE_KEY (optional): 0x-prefixed hex string. Required for on-chain registration and feedback submission. Never commit to version control. Use throwaway keys on testnets; hardware wallet or scoped signer for mainnet. The SDK signs transactions with this key.PINATA_JWT (optional): Bearer token for Pinata IPFS service. Required if calling agent.registerIPFS(). If absent, registration falls back to HTTPS-only mode (caller must host registration JSON and call agent.registerHTTPS() instead).Agent0 SDK Initialization:
{
chainId: number, // e.g. 84532 (Base Sepolia), 1 (Ethereum), 8453 (Base)
rpcUrl: string, // Optional; overrides RPC_URL env var
privateKey: string, // Optional; overrides PRIVATE_KEY env var
ipfs: 'pinata', // Pinata as IPFS provider
pinataJwt: string, // Optional; overrides PINATA_JWT env var
}
External Connections:
Agent Registration File Structure (JSON, hosted at agentURI):
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "MyAgent",
"description": "What it does, pricing, interaction methods",
"image": "https://example.com/agent.png",
"services": [
{ "name": "MCP", "endpoint": "https://mcp.example.com", "version": "2025-06-18", "mcpTools": ["tool1"] },
{ "name": "A2A", "endpoint": "https://example.com/.well-known/agent-card.json", "version": "0.3.0" },
{ "name": "OASF", "endpoint": "https://github.com/agntcy/oasf/", "version": "v0.8.0",
"skills": ["natural_language_processing/summarization"],
"domains": ["finance_and_business/investment_services"] },
{ "name": "ENS", "endpoint": "myagent.eth", "version": "v1" },
{ "name": "agentWallet", "endpoint": "eip155:8453:0x..." }
],
"registrations": [
{ "agentId": 42, "agentRegistry": "eip155:84532:0x8004A818BFB912233c491871b3d84c89A494BD9e" }
],
"supportedTrust": ["reputation", "crypto-economic", "tee-attestation"],
"active": true,
"x402Support": true
}
Input: npm package manager, Node.js 16+, agent0-sdk npm package
Steps:
npm install agent0-sdk
Create SDK instance with chain and signer:
import { SDK } from 'agent0-sdk';
const sdk = new SDK({
chainId: 84532, // Base Sepolia for testing
rpcUrl: process.env.RPC_URL,
privateKey: process.env.PRIVATE_KEY,
ipfs: 'pinata',
pinataJwt: process.env.PINATA_JWT,
});
Output: SDK instance ready for agent creation, search, and feedback operations.
Input: SDK instance, agent name (string), description (string), image URL (string)
Steps:
const agent = sdk.createAgent(
'MyAgent',
'An AI agent that analyzes crypto markets',
'https://example.com/agent-image.png'
);
Configure MCP endpoint (if available):
await agent.setMCP(
'https://mcp.example.com', // MCP server URL
'2025-06-18', // MCP version
true // auto-fetch tools from introspection
);
Configure A2A endpoint (if using Agent2Agent):
await agent.setA2A(
'https://example.com/.well-known/agent-card.json', // AgentCard URL
'0.3.0', // A2A version
true // auto-fetch on registration
);
Configure ENS (optional):
agent.setENS('myagent.eth');
Set active status, x402 support, and trust model:
agent.setActive(true);
agent.setX402Support(true); // Coinbase x402 HTTP payment protocol
agent.setTrust(true, false, false); // reputation=true, crypto-economic=false, tee-attestation=false
Add OASF taxonomy skills and domains (use slash-separated paths):
agent.addSkill('natural_language_processing/natural_language_generation/summarization', true);
agent.addDomain('finance_and_business/investment_services', true);
Output: Fully configured agent object with endpoints, trust model, and taxonomy metadata.
Input: Configured agent object, PRIVATE_KEY env var, PINATA_JWT env var, account with sufficient ETH for gas
Steps:
const tx = await agent.registerIPFS();
This transaction:
Wait for confirmation:
const { result } = await tx.waitConfirmed();
console.log(`Registered: ${result.agentId}`); // e.g. "84532:42"
Output: Confirmed transaction receipt, agentId (numeric tokenId), agentRegistry string (eip155:chainId:contractAddress), IPFS hash of registration file.
Input: Configured agent object, PRIVATE_KEY env var, account with sufficient ETH for gas, HTTPS URL where registration file is already hosted
Steps (alternative to step 3 if no PINATA_JWT):
const httpsUrl = 'https://example.com/agents/myagent-registration.json';
const tx = await agent.registerHTTPS(httpsUrl);
const { result } = await tx.waitConfirmed();
The registration file must include the registrations field pointing back to the on-chain NFT to enable domain verification via /.well-known/agent-registration.json.
Output: Confirmed transaction receipt, agentId, agentRegistry, HTTPS URL.
Input: SDK instance (no signer needed), optional chainId override
Steps:
const sdk = new SDK({ chainId: 84532, rpcUrl: process.env.RPC_URL });
const agents = await sdk.searchAgents({
hasMCP: true, // Must have MCP endpoint
active: true, // Must be marked active
x402support: true, // Must support x402 payments
mcpTools: ['financial_analyzer'], // Must expose this tool
supportedTrust: ['reputation'], // Must accept reputation feedback
});
Returns array of matching agents with agentId, name, description, endpoints.
Output: Array of agent objects matching search criteria.
Input: SDK instance, agentId string (format: "chainId:tokenId")
Steps:
const agent = await sdk.getAgent('84532:42');
console.log(agent.name);
console.log(agent.services);
console.log(agent.supportedTrust);
Fetches on-chain metadata (NFT owner, registration file URI) and resolves registration file from IPFS/HTTPS.
Output: Agent object with complete metadata (name, description, image, services array, supported trust models, active status, x402 support).
Input: SDK instance, keyword string
Steps:
const results = await sdk.searchAgents(
{ keyword: 'crypto market analysis' }, // Natural language query
{ sort: ['semanticScore:desc'] } // Sort by relevance descending
);
Uses embedding-based semantic search across agent descriptions and OASF taxonomy.
Output: Ranked array of agents by semantic relevance score.
Input: SDK instance, agentId string, feedback value (int, 0-100 or custom range), tag1 (reputation signal type), PRIVATE_KEY env var, account with sufficient ETH for gas
Steps (simple feedback):
const tx = await sdk.giveFeedback(
'84532:42', // agentId
85, // value: quality score 85/100
'starred', // tag1: reputation signal type
'', // tag2: optional second signal
'', // tag3: optional third signal
undefined // feedbackFile: optional off-chain details
);
await tx.waitConfirmed();
Steps (with off-chain feedback file):
const feedbackFile = await sdk.prepareFeedbackFile({
text: 'Accurate market analysis, responded in <1s',
capability: 'tools',
name: 'financial_analyzer',
proofOfPayment: {
txHash: '0x...',
chainId: '8453',
fromAddress: '0x...',
toAddress: '0x...' // Agent's wallet
},
});
const tx = await sdk.giveFeedback('84532:42', 85, 'starred', '', '', feedbackFile);
await tx.waitConfirmed();
Feedback values use fixed-point encoding: value (int128) + valueDecimals (uint8):
starred (quality 0-100): value=85, valueDecimals=0uptime (% as 9977 for 99.77%): value=9977, valueDecimals=2responseTime (ms): value=560, valueDecimals=0reachable (binary): value=1, valueDecimals=0successRate (%): value=89, valueDecimals=0Output: Confirmed transaction receipt, feedback index (counter incremented for this caller + agent pair).
Input: SDK instance, agentId string, optional clientAddresses array (trusted reviewers)
Steps:
const summary = await sdk.getReputationSummary('84532:42');
console.log(`Average: ${summary.averageValue}`);
console.log(`Count: ${summary.count}`);
console.log(`Feedback by tag:`, summary.byTag); // Breakdown by signal type
With trusted reviewer filter:
const summary = await sdk.getReputationSummary('84532:42', {
clientAddresses: ['0xAlice', '0xBob', '0xCharlie'] // Only these reviewers count
});
Output: Reputation summary object with averageValue, count, byTag breakdown, lastUpdated timestamp.
Input: Agent endpoint domain (e.g. https://example.com), agentId string
Steps:
// Agent publishes registration file at https://example.com/.well-known/agent-registration.json
// This file must contain the agent's agentId and agentRegistry pointing back to on-chain NFT
const isVerified = await sdk.verifyAgentDomain('https://example.com', '84532:42');
Creates bidirectional cryptographic link: NFT points to registration file, registration file points back to NFT.
Output: Boolean, true if domain ownership is verified.
Input: chainId (number)
Steps:
const contracts = sdk.getContractAddresses(84532); // Base Sepolia
console.log(contracts.identity); // Identity Registry address
console.log(contracts.reputation); // Reputation Registry address
console.log(contracts.validation); // Validation Registry address
Output: Object with identity, reputation, validation contract addresses (deterministic CREATE2 vanity addresses).
Branch: Read-only mode.
agent.registerIPFS(), agent.registerHTTPS(), or sdk.giveFeedback().sdk.getAgent(), sdk.searchAgents(), sdk.getReputationSummary().Branch: HTTPS-only registration.
agent.registerIPFS().agent.registerHTTPS() and host registration file on own domain.registrations field for domain verification.Branch: Fallback to public endpoints.
getReputationSummary() is called without clientAddressesBranch: Aggregate all feedback without Sybil filtering.
clientAddresses parameter to filter to trusted reviewers only.Branch: No matching agents.
active: true in registration file.registerIPFS() or giveFeedback() transaction failsBranch: Error handling by error type.
**Agent Registration (