Skip to main content

Building an AI Agent with Web3 Identity

Learn how to create an AI agent that uses ENS names, x402 micropayments, and on-chain identity.

Overviewโ€‹

This guide walks through building an autonomous AI agent with:

  • ENS identity โ€” Resolvable name (e.g., yourbot.aboutme.eth)
  • Wallet capability โ€” Sign transactions and payments
  • x402 integration โ€” Pay for API access without API keys
  • On-chain registration โ€” ERC-8004 agent identity

Time to build: ~2 hours
Prerequisites: Node.js, basic Ethereum knowledge, $5 in ETH/USDC


Architectureโ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Your Agent โ”‚
โ”‚ (Node.js app) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ”œโ”€โ”€> Wallet (viem)
โ”‚ โ””โ”€> Sign EIP-712 messages
โ”‚
โ”œโ”€โ”€> ENS Name (yourbot.aboutme.eth)
โ”‚ โ””โ”€> Resolves to your agent's wallet
โ”‚
โ””โ”€โ”€> Web3 Identity API
โ””โ”€> x402 payments for unlimited access

Step 1: Set Up Your Agent Walletโ€‹

Every agent needs a wallet for identity and payments.

Install Dependenciesโ€‹

npm install viem @x402/client dotenv

Generate a Walletโ€‹

// scripts/generate-wallet.js
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
import fs from 'fs';

const privateKey = generatePrivateKey();
const account = privateKeyToAccount(privateKey);

console.log('Agent Wallet:', account.address);
console.log('Private Key:', privateKey);

// Save securely (NEVER commit to git!)
fs.writeFileSync('.agent-wallet.key', privateKey, { mode: 0o600 });

Run it:

node scripts/generate-wallet.js
# Agent Wallet: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEa7
# Private Key: 0x...

โš ๏ธ Security: Add .agent-wallet.key to .gitignore immediately.


Step 2: Fund Your Agentโ€‹

Your agent needs:

  1. ETH โ€” For gas fees (~$2-5)
  2. USDC (Base) โ€” For x402 API payments (~$1-2)

Get Testnet Funds (Development)โ€‹

Base Sepolia:

Production Fundingโ€‹

Base Mainnet:

  • Bridge ETH/USDC from Ethereum mainnet using bridge.base.org
  • Or buy directly on Base via Coinbase

Step 3: Register Your ENS Nameโ€‹

Give your agent a human-readable identity.

// scripts/register-subname.js
import { createPublicClient, createWalletClient, http } from 'viem';
import { mainnet } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import fs from 'fs';

const privateKey = fs.readFileSync('.agent-wallet.key', 'utf8').trim();
const account = privateKeyToAccount(privateKey);

const client = createWalletClient({
account,
chain: mainnet,
transport: http()
});

// Register via Web3 Identity API
async function registerSubname(name) {
const response = await fetch(
`https://api.web3identity.com/api/subnames/aboutme.eth`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name,
owner: account.address,
records: {
description: 'AI agent for Web3 automation',
url: 'https://yourbot.example.com',
'com.twitter': '@yourbot'
}
})
}
);

const data = await response.json();

if (!response.ok) {
throw new Error(`Registration failed: ${data.error}`);
}

return data;
}

// Register yourbot.aboutme.eth
const result = await registerSubname('yourbot');
console.log('Registered:', result.name);
console.log('Cost:', result.payment.amount, 'USDC');

Pricing:

  • 5+ characters: $0.97/year
  • 3-4 characters: $4.97/year
  • First subname per address: FREE ๐ŸŽ‰

Option B: Buy a Custom ENS Nameโ€‹

If you want a top-level .eth name (e.g., yourbot.eth):

  1. Go to app.ens.domains
  2. Search for your desired name
  3. Purchase (prices vary: 3-letter = $640/yr, 5+ letter = $5/yr)

Step 4: Register as an ERC-8004 Agentโ€‹

On-chain agent registration provides:

  • Verifiable agent identity
  • Searchable registry
  • Reputation tracking (future)
