tesoro 0.1.3

Four kinds of AEGL

Not every layer that says no is the same thing. These are ordered by what each can express, and each type can do everything the ones above it can.

The four types

TypeDecides onCatchesCannot catch
1 · Per-payment cap one amount, in isolation a single payment that is too large ten payments that are each fine
2 · Cumulative envelope amount + history a budget exhausted over a day, a month, a window an affordable purchase of the wrong thing
3 · Governed budget amount, history, counterparty, purpose, identity drift from the task; an untrusted counterparty; a delegate exceeding its parent the shape of a sequence
4 · Behavioural all of the above + sequence shape structuring — many payments below every limit —
4 · behavioural — reads the shape of a sequence 3 · governed budget — purpose, counterparty, identity 2 · cumulative envelope — remembers history 1 · per-payment cap is this one amount too large? now table stakes — several SDKs ship one
Nested rather than sequential: a type-3 layer still enforces a per-payment ceiling, it just is not only that. The interesting boundary is between 2 and 3, because that is where the question changes from “can we afford it” to “should we be buying it”.

Type 1 · A per-payment cap

One number, checked against one amount. Refuse anything above it.

This is genuinely useful and it is also the easiest thing in the category to build, which is why it is now table stakes — the x402 SDKs ship maxAmountPerPayment, the Claude Agent SDK ships max_budget_usd, and several standalone tools do the same. If a per-payment cap is all you need, you probably already have one.

What it cannot express, concretely. Forty payments of one cent pass every per-payment cap ever written. So do five identical purchases when only the sixth exhausts a daily total. The limit has no memory, so every decision is the first decision.

Type 2 · A cumulative envelope

Now the layer remembers. An envelope is a limit plus the consumption against it — a daily total, a monthly total, a per-counterparty ceiling over thirty days.

purchase 1: $0.01  APPROVE
purchase 2: $0.01  APPROVE   daily: $0.02 of $0.05 used
purchase 3: $0.01  APPROVE
purchase 4: $0.01  APPROVE
purchase 5: $0.01  APPROVE   daily: $0.05 of $0.05 — exhausted
purchase 6: $0.01  REVIEW    ← binding: daily

The refused payment is byte-for-byte identical to the five approved before it. That outcome is unreachable for type 1 at any threshold — and it is worth being precise about why tightening does not substitute: lowering the per-payment ceiling to one cent would still admit all six, and would refuse every legitimate purchase above a cent.

Type 2 also introduces a question type 1 never has to answer: which limit bound? With four envelopes in play, “refused” is not actionable and “refused by the daily envelope, which has $0.00 headroom” is.

Type 3 · A governed budget

Everything above, plus the facts that are not amounts: who the counterparty is, what the agent was sent to do, and whose authority it acts under.

This is where a whole class of failure becomes catchable, and the cleanest example is one where every economic control is satisfied:

# an agent sent to buy market data buys a follower count instead.
# same amount. same counterparty. same resource shape.

treasury : ok=True  binding=nothing      ← affordable
trust    : 0.4800  no flags              ← counterparty is fine
risk     : 0.2100  no flags              ← nothing unusual
policy   : matched rule 'auto-approve-micro'
intent   : /social/followers is outside the intent's declared resources

REVIEW — attributed to: intent

Four controls say yes. One says no, and it is the only one that could — because nothing about the purchase is a money problem. No amount of tightening a budget catches this, which is the argument for declaring intent up front: without it, “within budget” and “doing the job” collapse into the same question, and they are not the same question.

Type 3 typically adds:

Intent

What the agent was sent to do, declared before it acts, with a budget and a scope. Drift becomes detectable.

Counterparty trust

Earned over settlements rather than asserted. A new counterparty is not a bad one, but it is not an established one either.

Identity & delegation

Who is acting, under whose authority — and a sub-agent that can never exceed its parent.

Attribution

Which control decided. With several controls able to refuse, this becomes the only actionable field in the record.

Type 4 · Behavioural

Everything above, plus the shape of a sequence rather than the size of any action.

Two attacks make the case, and neither is exotic:

No type-3 layer catches either, and Tesoro does not. It ships the structuring case as a runnable demonstration of its own gap rather than a paragraph about it — 40 payments, 0.08% of a daily envelope, nothing refused.

What would catch it is a control examining count, variance and distribution instead of magnitude: forty identical payments is not forty independent decisions. Every envelope in a type-3 layer answers how much, and the thing wrong with structuring is its shape.

Which type do you need?

If your situation isThen
one agent, one counterparty you chose, small amounts, a human watching Type 1 is honestly enough. Use what your SDK already ships
an agent running unattended, or repeatedly, against a budget that matters Type 2 minimum — a cap with no memory will not bound your total spend
an agent choosing its own counterparties, or sub-agents, or you need to explain a refusal later Type 3. This is where attribution and evidence start mattering
you have an adversary, or a regulator, or the sequence itself is the risk Type 4 — and nobody has built one. Be sceptical of claims otherwise

A note on reading vendor claims in this space, including this one: “spend limits” is used for all four types. The question that separates them is “can it refuse a payment that is individually within every limit?” — type 1 cannot, by construction.