Repository navigation
Principal Approvals
Marcus Richards edited this page Oct 7, 2026
·
2 revisions
A permit can carry an approval threshold. Spends at or below it go through the normal gate. Spends above it wait for a human.
- The agent spends more than the threshold.
- The pipeline runs a read-only
eligible()probe. If the gate would refuse anyway, the spend falls through tocheck()and gets an ordinary BLOCKED receipt. No approval request is made. - If the probe passes, an approval request is created. Receipts:
APPROVAL_REQUESTEDandAPPROVAL_PENDING. Result:pending_principal_approvalwith anapproval_id. No cap is reserved. - The principal approves or denies. Receipt:
APPROVAL_DECIDED. - The agent calls
complete_approved_spend(approval_id). This re-runs the full spend with the stored permit, amount, merchant, predicate and artifact hash.
| Rule | Code fact |
|---|---|
| Approval is a word, not a lock | Completion re-runs check(). If the budget moved, it fails closed |
| Binding |
spend(..., approval_id) rejects any mismatch on permit, amount or merchant: invalid_approval
|
| Single use | Status becomes consumed once the spend reserves |
| Denied is final | Only approved can complete (approval_not_approved) |
| Expiry | Default TTL 15 minutes (ttl_minutes=15). Expired lazily, recorded with actor system
|
| Failed recheck | An unconsumed approval stays approved. The agent may retry |
| Statuses |
pending, approved, denied, expired, consumed
|
| Tighten-only | A threshold can be set or lowered, never raised. See Tighten-Only Narrowing |
-
Dashboard (
dashboard/server.py):POST /api/approvals/<id>/approveor/deny. Recorded with actordashboard. - The JSON service
server.pyhas no approval endpoints. ItsPOST /api/permitsdoes not accept a threshold either. On the service, the only way to set a threshold isPOST /api/permits/<id>/tightenwithapproval_threshold_cents.
-
demo_approval.py(LLM agent, dashboard on port 8474): auto-allow, approve, deny, then approve followed by a cap tighten, which fails closed. -
tests/test_approval.py: 18 tests. That includestest_approval_fails_closed_when_parent_revoked(PR #10): the permit is revoked while an approved request is pending, completion is refused, PayPal is not called, and the approval staysapproved.
Permit · payment authority for AI agents · MIT · Wiki facts verified against commit 9900817 on 2026-10-07 (America/Edmonton). Where this wiki and the code disagree, the code wins.
Concepts
- Overview and Problem
- The Four-Clause Gate
- Spend Pipeline
- Delegation and Sub-Permits
- Principal Approvals
- Tighten-Only Narrowing
- E-Stop and Revocation
- Claim Ledger
- UNKNOWN and Reconcile
Using it
Design and status
Reference