Limulus · product summary · September 2026

Test tells you where the agent breaks. Protect covers exactly that.

Limulus is payment assurance for AI agents. Four stages — test, qualify, protect, monitor — but they are not a pipeline with four vendors' worth of features. Two of them are one mechanism used twice, and that is the whole idea.

Prototype · Increase sandbox · no production traffic

The argument

Why testing and protecting are the same product

Everyone building in this space sells one of the two. Eval companies test agents and hand you a score. Control companies sit in the payment path and block things. Each is weak alone, and weak in a way the other fixes.

Testing alone fails because

A score is a snapshot of one configuration. Change the prompt, the model, or one tool description and the score is stale — but nothing stops the agent paying. We measured this directly: swapping a frontier model for a small one took duplicate detection from mostly caught to never caught, and that swap is a cost decision someone makes without re-testing.

Protecting alone fails because

A gate configured without evidence guesses at which checks to require. Guess too loose and it misses the real failure. Guess too tight and it blocks correct payments — at which point somebody switches it off, and takes the useful checks with it. You cannot tune a gate you have no failure data for.

So the two run as a loop, and each leg of it does real work:

Test finds the weakness · Qualify writes it down as a bounded permission
Protect enforces that bound on every payment · Monitor finds what neither predicted

The gate is what makes testing honest, and testing is what makes the gate trustworthy.

You can only run 56 adversarial scenarios against a live agent because nothing settles — every payment is created frozen. And the gate only requires the right checks because the Lab showed which ones actually fire. Remove either and the other stops working.

Three concrete couplings

The four stages

What each one takes in, and what it hands to the next

01

Test — break it where no money moves

The agent runs 56 scenarios in a simulated world: forged approvals, bank details changed inside a PDF, invoices already settled, a rail that times out mid-submit. Graded on the tool calls it made, never on the explanation it wrote afterwards — an agent that narrates good behaviour and pays anyway scores zero.

Four axes are scored separately because they trade off. Capability matters as much as safety: an agent that refuses everything is perfectly safe and completely useless, and scoring it on safety alone would call it ready.

inThe agent, its prompt, its tools, its version
outSafety, capability, recovery, reliability — plus a sealed run whose hash names that exact configuration
02

Qualify — permission with edges on it

A passing agent earns a signed qualification: a workflow, a rail, a currency, a ceiling, a payee scope, an expiry. It is bound to the agent version and proven by an API key issued to that version — not by what the agent asserts about itself. An asserted identity yields identity_unverified and escalates rather than releasing.

It expires: 30 days autonomous, 90 supervised, 180 shadow. A new agent version starts at the bottom. And there is deliberately no tool an agent can call to widen its own authority — no set_policy, no issue_qualification. An agent that can grant itself permission has no permission system.

inA sealed run and its four scores
outOne of five readiness rungs, and a scope the gate can enforce mechanically
03

Protect — held before it is checked

This is the ordering that makes it a control rather than an opinion. The transfer is created at the bank first, with approval required, so it expires unsent rather than settling. Only then are the three records compared: what a person authorized, what the agent declared it was doing, and what it actually submitted.

Four verdicts, not two. ALLOW releases. BLOCK cancels — leaving no ledger entry at all, so there is nothing to reverse. ESCALATE holds for a person. And WAIT exists for the case that actually causes double payments: a duplicate the rail has not confirmed yet. A retrying agent told "no" invents a workaround; told "wait 30 seconds", it waits.

inAuthorization × declaration × payment order, plus the qualification
outA verdict, a stable explanation code, and a signed receipt in a hash chain
04

Monitor — ask the bank, not the customer

Every transfer is pulled from the rail and matched against the decision behind it. Four kinds of drift: unauthorized, unknown_payment, released_but_cancelled, amount_mismatch.

The one that matters is money that moved although we never released it — because that is the one nobody would think to report. We tested it by going around our own gate: we let a payment escalate, then approved it directly at Increase, the way an insider or a misconfigured job would. Reconciliation named it on the next pass.

inThe rail's own record of what settled
outNamed drift — and new scenarios for the Lab, closing the loop
Evidence

What we actually measured

Real agents against an ordinary payments API with no checks in it. Outcomes read from the records each side wrote — never from the agent's own account of what it did, which was one of our early mistakes.

The central finding

Scenario familyFrontier modelSmall model
Fraud and judgment traps
hidden bank changes, forged approvals, fake CFO, lookalike vendors
0 / 60 lost0/5 · but no work done
Invoice already paid in full0 / 55 / 5 paid
Retainer billed twice, no shared reference10 / 20 paid5 / 5 paid
Whole queue, trap at position eight15/65 lost · 0 halts32/50 lost · 18 halts

Models are good at judgment and bad at bookkeeping. The gate is bookkeeping.

Zero losses in sixty fraud trials. The threat the whole category sells against is the one current models already handle. Every loss we could actually produce was a reconciliation failure.

The gate against the same scenarios

MeasureResultWhy it matters
Duplicates blocked19 / 19The failure models cannot catch, caught mechanically
Legitimate payments blocked0 / 9Friction is what gets a control switched off
Checks passing in the Increase sandbox14 / 14Increase sandbox: allow→submitted, block→canceled, escalate→pending_approval
Ledger entries left by a block0Nothing to reverse, nothing to claw back
Bypass detectedyesApproved a held transfer directly at the bank; reconciliation named it

From the decision chain

513 decisions so far — 234 released, 238 held, 41 escalated — across 4,710 individual checks (4,157 pass, 431 fail, 65 not required, 57 sent to review). The checks that actually fire, in order: payee_account 124, duplicate 102, embedded_instructions 101, similar_recent_payment 91, invoice_approved 55.

That ranking is the loop working. Those are the checks the Lab predicted would matter, and they are the checks doing the work in production.

Limits

What we are not claiming

  • No customers and no production traffic. Everything above ran against the Increase sandbox. Every vendor, invoice and account is invented.
  • Small samples lie, including ours. The duplicate retainer failed 5/5 in two separate runs. At twenty trials the real rate is half. Both samples agreed with each other and both were wrong — five trials only detects failure rates above roughly 40%.
  • We made eight measurement mistakes. Every one of them made the product look worse than it was: reusing an invoice across trials so trial two was a duplicate of trial one; an empty sandbox balance logged as gate refusals; reading outcomes from agent prose so "asking about" an account counted as paying it. They are all written down.
  • Nineteen scenarios still need rewriting by hand. They convert badly into the simulated world, so they are excluded from the pack and named in the source rather than quietly dropped.
  • The hard part ahead is not technical. It is whether a finance team will put a gate in front of an agent before they have been burned once.