Recipes
Working patterns for wiring adversarial verification into an agent, priced per call (quick 2¢ · verify 20¢ · panel 75¢, USDC over x402 on Algorand · Base · Polygon · Solana). The first pattern is the one our first real customer runs in production.
1 · The monitoring loop
An autonomous pipeline re-checks a load-bearing claim on a schedule — is the API still rate-limited this way, is the regulation still in force, is the dependency still maintained — and escalates to web-researched verification only when the cheap check wobbles. Observed in the wild: twice daily, same claim, quick tier.
import { SecondOpinion } from "secondopinion-x402"; // npm install secondopinion-x402
const so = new SecondOpinion(); // rail inferred from whichever wallet key is set
// every 12h (cron):
const quick = await so.verify(CLAIM, { tier: "quick" }); // 2¢, ~15s, no web
if (quick.verdict === "inconclusive" || quick.confidence < 0.8) {
const deep = await so.verify(CLAIM, { tier: "verify" }); // 20¢, live web research
if (deep.verdict === "refuted") alertHuman(deep.summary, deep.citations);
}
Cost of monitoring one claim twice daily: about $1.20/month, plus
20¢ per escalation. No account to provision — the wallet is the identity.
Shortcut: the npm (≥0.4.0) and PyPI (≥0.3.0) clients run this whole if/then for you:
so.verify(CLAIM, { tier: "auto", maxUsd: 0.22 }) — quick first, escalate only on wobble, one spend cap,
lastAuto reports what ran. Funding the wallet in the first place: /fund.
2 · Verify before you answer
Give the agent a tool it can call mid-task when a claim's failure would be costly. The descriptions are written so models self-select correctly — call it before irreversible commitments, skip it for opinions.
JavaScript / TypeScript
// Vercel AI SDK
import { secondOpinionTool } from "secondopinion-x402/ai";
tools: { second_opinion: secondOpinionTool() }
// LangChain
import { secondOpinionTool } from "secondopinion-x402/langchain";
const tools = [await secondOpinionTool()];
// OpenAI Agents SDK
import { secondOpinionTool } from "secondopinion-x402/openai";
const agent = new Agent({ name: "researcher", tools: [await secondOpinionTool()] });
Python
# pip install secondopinion-x402
from secondopinion import langchain_tool, openai_agents_tool, SecondOpinionCrewTool
tools = [langchain_tool()] # LangChain; tier="verify" for web research
agent = Agent(..., tools=[openai_agents_tool()]) # OpenAI Agents SDK
crew_tools = [SecondOpinionCrewTool()] # CrewAI
MCP (Claude, Cursor, any MCP client)
Hosted, zero install: add https://secondopinionx402.com/mcp as a remote MCP server
Local key signing: npx secondopinion-x402 mcp
3 · Verify what your agent just read
Agents that ingest social posts, scraped pages, or paid data feeds act on other people's claims. Verify the claim the next action depends on — not the whole document. Worked example, run for real: one agent wallet buys a Twitter/X search from x402.twit.sh (another x402 API — 0.6¢ per search, no account there either), then buys adversarial verification of the top post before acting on it.
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch"; // npm i @x402/fetch @x402/evm viem
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
import { SecondOpinion } from "secondopinion-x402";
const account = privateKeyToAccount(process.env.AGENT_KEY); // one wallet, USDC on Base
const payFetch = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
// 1 · buy the data — 0.6¢ settles on Base before the response arrives
const r = await payFetch("https://x402.twit.sh/tweets/search?from=AlgoFoundation");
const post = (await r.json()).data.find((t) => hasSubstance(t.text)); // skip media-only posts
// 2 · verify before acting — 2¢, self-escalating to the researched tier only on wobble
const so = new SecondOpinion({ evmPrivateKey: process.env.AGENT_KEY });
const v = await so.verify(post.text, {
tier: "auto", maxUsd: 0.25,
context: `Posted on X by @${post.author.username}; an agent is about to act on it.`,
});
if (v.verdict !== "supported") holdAndReview(v);
so_a622fb38…,
$0.02 tx +
$0.20 tx).
Agent's total spend: $0.226, no human in the loop. Our first attempt is why the code skips media-only posts: the
newest post was a bare t.co link and the skeptic correctly refused to bless it — a shortened URL
asserts nothing.Rule of thumb: reading is cheap, acting is expensive — verify at the boundary between them. In a
real agent your LLM extracts the one load-bearing claim; the demo verifies the post itself and lets
context carry the provenance.
4 · Survive an empty wallet
Agent wallets run dry mid-pipeline. Our 402 responses tell you what happened in plain JSON:
error carries the decoded rejection reason (most commonly insufficient funds — you are never
charged for a failed attempt), and while the free trial is enabled, free_fallback points at a
no-payment endpoint serving the identical quick engine, so a monitoring loop can degrade gracefully instead of
going dark until someone tops up.
const res = await payAndCall("/v1/verify/quick", body);
if (res.status === 402) {
const b = await res.json(); // { error, hint, free_fallback?, docs }
if (b.free_fallback) {
const trial = await fetch(b.free_fallback.url, { // POST /v1/try — free, unsigned verdict
method: "POST", headers: { "content-type": "application/json" },
body: JSON.stringify({ claim: CLAIM.slice(0, 500) }),
});
return { ...(await trial.json()), degraded: true }; // flag it; top up for signed verdicts
}
}
5 · Keep the receipts
Every paid verdict is Ed25519-signed and verifies offline against the published key — an audit trail of what your agent knew, when, and what it paid to know it. Store the verdict JSON as-is; verify any time.
import { verifyReceipt } from "secondopinion-x402";
const ok = await verifyReceipt(verdictJson); // offline; or paste into https://secondopinionx402.com/verify-receipt
6 · Picking a rail
- Algorand — the home rail: sync + async, settles in seconds via GoPlausible. Wallet needs USDC (asset 31566704) opt-in.
- Base / Polygon — one EVM wallet covers all of them; USDC only, no gas token ever (the facilitator submits).
- Solana — use the
/asyncroutes (pay, get a job id in seconds, poll free) — its ~60s transaction validity cannot outlive a long sync call.
Unpaid requests to any paid route return HTTP 402 with exact terms in the
PAYMENT-REQUIRED header — the quote is the documentation. Full machine docs:
/llms.txt, /v1/schema, OpenAPI.