Once.
REFUND RETRY SAFETY / FINANCIAL SIDE EFFECTS

Prevent duplicate refunds after an ambiguous timeout.

If an AI agent sends a refund and then times out, do not assume the refund failed. Repeating the provider write blindly can refund the same logical transaction twice.

Short answer: If an AI agent sends a refund and then times out, do not assume the refund failed. Repeating the provider write blindly can refund the same logical transaction twice.

The duplicate-refund failure mode

The provider may commit the refund before the response reaches the agent. The caller sees a timeout and retries. Without stable logical identity or reconciliation, the second attempt can look like a brand-new refund.

Recovery sequence

  1. Reuse the same logical operation identity.
  2. Read durable operation state.
  3. Reconcile authoritative provider truth where supported.
  4. Replay stored results when already confirmed.
  5. Block another external execution if the outcome remains unsafe to determine.
Claim boundary: Once does not claim universal exactly-once execution. Safety depends on stable operation identity, durable Once state, the provider integration and sufficiently authoritative provider truth. When the outcome cannot be established safely, Once can preserve uncertainty rather than assume another external execution is safe.

Run the failure yourself

Minimal failure: send one refund; the provider commits; lose the response; retry after restart. A new request without effective deduplication can create another refund.

// Unsafe when the first refund may already have committed:
try { await refundCustomer(intent); }
catch { await refundCustomer(intent); }

Use the runnable local refund proof: a separate HTTP provider records two unprotected effects versus one with Once, followed by UNKNOWN blocking, authoritative reconciliation and changed-amount CONFLICT. No financial account is required.

When an idempotency key solves it

If the provider key binds the complete intended operation for your full retry horizon, use it. Once does not replace that guarantee. A local result table cannot make an arbitrary external write atomic with a database commit; preserve uncertainty when no trustworthy result exists.

Limits and next action

The controlled proof is not a real payment integration. Your developer must explicitly choose a stable, tenant-scoped refund-intent ID and complete effect/account fields. Use distinct IDs for genuine new partial refunds. UNKNOWN stays blocked when truth is unavailable; absence alone does not authorize local redispatch. Local SQLite is limited to one machine.

Run the proof and apply the wrapper pattern →