Skip to content

Spend Envelope

A spend envelope is the core authorization primitive in PQSafe AgentPay. It defines the exact conditions under which an AI agent is permitted to move money — and makes those conditions cryptographically unalterable once signed.

Motivation

AI agents need to spend money to function. Without spend envelopes, the only options are:

  1. Hardcoded credentials — agent has unrestricted access to payment methods. One compromised agent = unlimited liability.
  2. Human-in-the-loop for every payment — eliminates the value of autonomous agents.
  3. Post-hoc monitoring — you see what the agent spent after the fact, when it’s too late.

Spend envelopes solve all three: the agent is pre-authorized up to explicit limits, humans are notified only when needed (approval gate), and every action is recorded in an immutable ledger.

Structure

interface SpendEnvelope {
// Identity
envelopeId: string // Derived from hash of canonical JSON
agentId: string // Which agent this is for
issuedBy?: string // Who authorized it
// Amount bounds
maxAmount: number // Hard cap
currency: string // ISO 4217
// Time bounds
validFrom?: Date
validUntil: Date // Hard expiry
// Destination constraints
allowedRecipients: string[]
// Rail constraints
allowedRails: RailName[]
// Approval gate
requireApproval?: boolean
approvalThreshold?: number
// Memo
memo?: string
}

Invariants enforced at dispatch

Before executeAgentPayment() sends any money, the SDK checks:

CheckError if failed
Signature valid (ML-DSA-65)ENVELOPE_SIGNATURE_INVALID
validUntil not exceededENVELOPE_EXPIRED
amount ≤ maxAmountAMOUNT_EXCEEDS_ENVELOPE
recipient in allowedRecipientsRECIPIENT_NOT_ALLOWED
rail in allowedRailsRAIL_NOT_ALLOWED
Approval granted (if requireApproval)APPROVAL_REQUIRED

All six checks must pass. There is no bypass.

Canonical JSON binding

The signature is bound to the canonical JSON of the envelope (see Canonical JSON for the exact algorithm). This means:

  • Adding a field → signature invalid
  • Removing a field → signature invalid
  • Reordering keys → signature invalid
  • Changing any value → signature invalid

This ensures that what was signed is exactly what gets executed.

Single-use semantics

Each envelope is designed for a single payment dispatch. The ledger records the envelopeId on first use. A second dispatch with the same envelopeId fails with ENVELOPE_ALREADY_USED.

Next steps