paybondpaybond
Sign in

Recipe · Checkout

Next.js agent checkout with bounded spend

Build a Next.js App Router agent with Vercel AI SDK and Paybond — request-scoped bind, toolApproval, and spend-guarded checkout tools.

  1. 1Wire
  2. 2Authorize
  3. 3Smoke

You'll build

A Next.js checkout path with spend-guarded agent spend

Shopping and checkout agents in Next.js typically combine the App Router, the Vercel AI SDK, and server-side secrets. Paybond belongs on the server — bind middleware per request, never expose capability tokens to the browser.

TypeScript only. This guide uses @paybond/kit/vercel-ai (TypeScript-only). For Python shopping agents, use Let agents buy groceries with the agent-agnostic path.

Adapter reference: /docs/kit/vercel-ai.

  • Server-only Paybond

    Open Kit and instrument in Route Handlers — never expose capability tokens to the browser.

  • Request-scoped bind

    Lazy context + AsyncLocalStorage resolve intentId per request for streamText.

  • Vercel AI toolApproval

    Harbor authorize before checkout tools; client receives streamed text only.

  • TypeScript only

    App Router + Vercel AI samples are TypeScript; Python shopping uses the agent-agnostic grocery guide.

Why Paybond (not just Next.js and the AI SDK)?

App Router and Vercel AI SDK tool approvals do not enforce a spend limit, a per-operation permission check (capability token), or a signed completion receipt tied to a spend agreement (intent).

Next.js agent checkout alone versus Paybond Harbor spend controls
  • Model / input guardrails

    Next.js alone
    Yes — SDK or host checks and approvals
    With Paybond
    Yes — plus Harbor authorize at the tool boundary
  • Spend boundary

    Next.js alone
    No per-tool Harbor budget or capability token
    With Paybond
    Per-call and intent budgets enforced before invoke
  • Signed evidence

    Next.js alone
    SDK traces / logs only
    With Paybond
    Signed completion digests bound to the intent
  • Intent binding

    Next.js alone
    No Harbor intent or settlement receipt
    With Paybond
    Capability token + intentId from authenticated bind
  • Paid tool deny / HITL

    Next.js alone
    Host or SDK approvals only
    With Paybond
    spend verify, deny, or HITL hold before side effects

How it works

Next.js Route Handlers bind Paybond per request, pass guarded tools to Vercel AI, and keep capability tokens server-side.

App Router flow

  1. POST /api/agent

    Client sends prompt + session bind credentials

  2. instrumented.bind

    Harbor session scoped to this request

    • intentId + capabilityToken
    • Lazy context store
    • Never from raw client tenant ids
  3. streamText + toolApproval

    Vercel AI runs guarded checkout tools

  4. Evidence

    Wrapped execute finalizes spend + auto-evidence

Next.js Route Handlers bind Paybond per request, pass guarded tools to Vercel AI, and keep capability tokens server-side.

3-minute quickstart

Smoke the vercel-ai checkout sandbox contract — no Next.js server required for this check:

Terminal
Terminal commandSwipe to inspect long lines
paybond login
paybond agent demo vercel-ai smoke \
  --operation commerce.checkout \
  --requested-spend-cents 1000 \
  --evidence-preset cost_and_completion \
  --format table

Scaffold the shopping preset:

Terminal
Terminal commandSwipe to inspect long lines
paybond init --solution shopping --max-spend-usd 100 --framework vercel-ai --non-interactive
paybond policy init --preset shopping --out paybond.policy.yaml

When the smoke succeeds you should see:

  • ✓ Spend approved
  • ✓ Checkout completed
  • ✓ Evidence verified (cost_and_completion)

What success looks like

Example status after a Paybond-guarded Next.js agent checkout tool call: approved spend, requested amount, and verified cost_and_completion evidence.

What success looks like

Authorized checkout · illustrative

Sandbox path
Operation
commerce.checkout
Status
Approved
Requested
$10.00
Evidence
Verified
Preset
cost_and_completion

Wire middleware

Lazy context pattern (recommended)

Load policy once at module scope; resolve the active bind per request with AsyncLocalStorage.

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
// lib/paybond.ts
import { Paybond } from "@paybond/kit";
import { AsyncLocalStorage } from "node:async_hooks";

const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });
const requestStore = new AsyncLocalStorage<{ runtime: Awaited<ReturnType<typeof instrumented.bind>> }>();

const instrumented = await paybond.instrument({
  policy: "./paybond.policy.yaml",
  framework: "vercel-ai",
  tools: {
    checkout: checkoutToolDef,
    searchProducts: searchProductsToolDef,
  },
  context: () => requestStore.getStore()!.runtime,
});

export { paybond, instrumented, requestStore };

Route handler

paybond-session.ts

TS
TypeScript code sampleSwipe to inspect long lines
// app/api/agent/route.ts
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
import { instrumented, requestStore } from "@/lib/paybond";

export async function POST(req: Request) {
  const { prompt, intentId, capabilityToken } = await req.json();

  const runtime = await instrumented.bind({ intentId, capabilityToken });
  const { agentTools: tools, toolApproval } = runtime;

  return requestStore.run({ runtime }, async () => {
    const result = streamText({
      model: openai("gpt-4.1"),
      tools,
      toolApproval,
      prompt,
    });
    return result.toDataStreamResponse();
  });
}

Sandbox rehearsal: use paybond.agent({ policy: "shopping", framework: "vercel-ai", tools }) to skip manual bind during local dev.

Shopping preset defaults

ToolSide effectingCap
commerce.checkoutYes$100 per call / $100 intent budget
search.productsNo

See Let agents buy groceries for the full multi-tool shopping walkthrough.

Production checklist

Production checklist for Next.js agent checkout with Paybond.

Works with

Works with

  • Vercel
  • OpenAI
  • Stripe
  • MCP

Ready to test?

Developer reference: /docs/kit/vercel-ai.