@paybond/kit 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Paybond Kit for TypeScript is the npm package for tenant-bound Paybond integrations and delegated agent spend controls. It opens hosted Gateway sessions, verifies capability tokens, authorizes tool-call spend, signs intent and evidence payloads, uses Stripe Connect or x402 / USDC-on-Base settlement rails, reads tenant-scoped Signal, fraud, ledger, protocol, and A2A data, and includes agent-runtime integrations.
4
4
 
5
+ Paybond is the SDK to use when you do not want to build your own delegated agent spend-governance middleware. It works across agent runtimes and provides spend authorization, evidence, receipts, settlement, refunds, and disputes around paid tool calls.
6
+
5
7
  ## Install
6
8
 
7
9
  ```bash
@@ -64,16 +66,34 @@ try {
64
66
  Use Paybond Kit when an agent workflow needs delegated spend guardrails, tool-call budget checks, paid API or vendor action approval, evidence, release/refund logic, disputes, or audit-ready receipts.
65
67
 
66
68
  ```ts
67
- import { PaybondCapabilityBinding, PaybondSpendGuard } from "@paybond/kit";
69
+ import { Paybond } from "@paybond/kit";
70
+
71
+ const paybond = await Paybond.open({
72
+ apiKey: process.env.PAYBOND_API_KEY!,
73
+ expectedEnvironment: "sandbox",
74
+ });
68
75
 
69
- const binding = new PaybondCapabilityBinding(paybond.harbor, intentId, capabilityToken);
70
- const guard = new PaybondSpendGuard(binding);
76
+ const created = await paybond.intents.create({
77
+ // principal, payee, budget, predicate, evidence schema, deadline...
78
+ allowedTools: ["travel.book_hotel"],
79
+ settlementRail: "stripe_connect",
80
+ });
81
+
82
+ const intentId = String(created.intent_id);
83
+ const capabilityToken = String(created.capability_token ?? "");
84
+ if (!capabilityToken) {
85
+ throw new Error("fund the intent before guarding tools");
86
+ }
87
+
88
+ const guard = paybond.spendGuard(intentId, capabilityToken);
71
89
  const guardedTool = guard.guardTool(
72
90
  { operation: "travel.book_hotel", requestedSpendCents: 20_000 },
73
91
  async (input) => bookHotel(input),
74
92
  );
75
93
  ```
76
94
 
95
+ The `paybond.harbor` client is created by `Paybond.open(...)` and bound to the tenant resolved from the service-account API key. Normal integrations read `capability_token` from `paybond.intents.create(...)`, or from `paybond.intents.fund(...)` after an `x402_usdc_base` payment challenge is satisfied.
96
+
77
97
  Scaffold a wrapper:
78
98
 
79
99
  ```bash
@@ -89,7 +109,8 @@ Core SDK:
89
109
  - `paybond.signal` and `paybond.fraud` on `Paybond` sessions opened from one service-account API key
90
110
  - `PaybondIntents` helpers for principal-signed intent creation, x402 funding, and payee-signed evidence submission
91
111
  - `PaybondSpendGuard`, `authorizeSpend`, and `guardTool` for spend-named wrappers around capability verification
92
- - Provider and framework aliases: `paybondOpenAIToolSpendGuard`, `paybondGeminiToolSpendGuard`, `paybondClaudeToolSpendGuard`, `paybondAnthropicToolSpendGuard`, `paybondGoogleAIToolSpendGuard`, `paybondVercelAIToolSpendGuard`, `paybondLangGraphToolSpendGuard`, and `paybondMCPToolSpendGuard`
112
+ - Runtime-neutral and framework aliases: `paybondAgentToolSpendGuard`, `paybondRuntimeNeutralToolSpendGuard`, `paybondLangGraphToolSpendGuard`, and `paybondMCPToolSpendGuard`
113
+ - `paybondRuntimeToolCallAdapter` for agent SDKs and custom runtimes that expose a tool-call object plus an application-owned executor
93
114
 
94
115
  Gateway and trust helpers:
