Inspiration

An autonomous agent spent $8,000 on two online courses. Not a bug: it read the content, decided it was useful, and paid. Valid card on file, no approval step, no human in the loop. Link: https://www.reddit.com/r/SaaS/comments/1qzmldt/an_ai_agent_spent_8000_on_courses_by_mistake_your/

The purchase was under the spending limit. That's the part worth sitting with.

A fixed cap asks exactly one question: is this transaction under the number? It doesn't know the agent normally spends $200, has never used this seller, or was told to buy this by text an attacker hid in a webpage. It can't see a retry loop spending $40 forty times, because every charge looks ordinary. It can't see a subscription signed up for one afternoon's task and never cancelled.

I work in credit risk. Deciding how much to trust someone with money, based on what they've actually done, is my job. Nobody was doing it for agents — so every agent wallet on the market ships with a number a human guessed once and never revisited.

What it does

Link to Slides: https://docs.google.com/presentation/d/1wCFcrlnIUXCIqP4tp0aBV6sT7vHT-rxRZLn-V5-Kcxk/edit?usp=sharing

Demo Link: https://github.com/venvennnn/underwritten_autonomy/blob/main/underwritten-autonomy-demo.html (click on the 90s path please)

Github Link: https://github.com/venvennnn/underwritten_autonomy

Authorization asks whether an agent can spend. Underwriting asks how much it should be trusted to spend right now.

Underwritten Autonomy computes an agent's spending capacity from its own observed behaviour, and recomputes it on every request.

Two layers, and the split is load-bearing:

Hard gates: allowed categories, expiry, remaining budget, per-transaction ceiling. Deterministic, evaluated first, no model involved. These bound the maximum possible loss and are designed for on-chain enforcement through a scoped delegation on a smart account.

The risk engine sits inside that envelope and can only ever tighten capacity, never loosen it. It bounds the expected loss. Because it can only tighten, a model failure degrades to an ordinary static limit — never to unbounded exposure. It can't do worse than the status quo.

Capacity starts from robust statistics on the agent's own history (median, MAD, P90), then takes banded multiplicative haircuts across eight factors: transaction deviation, 24-hour burn rate, request frequency, grant pacing, counterparty novelty, spend concentration, stability, and history depth.

Three agents on identical infrastructure end up with three different limits: $133, $201, and $20 per transaction. Nobody typed those numbers.

Every escalation states why, in plain language, and each reason code carries the computed feature value, the band it fell into, and its multiplier. The text is rendered from the numbers, so a justification can't be invented. That pattern is borrowed directly from adverse-action notices in consumer lending.

How we built it

The engine. Python. A frozen scorecard, hard gates evaluated before any scoring, and reason codes that dereference to computed values.

The traffic simulator. No public dataset contains autonomous agent spending, so we generate it: parameterised, never scripted. Three personas (stable procurement, volatile research, high-frequency micro-ops), lognormal amounts, diurnal Poisson arrivals, and counterparties drawn from a Chinese Restaurant Process so vendor-novelty rate emerges from one parameter rather than being a number we picked.

Four adverse processes: runaway retry loop, prompt-injection hijack, zombie subscription, and a slow drain deliberately built to evade our own controls.

And the part that mattered most: three confounders: legitimate traffic that looks adverse. Quarter-end bulk buys, genuine growth, real new-supplier onboarding. Without a cost side, an escalation rate means nothing.

The evaluation. Replays traffic through six arms: a static cap, a static cap with a circuit breaker, our engine, gates-only, velocity-only, and deviation-only. Measures leakage (unauthorised dollars released before the control engages), time-to-containment, escalation rate on clean traffic, and autonomy rate.

Anti-circularity, taken seriously. The scorecard bands were frozen in a dated, tagged commit before the generator existed: bands-v1.0, commit d927759, 2026-08-11, checkable in the git history. Adverse behaviour is injected as a sampled process, not a hand-written transaction list. One adverse class was built specifically to beat us. A control study that only catches what it planted isn't a study.

Results

Mean leakage across the three agents: static cap $1,655 · static + circuit breaker $825 · underwritten $371. Clean autonomy holds at 73.7%.

Agent Leakage Clean escalation Autonomy
Procurement $310 27.0% 73.0%
Research $736 23.5% 71.9%
Micro-ops $65 23.7% 76.3%

All figures are from evaluate.py on simulated traffic.

Challenges we ran into

Our three scorecard versions aren't a ladder from broken to fixed — they're points on a trade-off frontier. v0.1 was permissive: 11.0% escalation, $545 mean leakage. v0.3 cuts leakage by a third and costs fourteen points of escalation. Which point you choose is a policy decision, not a modelling one. We report all three rather than presenting a single tuned number.

The sharper problem came out of the ablation, and it wasn't what we expected.

On our two stable personas, velocity alone matches the full eight-factor scorecard exactly — to the cent. $310 leakage for procurement, $65 for micro-ops, identical either way. But the full scorecard escalates 27.0% and 23.7% of legitimate traffic where velocity alone escalates 12.0% and 10.5%. Six factors charge a human interruption and return no containment whatsoever.

On the volatile research agent, those factors earn their keep: velocity alone leaks $2,197 against the full scorecard's $736.

So factor value is persona-dependent. A stable, predictable agent needs velocity detection and little else. A volatile, novelty-seeking one needs the whole scorecard. A single fixed scorecard applied to a mixed fleet is paying escalation cost on the agents that don't need it.

Two honest caveats we'd rather state than have found: the τ frontier is non-monotonic because it's a single-seed sweep, and gates_only leaks more than the static cap ($6,347 vs $2,484) — correct, because gates bound the envelope and don't police behaviour inside it.

Accomplishments that we're proud of

A working risk engine, a traffic simulator with a genuine cost side, and an evaluation rigorous enough to tell us that most of our own scorecard is dead weight on most of our agents.

Almost every control demo reports detection. Very few report what the control costs when it's wrong, and fewer still run the ablation that shows which components actually earn their place. That asymmetry is how unusable systems ship.

What we learned

Injection is contained by the scope gate, not by the risk model. The strongest containment in the system needs no statistics at all — the purchase simply isn't in an authorised category. Knowing which failures need a model and which need a rule is most of the design.

A control with no measured cost side is not evaluated. It's demonstrated.

Underwriting without loss history is a solved problem in credit risk. No agent-spend loss history exists yet, which is exactly why controls have to be built now. You use a documented expert-judgment scorecard with conservative caps and a recalibration path — standard practice for a new portfolio.

What's next

Persona-aware scorecards. The ablation says one scorecard for all agents is wrong. Factor sets should be selected per behavioural profile.

Stage 2: the grant contract enforcing the hard gates through scoped delegation on a smart account, a live agent loop settling in testnet stablecoin, and an end-to-end prompt-injection demonstration.

Recalibration. Every human override is a labelled example telling us where the bands are too tight. Over a few hundred decisions that becomes the loss history that doesn't exist yet, generated as a byproduct of operating.

Portfolio-level exposure. Six agents each spending within their own limits can still collectively drain a treasury or concentrate on one counterparty. Standard risk practice; nobody in agent payments is doing it.


Note: Everything measured here is on simulated traffic. Stage 1 is a validated risk engine; Stage 2 is the on-chain enforcement layer. Agent payment rails are shipping now — every one of them controls spend with a fixed cap.

Built With

Share this project:

Updates

Submission history