// scripts/register-erc8004.js
import { createPublicClient, createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import fs from 'fs';

const privateKey = fs.readFileSync('.agent-wallet.key', 'utf8').trim();
const account = privateKeyToAccount(privateKey);

const client = createWalletClient({
account,
chain: base,
transport: http()
});

const REGISTRY_ADDRESS = '0x...'; // ERC-8004 registry on Base

const agentName = 'yourbot.aboutme.eth';
const agentType = 1; // 1 = autonomous agent
const metadata = JSON.stringify({
name: 'YourBot',
description: 'AI agent for Web3 automation',
version: '1.0.0',
capabilities: ['ens-resolution', 'x402-payments', 'data-aggregation']
});

const tx = await client.writeContract({
address: REGISTRY_ADDRESS,
abi: [{
name: 'registerAgent',
type: 'function',
inputs: [
{ name: 'name', type: 'string' },
{ name: 'agentType', type: 'uint8' },
{ name: 'metadata', type: 'string' }
],
outputs: [{ name: 'agentId', type: 'uint256' }]
}],
functionName: 'registerAgent',
args: [agentName, agentType, metadata]
});

console.log('Registration TX:', tx);

Gas cost: ~$0.50 on Base


Step 5: Integrate x402 Paymentsโ€‹

Now your agent can pay for its own API access.

Install x402 Clientโ€‹

npm install @x402/client

Make Your First Paid Requestโ€‹

// scripts/agent-query.js
import { X402Client } from '@x402/client';
import { createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import fs from 'fs';

const privateKey = fs.readFileSync('.agent-wallet.key', 'utf8').trim();
const account = privateKeyToAccount(privateKey);

const wallet = createWalletClient({
account,
chain: base,
transport: http()
});

const x402 = new X402Client({
wallet,
chainId: 8453, // Base
facilitatorUrl: 'https://api.cdp.coinbase.com/platform/v2/x402'
});

// Query ENS name with automatic payment
async function resolveENS(name) {
const response = await x402.request(
`https://api.web3identity.com/api/ens/${name}`
);

return response.data;
}

const profile = await resolveENS('vitalik.eth');
console.log('Address:', profile.address);
console.log('Avatar:', profile.avatar);
console.log('Payment:', x402.lastPayment); // ~$0.01

How it works:

  1. Agent requests a paid endpoint
  2. x402 client signs an EIP-712 payment message
  3. Payment settles in USDC on Base
  4. API returns data instantly

Step 6: Build Agent Logicโ€‹

Now assemble your agent's core functionality.

Example: ENS Monitoring Agentโ€‹

// index.js
import { X402Client } from '@x402/client';
import { createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import fs from 'fs';

const privateKey = fs.readFileSync('.agent-wallet.key', 'utf8').trim();
const account = privateKeyToAccount(privateKey);

const wallet = createWalletClient({
account,
chain: base,
transport: http()
});

const x402 = new X402Client({
wallet,
chainId: 8453,
facilitatorUrl: 'https://api.cdp.coinbase.com/platform/v2/x402'
});

// Monitor ENS name changes
async function monitorENS(name) {
console.log(`[${new Date().toISOString()}] Monitoring ${name}...`);

const response = await x402.request(
`https://api.web3identity.com/api/ens/${name}`
);

const data = response.data;

// Check for changes
const lastState = loadState(name);

if (lastState && lastState.address !== data.address) {
console.log(`๐Ÿšจ ${name} address changed!`);
console.log(` Old: ${lastState.address}`);
console.log(` New: ${data.address}`);
await sendAlert(name, lastState.address, data.address);
}

saveState(name, data);
}

// Alert function (send to Discord, Telegram, etc.)
async function sendAlert(name, oldAddress, newAddress) {
await fetch('https://discord.com/api/webhooks/YOUR_WEBHOOK', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
content: `๐Ÿšจ **${name}** address changed!\n\`\`\`diff\n- ${oldAddress}\n+ ${newAddress}\n\`\`\``
})
});
}

// Simple state persistence
function loadState(name) {
try {
const data = fs.readFileSync(`.state/${name}.json`, 'utf8');
return JSON.parse(data);
} catch {
return null;
}
}

function saveState(name, data) {
fs.mkdirSync('.state', { recursive: true });
fs.writeFileSync(`.state/${name}.json`, JSON.stringify(data, null, 2));
}

// Monitor vitalik.eth every 5 minutes
setInterval(() => monitorENS('vitalik.eth'), 5 * 60 * 1000);
monitorENS('vitalik.eth'); // Initial check

Step 7: Deploy Your Agentโ€‹

Local Developmentโ€‹

node index.js

Production Deploymentโ€‹

Option A: PM2 (VPS/EC2)

npm install -g pm2
pm2 start index.js --name "yourbot-agent"
pm2 save
pm2 startup

Option B: Docker

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
CMD ["node", "index.js"]
docker build -t yourbot-agent .
docker run -d --restart=unless-stopped yourbot-agent

Option C: Systemd (Linux)

# /etc/systemd/system/yourbot-agent.service
[Unit]
Description=YourBot Agent
After=network.target