95
116
 
@@ -116,7 +137,7 @@ Gateway-backed protocol helpers throw `ProtocolHttpError` with parsed `errorCode
116
137
  ## What it does not include
117
138
 
118
139
  - No operator-tier settlement or console workflows
119
- - No model-provider-specific TypeScript agent wrapper; use the documented app-side wrapper pattern with `PaybondCapabilityBinding`
140
+ - No model-provider-specific TypeScript agent wrapper; use the documented app-side wrapper pattern with `paybond.spendGuard(...)`
120
141
  - No model-provider-specific MCP wrapper; the MCP server is host-agnostic and works with any MCP-compatible runtime
121
142
 
122
143
  ## Docs
package/dist/index.d.ts CHANGED
@@ -655,6 +655,11 @@ export declare class PaybondCapabilityBinding {
655
655
  verifySpendCapability(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
656
656
  authorizeSpend(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
657
657
  }
658
+ export type PaybondSpendGuardInit = {
659
+ harbor: Pick<HarborClient | GatewayHarborClient, "tenantId" | "verifyCapability">;
660
+ intentId: string;
661
+ capabilityToken: string;
662
+ };
658
663
  export type PaybondSpendAuthorizationInput = {
659
664
  operation: string;
660
665
  requestedSpendCents?: number;
@@ -666,23 +671,33 @@ export declare class PaybondSpendDeniedError extends Error {
666
671
  export type PaybondToolHandler<TArgs extends unknown[], TResult> = (...args: TArgs) => TResult | Promise<TResult>;
667
672
  export type PaybondGuardedToolHandler<TArgs extends unknown[], TResult> = (...args: TArgs) => Promise<Awaited<TResult>>;
668
673
  export declare class PaybondSpendGuard {
669
- readonly binding: PaybondCapabilityBinding;
670
- constructor(binding: PaybondCapabilityBinding);
674
+ readonly harbor: Pick<HarborClient | GatewayHarborClient, "tenantId" | "verifyCapability">;
675
+ readonly intentId: string;
676
+ readonly capabilityToken: string;
677
+ constructor(init: PaybondSpendGuardInit | PaybondCapabilityBinding);
671
678
  verifySpendCapability(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
672
679
  authorizeSpend(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
673
680
  assertSpendAuthorized(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
674
681
  guardTool<TArgs extends unknown[], TResult>(input: PaybondSpendAuthorizationInput, handler: PaybondToolHandler<TArgs, TResult>): PaybondGuardedToolHandler<TArgs, TResult>;
675
682
  }
676
- export declare function authorizeSpend(binding: PaybondCapabilityBinding, input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
677
- export declare function guardTool<TArgs extends unknown[], TResult>(binding: PaybondCapabilityBinding, input: PaybondSpendAuthorizationInput, handler: PaybondToolHandler<TArgs, TResult>): PaybondGuardedToolHandler<TArgs, TResult>;
678
- export declare const paybondOpenAIToolSpendGuard: typeof guardTool;
679
- export declare const paybondAnthropicToolSpendGuard: typeof guardTool;
680
- export declare const paybondClaudeToolSpendGuard: typeof guardTool;
681
- export declare const paybondGeminiToolSpendGuard: typeof guardTool;
682
- export declare const paybondGoogleAIToolSpendGuard: typeof guardTool;
683
- export declare const paybondVercelAIToolSpendGuard: typeof guardTool;
683
+ export declare function authorizeSpend(source: PaybondSpendGuardInit | PaybondCapabilityBinding, input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
684
+ export declare function guardTool<TArgs extends unknown[], TResult>(source: PaybondSpendGuardInit | PaybondCapabilityBinding, input: PaybondSpendAuthorizationInput, handler: PaybondToolHandler<TArgs, TResult>): PaybondGuardedToolHandler<TArgs, TResult>;
685
+ export declare const paybondAgentToolSpendGuard: typeof guardTool;
686
+ export declare const paybondRuntimeNeutralToolSpendGuard: typeof guardTool;
684
687
  export declare const paybondLangGraphToolSpendGuard: typeof guardTool;
685
688
  export declare const paybondMCPToolSpendGuard: typeof guardTool;
689
+ export type PaybondRuntimeOperation<TCall> = string | ((call: TCall) => string);
690
+ export type PaybondRuntimeSpendCents<TCall> = number | ((call: TCall) => number | undefined);
691
+ export type PaybondRuntimeToolExecutor<TCall, TResult> = (call: TCall) => TResult | Promise<TResult>;
692
+ export type PaybondRuntimeDenyHandler<TCall, TResult> = (result: VerifyCapabilityResult, call: TCall) => TResult | Promise<TResult>;
693
+ export type PaybondRuntimeToolCallAdapterInit<TCall, TResult> = {
694
+ source: PaybondSpendGuardInit | PaybondCapabilityBinding;
695
+ operation: PaybondRuntimeOperation<TCall>;
696
+ execute: PaybondRuntimeToolExecutor<TCall, TResult>;
697
+ requestedSpendCents?: PaybondRuntimeSpendCents<TCall>;
698
+ onDeny?: PaybondRuntimeDenyHandler<TCall, TResult>;
699
+ };
700
+ export declare function paybondRuntimeToolCallAdapter<TCall, TResult>(init: PaybondRuntimeToolCallAdapterInit<TCall, TResult>): (call: TCall) => Promise<Awaited<TResult>>;
686
701
  export type PaybondOpenOptions = {
687
702
  apiKey: string;
688
703
  gatewayBaseUrl?: string;
package/dist/index.js CHANGED
@@ -178,15 +178,24 @@ export class PaybondSpendDeniedError extends Error {
178
178
  }
179
179
  }
180
180
  export class PaybondSpendGuard {
181
- binding;
182
- constructor(binding) {
183
- this.binding = binding;
181
+ harbor;
182
+ intentId;
183
+ capabilityToken;
184
+ constructor(init) {
185
+ this.harbor = init.harbor;
186
+ this.intentId = init.intentId;
187
+ this.capabilityToken = init.capabilityToken;
184
188
  }
185
189
  async verifySpendCapability(input) {
186
- return this.binding.verifySpendCapability(input);
190
+ return this.harbor.verifyCapability({
191
+ intentId: this.intentId,
192
+ token: this.capabilityToken,
193
+ operation: input.operation,
194
+ requestedSpendCents: input.requestedSpendCents,
195
+ });
187
196
  }
188
197
  async authorizeSpend(input) {
189
- return this.binding.authorizeSpend(input);
198
+ return this.verifySpendCapability(input);
190
199
  }
191
200
  async assertSpendAuthorized(input) {
192
201
  const result = await this.authorizeSpend(input);
@@ -202,20 +211,45 @@ export class PaybondSpendGuard {
202
211
  };
203
212
  }
204
213
  }
205
- export async function authorizeSpend(binding, input) {
206
- return binding.authorizeSpend(input);
214
+ export async function authorizeSpend(source, input) {
215
+ return new PaybondSpendGuard(source).authorizeSpend(input);
207
216
  }
208
- export function guardTool(binding, input, handler) {
209
- return new PaybondSpendGuard(binding).guardTool(input, handler);
217
+ export function guardTool(source, input, handler) {
218
+ return new PaybondSpendGuard(source).guardTool(input, handler);
210
219
  }
211
- export const paybondOpenAIToolSpendGuard = guardTool;
212
- export const paybondAnthropicToolSpendGuard = guardTool;
213
- export const paybondClaudeToolSpendGuard = guardTool;
214
- export const paybondGeminiToolSpendGuard = guardTool;
215
- export const paybondGoogleAIToolSpendGuard = guardTool;
216
- export const paybondVercelAIToolSpendGuard = guardTool;
220
+ export const paybondAgentToolSpendGuard = guardTool;
221
+ export const paybondRuntimeNeutralToolSpendGuard = guardTool;
217
222
  export const paybondLangGraphToolSpendGuard = guardTool;
218
223
  export const paybondMCPToolSpendGuard = guardTool;
224
+ function resolveRuntimeOperation(operation, call) {
225
+ const value = typeof operation === "function" ? operation(call) : operation;
226
+ const trimmed = String(value).trim();
227
+ if (!trimmed) {
228
+ throw new Error("Paybond operation must be a non-empty string");
229
+ }
230
+ return trimmed;
231
+ }
232
+ function resolveRuntimeSpendCents(requestedSpendCents, call) {
233
+ if (requestedSpendCents === undefined) {
234
+ return undefined;
235
+ }
236
+ return typeof requestedSpendCents === "function" ? requestedSpendCents(call) : requestedSpendCents;
237
+ }
238
+ export function paybondRuntimeToolCallAdapter(init) {
239
+ const guard = new PaybondSpendGuard(init.source);
240
+ return async (call) => {
241
+ const operation = resolveRuntimeOperation(init.operation, call);
242
+ const requestedSpendCents = resolveRuntimeSpendCents(init.requestedSpendCents, call);
243
+ const result = await guard.authorizeSpend({ operation, requestedSpendCents });
244
+ if (!result.allow) {
245
+ if (init.onDeny) {
246
+ return await init.onDeny(result, call);
247
+ }
248
+ throw new PaybondSpendDeniedError(result);
249
+ }
250
+ return await init.execute(call);
251
+ };
252
+ }
219
253
  /**
220
254
  * HTTP client for Harbor: capability verify, intents, evidence, and tenant-scoped ledger reads
221
255
  * (`GET /ledger/v1/*`, PAYBOND-007).
@@ -1790,7 +1824,7 @@ export class Paybond {
1790
1824
  await Promise.resolve();
1791
1825
  }
1792
1826
  spendGuard(intentId, capabilityToken) {
1793
- return new PaybondSpendGuard(new PaybondCapabilityBinding(this.harbor, intentId, capabilityToken));
1827
+ return new PaybondSpendGuard({ harbor: this.harbor, intentId, capabilityToken });
1794
1828
  }
1795
1829
  async authorizeSpend(input) {
1796
1830
  return this.harbor.authorizeSpend(input);
package/dist/init.js CHANGED
@@ -2,7 +2,7 @@
2
2
  const FRAMEWORKS = new Set([
3
3
  "generic",
4
4
  "provider-agnostic",
5
- "openai-agents",
5
+ "openai",
6
6
  "claude",
7
7
  "anthropic",
8
8
  "gemini",
@@ -14,7 +14,7 @@ const FRAMEWORKS = new Set([
14
14
  const FRAMEWORK_NOTES = {
15
15
  generic: "Wrap the returned function around any side-effecting tool handler.",
16
16
  "provider-agnostic": "Use the guarded handler with OpenAI, Gemini, Claude/Anthropic, local models, or any custom runtime.",
17
- "openai-agents": "Register the guarded handler where your OpenAI Agents tool handler is defined.",
17
+ openai: "Call the guarded handler before the OpenAI tool call performs paid or external work.",
18
18
  claude: "Call the guarded handler before the Claude tool-use action performs paid or external work.",
19
19
  anthropic: "Call the guarded handler before the Anthropic tool-use action performs paid or external work.",
20
20
  gemini: "Call the guarded handler before the Gemini function call performs paid or external work.",
@@ -25,7 +25,7 @@ const FRAMEWORK_NOTES = {
25
25
  };
26
26
  function usage() {
27
27
  return [
28
- "Usage: paybond-init [--framework generic|provider-agnostic|openai-agents|claude|anthropic|gemini|google-ai|vercel-ai|langgraph|mcp] [--out paybond-spend-guard.ts] [--force]",
28
+ "Usage: paybond-init [--framework generic|provider-agnostic|openai|claude|anthropic|gemini|google-ai|vercel-ai|langgraph|mcp] [--out paybond-spend-guard.ts] [--force]",
29
29
  "",
30
30
  "Scaffolds a Paybond spend guard wrapper for delegated agent spend controls.",
31
31
  ].join("\n");
@@ -68,32 +68,58 @@ function parseArgs(argv) {
68
68
  return { framework, out, force };
69
69
  }
70
70
  function template(framework) {
71
- return `import { Paybond, PaybondCapabilityBinding, PaybondSpendGuard } from "@paybond/kit";
71
+ return `import { Paybond, type FundIntentResult } from "@paybond/kit";
72
72
 
73
73
  type ToolInput = {
74
74
  city: string;
75
75
  maxPriceCents: number;
76
76
  };
77
77
 
78
+ type FundedIntent = {
79
+ intentId: string;
80
+ capabilityToken: string;
81
+ };
82
+
83
+ export async function openPaybond(): Promise<Paybond> {
84
+ return Paybond.open({
85
+ apiKey: process.env.PAYBOND_API_KEY!,
86
+ expectedEnvironment: "sandbox",
87
+ });
88
+ }
89
+
90
+ export function fundedIntentFromCreate(created: Record<string, unknown>): FundedIntent {
91
+ const intentId = String(created["intent_id"] ?? "");
92
+ const capabilityToken = String(created["capability_token"] ?? "");
93
+ if (!intentId) {
94
+ throw new Error("intent create response missing intent_id");
95
+ }
96
+ if (!capabilityToken) {
97
+ throw new Error("intent is not funded yet; call paybond.intents.fund(...) before guarding tools");
98
+ }
99
+ return { intentId, capabilityToken };
100
+ }
101
+
102
+ export function fundedIntentFromFund(funded: FundIntentResult): FundedIntent {
103
+ if (!funded.capabilityToken) {
104
+ throw new Error("intent funding did not return a capabilityToken yet");
105
+ }
106
+ return { intentId: funded.intentId, capabilityToken: funded.capabilityToken };
107
+ }
108
+
78
109
  async function bookHotel(input: ToolInput): Promise<{ confirmation: string }> {
79
110
  // Put the side-effecting tool call here.
80
111
  return { confirmation: \`demo-\${input.city}-\${input.maxPriceCents}\` };
81
112
  }
82
113
 
83
114
  export async function buildGuardedHotelTool(params: {
115
+ paybond: Paybond;
84
116
  intentId: string;
85
117
  capabilityToken: string;
86
118
  }): Promise<(input: ToolInput) => Promise<{ confirmation: string }>> {
87
- const paybond = await Paybond.open({
88
- apiKey: process.env.PAYBOND_API_KEY!,
89
- expectedEnvironment: "sandbox",
90
- });
91
- const binding = new PaybondCapabilityBinding(
92
- paybond.harbor,
93
- params.intentId,
94
- params.capabilityToken,
95
- );
96
- const guard = new PaybondSpendGuard(binding);
119
+ if (!params.capabilityToken.trim()) {
120
+ throw new Error("fund the intent before guarding tools");
121
+ }
122
+ const guard = params.paybond.spendGuard(params.intentId, params.capabilityToken);
97
123
 
98
124
  // ${FRAMEWORK_NOTES[framework]}
99
125
  return guard.guardTool(
@@ -364,6 +364,8 @@ export class PaybondMCPServer {
364
364
  version: SERVER_VERSION,
365
365
  },
366
366
  instructions: "This MCP server is tenant-bound to the configured Paybond service-account API key. " +
367
+ "Use paybond_create_spend_intent or paybond_fund_intent to obtain the intent_id and " +
368
+ "capability_token, then call paybond_authorize_agent_spend before side-effecting tools. " +
367
369
  "It works with any MCP-compatible host and does not assume a specific model provider.",
368
370
  },
369
371
  };
@@ -447,10 +449,13 @@ export class PaybondMCPServer {
447
449
  },
448
450
  {
449
451
  name: "paybond_verify_capability",
450
- description: "Verify a capability token for one tenant-bound Harbor intent through the gateway compatibility route.",
452
+ description: "Verify a capability token returned by a created or funded Paybond intent for one tenant-bound Harbor intent.",
451
453
  inputSchema: objectSchema({
452
454
  intent_id: { type: "string", description: "Canonical Harbor intent UUID." },
453
- token: { type: "string", description: "Capability token to verify." },
455
+ token: {
456
+ type: "string",
457
+ description: "Capability token returned by paybond_create_spend_intent or paybond_fund_intent.",
458
+ },
454
459
  operation: { type: "string", description: "Delegated operation or tool name." },
455
460
  requested_spend_cents: {
456
461
  type: "integer",
@@ -468,10 +473,13 @@ export class PaybondMCPServer {
468
473
  },
469
474
  {
470
475
  name: "paybond_authorize_agent_spend",
471
- description: "Authorize delegated agent spend before a side-effecting tool, paid API, vendor action, or settlement workflow executes.",
476
+ description: "Provider-agnostic spend gate: verify the funded intent's capability token before a side-effecting tool, paid API, vendor action, or settlement workflow executes.",
472
477
  inputSchema: objectSchema({
473
478
  intent_id: { type: "string", description: "Canonical Harbor intent UUID." },
474
- token: { type: "string", description: "Capability token to verify." },
479
+ token: {
480
+ type: "string",
481
+ description: "Capability token returned by paybond_create_spend_intent or paybond_fund_intent.",
482
+ },
475
483
  operation: { type: "string", description: "Delegated operation or tool name." },
476
484
  requested_spend_cents: {
477
485
  type: "integer",
@@ -653,7 +661,7 @@ export class PaybondMCPServer {
653
661
  },
654
662
  {
655
663
  name: "paybond_create_spend_intent",
656
- description: "Create a signed Paybond spend intent through the gateway /harbor route. Use this when an agent workflow needs bounded budget, allowed operations, evidence, and settlement review.",
664
+ description: "Create a signed Paybond spend intent through the gateway /harbor route. Use this when an agent workflow needs bounded budget, allowed operations, evidence, and settlement review. If the selected rail funds immediately, use the returned intent_id and capability_token with paybond_authorize_agent_spend.",
657
665
  inputSchema: objectSchema({
658
666
  body: { type: "object", additionalProperties: true },
659
667
  recognition_proof: { type: "object", additionalProperties: true },
@@ -667,7 +675,7 @@ export class PaybondMCPServer {
667
675
  },
668
676
  {
669
677
  name: "paybond_fund_intent",
670
- description: "Advance Harbor funding through the gateway /harbor path with a replay-safe recognition proof.",
678
+ description: "Advance Harbor funding through the gateway /harbor path with a replay-safe recognition proof. When funding succeeds, use the returned capability_token with intent_id in paybond_authorize_agent_spend.",
671
679
  inputSchema: objectSchema({
672
680
  intent_id: { type: "string" },
673
681
  recognition_proof: { type: "object", additionalProperties: true },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@paybond/kit",
3
- "version": "0.8.0",
4
- "description": "Paybond Kit for TypeScript: agent spend controls, hosted Gateway sessions, capability verification, signed intent/evidence flows, and Stripe Connect or x402 / USDC-on-Base settlement.",
3
+ "version": "0.9.1",
4
+ "description": "Paybond Kit for TypeScript: agent spend governance for paid tool calls with spend authorization, evidence receipts, refunds, disputes, hosted Gateway sessions, and settlement.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -42,12 +42,17 @@
42
42
  "kit",
43
43
  "agents",
44
44
  "agent-runtime",
45
+ "agent-spend-governance",
45
46
  "agent-spend-controls",
46
47
  "ai-agent-budget",
48
+ "paid-tool-calls",
49
+ "spend-authorization",
50
+ "evidence-receipts",
51
+ "refunds",
52
+ "disputes",
47
53
  "delegated-spend",
48
54
  "spend-guardrails",
49
55
  "tool-call-spend-limits",
50
- "openai-agents",
51
56
  "gemini",
52
57
  "claude",
53
58
  "anthropic",