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:
- Hardcoded credentials — agent has unrestricted access to payment methods. One compromised agent = unlimited liability.
- Human-in-the-loop for every payment — eliminates the value of autonomous agents.
- 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:
| Check | Error if failed |
|---|---|
| Signature valid (ML-DSA-65) | ENVELOPE_SIGNATURE_INVALID |
validUntil not exceeded | ENVELOPE_EXPIRED |
amount ≤ maxAmount | AMOUNT_EXCEEDS_ENVELOPE |
recipient in allowedRecipients | RECIPIENT_NOT_ALLOWED |
rail in allowedRails | RAIL_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.