Infrastructure for AI agents

Make AI actions reliable.

Your AI agent decides a customer deserves a refund. Onceproof checks it against your policy, sends it to Stripe exactly once, confirms what Stripe actually did, and signs a receipt. When the answer is uncertain, it says so, and never retries blindly.

Today: Stripe refunds and customer balance credits. Nothing else, done carefully.

An AI agent requests a refund. Onceproof runs it through intent, policy, execution, verification and commit against Stripe, and returns a verified result. In some runs Stripe's answer is lost; the refund becomes Unknown, is reconciled, and is then verified without being sent twice.

The problem

Agents retry. Networks time out. Money moves twice.

A refund request that times out may or may not have happened. Logs record what the agent tried, not what Stripe did.

Duplicate

A timeout, then a retry

The first refund went through, the response was lost, and the agent sent it again. The customer is refunded twice.

Phantom success

"Refunded" that never settled

Stripe accepted the refund, then it failed at the bank. The agent already told the customer it was done.

No proof

Nobody can say what happened

Finance, an auditor or the customer asks. There is no record anyone can check independently.

How it works

The agent asks. Onceproof decides, acts once and checks.

Your agent never holds the Stripe key. It calls Onceproof, which holds a restricted key and owns execution.

Your agent
  • Python SDK or REST
  • MCP for Claude and Cursor
  • Business key from the ticket
Onceproof
  • Policy outside the model
  • Idempotency and target locks
  • Reconciliation of unknowns
  • Verification by read-back
  • Hash-chained evidence, signed receipts
Stripe
  • Refunds
  • Customer balance credits
  • Webhooks back when refunds settle
IntentAgent asks, with a reason
AuthorizationPolicy allows $49
PreconditionsCharge refundable
ExecutionResponse lost: unknown
ReconciliationFound in Stripe by action id
VerificationExactly one, right amount
CommitReceipt signed
ConfirmedUnknown: not yet confirmed either wayRecovered by reconciliation

Unknown is not failed

"We don't know yet" is an honest answer.

When Stripe doesn't answer, the refund is marked Unknown. New refunds on that charge are blocked, and Onceproof looks the refund up in Stripe by its own id. It re-sends only if the refund is proven absent. Most unknowns resolve in seconds; the rest go to a person with the evidence.

This panel uses the same component operators see in the console.

Unknown

We cannot yet confirm whether this refund exists in Stripe. It is not treated as failed, and it will not be retried until the external state is known.

What was attempted
Refund $49.00 USD on ch_3Q9xYz
What we know
1 request sent · other actions on this charge are locked
What we do not know
Whether Stripe created the refund (response lost)
Current action
Searching Stripe by action id
Risk if retried blindly
Duplicate refund. Blind retries are blocked.
Escalation
To a person in 12m 42s if still unknown

Verification

Expected, then observed. Side by side.

After Stripe answers, Onceproof reads the refund back and compares it with what was asked. A mismatch goes to a person; nothing is called "verified" until Stripe shows it.

Expected (from the request)
ActionRefund
Amount$49.00
Chargech_3Q9xYz
Effectsexactly 1
Observed (in Stripe)
ActionRefund
Amount$49.00
Chargech_3Q9xYz
Effects1
VerifiedMatches the intent exactly once, and is final.

Signed receipts

Proof anyone can check.

Every verified refund gets a receipt signed with Onceproof's key: what was asked, who approved it, what Stripe shows. Change one character and the check fails. Give it to finance, an auditor or the customer.

AuthenticEd25519
Transaction
act_4be1c0f5d2a94c77
Intent
“Customer charged twice for March”
Agent
support-refunds-agent
Approved by
maria.khan@finance
Stripe
re_3Q9xYz… · succeeded
Final state
Committed
Signature
MEUCIQDk…7Qx9 · verifies against the public key

Control

People stay in charge of the money.

Limits and approval thresholds live outside the model. Above a threshold, a person approves the exact amount; the server re-checks state, policy and parameters when they click.

Human review required

Refund $278.00

Why review is required
  • Amount $278.00 > approval threshold $250.00
  • Agent: support-refunds-agent
Customer
cus_pJG2T…
Bound to
params 453a3fa1…
Decided by maria.khan@finance
Hard limit · v3Active
WHENrefund > $500.00
THENBlock
Approval threshold · v3Active
WHENrefund > $250.00
THENRequire human approval

Already in production? Start in shadow mode: report the refunds your agent already makes, and Onceproof finds orphans, ghosts and duplicates without touching execution.

Developers

Replace one Stripe call.

Call Onceproof instead of Stripe from your agent, or give Claude the MCP tools. The result tells your code, or the model, exactly what happened and whether it may act again.

API reference · SDK guide · MCP server

from onceproof import Client, business_key

aa = Client(OP_URL, api_key=AGENT_KEY)
r = aa.refund(charge_id="ch_3Q9xYz", amount=4900, currency="usd",
              business_key=business_key("zendesk", ticket_id, "ch_3Q9xYz"))

if r.done:          reply("Your refund is on its way.")
elif r.needs_human: reply("A teammate is confirming it.")
elif r.in_flight:   reply("It's being confirmed; no need to ask again.")

Security and control

Built for money that must not move twice.

The agent never holds the Stripe key

A restricted key stays inside Onceproof. Live keys are refused unless you opt in.

Per-agent keys and a kill switch

Stop any agent instantly; resuming needs an admin.

Roles for people

Viewers, approvers and admins. Approvals are recorded as the signed-in person.

Tamper-evident history

Every state change is hash-linked; the console recomputes the chain.

Signed receipts and webhooks

Ed25519 receipts; HMAC-signed events to your systems, private addresses refused.

Honest scope

Stripe refunds and credits only. No single sign-on or MFA yet; we say so.

See a lost Stripe response recover, live.

Open the demo, press “Simulate lost Stripe response”, and watch the refund go from Unknown to Verified without being sent twice.