Mastra agents expose tools via createTool({ execute }). Paybond ships createPaybondMastraConfig on @paybond/kit/mastra and @paybond/mastra. spend verify runs before side-effecting tools execute; auto-evidence fires after success.
TypeScript only. Python Kit does not ship a Mastra adapter. Use agent-agnostic spend controls or MCP agent spend controls for Python hosts.
Adapter reference: /docs/kit/mastra.
spend verify before execute
createPaybondMastraConfig wraps createTool execute on side-effecting tools.
Auto-evidence
Wrapped execute finalizes spend and submits signed evidence after success.
Policy budgets
Versioned YAML caps per-call and intent spend — default-deny for paid tools.
TypeScript native
Use @paybond/mastra or @paybond/kit/mastra; Python hosts use agent-agnostic or MCP.
Why Paybond (not just Mastra checks)?
Mastra tool wrappers 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
- Mastra alone
- Yes — SDK or host checks and approvals
- With Paybond
- Yes — plus Harbor authorize at the tool boundary
Spend boundary
- Mastra alone
- No per-tool Harbor budget or capability token
- With Paybond
- Per-call and intent budgets enforced before invoke
Signed evidence
- Mastra alone
- SDK traces / logs only
- With Paybond
- Signed completion digests bound to the intent
Intent binding
- Mastra alone
- No Harbor intent or settlement receipt
- With Paybond
- Capability token + intentId from authenticated bind
Paid tool deny / HITL
- Mastra alone
- Host or SDK approvals only
- With Paybond
- spend verify, deny, or HITL hold before side effects
| Capability | Mastra 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
createTool execute
Mastra agent invokes a side-effecting tool
Paybond wrap
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 execute finalizes spend + auto-evidence
Paybond wraps Mastra createTool execute: Harbor authorize before the tool runs, then auto-evidence after success.
3-minute quickstart
Smoke the mastra adapter sandbox contract — no Mastra runtime required for this check:
terminal
paybond login
paybond agent demo mastra smoke \
--operation paid-tool \
--requested-spend-cents 100 \
--evidence-preset cost_and_completion \
--format tableInstall the optional peer when running the native adapter in your app:
terminal
npm install @paybond/mastra @mastra/coreWhen 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 init agent-middleware --framework mastra --out paybond-mastra.ts
paybond init --template mastra-travel-agent --framework mastra
paybond policy init --preset travel --out paybond.policy.yamlWire middleware
Recommended wiring
paybond.instrument with framework mastra wraps createTool execute on side-effecting tools.
paybond-session.ts
import { createTool } from "@mastra/core/tools";
import { z } from "zod";
import { Paybond } from "@paybond/kit";
const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });
const { tools } = await paybond.instrument({
policy: "travel",
framework: "mastra",
tools: [
createTool({
id: "travel.book_hotel",
description: "Book a hotel room",
inputSchema: z.object({
city: z.string(),
estimatedPriceCents: z.number().int().nonnegative(),
}),
execute: async (args) => bookHotel(args),
}),
createTool({
id: "search.web",
description: "Search the web",
inputSchema: z.object({ query: z.string() }),
execute: async (args) => searchWeb(args),
}),
],
});
// Register `tools` with your Mastra agent.Already bound a run? createPaybondMastraConfig(run, tools) from @paybond/mastra wraps execute without reloading policy.
Production: await instrumented.bind({ intentId, capabilityToken }) per session — see Agent middleware.
Production checklist
Production checklist
- Scaffold middleware with paybond init agent-middleware --framework mastra
- Init a policy preset (e.g. travel) and validate tools
- Wire paybond.instrument({ framework: "mastra", tools })
- Bind intentId and capabilityToken per session in production
- Smoke with paybond agent demo mastra smoke before ship
Works with
Works with
- Mastra
- Vercel
- OpenAI
- MCP
Ready to test?
Related guides
- Agent-agnostic spend controls — fallback for mixed or Python stacks
- Vercel AI SDK spend controls — similar execute-boundary pattern
- MCP agent spend controls — stdio MCP for external hosts
Developer reference: /docs/kit/mastra.