AttestPage · Docs · Pricing · OpenAPI · llms.txt

OpenAI Agents SDK: check a quote before citing it, paid per call

Last updated: 2026-10-10

An OpenAI Agents SDK agent with two AttestPage tools: verify_quote (US$0.01 a call) and check_links (US$0.005 per batch of up to 10 URLs). With no key, the client uses the free trial and returns the price when a call needs payment. With ATTESTPAGE_X402_KEY set, it pays each call with x402 through @x402/fetch, and refuses any offer above its limit.

Install

Node.js 20 or later.

npm init -y && npm pkg set type=module
npm install @openai/agents zod
npm install @x402/fetch @x402/evm viem   # only needed to pay
export OPENAI_API_KEY=...

To pay, set ATTESTPAGE_X402_KEY to the private key (0x and 64 hex digits) of a Base Sepolia wallet made only for testing, holding test USDC. The key stays in this process.

attestpage.mjs

// AttestPage client for agent tools. With no key it sends the free-trial header. With ATTESTPAGE_X402_KEY
// it pays each call with x402 on Base Sepolia (test USDC), up to MAX_USD a call. A 402 it does not pay
// comes back as { payment_required, price_usd, network } instead of an exception.
const BASE = (process.env.ATTESTPAGE_URL || 'https://vehcdj664efetfrsolne5umanq.srv.us').replace(/\/+$/, '');
const NETWORK = 'eip155:84532'; // Base Sepolia
const MAX_USD = Number(process.env.MAX_USD || '0.01'); // the most one call may cost

// A fetch that answers 402 offers with a payment signed by key. Loaded only when a key is set.
async function payingFetch(key) {
  const [{ wrapFetchWithPayment, x402Client }, { registerExactEvmScheme }, { privateKeyToAccount }] = await Promise.all([
    import('@x402/fetch'), import('@x402/evm/exact/client'), import('viem/accounts'),
  ]);
  const client = new x402Client();
  registerExactEvmScheme(client, { signer: privateKeyToAccount(key) });
  // Sign only offers on Base Sepolia at or under MAX_USD (amounts are USDC with 6 decimals).
  client.registerPolicy((_version, reqs) => reqs.filter((r) => r.network === NETWORK && Number(r.amount) <= MAX_USD * 1e6));
  return wrapFetchWithPayment(fetch, client);
}

function offer(header) {
  try {
    const first = JSON.parse(Buffer.from(header, 'base64').toString('utf8')).accepts[0];
    return { price_usd: Number(first.amount) / 1e6, network: first.network };
  } catch {
    return {};
  }
}

export async function createClient({ key = process.env.ATTESTPAGE_X402_KEY } = {}) {
  const fetchFn = key ? await payingFetch(key) : fetch;

  async function call(path, body, { trial = !key } = {}) {
    const headers = { 'content-type': 'application/json', accept: 'application/json' };
    if (trial) headers['quoteproof-trial'] = '1';
    let res;
    try {
      res = await fetchFn(`${BASE}${path}`, { method: 'POST', headers, body: JSON.stringify(body) });
    } catch (err) {
      // @x402/fetch throws when no offer passes the policy, or when signing fails.
      return { error: 'payment_not_made', message: String(err?.message ?? err) };
    }
    const json = await res.json().catch(() => ({}));
    if (res.ok) return json;
    // The trial is used up for today: ask again without it, for the price.
    if (res.status === 429 && trial && json.error?.code === 'trial_exhausted') return call(path, body, { trial: false });
    if (res.status === 402) {
      return { payment_required: true, ...offer(res.headers.get('payment-required') ?? ''),
        message: 'This call needs an x402 payment; set ATTESTPAGE_X402_KEY to pay.' };
    }
    return { error: json.error?.code ?? `http_${res.status}`, status: res.status, message: json.error?.message ?? '' };
  }

  return {
    verifyQuote: ({ url, quote, match = 'fuzzy' }) => call('/v1/verify/quote', { url, quote, match }),
    checkLinks: ({ urls }) => call('/v1/check/links', { urls }),
    verifyReceipt: ({ receipt }) => call('/v1/receipt/verify', { receipt }, { trial: false }),
  };
}

openai-agents-sdk.mjs

// OpenAI Agents SDK agent that checks a quote with AttestPage before it cites it.
import { Agent, run, tool } from '@openai/agents';
import { z } from 'zod';
import { createClient } from './attestpage.mjs';

const attestpage = await createClient();

const verifyQuote = tool({
  name: 'verify_quote',
  description: 'Use before quoting a web page: is this exact or near-exact quote on the page at url? '
    + 'Returns result.match (exact, fuzzy or none), page.content_kind and a signed receipt. US$0.01.',
  parameters: z.object({ url: z.string(), quote: z.string() }),
  execute: async ({ url, quote }) => attestpage.verifyQuote({ url, quote }),
});

const checkLinks = tool({
  name: 'check_links',
  description: 'Use before putting links in an answer: status, final URL and content_kind for each URL. '
    + 'Up to 10 URLs (3 on the free trial). US$0.005 per batch.',
  parameters: z.object({ urls: z.array(z.string()).min(1).max(10) }),
  execute: async ({ urls }) => attestpage.checkLinks({ urls }),
});

const agent = new Agent({
  name: 'Source checker',
  instructions: 'Before you quote a web page, call verify_quote. Cite a quote only when result.match is exact or fuzzy '
    + 'and page.content_kind is real. If a tool returns payment_required, give the price and stop.',
  tools: [verifyQuote, checkLinks],
});

const question = process.argv.slice(2).join(' ')
  || 'Does https://www.iana.org/help/example-domains say "These domains may be used as illustrative examples in documents"?';
const result = await run(agent, question);
console.log(result.finalOutput);

Run

node openai-agents-sdk.mjs                             # free trial
ATTESTPAGE_X402_KEY=0x... node openai-agents-sdk.mjs   # pays US$0.01 per verify_quote in test USDC

What comes back