x402 payment security for Vercel AI SDK agents

TollWarden is a payment security firewall for x402 micropayments. Agents that pay for APIs and data over x402 get drained in predictable ways, through payments triggered by prompt-injected content, replayed authorizations, inflated prices, secrets leaking through payment metadata, lookalike tokens, and address poisoning. @tollwarden/ai-sdk gives a Vercel AI SDK agent an allow / flag / block verdict on every payment before it settles, plus an onStepFinish handler that makes TollWarden's strongest detector work automatically.

Installation

npm install @tollwarden/ai-sdk

Two additions

import { generateText } from "ai";
import { TollWardenClient } from "@tollwarden/client";
import { tollwardenTools, tollwardenProvenance } from "@tollwarden/ai-sdk";

const tollwarden = new TollWardenClient({ agentId: "my-agent" }); // free API key auto-minted (100 free scans)

await generateText({
  model,
  tools: { ...tollwardenTools(tollwarden), ...yourOtherTools },
  onStepFinish: tollwardenProvenance(tollwarden),
  prompt: "...",
});

Why the provenance handler matters

TollWarden's strongest check catches payments whose decision came from content the agent just read (a prompt-injected page or tool result). tollwardenProvenance returns an onStepFinish handler that observes every tool result the step produced automatically, so the next scan is provenance-tagged and that check runs with real input. No prompt engineering required. TollWarden's own tool results are excluded so verdicts never pollute the signal. It reads both the current toolResults[].output shape and the older .result shape, and works the same under streamText.

The toolset

Payments that cannot execute when blocked

import { guardedPayment } from "@tollwarden/ai-sdk";

const safePay = guardedPayment(executeX402Payment, tollwarden);
const { result } = await safePay(payment, expectedPriceUsd);
// throws TollWardenBlockedError on a block verdict; the executor is never called

For wallet-level enforcement (the signer itself refuses unscanned payments), see wrapFetchWithTollWarden and TollWardenEnforcer in the @tollwarden/client SDK.

Reference

Other integrations