Mandate
Start free
scoped spending authority for AI agents · open source · self-hosted or hosted
claudeclaude mcp add --transport http mandate https://mandate-ashen.vercel.app/api/mcp

Give your agents a limit,
not a card.

An agent gets a mandate: how much per purchase, per day and in total, which merchants, which hours, and the point above which it must ask you. Every request is decided against those terms before money moves, and every decision is written to a ledger you can prove. One button freezes everything.

MCP · OAuth 2.1REST tokenPython SDKTypeScript SDKOpenAI · Anthropic · Gemini proxyany API targetvirtual cardsvouchers
55 / 55adversarial attempts stopped in the red-team run
199tests: engine, service layer against Postgres, a real browser through every flow
0cards, passwords or provider keys an agent ever holds
1 tapto approve, deny, or freeze every rail from your phone

Two minutes, narrated. A real agent against a real mandate: approved as a hold, declined off-list, held for a human, approved once, frozen, delegated, revoked — and all of it in the ledger.

research-assistant · $50 / purchase · $150 / day · ask above $20live
approved$12.00 at OpenAIin scope · held · captured $11.00, $1.00 released
declined$15.00 at Namecheaprule merchant · remedy: OpenAI, Anthropic or Vercel, or ask the owner to add it
pending$35.00 at Anthropicabove $20 · the owner has a one-tap link · retry after approval
frozen$5.00 at OpenAIthe owner pressed Freeze all · every rail declines until unfrozen
agent → authorize · 1200 · OpenAI · limitsowner → approved once · 3500 · Anthropicagent → delegate · “Price checker” · $10 / purchase · OpenAI onlyledger → #48 · hash a1f6d4… · anchored publicly
01 · The problem

Agents are the first counterparty that spends without a limit, a condition, or a record.

Today the only way to let an agent buy something is to hand it your card or your API key. Then it holds all of your money, and you find out what it did from the statement. Spend caps on one provider cap that provider; they do not say which purchases, do not ask a human, do not cover the next vendor, and leave nothing an auditor could read.

With a card or a keyWith a mandate
What the agent holdsYour card or your provider key — everythingA token scoped to one mandate, or an OAuth grant bound to one workspace
How much it can spendWhatever is on the cardPer purchase, per day, in total; at these merchants; in these hours; until this date
Big purchasesGo throughWait as a hold until a person taps approve — or two people, or a passkey
A helper the agent spins upGets the same keyGets a narrower sub-mandate whose spend counts against the parent; dies when the parent is revoked
Something goes wrongCancel the cardOne button freezes every rail; nothing is deleted; unfreeze puts it back
What happenedThe statement, laterEvery decision in a hash-chained ledger, signed and anchored publicly every day
02 · What Mandate is

Authority to spend, as a thing you issue, narrow, share and revoke.

Mandate is the layer between an agent and money. It is not a bank and not another agent: it decides, records, and asks. Four things, together, that a budget alert or a provider cap does not do.

01

Scoped

Limits, merchants, categories, hours, expiry and an ask-me-above threshold — enforced in a fixed order on every request, from every rail, by one policy engine.

02

Human where it matters

Above the threshold the agent waits. Approvals arrive as one-tap links by email, push or webhook; an approval is for that amount at that merchant, once. Large asks can require two to five named approvers, or a passkey.

03

Holds, not charges

An approval authorises; the agent captures what it actually spent and the rest goes back. A hold expires on its own. Merchants can redeem a signed voucher without an account, once, for at most what was authorised.

04

A record you can prove

Every grant, ask, allowance and refusal is a row in a hash-chained ledger. Receipts verify offline against a published key; the head is signed into a public anchor chain daily, so even the operator cannot rewrite history unnoticed.

03 · How it works

Issue, connect, ask, decide, settle, record.

