T23 · Tutorial
Production Stripe & Shopify charges
Guard live Stripe charges and Shopify checkouts after production attach: policy presets, server-side amounts, binding metadata, partner secrets.
Outcome: payments.charge_customer (stripe_charge) and/or commerce.checkout run on live attach with server-owned amounts and partner keys in secrets only.
Learning view: objectives and extras expanded. Switch for commands only.
Mental model
Providers move money; Kit authorizes the tool and signs completion evidence. Sandbox smokes are contract-only; live needs attach + partner secrets.
You will be able to
You will be able to
- Scaffold stripe-commerce or shopping policy and validate-tools before deploy
- Instrument at charge/checkout boundary; keep provider SDKs inside handlers
- Load amounts from invoice/catalog — never free-form model amount_cents
- Attach binding metadata (buildPaybondStripeMetadata / Shopify note attributes)
- Bind with intentId + capabilityToken (or attach: env) — never sandbox: true for live charges
- Name which smoke is sandbox contract vs funded production attach
Prerequisites
Prerequisites
- · Protect first agent tool (production) — live open, deferred instrument, funded bind
- · Settlement rail for your provider path (Stripe Connect / Shopify)
- · For real money: STRIPE_SECRET_KEY and/or Shopify credentials in secrets manager — not required for policy and sandbox contract smoke
Provider charges on production attach
Stripe and Shopify execute the payment; Kit authorizes the tool and signs completion evidence. Sandbox presets prove the contract without partner credentials — live money needs production attach (previous tutorials) plus provider secrets.
01
Settlement and live open
Rails in Settlement; Paybond.open expectedEnvironment live.
02
Provider policy
stripe-commerce or shopping policy; validate-tools --local-only.
03
Funded attach
intentId and capabilityToken or attach: env (not sandbox smoke).
04
Guard charge tool
Instrument charge/checkout; amount from invoice/catalog.
05
Evidence and Console
stripe_charge / completion evidence; inspect Intents / Agent runs.
Policy and sandbox contract (no partner money)
Contract only — not live attachStep 1 of 4
Scaffold Stripe commerce policy
Adjust ceilings before deploy. Shopping preset for Shopify path.
Goal: Same policy schema as sandbox; register payments.charge_customer (stripe_charge) or commerce.checkout.
Run this
paybond policy init --preset stripe-commerce --out paybond.policy.yaml # Shopify/shopping alternative: # paybond policy init --preset shopping --out paybond.policy.yamlExample response
Wrote paybond.policy.yaml (stripe-commerce preset) tools: payments.charge_customer evidence_preset: stripe_chargeYou should see: paybond.policy.yaml lists your charge/checkout tool with evidence_preset.
Step 2 of 4
Validate policy locally
CI-friendly check without Gateway credentials.
Goal: Catch allowlist / evidence misconfig before a live deny.
Run this
paybond policy validate-tools --file paybond.policy.yaml --local-onlyExample response
✓ tools registry ok ✓ every side-effecting tool has evidence_preset ✓ intent.allowed_tools alignedYou should see: Exit 0.
Step 3 of 4
Sandbox stripe contract (optional)
No Stripe secret required — synthetic stripe_charge evidence path only.
Goal: Rehearse the evidence contract without partner charge APIs.
Run this
paybond agent sandbox smoke --preset stripe-commerce --format tableExample response
PHASE DETAIL authorize payments.charge_customer ok charge synthetic stripe_charge evidence verified · releasedYou should see: Spend approved · Charge completed · Evidence verified (table).
Note: Still not live attach. For attach smoke use the previous tutorial after fund.
Step 4 of 4
Sandbox Shopify checkout contract (optional)
No Shopify store required for this sandboxed guardrail path.
Goal: Same guardrail shape you will wire with instrumentShopifyCheckout on live.
Run this
paybond agent sandbox smoke \ --operation commerce.checkout \ --requested-spend-cents 4500 \ --evidence-preset cost_and_completion \ --format tableExample response
PHASE OP RESULT authorize commerce.checkout ok evidence cost_and_completion released # contract only — not live UCP moneyYou should see: Spend approved · checkout path and receipt stages in table.
Live preconditions (honest)
Real charges and checkouts need more than sandbox smoke. Complete production attach first, then inject partner credentials only into the agent runtime secrets manager.
- Paybond: paybond_sk_live_…, expectedEnvironment live, funded intent and capability_token (or PAYBOND_ATTACH_* and PAYBOND_ATTACH_BUNDLE).
- Stripe live path: STRIPE_SECRET_KEY (and Settlement Stripe Connect already configured). Optional: mapStripeToolResultToEvidence after charge.
- Shopify live path: store domain and Admin / storefront / UCP credentials you already use for checkout — Kit does not ship fake Shopify APIs.
- Amounts: invoice.amount_due or catalog unit price × quantity — never free-form model amount_cents.
- Console: Settlement for rails; Machine access for keys/bundles; Intents and Agent runs after execute.
Step-by-step product wiring
Guard payments.charge_customer with stripe_charge evidence. Load amount from a trusted invoice; attach buildPaybondStripeMetadata so webhooks can bind tenant and intent. Full recipe: Charge customers from agents.
- Open with expectedEnvironment live — omit sandbox bootstrap.
- Pass invoiceId (not amountCents) from trusted session context.
- mapStripeToolResultToEvidence rejects funding webhook envelopes as completion evidence.
- Bind after create/fund; inspect evidence under Console Intents / Agent runs.
Load amount from Stripe (invoice/server), attach Paybond metadata, return evidence-shaped tool result.
stripe-charge.ts
import Stripe from "stripe";
import {
Paybond,
buildPaybondStripeMetadata,
mapStripeToolResultToEvidence,
} from "@paybond/kit";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); // partner secret
const paybond = await Paybond.open({
apiKey: process.env.PAYBOND_API_KEY!,
expectedEnvironment: "live",
});
async function chargeCustomer(args: {
customerId: string;
invoiceId: string; // trusted — load amount server-side
tenantId: string;
intentId: string;
}) {
const invoice = await stripe.invoices.retrieve(args.invoiceId);
const amountCents = invoice.amount_due;
const metadata = buildPaybondStripeMetadata({
tenantId: args.tenantId,
intentId: args.intentId,
rail: "stripe_connect",
});
const pi = await stripe.paymentIntents.create({
amount: amountCents,
currency: invoice.currency,
customer: args.customerId,
confirm: true,
metadata,
automatic_payment_methods: { enabled: true },
});
const toolResult = {
status: pi.status,
cost_cents: amountCents,
invoice_id: invoice.id,
payment_intent_id: pi.id,
charge_id:
typeof pi.latest_charge === "string"
? pi.latest_charge
: pi.latest_charge?.id,
};
mapStripeToolResultToEvidence(toolResult, { preset: "stripe_charge" });
return toolResult;
}
const instrumented = await paybond.instrument({
policy: "./paybond.policy.yaml",
tools: { "payments.charge_customer": chargeCustomer },
});
// Production: await instrumented.bind({ intentId, capabilityToken });
// Omit sandbox bootstrap for live charges.Result: Partner Stripe charge succeeds only after Kit spend authorize; evidence maps via stripe_charge.
Also: Production attach · Paybond with Stripe agentic commerce · Paybond with Shopify agentic commerce.
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
Accepting amountCents from the LLM for Stripe charge
Do this
Pass trusted invoiceId (or order id); load amount_due server-side in the handler before PaymentIntent create.
If you see
Using payment_intent.succeeded webhook body as tool evidence
Do this
mapStripeToolResultToEvidence rejects funding webhook shapes — submit tool-result evidence after the guarded charge returns.
If you see
Shopify order webhooks treated as completion evidence
Do this
orders/create and orders/paid are funding/binding signals; completion evidence still follows the guarded checkout tool under capability_token.
If you see
Deploy still has sandbox: true on commerce instrument
Do this
Production: deferred instrument and bind({ intentId, capabilityToken }) or attach: "env" after fund — same as Protect first agent tool (production).
Self-check
Self-check
Answer without scrolling up — then reveal the model answer to compare.
Why can paybond agent sandbox smoke --preset stripe-commerce be green while live charges still fail, and what two secret classes are missing?
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.