paybondpaybond
Sign in

Recipe · Framework

Spend controls for Pydantic AI tools

spend verify before Tool / callable handlers run, auto-evidence after success, and policy budgets for Pydantic AI — Python.

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

You'll build

Pydantic AI tools with Harbor authorize + auto-evidence

Pydantic AI agents call tools through Tool instances and plain callables. Paybond hooks that execution boundary — spend verify before side-effecting tools execute, then auto-evidence after success. Model inference stays on your provider client.

Python only — install paybond-kit[pydantic-ai] for the native adapter.

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

  • spend verify before Tool

    Wrapped Tool / callable handlers authorize operation and amount before paid work.

  • Auto-evidence

    Guarded tools finalize spend and submit signed evidence after success.

  • Policy budgets

    Versioned YAML caps per-call and intent spend for type-safe Python agents.

  • Python native

    Install paybond-kit[pydantic-ai] — TypeScript stacks use agent-agnostic or another adapter.

Why Paybond (not just Pydantic AI checks)?

Pydantic AI prepare hooks and host 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).

Pydantic AI alone versus Paybond Harbor spend controls
  • Model / input guardrails

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

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

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

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

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

How it works

Paybond wraps Pydantic AI Tool / callable handlers: Harbor authorize before the tool runs, then auto-evidence after success.

Adapter flow

  1. Tool / callable

    Pydantic AI agent invokes a side-effecting tool

  2. Paybond wrap

    Harbor authorize before your handler runs

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

    Your tool body performs the paid work

  4. Evidence

    Wrapped tool finalizes spend + auto-evidence

Paybond wraps Pydantic AI Tool / callable handlers: Harbor authorize before the tool runs, then auto-evidence after success.

3-minute quickstart

Smoke the pydantic-ai adapter sandbox contract:

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

Install the extra first:

Terminal
Terminal commandSwipe to inspect long lines
pip install "paybond-kit[pydantic-ai]"

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 Pydantic AI 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 pydantic-ai --out paybond_pydantic_ai.py
paybond policy init --preset saas --out paybond.policy.yaml

Wire middleware

Recommended wiring

paybond.agent with framework pydantic-ai returns guarded agent_tools for your Pydantic AI Agent.

paybond_session.py

PY
Python code sampleSwipe to inspect long lines
from pydantic_ai import Agent
from paybond_kit import Paybond
from paybond_kit.agent.registry import create_paybond_tool_registry
from paybond_kit.pydantic_ai import create_paybond_pydantic_ai_config

# Price lives in your fare table — not in an LLM-invented amount_cents.
FARES = {"SFO-SEA": 18_900}

def book_flight(route: str, seats: int = 1) -> dict:
    """Book a flight. Fare comes from the fare table, not the model."""
    return {
        "status": "completed",
        "route": route,
        "cost_cents": FARES[route] * seats,
    }

paybond = await Paybond.open(api_key=os.environ["PAYBOND_API_KEY"])
run = await paybond.agent_run.bind(
    {
        "bootstrap": {
            "kind": "sandbox",
            "operation": "book_flight",
            "requested_spend_cents": 18_900,
            "completion_preset": "cost_and_completion",
        },
        "registry": create_paybond_tool_registry(
            {
                "default_deny": True,
                "side_effecting": {
                    "book_flight": {
                        "operation": "book_flight",
                        "evidence_preset": "cost_and_completion",
                        "spend_cents": lambda args: FARES[args["route"]]
                        * int(args.get("seats", 1)),
                    }
                },
            }
        ),
    }
)
guarded = create_paybond_pydantic_ai_config(run, [book_flight, search_catalog]).tools
agent = Agent("openai:gpt-4o", tools=guarded)

Manual hook wiring

When you already bound a PaybondAgentRun:

paybond_session.py

PY
Python code sampleSwipe to inspect long lines
from paybond_kit.pydantic_ai import create_paybond_pydantic_ai_config

config = create_paybond_pydantic_ai_config(run, tools)
guarded_tools = config.tools
# Or wrap incrementally: config.wrap_tool(new_tool)

Approval holds: when Paybond returns an approval hold, guarded tools raise pydantic_ai.ModelRetry with a Paybond message. Approve in the tenant console, then retry with the same operation, amount, metadata, and approvalToken. Hard denials must not execute the tool.

Bypass classes: provider native tools, unwrapped MCP/toolsets, and tools registered with @agent.tool without going through Paybond wrap are not governed.

Production checklist

Production checklist for Paybond-guarded Pydantic AI tools.

Production checklist

Works with

Works with

  • Pydantic AI
  • OpenAI
  • Anthropic
  • MCP

Ready to test?

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