paybondpaybond
Sign in

Recipe · Framework

Spend controls for Claude Agent SDK tools

spend verify before in-process MCP tool() handlers run, auto-evidence after success, and policy budgets for Claude Agent SDK — TypeScript and Python.

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

You'll build

Claude Agent SDK tools with spend verify at the tool boundary

Before you start

  • paybond-kit[claude-agents]
  • demo smoke
  • ~3 min

The Claude Agent SDK registers paid work through in-process MCP tool() definitions. Paybond wraps those handlers so Harbor verifies spend before execution and auto-submits evidence after success. Built-in Claude tools (Read, Bash, etc.) pass through unguarded.

Beta: The Claude Agent SDK is evolving. Treat this adapter as beta until Anthropic stabilizes the SDK.

Adapter reference: /docs/kit/claude-agents.

  • spend verify before handlers

    In-process MCP tool() handlers authorize operation and amount before paid work runs.

  • Auto-evidence

    Wrapped handlers finalize spend and submit signed evidence after tool success.

  • Policy budgets

    Versioned YAML caps per-call and intent spend — built-in Claude tools pass through unguarded.

  • TypeScript and Python

    Same claude-agents adapter on npm and pip (paybond-kit[claude-agents]).

Why Paybond (not just SDK guardrails)?

Claude Agent SDK approvals and host checks do not enforce a spend limit, a per-operation permission check (capability token), or a signed completion receipt tied to a spend agreement (intent).

Claude Agent SDK alone versus Paybond Harbor spend controls
  • Model / input guardrails

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

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

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

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

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

How it works

Paybond wraps Claude Agent SDK tool() handlers: Harbor authorize before the handler runs, then auto-evidence after success.

Adapter flow

  1. tool() handler

    Claude Agent SDK calls an in-process MCP custom tool

  2. Paybond wrap

    Harbor authorize before your handler runs

    • Verify spend and operation
    • Deny or HITL hold
    • Issue / check capability
  3. Handler runs

    Your tool body performs the paid work

  4. Evidence

    Wrapped handler finalizes spend + auto-evidence

Paybond wraps Claude Agent SDK tool() handlers: Harbor authorize before the handler runs, then auto-evidence after success.

3-minute quickstart

Smoke the claude-agents adapter sandbox contract — no Anthropic credentials required for this check:

Terminal
Terminal commandSwipe to inspect long lines
paybond login
paybond agent demo claude-agents smoke \
  --operation paid-tool \
  --requested-spend-cents 100 \
  --evidence-preset cost_and_completion \
  --format table

When the smoke succeeds you should see:

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

What success looks like

Example status after a Paybond-guarded Claude Agent SDK tool call: approved spend, requested amount, and verified cost_and_completion evidence.

What success looks like

Authorized tool call · illustrative

Sandbox path
Operation
paid-tool
Status
Approved
Requested
$1.00
Evidence
Verified
Preset
cost_and_completion

Scaffold

Terminal
Terminal commandSwipe to inspect long lines
paybond init agent-middleware --framework claude-agents --out paybond-claude-agents.ts
paybond policy init --preset travel --out paybond.policy.yaml

Validate before deploy:

Terminal
Terminal commandSwipe to inspect long lines
paybond policy validate-tools --file paybond.policy.yaml --local-only

Wire middleware

Recommended wiring

paybond.agent with framework claude-agents returns claudeAgentsConfig so Harbor wraps tool() handlers before query().

paybond-session.ts

TS
Code exampleSwipe to inspect long lines
import { tool, query } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";
import { Paybond } from "@paybond/kit";

const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });

const sdkTools = [
  tool(
    "travel.book_hotel",
    "Book a hotel room",
    { city: z.string(), estimatedPriceCents: z.number() },
    async (args) => ({
      content: [{ type: "text", text: JSON.stringify(await bookHotel(args)) }],
      structuredContent: await bookHotel(args),
    }),
  ),
];

const { claudeAgentsConfig } = await paybond.agent({
  policy: "travel",
  framework: "claude-agents",
  tools: sdkTools,
});

const { mcpServer, allowedTools } = claudeAgentsConfig!;

await query({
  prompt: "Book a hotel in Lisbon under budget.",
  options: {
    mcpServers: { paybond: mcpServer },
    allowedTools,
  },
});

Install extras: pip install "paybond-kit[claude-agents]".

Production: omit sandbox defaults, use deferred bind, then instrumented.bind({ intentId, capabilityToken }) per session. Tenant and intent IDs come from the Paybond session binding — never from unauthenticated tool args.

Production checklist

Production checklist for Paybond-guarded Claude Agent SDK tools.

Production checklist

Works with

Works with

  • Anthropic
  • OpenAI
  • Vercel
  • MCP

Ready to test?

Developer reference: /docs/kit/claude-agents.