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

npm install @x402/fetch @x402/evm viem

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);
}