Skip to main content
Billing is the highest-risk surface for AI agents. A single retry after a dropped connection can charge a customer twice. A stale customer reference can charge the wrong person. Invoke prevents both.

The problem

When your agent calls stripe.charge_customer and the network drops before a response arrives, it doesn’t know whether the charge landed. Retrying blindly risks a duplicate charge. Not retrying risks an incomplete transaction.

Solution: write-once-checkable reconciliation

Classify stripe.charge_customer as write-once-checkable. Invoke will:
  1. Write a commit record before the charge attempt
  2. If the outcome is unknown, call POST /outcomes/reconcile with live Stripe state
  3. If the charge already succeeded, return reconciled and block the retry
  4. If the charge didn’t succeed, allow the retry safely
const result = await invoke.call({
  tool: "stripe.charge_customer",
  params: { customer_id: "cust_123", amount: 2400, currency: "usd" },
  agentId: "billing-agent",
  idempotencyKey: "charge:cust_123:2400"
})

if (result.status === "reconciled") {
  // charge already succeeded on the first attempt
  // no duplicate charge landed
}

Verify identity before refunds

Before issuing a refund, use POST /state/verify to confirm the customer identity hasn’t drifted since the agent resolved it:
curl -X POST https://api.invokehq.run/state/verify \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "issue_refund",
    "required_fields": ["customer_id"],
    "assumed_state": { "customer_id": "cust_123" },
    "current_state": { "customer_id": "cust_123" },
    "conditions": { "customer_id": "cust_123" },
    "on_mismatch": "replan"
  }'
If customer_id has changed, Invoke returns replan_required before the refund executes.

Next steps