[Service]
Type=simple
User=youruser
WorkingDirectory=/home/youruser/yourbot-agent
ExecStart=/usr/bin/node index.js
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl enable yourbot-agent
sudo systemctl start yourbot-agent

Cost Breakdownโ€‹

ItemOne-TimeMonthly
ENS subname (5+ chars)$0.97$0.08
ERC-8004 registration$0.50-
x402 API calls (1000/day)-$10
Server (AWS t3.micro)-$10
Total$1.47~$20

Free tier alternative:

  • 100 API calls/day: $0/month
  • Use free hosting (Render, Railway)
  • Total: $1.47 one-time

Advanced Featuresโ€‹

Multi-Chain Identityโ€‹

Your agent can resolve names across chains:

// Resolve Base name
const baseProfile = await x402.request(
'https://api.web3identity.com/api/basename/hyperwave.base.eth'
);

// Resolve ENS on L2
const l2Profile = await x402.request(
'https://api.web3identity.com/api/ens/l2/vitalik.eth'
);

Batch Operationsโ€‹

Save on payments by batching requests:

const names = ['vitalik.eth', 'nick.eth', 'brantly.eth'];

const response = await x402.request(
'https://api.web3identity.com/api/ens/batch',
{
method: 'POST',
body: JSON.stringify({ names })
}
);

console.log('Resolved:', response.data); // All 3 names
console.log('Cost:', x402.lastPayment); // Single payment for all

Rate Limit Managementโ€‹

x402 has no hard rate limits, but implement backoff for reliability:

async function requestWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await x402.request(url);
} catch (error) {
if (error.status === 429 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}

Security Best Practicesโ€‹

1. Secure Your Private Keyโ€‹

// โœ… Good: Use environment variables or encrypted key files
const privateKey = process.env.AGENT_PRIVATE_KEY;

// โŒ Bad: Hardcode in source
const privateKey = '0x1234...'; // NEVER DO THIS

2. Monitor Spendingโ€‹

// Track cumulative spend
let totalSpent = 0;
const DAILY_LIMIT = 100; // $100/day

x402.on('payment', (payment) => {
totalSpent += payment.amount;
if (totalSpent > DAILY_LIMIT) {
console.error('โš ๏ธ Daily spending limit reached!');
process.exit(1);
}
});

3. Implement Circuit Breakersโ€‹

let consecutiveFailures = 0;
const MAX_FAILURES = 5;

async function safeRequest(url) {
try {
const response = await x402.request(url);
consecutiveFailures = 0; // Reset on success
return response;
} catch (error) {
consecutiveFailures++;
if (consecutiveFailures >= MAX_FAILURES) {
console.error('Circuit breaker triggered!');
await sendAdminAlert('Agent failing repeatedly');
// Pause for 5 minutes
await new Promise(resolve => setTimeout(resolve, 5 * 60 * 1000));
consecutiveFailures = 0;
}
throw error;
}
}

4. Log All Transactionsโ€‹

import fs from 'fs';

x402.on('payment', (payment) => {
const log = {
timestamp: new Date().toISOString(),
amount: payment.amount,
currency: 'USDC',
endpoint: payment.endpoint,
txHash: payment.txHash
};

fs.appendFileSync(
'logs/payments.jsonl',
JSON.stringify(log) + '\n'
);
});

Troubleshootingโ€‹

"Insufficient funds for gas"โ€‹

Cause: Not enough ETH for transaction fees.

Fix: Bridge more ETH to Base:

# Check balance
cast balance YOUR_AGENT_ADDRESS --rpc-url https://mainnet.base.org

"402 Payment Required but no payment made"โ€‹

Cause: x402 client not properly initialized or wallet not funded with USDC.

Fix:

  1. Verify USDC balance on Base
  2. Check wallet client configuration
  3. Ensure chainId: 8453 (Base mainnet)

"ENS name not resolving"โ€‹

Cause: Subname registration pending or not propagated.

Fix: Wait 1-2 minutes after registration, then verify:

curl "https://api.web3identity.com/api/ens/yourbot.aboutme.eth"

Next Stepsโ€‹

  • Add intelligence: Integrate OpenAI or Anthropic for NLP
  • Agent-to-agent messaging: Use XMTP for decentralized communication
  • On-chain actions: Add token swaps, NFT minting, governance voting
  • Reputation system: Track agent reliability on-chain

Example Agents to Studyโ€‹

AgentENSPurpose
ATVatv.ethIdentity verification & trust
clawd.atgclawd.atg.ethWeb3 development assistant
Laukilauki.ethDeFi automation

Resourcesโ€‹


Supportโ€‹

Need help building your agent?


Guide last updated: February 10, 2026