Token Delegation
Create hierarchical token trees with budgets that cascade from parent to child.
What is delegation?
Delegation lets a parent token create child tokens with reduced capabilities. Each child inherits the parent's caveats and can add new restrictions — but can never exceed the parent's scope. This is the core property of macaroons: capabilities can only shrink, never grow.
How it works
When you delegate a token, you specify:
- Budget (credits) — maximum the child can spend
- Cost center — organizational label for spend tracking (e.g., "Engineering")
- Department — finer-grained grouping (e.g., "ML Team")
- Expiry — when the delegation expires
- Additional caveats — any further restrictions
Delegation tree
Root Key (∞ credits)
├── Engineering (10,000 cr)
│ ├── ML Team (5,000 cr)
│ │ ├── Agent: code-reviewer (1,000 cr)
│ │ └── Agent: test-runner (2,000 cr)
│ └── Platform Team (3,000 cr)
│ └── Agent: deploy-bot (500 cr)
└── Finance (5,000 cr)
└── Agent: expense-analyzer (1,000 cr)Spending rolls up the tree. When code-reviewer spends 100 credits, it's deducted from ML Team (5,000 → 4,900), Engineering (10,000 → 9,900), and the root.
Creating a delegation
Go to Delegation & Budgets in the dashboard:
- Click "Create Delegation"
- Select the parent token (or use root)
- Set the credit budget
- Add cost center and department labels
- Optionally set an expiry
- Click "Delegate" — the child token is minted immediately
Via the API
curl -X POST https://cloud.satgate.io/api/cloud/delegation \
-H "Authorization: Bearer <parent-token>" \
-H "Content-Type: application/json" \
-d '{
"budget_credits": 1000,
"cost_center": "Engineering",
"department": "ML Team",
"label": "code-reviewer",
"expiry": "720h"
}'Key properties
- Irrevocable scope — a child can't exceed the parent's budget or access. Caveats only shrink.
- Budget isolation — each child has its own budget. One agent can't starve another.
- Cascading spend — all spending rolls up to the parent, giving visibility at every level.
- Revocation — revoke a parent token and all children are automatically invalid.