The OpenAI Responses API exposes function tools on a streaming response object. Paybond does not ship a dedicated Responses adapter; use the agent-agnostic path: wrap { name, execute } handlers and map Responses tool calls to Paybond envelopes at execute time. spend verify runs before side effects; auto-evidence fires after success.
TypeScript and Python — same agent-agnostic instrument() contract in both Kit languages.
Adapter reference: /docs/kit/agent-agnostic.
Tool boundary, not model middleware
Guard function tool execute — keep openai.responses.create for inference.
Agent-agnostic wrap
Map Responses function_call items to Paybond { name, execute } envelopes.
Auto-evidence
Wrapped execute finalizes spend and submits signed evidence after success.
TypeScript and Python
Agent-agnostic instrument() in both Kit languages — map Responses function_call items the same way.
Why Paybond (not just Responses API)?
Responses API function tools 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
- Responses API alone
- Yes — SDK or host checks and approvals
- With Paybond
- Yes — plus Harbor authorize at the tool boundary
Spend boundary
- Responses API alone
- No per-tool Harbor budget or capability token
- With Paybond
- Per-call and intent budgets enforced before invoke
Signed evidence
- Responses API alone
- SDK traces / logs only
- With Paybond
- Signed completion digests bound to the intent
Intent binding
- Responses API alone
- No Harbor intent or settlement receipt
- With Paybond
- Capability token + intentId from authenticated bind
Paid tool deny / HITL
- Responses API alone
- Host or SDK approvals only
- With Paybond
- spend verify, deny, or HITL hold before side effects
| Capability | Responses API 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
responses.create
Model returns a function_call output item
Map to Paybond envelope
toolName + call_id + arguments
Paybond wrap
Harbor authorize before your handler runs
- Verify spend and operation
- Deny or HITL hold
- Issue / check capability
Evidence
Wrapped execute finalizes spend + auto-evidence
Responses API returns function_call items; your loop maps them to Paybond-wrapped execute before side effects.
3-minute quickstart
Smoke the generic sandbox contract used by Responses API wiring:
terminal
paybond login
paybond agent demo generic 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
paybond policy init --preset saas --out paybond.policy.yaml
paybond policy validate-tools --file paybond.policy.yaml --local-onlyWire middleware
Map Responses function calls
Define side-effecting tools once; Paybond wraps them for authorization and evidence.
paybond-session.ts
import OpenAI from "openai";
import { Paybond } from "@paybond/kit";
const openai = new OpenAI();
const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });
const { tools } = await paybond.instrument({
policy: "./paybond.policy.yaml",
tools: {
"saas.provision_seat": provisionSeat,
"saas.list_plans": listPlans,
},
});
const toolByName = new Map(tools.map((t) => [t.name, t]));
const response = await openai.responses.create({
model: "gpt-4.1",
tools: [
{
type: "function",
name: "saas.provision_seat",
description: "Provision a SaaS seat",
parameters: {
type: "object",
properties: {
planId: { type: "string" },
priceCents: { type: "integer" },
},
required: ["planId", "priceCents"],
},
},
],
input: "Provision a starter seat for acme-corp.",
});
// When the response includes a function_call output item:
for (const item of response.output) {
if (item.type === "function_call" && item.name === "saas.provision_seat") {
const wrapped = toolByName.get(item.name)!;
const args = JSON.parse(item.arguments);
const result = await wrapped.execute({
toolName: item.name,
toolCallId: item.call_id ?? item.id,
arguments: args,
});
// Feed result back into a follow-up responses.create call
}
}Mapping rules
- Register every side-effecting function name in
paybond.policy.yamlwith matchingtools.*entries. - Use the Responses
call_id(or stable id) astoolCallIdin the Paybond envelope. - Read-only tools can omit Paybond wrapping or stay unregistered with
default_deny: falseonly when you accept the risk.
OpenAI Agents SDK vs Responses API
| Surface | Paybond path |
|---|---|
OpenAI Agents SDK (@openai/agents) | Native adapter — OpenAI Agents spend controls |
Responses API (openai.responses.create) | Agent-agnostic instrument() — this guide |
Choose the Agents SDK adapter when you use Runner.run and FunctionTool; use this guide when you integrate directly against Responses function tools.
Production checklist
Production checklist
- Init a policy preset and register every side-effecting function name
- Wire paybond.instrument() with agent-agnostic tools
- Map Responses call_id to toolCallId in the Paybond envelope
- Bind intentId and capabilityToken per session in production
- Smoke with paybond agent demo generic smoke before ship
Works with
Works with
- OpenAI
- Agent-agnostic
- Anthropic
- MCP
Ready to test?
Related guides
- Agent-agnostic spend controls — default
{ name, execute }wiring - OpenAI Agents SDK spend controls — native adapter
- Agent middleware — production bind
Developer reference: /docs/kit/agent-agnostic.