One request, six steps, each of them an event you can read later.

  1. 01

    Issue

    The owner writes the terms: $50 a purchase, $150 a day, OpenAI and Anthropic, ask above $20, until the end of the quarter. The agent gets a token that only works inside them.

    mandate issued · research-assistant · USD · expires 06 Dec
  2. 02

    Connect

    Add the MCP server in Claude, Cursor or any MCP client and consent once; or put the token in the SDK; or point an OpenAI/Anthropic/Gemini SDK at the proxy and change nothing else.

    claude mcp add --transport http mandate mandate-ashen.vercel.app/api/mcp
  3. 03

    Ask

    Before paying, the agent sends the amount, the merchant and a purpose. Retries carry an idempotency key, so a flaky network never decides twice.

    POST /api/agent/authorize { amount: 1200, merchant: "OpenAI" }
  4. 04

    Decide

    frozen → paused → status → expiry → hours → merchant → category → per-purchase → daily → total → balance → every ancestor → plan → escalation. Approved as a hold, declined with the rule and a remedy, or pending a person.

    200 approved · rule limits · hold until 09:28 tomorrow
  5. 05

    Settle

    The agent captures what it spent, or voids; a merchant redeems a voucher; a card authorisation is reconciled from Stripe; an expired hold closes by the mandate's policy.

    captured 1100 · released 100
  6. 06

    Record

    Every step is a ledger row whose hash covers the one before it. Export a signed receipt; anyone can re-run the hashes. The head is anchored publicly once a day.

    ledger #48 · hash a1f6d4… · anchor #31
04 · Every rail, one engine

However the agent pays, the same terms decide.

MCP + OAuth 2.1

Claude, ChatGPT, Cursor, Windsurf, Claude Code. Nine tools: list, check, request, capture, void, get, propose a plan, get a plan, delegate. The grant is bound to one workspace and re-checks the member's role on every call.

REST token + SDKs

Plain HTTP with a mnd_ token, or pip install mandate-agent / npm install mandate-agent with ready-made tools for the OpenAI Agents SDK, LangChain and the Vercel AI SDK.

LLM proxy

Point the OpenAI, Anthropic or Gemini SDK at mandate-ashen.vercel.app/api/proxy/… with a proxy key. Every call is priced before it is forwarded and settled on reported usage; your real provider key never leaves the server.

Any API target

Register any https API with its credential injected in a header, priced per call or from the response. The agent gets a key bound to that target and nothing else.

Virtual cards

With Stripe Issuing, each mandate can carry a card whose every swipe is decided by the same terms in real time, including incremental authorisations, against a prepaid balance.

Vouchers

An approved hold can be presented to a merchant as a signed voucher (mv1.…, Ed25519) they verify offline and redeem once, for at most the authorised amount.

05 · When it says no

A refusal names the rule it broke and what would pass.

An agent that is told only “no” loops. Every non-approval carries a remedy: when the same request would pass, the most that would pass right now, and one sentence of advice the agent can act on. Pending answers are never cached, so the retry after approval goes through.

frozenpausedstatusexpiryhoursmerchantcategoryper_txndailytotalbalanceparent_*planapprovalvetoallowance
HTTP 403
{
  "decision": "declined",
  "rule": "daily",
  "reason": "Today's limit of $150.00 has $18.00 left.",
  "remedy": {
    "retryAt": "2026-11-07T00:00:00Z",
    "maxAmountNow": 1800,
    "approvalRequired": false,
    "message": "Up to $18.00 passes now; the day resets at midnight UTC."
  },
  "remaining": { "today": 1800, "total": 48200, "perTransaction": 5000 }
}
06 · Controls for the owner

Built for the person who answers for the money.

Panic button

Two clicks freeze every rail in the workspace. The engine checks it before it even loads the mandate. Nothing is revoked.

Co-signing

Above a threshold, two to five distinct approvers must sign; one denial ends it; signatures are counted per account, not per e-mail spelling.

Routing

