T03 · Tutorial
Middleware for one paid tool
instrument → bind → execute → auto-evidence for one side-effecting tool — no per-handler guard ceremony.
Outcome: One paid handler is run-bound; evidence auto-submits after success.
Learning view: objectives and extras expanded. Switch for commands only.
Mental model
Middleware is one run-scoped layer: open → instrument → bind → execute → auto-evidence.
You will be able to
You will be able to
- Instrument a single paid tool with sandbox bind
- Explain deferred shells vs bound execute
- Confirm evidence auto-submits after successful side-effecting work
Prerequisites
Prerequisites
- · First guarded spend (CLI loop green offline or sandbox)
- · TypeScript or Python project with @paybond/kit / paybond-kit
Middleware lifecycle
Agent middleware replaces per-tool guardTool ceremony with a run-scoped layer. One intent and capability per task; automatic evidence after every successful side-effecting call.
01
Open session
Paybond.open with sandbox or live service-account key from env.
02
Instrument
Load policy and tools; receive deferred shells until bound.
03
Bind / sandbox
sandbox: true for local, or bind({ intentId, capabilityToken }).
04
Execute and evidence
Handler runs; evidence_preset auto-submits; inspect settlement.
Instrument one paid tool
Use middleware when even one tool can spend. Keep max spend and evidence presets in policy (GitOps), not scattered in handlers.
- instrument() without a session is deferred — register tools early, bind per session.
- sandbox: true bootstraps a sandbox intent so you can complete the loop without production funding.
- Unregistered tools fail closed when the policy uses default_deny.
Framework adapters (LangGraph, Vercel AI, OpenAI Agents, …) plug into the same core — start agent-agnostic, then specialize. See Agent middleware reference.
Minimal sandbox instrument — open Kit, wrap one tool, hand tools to your agent.
instrument.ts
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 e.g. "travel"
tools: {
"travel.book_hotel": async (args) => bookHotel(args),
},
sandbox: true,
});
// Hand instrumented.tools to your agent runtime.
// On success, Kit submits evidence automatically.
await paybond.aclose();Result: Authorized calls run the handler; evidence posts automatically. Spend beyond policy returns spend_denied.
Verify before you continue
Check these off against your terminal or timeline output — progress stays on this device.
If something goes wrong
If something goes wrong
If you see
Tools execute before bind
Do this
Deferred shells are registration-only until sandbox or attach binds the run.
If you see
Unregistered tool still invoked by the agent
Do this
default_deny plus policy registry — register or drop the operation name.
If you see
Per-tool guardTool left next to middleware
Do this
Pick one path: middleware for run-scoped policy, or explicit runtime guard — don’t double-authorize.
Self-check
Self-check
Answer without scrolling up — then reveal the model answer to compare.
Which responsibilities moved from your handler into instrument() for this paid tool?
Next steps
Pick a branch — not every path needs every tutorial.
Related docs & recipes
Recipes are copy-paste production smokes — not repeated inside this tutorial.