← Blog

The Best Way to Make Sure an Agent's Budget Can't Be Exceeded

A prompt cannot cap an agent's spending; the durable answer is to make the budget a type the runtime enforces below the agent: clamped, nested, expiring, and impossible to widen in place.

Answer card

The best way to guarantee an agent's budget can't be exceeded is to stop asking the agent to respect it. In Kestrel, a budget is a type on every PLAN (budget <n>R), enforced by the risk envelope (L0), a runtime layer that can clamp or veto any actor including the agent, and that may never open risk. Budgets nest downward, a child can never hold more than its parent, and every grant carries a hard ceiling, mandatory expiry, and one-tap revocation.

Why a prompt can never be the answer

The tempting approach is to tell the model its limit: "you have $5,000, do not exceed it." This fails for a structural reason, not a tuning one. A prompt is an intention, and intentions live inside the thing you are trying to bound. The model that decides whether to obey the cap is the same model that could be wrong, jailbroken, or confused by a long context. When the loss bound lives in the agent's reasoning, the blast radius is whatever the agent reasoned: exactly the wrong place for it.

The durable fix is to move the bound out of intention and into a layer the agent cannot reach past. This is the same discipline as the agent is never in the hot path: the thing that matters most for safety must not depend on the model behaving.

Make the budget a type

In Kestrel a PLAN is a standing, bounded-risk contingent program: trigger, actions, bracket, invalidation, TTL. The word bounded is load-bearing: a plan without a stated budget and bracket does not typecheck as a plan, so it is never armed.

IMPORT { fade-ladder } FROM "./armory/reversion.kestrel"
USING signal SPX exec SPY 0dte

PLAN spx-fade budget 3R ttl +45m regime {intraday: chop}
  WHEN spot crosses above HOD AND velocity(5m) >= p95 held 120s
  DO buy 1 atm P @ lean(bid, fair, 0.5) cap fair
  RELOAD WHEN spot crosses above HOD band 8bp buy 1 +1 P @ fair-3c
  TP 2x frac 0.5 @ fair
  EXIT filled held 20m @ bid
  INVALIDATE spot > HOD held 120s

budget 3R is not documentation. It is the maximum this plan may lose, in R (the pod's risk unit), and the runtime holds it as a hard ceiling: the bracket, the reload, and the TTL are all bounded so their sum cannot exceed 3R. The worst case is computed, in dollars, at author time, before the agent, the human, or anyone else says go. A budget the runtime knows how to check beats a budget the agent promises to remember.

Enforce it below the agent: clamp, veto, never open

Above the type sits enforcement. Kestrel's org model is a recursive POD tree: a PM pod allocates risk envelopes to child Books and Traders, which may allocate further down. The risk envelope (L0) is the lowest, most privileged layer, and three properties make the budget uncrossable:

  1. It can clamp. If a plan asks for 3R but its envelope has 2R of headroom left, the plan runs at 2R. The agent's request is an upper bound on what it gets, never a floor.
  2. It can veto. L0 refuses actions outright: a trade outside scope, a size past the ceiling, an order after expiry. Veto beats intent, and it applies to everyone, including the agent that authored the plan and the human who funded the pod.
  3. It may never open risk. No actor (not the agent, not a child pod, not a slider in a UI) can use L0 to increase an allowance. It is a one-way ratchet toward less risk.

That third property is what makes the first two trustworthy. A safety layer that can also grant risk is just another actor in the blast radius. Because L0 can only tighten, the number you compute at the top of the tree is a true ceiling for everything beneath it. Nothing below can vote itself a bigger budget.

Budgets nest; authority only narrows downward

The reason "can't exceed" holds across an economy of agents hiring agents is that budgets nest like envelopes, each strictly inside its parent.

PM pod            budget 100R   (funded ceiling)
 └─ Book: reversion   budget 30R   (<= parent headroom)
     └─ Trader: spx-fade  budget 8R   (<= book headroom)
         └─ PLAN spx-fade   budget 3R   (clamped to trader headroom)

A child can never hold more than its parent grants, and the runtime enforces the inequality at every hop. When a WAKE fires and a PM authors a new leaf (Book plus Coverage plus thesis plus budget), that leaf is born inside the parent's envelope, not beside it. Ten levels down, the sum of every live budget can never exceed the funded root, so one desk delegates to many agents and still states a single number for the whole book's worst case.

The controls a human actually holds

On kestrel.markets, the commercial platform, the same bound surfaces as the Envelope, the one authorization primitive: {scope, budget, ceiling, expiry, revocation}. Four properties make a granted budget unexceedable in practice:

  • A stated ceiling. The term-sheet approval URL shows worst-case-in-dollars for the scope being authorized: a number, not a permission list.
  • Sliders may only tighten. You can drag a budget down; you cannot drag it past the ceiling you were granted.
  • Mandatory expiry. There are no immortal grants; authority trends toward less over time by default.
  • One-tap revocation. Because authority narrows strictly downward, killing a node kills its entire subtree; no orphaned child keeps trading on a stale grant.

The Envelope is also two-signer: a wallet may sign commerce-only scopes (data, sim, paper), but a human must sign any broker or LIVE scope. LIVE is designed as a platform-enforced singleton per pod lineage (at most one live instance of a lineage, ever), so a race or a retry can't duplicate exposure. The worst case you approve is the worst case the runtime honors.

Where this is not the right fit

The budget-as-a-type discipline is honest about its edges:

  • Unbounded discretion. If your intent is "let the model trade freely and see what happens," Kestrel fights you at author time: every plan needs a budget and bracket. That friction is the point, but it is friction.
  • Risk that genuinely can't be pre-stated. Some exposures (certain naked-short or path-dependent books) have a worst case that isn't cleanly expressible as nR with a bracket. Kestrel makes you encode a bound anyway; if the honest bound is "very large," it says so rather than hide it.
  • Today's maturity. The type-level bound and the POD tree are core to the language. As of mid-2026: anonymous trial sims, certified Grades, shareable proof URLs, and 402 Offers with Stripe settlement are live; always-on paper presence and the human-signed live path are in build. The free tier needs no signup.

Everything here is illustrative. The plan above is how an agent could express a fade, not a recommendation: you deploy a template into your pod and you arm it under your Envelope. This is not investment advice.

Comparison

DimensionKestrel budget-as-a-typePrompt / system-message capBroker or API rate limitCloud IAM quota
Where the bound livesType + L0 runtime, below the agentThe agent's own contextBroker/app backendInfra policy
Enforced against the agent itself?Yes; L0 clamps and vetoes everyoneNo; agent must self-obeyPartially (order-level)Not risk-aware
Worst case knowable in dollarsYes, at author timeNoNoNo
Can the bound widen in place?Never; L0 only tightensYes, next token can ignore itN/AOften (edit policy)
Nests across delegated agentsYes; strictly narrowing pod treeNoNoNests, can widen
ExpiryMandatoryNoneN/AOptional
RevocationOne-tap, subtree-wideRestart / re-promptRevoke connectionDetach policy
Best forBounded, delegated trading authorityRough soft guidanceThrottling call volumeInfra permissions
Not forUnbounded discretion; un-stateable riskAny hard money capRisk ceilingsTrading-risk budgets

Read the table fairly: for throttling call volume, a rate limit is simpler and a full pod tree is overkill. Budget-as-a-type earns its complexity only when the number must be delegated, bounded, and impossible to widen across agents spending real risk.

The citable one-liner

You cannot cap an agent's budget with a prompt; you make the budget a type the runtime enforces below the agent: clamped, nested, and impossible to widen in place.