Skip to content
Agent Engineering Lab
Pattern

Bounded Grant

Scope, magnitude, expiry, revocation, all four or none.

Kind
Pattern
Layer
Control
Stage
Design
Status
Restated. Nearest prior description:
  • Least-privilege tool binding, a grant carries scope, magnitude and expiry rather than standing access, Microsoft
Forces
  • The property easiest to write down is the one the task already implies; the other three take separate, deliberate work
  • A missing scope or magnitude fails loud, on the next call that reaches past it; a missing expiry or revocation fails silent, until the day a grant that should have stopped, doesn't
  • A record with four fields is not a verifier that checks all four; the gap between a documented shape and an enforced one is where a bounded-looking grant keeps running
Bounded Grant pattern diagram

The problem

Ask an engineering team what access a subagent holds and the answer usually names one property: it can only read documents in this region, or it can only spend under five hundred dollars a call. That sounds like discipline, because a single restriction is already more than an unscoped credential offers. It is not, by itself, what makes a grant safe to hand to something acting while nobody watches every call.

A grant that states what may be done and stops there has said nothing about how much of it, until when, or how to take it back if that description turns out to be wrong. Each omission looks the same from outside: nothing about the grant reads as broken. It reads as scoped, because it is, on the one dimension somebody thought to write down.

Microsoft’s least-privilege guidance for agent tools states three of these directly: constrain by resource, data and operation boundary for scope; build roles around the task, not the org chart, for magnitude; drop back to baseline once the workflow completes, because temporary access with no expiry mechanism becomes permanent access in practice. The same guidance covers revocation too, disabling an identity, rotating a leaked credential, but as an operational practice for when something has gone wrong, not a property the grant’s shape itself carries. That gap is where this pattern lives.

Forces

The property easiest to write down is the one the task already implies; the other three are separate work someone has to choose to do. A subagent built to read applicant files needs a scope that says so, and that falls out of the task almost for free: read, applications, this case id. Nothing about the task specifies a call ceiling, a clock, or a channel for pulling the credential back early. Those have to be designed on purpose; skipped, each costs nothing today, though the grant only isn’t bounded the way its scope line implies.

A missing scope or magnitude fails loud; a missing expiry or revocation fails silent. A grant with no resource boundary shows up the first time the agent reaches for something adjacent to the task, and the call goes through when it should have been refused. A grant with no expiry or no revocation shows up only on the day something has gone wrong: a credential leaked, a subagent compromised, a session that should have ended still answering calls. Nothing before that day distinguishes a grant that expires from one that doesn’t, or one that can be pulled back from one that can only be waited out.

A record with four fields is not the same claim as a verifier that checks all four. It costs little to add expires and a revocation block to a schema, much more to build the code path that refuses a call when either is missing, or when revocation has actually been exercised. The gap between a documented shape and an enforced one is where a bounded-looking grant keeps running past the point where any of its four properties should have stopped it.

The pattern

State the rule plainly: a grant counts as bounded only if it carries all four properties at once, scope, magnitude, expiry and revocation, and a verifier fails closed on any one being absent. Three out of four is not a narrower bounded grant. It is an unbounded grant with paperwork, because the missing property is exactly the dimension nothing stops.

Work through each omission, holding the other three fixed. No scope is a blank cheque: a ceiling, a clock and a revocation channel only bound how fast, how long, and how reversibly it can be cashed, not against what. No magnitude is the same cheque on a narrower page: scoped to one applicant’s case, but with no ceiling on calls or size, still unbounded within that case. No expiry is the failure this catalogue already names: The Expiring Exception treats a relaxation with no expiry as a permanent hole rather than a control, and a credential is the same shape one layer down, temporary in name and permanent in effect.

No revocation looks like expiry’s job already. It mostly isn’t. Birgisson et al., whose caveat mechanism Attenuating Delegation carries into a delegation chain, list short-lived credentials as one of four strategies for what they call revocation, alongside third-party freshness checks, revocation lists, and split credentials. Only the last three let anyone interrupt a grant before its own clock runs out; a short expiry just narrows the window something can go wrong in, it does not give anyone a way to act inside that window. This pattern’s fourth property means the active kind: expiry bounds a grant’s life by default, revocation ends that life on someone’s decision, ahead of the clock. Lose it and a grant is only as good as its expiry window: if that window is a session, and the session gets compromised at minute one, the only remedy left is waiting out the rest.

None of this is a new mechanism; the pieces above are already Microsoft’s. This pattern’s contribution is the conjunction: one shape a grant either has or doesn’t, not three fields on a schema and a fourth practice in an incident runbook.

A grant built to this shape gives a verifier four facts to check, not the agent’s account of the call. The identifiers below are illustrative; the fields are the point.

