from gl_iam import DelegationScopescope =DelegationScope(scopes=["docs:read"],resource_constraints={"department":"engineering","project_ids":["proj-1","proj-2"]},max_actions=50,expires_in_seconds=1800,)
The Attenuation Invariant
Every sub-delegation must be equal to or narrower than its parent. This is enforced automatically:
Attempting to widen any of these results in a SCOPE_ESCALATION_DENIED error.
DelegationScope Fields
Field
Type
Default
Description
scopes
list[str]
(required)
Permission strings the agent is granted
resource_constraints
dict[str, Any]
{}
Key-value constraints on accessible resources
max_actions
int | None
None
Maximum number of actions the agent can perform
expires_in_seconds
int
3600
How long the delegation token is valid
Step-by-Step
1
Scope Attenuation
Scopes narrow at each hop in the delegation chain:
2
Action Budgets
Action budgets limit how much work an agent can do. Each sub-delegation's budget must be less than or equal to the parent's:
Budgets are declarative, not tracked. GL IAM records the budget in the token but does not count actions. Your application must enforce action counting.
3
Resource Constraints
Resource constraints restrict which resources an agent can access:
After validation, the receiving service can enforce these constraints:
Resource constraints are opaque to GL IAM — the SDK stores them in the token but your application defines their meaning and enforces them.
4
Error Handling
Handle scope-related errors in delegation:
You've learned how to control agent authority with scope attenuation, budgets, and resource constraints!
Complete Example
Create scope_and_budget.py:
Run it:
Expected output:
Common Pitfalls
Pitfall
Solution
Budget doesn't track usage
GL IAM records the budget but does not count actions — your app must enforce this
expires_in_seconds=0
A zero expiry creates an immediately-expired token. Use a positive value.
Resource constraints not enforced by GL IAM
Constraints are stored in the token but your application must check them
Assuming wildcard behavior
docs:* does not automatically match docs:read. Scopes are exact string matches unless your app implements wildcards.