Send requests to the right deciders by amount band, category, merchant or mandate; the route is recorded on the request.

Veto windows

Let a purchase through by itself after a delay unless someone cancels it — for the ones you want to see, not sign.

Plans

An agent proposes a shopping list; you approve it once; each item passes exactly once at its named merchant.

Sub-mandates

An agent carves narrower mandates for helpers, three levels deep; the family's spend counts against every ancestor; revoking the parent revokes them all.

Disputes

Contest any decision from its row; the mandate can pause; settle it as refunded, upheld or withdrawn — the limits net down accordingly.

Shadow mode

Observe before enforcing: nothing is declined, every verdict is recorded, the report shows what would have happened. Hard rules still hold.

Time-travel

Replay a mandate's real history against hypothetical terms and see which past decisions would change before you tighten anything.

Graduated autonomy

Clean decisions raise the limits step by step towards a ceiling you set; a denial steps back.

Passkey-signed approvals

A receipt can prove a person on a registered device decided — not a script with a cookie.

Sandboxes

mnd_test_ tokens for CI: same engine, no cards or proxy keys, excluded from the books, reset in one click.

07 · Proof

Tested the way an attacker would use it.

npm run redteam plays a misbehaving agent against a running instance over plain HTTP: over its limits, off its merchant list, salami-slicing the day, forging an approval link, replaying an allowance, widening a delegation, settling someone else's hold, editing a voucher. Each attempt is checked for one thing — did a capturable authorisation come out?

Three suites run on every push: 22 engine tests, 41 integration tests against Postgres, 136 checks in a real browser. The security review — threat model, every finding, every fix, what is still open — is public.

55 attempts · 55 stopped
  • 403 one cent over the per-purchase limit
  • 403 “OpenAI Marketplace Reseller” against an allow-list of “OpenAI”
  • 403 a forged one-tap link; the real link, replayed
  • 202 an allowance reused for a different amount, merchant, or twice
  • 404 another mandate's token voiding this hold
  • 409 capturing a hold after its voucher was handed out
  • 400 a sub-mandate wider than its parent, or that never asks
  • 422 the same idempotency key with a bigger purchase
  • 403 a valid allowance while the workspace is frozen
  • ok the ledger chain verifies end to end afterwards
08 · Your machines, your data

Run the hosted beta, or run it yourself.

AGPL-3.0. One Next.js app and one Postgres. Nothing leaves your deployment except the calls your agents make to the merchants and providers you chose, with your keys.

Keys stay encrypted

Provider keys, target credentials and webhook secrets are AES-256-GCM under a key held outside the database; mandate and proxy tokens are stored only as hashes and shown once.

Egress is pinned

Webhooks and API targets must be on the public internet; the DNS answer that passed the check is the address connected to, redirects are not followed, time and size are capped.

Fails closed

If Mandate is down, nothing can be authorised. There is no mode in which an agent spends because the safeguard was unavailable.

Verifiable from outside

Receipts verify against a published key; the anchor chain at /anchors lets anyone check that a ledger was not rebuilt after the fact.

09 · Get started

Three ways in. All of them end at the same engine.

The hosted beta

Sign in with an email link, Google or a passkey. Issue a mandate from a template, connect an agent, approve from your phone. Free.

Start free

From Claude, Cursor or any MCP client

Add the server, consent once on the page it sends you to, and ask the agent to “request a $5 purchase at OpenAI”.

mcphttps://mandate-ashen.vercel.app/api/mcp

On your own machine

Postgres and the app on localhost:3000, migrations applied, sign-in links printed to the terminal.

shellgit clone https://github.com/Ivan825/Mandate && cd Mandate && docker compose up

Full instructions, the REST reference and the SDK snippets are in the docs; deployment to Vercel, Docker, AWS and ECS is in DEPLOY.md.

The agent gets a limit. You get the record.

Issue a mandate in a minute, connect the agent you already use, and watch the first decision land in the ledger.