Stipendex specification 0.1-draft: overview
The normative words MUST / SHOULD / MAY follow RFC 2119. Object details — envelope.md, authority — mandate-wallet.md, transports — transports.md, rails — rails.md.
Roles
| Role | Who | Holds funds? |
|---|---|---|
| Principal | human/organization — the source of funds and authority | yes (their own) |
| Agent | LLM loop; initiates spending but does not control it | no |
| Wallet | deterministic component at the agent host; checks the mandate, signs payments | no (keys only) |
| Receiver | MCP server / HTTP API / merchant issuing Quotes | yes (their own) |
| Rail | payment system executing settlement (Stripe, x402, ledger) | in transit, under its own license |
| Facilitator | operator of accounts/verification behind the account rail; HITL queue, anti-fraud |
yes, under its own license |
| Trust registry | issuer of signed descriptors of verified receivers | no |
Objects
| Object | Signed by | Purpose |
|---|---|---|
| Mandate | principal | the wallet's authority: limits, allowlist, thresholds, validity |
| Quote | receiver | single-use offer: amount or estimate+tolerance, rails, TTL |
| Confirmation | wallet (opt. + principal's passkey) | recorded human consent to a total+tolerance |
| Proof | wallet | proof of payment/hold for a specific Quote |
| Receipt | receiver | "received and executed": final amount, result hash |
All objects are JSON signed with JWS (Ed25519); amounts are decimal strings
("0.0042"), never floats; identifiers are prefixed (m_, q_, c_, p_, r_)
and unique per issuer.
The base cycle
Agent Wallet Receiver Rail/Facilitator
│ call ─────────────────────────────────▶│
│ ◀──── payment_required + Quote ────────│
│──Quote──▶│ 1 allowlist (default deny) │
│ │ 2 mandate limits │
│ │ 3 HITL threshold → Confirmation
│ │ 4 pay/hold via rail ────────────────────────────────▶│
│ │◀──────────── Proof ──────────────────────────────────│
│ retry call + Proof ────────────────────▶│──── verification ────▶│
│ ◀────── result + Receipt ──────────────│
Invariants (normative):
- I1. The wallet is the only point of payment decision. The agent (LLM) MUST NOT
have any interface with an arbitrary receiver or amount; the only operation is
pay(quote). - I2. A Quote is single-use and time-bounded; a Proof is idempotent (replay does not create a second charge).
- I3. A capture MUST NOT exceed the Quote amount, and with an
estimate— the confirmed amount ≤ estimate + tolerance. - I4. A receiver outside the mandate's allowlist sources → deny; escalation to a human, never a "soft pass".
- I5. Every payment is reproducible from the chain
mandate → (confirmation) → quote → proof → receipt— that chain is the audit.
Profiles
- Service (default):
Quote.amountis fixed; Proof mode iscapture; aggregation via a tab session (envelope.md). - Checkout:
Quote.estimate + tolerance; Proof inholdmode, capture after the receiver confirms the final amount; Confirmation is mandatory (checkout-profile.md).
Receiver adoption levels
| Level | What it does | Payment code |
|---|---|---|
| L0 | declares prices in metadata (pricing) — agents account for cost when planning |
0 lines |
| L1 | paywall via a hosted facilitator (the account rail) |
~10 lines |
| L2 | own rails (direct x402, own ledger, Stripe) | an adapter |
| L3 | extensions: subscriptions, metered quotas, checkout profile | as needed |
Versioning
Every object carries stipendex: "<type>/<version>" (e.g. "quote/0.1"). A major
version breaks compatibility; a wallet MUST reject objects of an unknown major
version. Transport capability negotiation — transports.md.