返回 Skill 列表
extension
分类: 内容与媒体无需 API Key

8004

ERC-8004 代理信任协议用于Celo上的AI代理身份、声誉和验证。在构建需要跨组织边界进行身份注册、声誉追踪或信任验证的AI代理时使用。

person作者: jakexiaohubgithub

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';

// 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 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,                              // 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