paybondpaybond
Sign in

Recipe · Framework

Spend controls for OpenAI Responses API tools

Guard OpenAI Responses API function tools with Paybond agent-agnostic middleware — Harbor authorize at the tool execute boundary before side effects.

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

You'll build

Responses API tool calls with Harbor spend verification

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).

OpenAI Responses API alone versus Paybond Harbor spend controls
  • 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

How it works

Responses API returns function_call items; your loop maps them to Paybond-wrapped execute before side effects.

Adapter flow

  1. responses.create

    Model returns a function_call output item

  2. Map to Paybond envelope

    toolName + call_id + arguments

  3. Paybond wrap

    Harbor authorize before your handler runs

    • Verify spend and operation
    • Deny or HITL hold
    • Issue / check capability
  4. 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
Terminal commandSwipe to inspect long lines
paybond login
paybond agent demo generic 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 OpenAI Responses API 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 policy init --preset saas --out paybond.policy.yaml
paybond policy validate-tools --file paybond.policy.yaml --local-only

Wire middleware

Map Responses function calls

Define side-effecting tools once; Paybond wraps them for authorization and evidence.

paybond-session.ts

TS
Code exampleSwipe to inspect long lines
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

  1. Register every side-effecting function name in paybond.policy.yaml with matching tools.* entries.
  2. Use the Responses call_id (or stable id) as toolCallId in the Paybond envelope.
  3. Read-only tools can omit Paybond wrapping or stay unregistered with default_deny: false only when you accept the risk.

OpenAI Agents SDK vs Responses API

SurfacePaybond 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 for Paybond-guarded OpenAI Responses API tools.

Production checklist

Works with

Works with

  • OpenAI
  • Agent-agnostic
  • Anthropic
  • MCP

Ready to test?

Developer reference: /docs/kit/agent-agnostic.