The OpenAI Agents SDK runs tools through FunctionTool.invoke. Paybond hooks that boundary — Harbor verifies spend before side effects and auto-submits evidence after success — not as model middleware.
Install @paybond/openai-agents (npm) or paybond-kit[openai-agents] (pip). Adapter reference: /docs/kit/openai-agents.
spend verify before invoke
Input guardrails authorize operation and amount before FunctionTool.invoke runs.
Auto-evidence
Wrapped invoke finalizes spend and submits signed evidence after tool success.
Policy budgets
Versioned YAML caps per-call and intent spend — default-deny for side-effecting tools.
TypeScript and Python
Same openai-agents adapter on npm (@paybond/openai-agents) and pip (paybond-kit[openai-agents]).
Why Paybond (not just SDK guardrails)?
OpenAI Agents SDK guardrails check model input/output and can pause for approvals. They 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
- SDK guardrails alone
- Yes — SDK input/output checks and approvals
- With Paybond
- Yes — plus Harbor authorize at the tool boundary
Spend boundary
- SDK guardrails alone
- No per-tool Harbor budget or capability token
- With Paybond
- Per-call and intent budgets enforced before invoke
Signed evidence
- SDK guardrails alone
- SDK traces / logs only
- With Paybond
- Signed completion digests bound to the intent
Intent binding
- SDK guardrails alone
- No Harbor intent or settlement receipt
- With Paybond
- Capability token + intentId from authenticated bind
Paid tool deny / HITL
- SDK guardrails alone
- OpenAI approval interruptions only
- With Paybond
- spend verify, deny, or HITL hold before side effects
| Capability | SDK guardrails alone | With Paybond |
|---|---|---|
| Model / input guardrails | Yes — SDK input/output 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 | OpenAI approval interruptions only | spend verify, deny, or HITL hold before side effects |
How it works
Adapter flow
FunctionTool.invoke
OpenAI Agents SDK calls a side-effecting tool
Paybond input guardrail
Harbor authorize before your handler runs
- Verify spend and operation
- Deny or HITL hold
- Issue / check capability
Tool runs
Your execute handler performs the paid work
Evidence
Wrapped invoke finalizes spend + auto-evidence
Paybond hooks FunctionTool.invoke: Harbor input guardrail before the tool runs, then wrapped invoke submits evidence after success.
3-minute quickstart
Smoke the openai-agents adapter sandbox contract — no OpenAI credentials required for this check:
terminal
paybond login
paybond agent demo openai-agents smoke \
--operation paid-tool \
--requested-spend-cents 100 \
--evidence-preset cost_and_completion \
--format tableWhen 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
# TypeScript
paybond init agent-middleware --framework openai --out paybond-openai-agents.ts
# Python
paybond init agent-middleware --framework openai --out paybond_agent_middleware_openai.py
paybond policy init --preset travel --out paybond.policy.yamlValidate before deploy:
terminal
paybond policy validate-tools --file paybond.policy.yaml --local-onlyWire middleware
Recommended wiring
paybond.agent with framework openai-agents returns agentTools plus runConfig so Harbor guardrails run before FunctionTool.invoke.
paybond-session.ts
import { tool, Agent, Runner } from "@openai/agents";
import { z } from "zod";
import { Paybond } from "@paybond/kit";
const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });
const bookHotelTool = tool({
name: "travel.book_hotel",
description: "Book a hotel room",
parameters: z.object({
city: z.string(),
estimatedPriceCents: z.number().int().nonnegative(),
}),
execute: async (args) => bookHotel(args),
});
const { agentTools: tools, runConfig } = await paybond.agent({
policy: "travel",
framework: "openai-agents",
tools: [bookHotelTool, searchWebTool],
});
const agent = new Agent({ name: "Travel", tools });
await Runner.run(agent, "Book a hotel in Lisbon under $200.", { ...runConfig });Install Python extra: pip install "paybond-kit[openai-agents]". The scaffold (paybond_agent_middleware_openai.py) shows FunctionTool and create_guarded_agent for policy-driven bootstrap.
Manual hook wiring
When you already bound a PaybondAgentRun:
paybond-session.ts
import { createPaybondOpenAIAgentsConfig } from "@paybond/kit/openai-agents";
const config = createPaybondOpenAIAgentsConfig(run, sdkTools);
const guardedTools = config.tools;Production: omit sandbox defaults on paybond.agent() / paybond.instrument(), 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
- Scaffold middleware with paybond init agent-middleware --framework openai
- Init a policy preset (e.g. travel) and validate tools
- Wire paybond.agent({ framework: "openai-agents", tools })
- Bind intentId and capabilityToken per session in production
- Smoke with paybond agent demo openai-agents smoke before ship
Works with
Works with
- OpenAI
- Anthropic
- Vercel
- MCP
Ready to test?
Related guides
- Agent middleware — bind, registry, tenant isolation
- OpenAI Responses API spend controls — Responses API tool boundary
- Agent policy-as-code — versioned YAML
- Agent-agnostic spend controls — default
{ name, execute }wiring
Developer reference: /docs/kit/openai-agents.