An agent asks for Stripe access. You approve. It works.
Watch the full loop: Butler proposes a scoped policy, you approve in Slack, the gateway grants it, the agent retries — every step audited.
Read-only Stripe API for a billing-reconciliation agent
Project project-billing has a new agent that reconciles Stripe charges against an internal ledger. It needs stripe:charges:read for 24h. Right now it has zero Stripe permissions — deny by default.
The baseline policy
Every project gets a YAML policy file. Deny by default — only listed grants are enforced. Stripe is not on the list.
project: project-billing
agents:
- billing-reconciler-1
- invoice-generator
grants:
- service: aws
actions: [s3:GetObject, s3:PutObject]
resources: ["arn:aws:s3:::ledger-internal/*"]
- service: git
actions: [read, push]
resources: ["reidataai/billing-ledger"]
branches: ["feature/*"]
- service: tools
actions: [Read, Edit, Bash]
deny: ["rm -rf", "git push --force"]
Agent gets denied
The agent calls the Stripe API. The gateway intercepts and denies — and it logs the denial.
{
"ts": "2026-05-01T17:42:11Z",
"agent": "billing-reconciler-1",
"project": "project-billing",
"action": "stripe:charges:read",
"resource": "stripe.com/v1/charges",
"decision": "DENY",
"reason": "no policy grants stripe:* for project-billing",
"http_status": 403
} Agent asks Butler for access
Following the access-request protocol, the agent files a tight, scoped request through Butler.
@butler I'm blocked — need read-only Stripe charges for ledger reconciliation.
Butler proposes a scoped policy diff
Butler doesn't grant — it proposes. The diff goes to a human for approval.
Proposed policy patch for project-billing. Approval required.
You approve in Slack (or Telegram)
One tap. Risky operations gate on a real human — no agent bypass, no automation override.
stripe.com/v1/charges · expires in 24h · read-onlyGateway applies the grant. A2A pings the agent. It retries.
No restart, no manual nudge — the gateway notifies the waiting agent over A2A and the original call goes through.
butler → gateway: apply_grant("req_5c94d8", approved_by="jordan")
gateway: policy reloaded for project-billing (1 grant added)
gateway → billing-reconciler-1: grant_ready(stripe:charges:read, ttl=24h)
billing-reconciler-1: retrying stripe.com/v1/charges … {"ts": "2026-05-01T17:43:04Z", "agent": "billing-reconciler-1",
"action": "stripe:charges:read", "decision": "ALLOW",
"grant_id": "req_5c94d8", "http_status": 200,
"approved_by": "jordan", "expires": "2026-05-02T17:42:11Z"} Every step — denial, request, proposal, approval, grant, retry — is one immutable JSONL line. Replay any agent's session.
No agent self-grants. Butler proposes; humans approve. Slack, Telegram, or dashboard — same one-tap UX.
Butler, gateway, and the requesting agent coordinate over A2A. Live session tracking shows it all in real time.
Free trial · No credit card · 5 minutes to first agent