This guide walks through building an AI agent that can search Book402 and pay for results automatically.
Prerequisites¶
- Node.js 18+
- A wallet with USDC on Base
- Tiny amount of ETH on Base (for the facilitator's settlement gas)
Install Dependencies¶
Complete Example¶
import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { ExactEvmScheme, toClientEvmSigner } from '@x402/evm';
import { createWalletClient, createPublicClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
// --- Setup ---
const account = privateKeyToAccount(process.env.WALLET_KEY as `0x${string}`);
const transport = http('https://mainnet.base.org');
const publicClient = createPublicClient({ chain: base, transport });
const walletClient = createWalletClient({ account, chain: base, transport });
// Create x402 payment client
const signer = toClientEvmSigner(account, publicClient, walletClient);
const client = new x402Client();
client.register('eip155:8453', new ExactEvmScheme(signer));
const fetchWith402 = wrapFetchWithPayment(globalThis.fetch, client);
// --- Use Book402 ---
// 1. Free: Browse books
async function searchBooks(query: string) {
const res = await fetch(`https://book402.com/books?q=${encodeURIComponent(query)}`);
return res.json();
}
// 2. Paid: Hybrid search ($0.01)
async function hybridSearch(query: string, limit = 10) {
const res = await fetchWith402(
`https://book402.com/search/hybrid?q=${encodeURIComponent(query)}&limit=${limit}`
);
return res.json();
}
// 3. Paid: Get book summary ($0.05)
async function getBookSummary(bookId: number) {
const res = await fetchWith402(
`https://book402.com/books/${bookId}/summary`
);
return res.json();
}
// --- Agent Loop ---
async function agent() {
// Step 1: Find relevant books (free)
const books = await searchBooks('productivity');
console.log(`Found ${books.total} books about productivity`);
// Step 2: Deep search with semantics (paid - $0.01)
const results = await hybridSearch('how to build better habits', 5);
console.log('Top results:', results.data.map(r => r.title));
// Step 3: Get full summary of the best match (paid - $0.05)
const summary = await getBookSummary(results.data[0].id);
console.log('Summary:', summary.summary.slice(0, 200) + '...');
}
agent().catch(console.error);
Agent Architecture¶
graph TD
subgraph Agent["🤖 Your AI Agent"]
LLM[LLM / Reasoning Engine]
TOOLS[Tool Registry]
WALLET[x402 Wallet Client]
end
subgraph Book402["📚 Book402"]
FREE[Free Endpoints]
PAID[Paid Endpoints]
end
LLM -->|"decides to search"| TOOLS
TOOLS -->|"free: browse"| FREE
TOOLS -->|"paid: deep search"| WALLET
WALLET -->|"auto-pays $0.01"| PAID
PAID -->|"results"| TOOLS
TOOLS -->|"context"| LLM
Using with MCP¶
Book402 can be used as an MCP tool. Add it to your MCP config:
{
"tools": [
{
"name": "book402_search",
"description": "Search 3,807 books using hybrid BM25+vector search",
"endpoint": "https://book402.com/search/hybrid",
"parameters": {
"q": { "type": "string", "description": "Search query" },
"limit": { "type": "number", "description": "Max results" }
}
}
]
}
Agent Discovery
Book402 will soon publish /.well-known/agent.json (A2A) and /.well-known/mcp.json for automatic agent discovery.
Cost Management¶
Set a budget for your agent:
// Track spending
let totalSpent = 0;
const MAX_BUDGET = 1.00; // $1.00 max
async function paidSearch(query: string) {
if (totalSpent >= MAX_BUDGET) {
throw new Error('Budget exceeded!');
}
const res = await fetchWith402(
`https://book402.com/search/hybrid?q=${encodeURIComponent(query)}`
);
totalSpent += 0.01;
console.log(`Spent: $${totalSpent.toFixed(2)} / $${MAX_BUDGET}`);
return res.json();
}
Error Handling¶
try {
const res = await fetchWith402('https://book402.com/search/hybrid?q=test');
if (res.status === 200) {
// Success — payment was made and content delivered
const data = await res.json();
} else if (res.status === 402) {
// Payment failed — insufficient USDC balance?
console.error('Payment failed');
}
} catch (err) {
// Network error, wallet error, etc.
console.error('Request failed:', err.message);
}