grant:
  id: GRANT-2026-0143
  subject: research-subagent            # who this credential is issued to
  scope:                                 # what may be done, never "any"
    action: read
    resource: applications
    resource_id: case-2026-88231
  magnitude:                             # a ceiling, not a habit
    max_calls: 20
    max_bytes: 5_000_000
  expiry: 2026-08-22T18:00                # required; no default, no silent rollover
  revocation:                             # how it's taken back before expiry
    checked_at: call_site
    denylist: token-revocations
# missing any one of scope, magnitude, expiry or revocation
# fails the grant, regardless of how the other three read

Be precise about what this pattern is not: a claim about how authority moves between hops. The two are easy to conflate, because a caveat, in Attenuating Delegation’s own telling, is exactly a restriction on scope, magnitude, expiry or target. Bounded Grant checks whether one grant, alone, has the shape those caveats are supposed to produce. Attenuating Delegation checks something a single grant’s shape cannot answer: whether a grant handed to a subagent is narrower than the one its caller held. A grant can pass every check here and still widen authority the moment it is handed down carelessly: boundedness is a property of one grant alone, widening is a property of the relationship between two. Authority at the Call Site is where a verifier like this actually has to run; a check upstream of the call is one the call never has to pass.

Worked example

Return to Attenuating Delegation’s case-worker scenario, but ask it a different question. That worked example narrates a grant re-widening across a chain three hops deep, ending in a shared service account. Bounded Grant doesn’t need three hops to fail. Two grants, each individually well-formed, are enough.

The case-worker’s session is scoped, as in that story, to read and write applications in one region and approve amounts under a set threshold. It asks an orchestrating agent to pull a file and draft a decision, and the platform issues the orchestrator its own grant: scope, read and draft only, this one applicant’s case id; magnitude, a ceiling of fifty calls; expiry, end of the session; revocation, a token checked against a denylist at every call site. It holds on all four properties. A bounded grant, built correctly.

The orchestrator then delegates decisioning to a specialist subagent, built by a different team on a different deadline, which also builds a bounded grant, carefully: scope, write to loan decisions; magnitude, ten thousand calls a day, sized for peak volume; expiry, ninety days, matching the specialist’s own service-level agreement; revocation, checked at the call site, same mechanism as the orchestrator’s.

It is also, compared to the orchestrator’s own grant, strictly wider on every axis: fifty calls for one session against one case became ten thousand calls a day against branch-wide decisions, for three months. Neither grant’s shape is broken. Bounded Grant has nothing left to say here, because both pass, individually, on every property it checks. What it cannot tell you is that the second grant should never have been issued to a subagent spawned by the first. That comparison is not a property of either grant alone, it is a property of the hop between them, and catching it needs Attenuating Delegation checking the second grant against the first, not a sharper reading of either grant’s own four fields.

When not to use it

The cost of this pattern is four pieces of real infrastructure: a scope model precise enough to reject the call that shouldn’t happen, a magnitude ledger something decrements, an expiry a clock enforces, and a revocation channel a verifier consults on every call. Building all four for a credential that never leaves a single trust boundary, one agent calling its own tools with no hop to another agent, spends that infrastructure on a delegation that was never at risk. Authority at the Call Site covers that case with one check at the point of use; there is no second party’s grant to bound.

Revocation has a narrower exemption than the other three. A token minted for exactly one call, consumed and discarded before the response returns, has no interval in which pulling it back early could land ahead of its own expiry. Scope and magnitude still have to hold, because they bound what that single call can do; a live denylist consulted for a credential whose entire lifetime is one function call defends a window that already closed.

That exemption does not survive the token outliving the call it was minted for. The moment a short-lived credential gets cached, retried, or handed to a second caller, the interval a revocation check would need reappears. A team that keeps the short-lived justification on a credential that quietly stopped being short-lived is the failure The Expiring Exception already names, applied to a credential instead of a governance relaxation.

Attenuating Delegation is what this pattern is not: the worked example above shows a grant bounded by every property named here and still wider than the one that spawned it, and catching that needs a comparison across hops, not a sharper read of one grant’s shape. Authority at the Call Site is where the verifier this pattern describes has to run; a grant’s expiry and revocation fields mean nothing if the check sits upstream of the call. The Expiring Exception names the same failure this pattern’s third property guards against, one layer up the stack: a relaxation and a credential, each with no expiry, decay into the same permanent hole, because nobody forced the question to come up again. Capability Gate covers what a bounded grant, however correctly shaped, should never authorize alone: a destructive call needs a gate outside the grant’s own authority. Decision Record is what proves, after a call has run, that the grant behind it carried all four properties when checked, not a scope and a magnitude that looked right beside an expiry or a revocation channel nobody verified was there.

Sources

  1. (2026) Least privilege for AI agents: Identity, access, and tool binding
  2. (2014) Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud