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).
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
| Capability | Pydantic AI alone | With Paybond |
|---|---|---|
| Model / input guardrails | Yes — SDK or host checks and approvals | Yes — plus Harbor authorize at the tool boundary |
| Spend boundary | No per-tool Harbor budget or capability token | Per-call and intent budgets enforced before invoke |
| Signed evidence | SDK traces / logs only | Signed completion digests bound to the intent |
| Intent binding | No Harbor intent or settlement receipt | Capability token + intentId from authenticated bind |
| Paid tool deny / HITL | Host or SDK approvals only | spend verify, deny, or HITL hold before side effects |
How it works
Adapter flow
Tool / callable
Pydantic AI agent invokes a side-effecting tool
Paybond wrap
Harbor authorize before your handler runs
- Verify spend and operation
- Deny or HITL hold
- Issue / check capability
Tool runs
Your tool body performs the paid work
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
paybond login
paybond agent demo pydantic-ai smoke \
--operation paid-tool \
--requested-spend-cents 100 \
--evidence-preset cost_and_completion \
--format tableInstall the extra first:
terminal
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
What success looks like
Authorized tool call · illustrative
- Operation
- paid-tool
- Status
- Approved
- Requested
- $1.00
- Evidence
- Verified
- Preset
- cost_and_completion
Scaffold
terminal
paybond init agent-middleware --framework pydantic-ai --out paybond_pydantic_ai.py
paybond policy init --preset saas --out paybond.policy.yamlWire middleware
Recommended wiring
paybond.agent with framework pydantic-ai returns guarded agent_tools for your Pydantic AI Agent.
paybond_session.py
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
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
- Scaffold middleware with paybond init agent-middleware --framework pydantic-ai
- Init a policy preset (e.g. saas) and validate tools
- Wire paybond.agent(framework="pydantic-ai", tools=...)
- Bind intentId and capabilityToken per session in production
- Smoke with paybond agent demo pydantic-ai smoke before ship
Works with
Works with
- Pydantic AI
- OpenAI
- Anthropic
- MCP
Ready to test?
Related guides
- Agent middleware — run binding and policy hot-reload
- Agent policy-as-code — long-lived agents with GitOps YAML
- Agent-agnostic spend controls — fallback for mixed runtimes
Developer reference: /docs/kit/pydantic-ai.