paybondpaybond
Sign in

Agent middleware

Model-agnostic run binding, tool registry, interceptors, and automatic evidence for multi-tool agent integrations.

Paybond agent middleware is the recommended integration path for multi-tool agents. Call paybond.instrument() to load policy and register tools (deferred by default), then bind() per session, pass a lazy context provider, or use paybond.agent() for sandbox quickstart.

Agent selection rule

Prefer middleware for multi-tool agents

When building agents with several side-effecting tools, start with paybond.instrument() or paybond.wrapTools() / paybond.wrap_tools(). Reserve per-tool guardTool / guard_tool for single-handler integrations or advanced evidence timing.

  • Middleware: instrument() → run binding, registry, interceptor, required auto-evidence.
  • Manual guard: per-tool guardTool / guard_tool; you call submitEvidence yourself.
  • Model token caps: use provider-native usage controls — not Paybond.

Public product page: /kit/agent-middleware. Developer reference: /docs/kit/agent-middleware. CLI overview: /kit/cli.

When to use middleware vs manual guard

ApproachBest for
Agent middlewareMulti-tool agents, coding-agent automation, any integration that must not forget evidence on side-effecting tools
Per-tool guardToolSingle paid handler, legacy code, or advanced cases where you control evidence timing explicitly

Use middleware when:

  • The agent exposes multiple paid or side-effecting tools.
  • You want automatic evidence on every successful side-effecting call.
  • You need defaultDeny to catch forgotten wraps before production.
  • Coding agents or CI should test the full authorize → evidence path without vendor APIs.

Keep per-tool guardTool / guard_tool when:

  • You have a single paid tool and full control over evidence timing.
  • You are migrating incrementally from an existing guard wrapper.

See Agent integrations for single-handler examples.

Sandbox smoke (no integration code)

Local dev loop (recommended — policy scaffold, validate, smoke, trace URL):

Terminal
Terminal commandSwipe to inspect long lines
paybond dev loop --offline   # terminal 1
paybond dev trace            # terminal 2 — same project directory

With sandbox credentials:

Terminal
Terminal commandSwipe to inspect long lines
paybond login
paybond dev loop
paybond dev trace

The trace dashboard at http://127.0.0.1:9477 renders a vertical timeline (authorize → execute → evidence → settlement). Events persist to .paybond/dev-trace.jsonl so smoke and trace can run in separate terminals. See the middleware trace guide and developer reference for the event model and UI phases.

Manual smoke (explicit flags):

Terminal
Terminal commandSwipe to inspect long lines
paybond login
paybond agent sandbox smoke \
  --operation paid-tool \
  --requested-spend-cents 100 \
  --evidence-preset cost_and_completion \
  --result-body '{"status":"ok","cost_cents":100}' \
  --format json

For multi-step runs: paybond agent run bind --sandbox ... then paybond agent tool execute --run-id ..., then paybond agent run trace --run-id ... to inspect authorize → execute → evidence steps from the CLI. See the agent quickstart for paybond dev workflows, middleware trace for the visual dashboard, the agent middleware docs for SDK traceSink, and paybond doctor --agent for the same smoke path in diagnostics.

Trace events (SDK)

The interceptor emits structured events as each side-effecting tool runs: tool_selectedspend_authorizedtool_executedspend_finalizedevidence_submitted. Pass traceSink on bind to debug denied calls or wire custom telemetry:

const run = await paybond.agentRun.bind({
  bootstrap: { kind: "sandbox", operation: "travel.book_hotel", requestedSpendCents: 20_000 },
  registry,
  traceSink: (event) => console.log(event.type, event),
});

paybond dev loop + paybond dev trace collect the same events locally without app code — timeline steps are written to .paybond/dev-trace.jsonl and rendered in the dashboard. For bind → execute workflows, paybond agent run trace --run-id <id> prints the per-run timeline from .paybond/runs/<run_id>.trace.json. Python: trace_sink on agent_run.bind(). Full reference: Trace events and observability.

SDK shape (TypeScript)

import { Paybond } from "@paybond/kit";

const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });

const instrumented = await paybond.instrument({
  policy: "./paybond.policy.yaml", // or preset id "travel"
  tools: {
    "travel.book_hotel": bookHotel,
    searchWeb: searchWeb,
  },
});

// Sandbox quickstart: paybond.agent({ policy: "travel", tools }) binds sandbox automatically.
// Production: const runtime = await instrumented.bind({ intentId, capabilityToken });
// Or lazy: instrument({ ..., context: () => activeRequest.paybond })

Python: await paybond.instrument(policy=..., tools=...) with the same semantics; await instrumented.bind(...) or context=lambda: ... for lazy binding.

For step-by-step registry + bind control, see Agent middleware docs.

Framework adapters

Shipped adapter packs plug into the same run binding and registry:

FrameworkDocSmoke
Agent-agnostic (default)/docs/kit/agent-agnosticpaybond agent demo generic smoke
LangGraph (TypeScript + Python)/docs/kit/langgraphpaybond agent demo langgraph smoke
Claude Agent SDK (TypeScript + Python)/docs/kit/claude-agentspaybond agent demo claude-agents smoke
Vercel AI SDK (TypeScript only)/docs/kit/vercel-aipaybond agent demo vercel-ai smoke
OpenAI Agents SDK (TypeScript only)/docs/kit/openai-agentspaybond agent demo openai-agents smoke
MCP hosts (TypeScript + Python)/docs/kit/mcp-serverpaybond loginpaybond-mcp-server (see coding-agent setup)

Planned (use agent-agnostic or MCP today; request an adapter):

FrameworkDocRecipe guide
Mastra/docs/kit/mastra/guides/mastra-spend-controls
CrewAI/docs/kit/crewai
Cloudflare Agents/docs/kit/cloudflare-agents/guides/cloudflare-agents-spend-controls

Use paybond init agent-middleware --framework <name> to scaffold integration files.

Policy-as-code

For GitOps-friendly configuration, version a paybond.policy.yaml and validate before deploy:

Terminal
Terminal commandSwipe to inspect long lines
paybond policy validate-tools --file paybond.policy.yaml --local-only --format json

Buyer guide: /guides/agent-policy. Remote validation: /docs/kit/agent-policy-validate. Enterprise org inheritance: /docs/kit/enterprise-policy-inheritance. Long-lived processes: /docs/kit/policy-hot-reload.

Going to production

Sandbox smoke and paybond.agent() never require payee identities or signing seeds. When you attach to a funded production intent, see Production attach for CLI flags, SDK productionEvidence, and env fallbacks.