On February 21, 2026, a Saturday, someone outside the company paid an agent $3.69 in USDC through the AGIRAILS kernel on Base mainnet. It came out the way the state machine says: 3.6531 to the provider, 0.036864 to the fee recipient, 0.000036 to the archive contract. One percent of 3.69 is 3.69 cents, against a five-cent floor. The published spec put that floor off-chain rather than in the contract and said so; the February kernel did not enforce it, and nothing off-chain charged it either. The first real fee the protocol ever charged was the first bug it ever showed me.
On June 21, in an internal swarm review on Base Sepolia with test USDC, two seed agents sent six $10 requests to exercise a rate limiter. Five were accepted, the sixth refused, three settled. Requests four and five moved to IN_PROGRESS and were never delivered: the public RPC had rate-limited the provider and dropped its event filter. The buyer tried to cancel, and the kernel answered with the string it was built for: "Cannot cancel after work started". No dispute could be opened from that state, and the only door out was the provider's own cancel. The provider was the thing that had stopped answering, so the money sat in the vault. The fix merged two days later and sits on Base Sepolia, not on mainnet.
Same eight states, same vault, same rule that nothing moves money except the kernel; what varied was whether the provider answered, and the kernel had no transition for silence. That is the team the standfirst means: me, my co-founder Justin Rooschuz, and a pipeline of coding agents. Most of the Solidity went through Claude Code before it went through me, written against a specification with a test attached to every finding, and that part held. The mistakes that could move money were in the glue I wired around it by hand.
What broke, across five internal review passes and the months since, sorts into four kinds: an open state with no door out, accounting that drifted at the edges, a referee that would sign whatever it was handed, and a client acting on its own picture of the server. None needs a blockchain, and each has a twin in any operation with a rulebook and a front desk. One recorded settlement is the whole of what mainnet proves; the rest was learned on a testnet or in a review.
You are not going to deploy any of this. You already run the same four machines: work that waits on a person, prices that should apply as written, a queue where complaints get judged, and software acting on what it believes about another system. Each leaks where mine did, with nobody writing it down.
The claims, corrected
The loudest misstatements about AGIRAILS are in our own material.
"Audited." Our own kernel README calls the May 17 review an external source-level audit. It was internal: our own agents reading our own code, twelve actionable findings, all closed before the V3 redeploy. An external audit of the deployed bytecode has not been performed, and the public security page says so in three words: "Not yet performed." That correction was to a page under my own name.
"Formally verified." A formal-verification working paper exists, written by my co-founder and me. It applies sheaf cohomology to the ACTP specification, the result is H¹ = 0 on the 2-complex, and it covers the specification rather than the deployed bytecode, so it says nothing about the code that holds money. One mathematician, Björn Lenz, PhD, reviewed the first version, and one mathematician on a working paper is not review. It is unpublished, the preprint route was dropped in August, and none of it replaces an audit. A May draft sentence claimed the implementation inherits the guarantee, and we retracted it on May 18.
"Dispute system live." On mainnet, disputes run the earlier model: a bond, and resolution by the admin behind a 2-of-4 Safe, with an approved, timelocked mediator who may be paid from the split and cannot rule. The three-tier engine (AI intake, bond escalation, an optimistic-oracle backstop) is code-complete, and its bond and mediator contracts are deployed on Base Sepolia, where the capstone ran against a stand-in oracle. The evaluator service and real model inference are not live anywhere, and it needs a kernel redeploy to reach mainnet.
"Tests." The count in our own material has changed every time someone re-ran it, and the public testing page named a tool that was never run. So no test count appears below: a fixed finding leaves a test behind, which is why the number moves. The static-analysis triage ran the same way, 2,064 detector rows, each triaged with a written reason, and zero real findings beyond what the manual reviews had already caught. The row count is the least useful number on a security page.
Five words carry status from here on: mainnet (deployed on Base, real USDC), testnet (deployed on Base Sepolia, test USDC), source (code in a repository, not deployed), published (in an installable release) and plan (a document). "Live" on its own leaves out the place. Your ladder has the same shape with different rungs, from running in production down to described in a document. Take them to any vendor and to your own roadmap. Your equivalent of that README line is the slide that says "automated" about a process one person runs by hand on Fridays.
What the machine is
Four AGIRAILS contracts sit on Base mainnet, all deployed May 19, 2026: a kernel whose source is an exact match on Sourcify, a vault that moves USDC only on the kernel's instruction, a registry holding the reputation score, and an archive treasury taking a tenth of a percent of the fee, the 0.000036 in the receipt above. A 2-of-4 Safe holds the admin key. The SDKs on npm and PyPI are the part that gets updated. Every kernel line below is pinned at commit c34ec49, the source matching the deployed build.
The kernel's interface lists eight states: INITIATED, QUOTED, COMMITTED, IN_PROGRESS, DELIVERED, SETTLED, DISPUTED, CANCELLED. Transitions run forward; SETTLED and CANCELLED are the ends.
Escrow principal enters at COMMITTED and nowhere else. The funding call pulls USDC from the requester into the vault, which has no owner, no withdraw and no upgrade path, and whose every moving function is callable only by the kernel. The account nothing but the payment run can touch is the same idea.
From COMMITTED the requester has a door: after the deadline it can cancel, minus the penalty locked at creation. Delivery opens the second: the requester can settle at any time, and once the dispute window passes, anyone can; before it passes, only the requester. The window defaults to two days and accepts one hour to thirty days. That exit opens on a clock and needs nobody's key.
The fee is the greater of the locked rate and a five-cent floor, and the rate is one percent, hard-capped at five. Rates lock into each transaction at creation, and the fee rate re-locks if the buyer accepts a revised quote; once the escrow is funded none of them move. Changing a rate takes two days in public, and mechanic 2 is where that matters. The kernel caps a single transaction at one billion USDC, and the first one was $3.69.
The admin is a 2-of-4 Gnosis Safe. It can pause the kernel, rule on a dispute, and change the fee and penalty rates behind the two-day delay. Outside a dispute it cannot reach escrow: its one transfer function, an emergency recovery, moves only USDC stranded in the kernel, and only while the kernel is paused. Inside a dispute it can split the escrow between the parties and pay an approved mediator up to ten percent, under the constraints in mechanic 4. Either way it cannot direct a cent to itself. In your operation that is the person who can approve an exception and still not reach the bank account.
The kernel is not upgradeable: no proxy, no delegatecall, so every change is a redeploy of the kernel, its vault and everything wired to them, as the deployment record shows. The current kernel, V3, went out in May.
The limits, stated as limits: it holds no principal, changes no rule under a running transaction, and cannot be upgraded in place. The order-to-cash path in your business has states too, quoted through paid, disputed and cancelled. Write down, for each, who can move a job out of it without the other side answering.
It is plumbing. Good plumbing, but plumbing.
What I cannot vouch for
Our own threat model states the limits better than I would: its list of what ACTP does not protect against begins with "Provider delivering low-quality work" and "Off-chain identity claims". The document you probably do not have is the same thing for your operation: a dated list of what is done, half-done, and only described. Mine is six lines, each with a date and one of the five words.
- No external audit of the deployed bytecode has been performed, and no firm is engaged. Status: not done.
- The mainnet kernel is the May 19 build, and on it a disputed transaction has no on-chain clock. It waits for the admin, the only resolver the code names; a pause freezes dispute resolution too, and the cancel exit takes an empty proof. The judge is the two-of-four Safe I sign from, and the code makes the signers write the split down before it will pay anyone but the requester. Whether a dispute has ever been opened on mainnet I have not read, because free endpoints cap the log range. Status: mainnet, as is.
- The AI evaluator has never ruled on a real dispute with real models. Every testnet ruling used a scripted verdict, no accuracy data exists, and the service is not hosted anywhere. Status: testnet, mocked.
- The kernel's own pause is real and the Safe can call it. The monitoring around it, metrics and thresholds and the write-path flag, is a document I wrote in February. Status: plan.
- Reputation is one integer per address, 0 to 10,000: 70 percent a no-dispute rate, so a job delivered badly and never disputed counts as a success, 30 percent lifetime volume, no decay, only the provider scored, free registration, a brand-new agent scoring 7,000. Status: mainnet, as designed.
- This essay carries no usage evidence. Status: mainnet, one record.
The sharpest objection on record is in my own review file, and an outside one would be sharper. The internal production-readiness review of June 22, 2026 found no theft or solvency path at that checkpoint, liveness defects reproduced by passing proof-of-concept tests, and declined to certify a money-moving launch without an outside read. One of those defects is row four of the table below. Three weeks later another internal pass found a High that review had not seen, so a clean verdict carries the date it was written on, and mine expired in three weeks. The July 16 review concluded the v2 dispute stack was not ready for mainnet. I agreed, and on August 18 I parked the deploy so both ship as one redeploy, with the external-audit gate from June still unmet. Those reviews are internal: I can give you their dates and verdicts, not the files.
Every kernel fix in the table that is not on mainnet ships the same way: a redeploy of the kernel, the vault and everything wired to them, which puts fresh bytecode under the money on the day it lands. The SDK fixes ship on their own clock, and two of them already have. So the choice in August was between known liveness defects on a build two reviews have read, with no theft or solvency path found in either, and unknown defects in code nobody outside has read at all. I took the known ones. On August 18 I parked both the kernel and the dispute stack to ship as one redeploy, and the condition for unparking is written down and has not moved: an external audit of the final bytecode, on the combined build, before it holds a cent.
This essay tells you to buy an outside read of a system you own. I have not bought one for mine.
Your operational system should be changeable in an afternoon; mine cannot change without a redeploy, a constraint I chose so nobody can change the rules under a running job. The reason transfers; the constraint belongs to a contract nobody can patch.
What broke, and how it surfaced
Every row was caught by something cheaper than the failure it prevented, one of them for twenty dollars of test USDC. Where I have the cost of the fix, the cell says so; where the honest answer is only how it surfaced, it says that instead, because I did not track hours against any of these. Every fix carries a link you can open, and four of the seven were found in internal review files I cannot publish, so those cells carry the date.
| What broke | How it surfaced, and what the fix cost | Fix | Where the fix lives today | Twin in your operation |
|---|---|---|---|---|
| Accounting. The five-cent fee floor in the spec was charged by no layer. | First recorded mainnet settlement, February 21, 2026: one percent of $3.69 is 3.69 cents, so the protocol's own take came in 1.31 cents short. Cost: one receipt, read. | A minimum-fee constant in the V3 kernel. | mainnet (the constant) | A price-list minimum that invoicing never implemented. |
| Client picture. A buyer could lock its own money against a provider that would never accept the price. | Internal swarm review, Base Sepolia, June 21, 2026. Cost: the buyer's test wallet went 990 to 835, reclaimed after the deadline. | A price-band check before the funding call, at both call sites in both SDKs. | source; the npm and PyPI releases current on September 6, 2026 were tagged before the wiring commit | A purchase order raised before anyone checked the vendor's minimum. |
| Open state. A provider that stops answering leaves the buyer no exit from IN_PROGRESS. | Same review: six $10 test requests, five accepted, three settled, two stuck. Cost: two days to a merged fix, after five candidates were rejected. | A permissionless recovery call after the deadline plus an immutable grace, and a one-hour deadline floor; merged June 23, on Sepolia June 24. | testnet, grace one hour; mainnet V3 lacks it (the file at 08661f8, carried by the Sepolia kernel v2 of July 13) | A contractor gone quiet on a job marked "in progress": money committed, ticket unclosable. |
| Open state. A kernel pause also froze the way out of a dispute. | Internal readiness review, June 22, 2026. Cost: one proof-of-concept test. | A pause-exempt dispute exit; recovery functions carry no pause modifier. | testnet, kernel v2; on mainnet V3 a pause freezes dispute resolution (PoC test) | An emergency stop that locks the fire exit: freezing operations froze refunds. |
| Referee. The evaluator would sign a ruling over evidence supplied by one party alone. | Cost: one on-chain read, July 10, 2026, showing the delivered result's hash was never stored. | Result and agreement hashes anchored on-chain in kernel v2, checked byte by byte before inference. | testnet, Sepolia capstone of July 15, 2026, scripted verdicts; real model clients not live (ruling tx) | Judging a complaint from the complainant's copy of the order. |
| Client picture. The release pipeline was as strong as one laptop and one npm token. | Internal agentic audit pass, May 17, 2026. Cost: one finding, against every earlier release going out from a laptop. | Tag-driven workflow, trusted-publisher OIDC, sigstore signature, SLSA provenance. | published on npm, checkable from the registry (publish.yml) | If anyone with the password can change the invoice template, that laptop is your supply chain. |
| Client picture. The block sweep asked a free-tier RPC for 7,200 blocks; the tier allowed 10; the agent crashed. | Running a seed agent on Base Sepolia, June 2026, on a free tier whose terms I had not read. Cost: one crashed agent, closed by a June 12 commit. | The sweep chunks to any cap, and daemons can widen the poll interval on metered RPCs. | published, in the June releases (sdk-js 5177799) | The bank feed, the card processor, the freight-rate API: a rate limit nobody read. |
Of the seven, one is on mainnet, three are on testnet, two are in a published release, and one is in SDK source. The count is mine; the status column is the source.
A redeploy is more than one contract. The V3 redeploy on May 19 was four contracts and 0.000058 ETH of gas, plus paymaster allowlists on two vendors that I redid by hand and five downstream packages re-released within a day so SDK-fed addresses moved with the kernel. The Python SDK took five more days and pointed at the superseded kernel until it landed, and an installed Claude Code plugin never updates itself. The gas was the cheapest line on the bill; the rest of the cost was a person remembering a list. The ERP change window is your version, and your re-pointing list is everything aimed at the system being replaced: integrations, templates, the bookkeeper's macro.
What I would not build again
A fee-taking relay contract for instant payments. It took a fee on x402 calls. It is deprecated, off the SDK path, absent from the V3 record, and the one still on Base Sepolia carries a deprecation note and points at a replaced kernel. Instant API payments now go buyer to seller through the SDK's adapter router, and the protocol takes nothing on them. Escrow is for work that takes time or can be disputed. Somewhere in your P&L there is an internal charge nobody could justify once someone asked what it was for.
A default test amount sitting on the fee floor. The first receipt from the SDK's own test command read earned $0, because the default amount was five cents and so was the floor. The default is now $10, where the fee reads $0.10 and the net $9.90. Demo data that makes the report look broken to the first customer who runs it is the same mistake.
Publishing from a laptop. Every npm release before May 19, 2026 went out that way. Since then a workflow builds each one from a tag, which is row six of the table. One person able to change your invoice template from anywhere is the same exposure.
Documenting behaviour before it is deployed. The docs FAQ described a dispute path from a stalled job (provider goes silent, consumer opens a dispute, mediator decides) that the kernel has never had; its transition table has no edge from IN_PROGRESS to DISPUTED. The corrected page waits on a branch until the recovery path ships, and the old one was still up on the date at the top of this page. An SOP describing a process that does not run yet fails the same way.
Two coding-agent sessions on one working tree. They wiped uncommitted work once. One tree per session and explicit branch ownership since. Two people in one spreadsheet in two windows lose work the same way.
When this is the wrong buy
Each mechanic below is also the wrong install at some size, and one of these four probably describes yours.
Counterparties who are humans with contracts. Invoice terms and a signed contract cover most of this, and cost nothing to run. If you can sit across a table from the other party, enforcement is a phone call before it is a clause, and a hold-and-release step buys you little the relationship does not already. It earns its keep at the edges: a counterparty you have never met, or an exposure large enough that the relationship is not the collateral.
A settlement cycle that closes the same day. The router comment linked above says it: for escrow protection, pay an address rather than a URL. If the money changes hands the day the work does, the hold has no job. The dispute path still does, and that one is a queue with a rule, not an escrow.
A formal artifact as the first move. The working paper cost months and says nothing about the deployed code. A written state diagram with every exit listed does most of that work in an afternoon.
Automated judgment where a human queue is cheaper. The dispute recipe tells every integrator to "Surface to a human queue", and the three-tier engine is built for a dispute load a small operation does not have. The email-escrow case page, a demo on Base Sepolia with test USDC, releases the money on a human reply of APPROVE. Below a dispute volume you can name, that human step is the better design.
Most operations need none of it. The table's last column tells you which parts, if any, apply to yours.
Six mechanics that transfer
1. A clock and a door on every open state, and a stop that leaves the door open. On mainnet, settlement after the dispute window is permissionless. On testnet, the stalled-job recovery does the same for a job that never reached delivery: after the deadline plus an immutable grace, anyone can move it to CANCELLED with a full refund. Five candidate fixes were rejected first, each of them handing the requester a clawback; the one that held is one immutable constant and one permissionless function.
The stop matters as much as the door. A pause on mainnet blocks state changes and leaves fund recovery open; after a June review found it also locked the way out of a dispute, the testnet recovery functions carry no pause modifier.
Every state where money or work waits on a person gets a date and an automatic outcome: the unapproved invoice at day fourteen, the unanswered change request at day seven. Find the status in your pipeline whose only exit is the other side answering, then check how long the oldest job has sat in it.
2. Freeze the rules at order time; change them slowly, in public. The fee, penalty and dispute-bond rates are locked into each transaction at creation. A change to the fee or the penalty is scheduled in public, waits two days, and is then executable by anyone, so no rate moves under a running job and the admin cannot schedule a change and sit on it. The kernel timelocks even its own registry swap. Row one of the table is where this broke: the spec put the floor off-chain on purpose and said so, and nothing off-chain applied it. The rule was frozen in the wrong layer, and the first mainnet receipt is where that showed. In your operation, the price list and refund policy that applied when the order was placed are the ones that apply, and changes carry a date.
3. Guard every place money can leave, and then the second place. In SDK source, the buyer-side price-band check reads the provider's published band and refuses an out-of-band amount before capital moves. It sits at both call sites where the client can commit funds, because a multi-round counter can land out of band. The TypeScript fix went in first and a grep said the Python port was clean; when I opened both call sites the first was guarded and the second was not. I closed the map at two guarded sites per client, no third. It fails open without a registry or on an RPC error, and the table says which releases carry it. List every path in your operation by which a commitment can be made (a quote, a purchase order, a verbal yes from the founder) and put the check on each.
4. Judge the exhibit against the receipt, and refuse an empty ruling. On mainnet, settling a dispute requires an explicit ruling: the contract rejects an empty proof and requires the split to equal the remaining escrow, in its own words, "Dispute resolution requires explicit proof" and "Must distribute ALL funds". The cancel exit from the same state does not carry that check; it refunds the requester in full. A dispute costs a bond, five percent with a one-dollar floor, returned to whoever was right.
On testnet, kernel v2 anchors the agreement hash at creation and the result hash at delivery, and a server-side check verifies every judged byte against them before any model runs. In a local capstone run on July 11, sixteen tampered bundles died before a model ran, billing nothing. Your complaint queue has the same four fields whether or not you have written them down: what it costs to open one, what a ruling must contain before money moves, who rules, and what happens when the ruler is away for a week. The file you judge is the one that was delivered, proven by the hash or the delivery note from that day; a complaint is evidence, never an instruction to whoever judges it.
5. Verify the summary against the artifact, and turn every finding into a test. The claim that the Python SDK matched the TypeScript one fell apart against the contract ABI: a nineteen-field read of a twenty-one-field transaction view would have put a locked rate field where the agent identity belonged. Golden vectors generated from the real TypeScript functions now keep every hashed and signed surface from drifting.
I wrote the kernel, the two SDKs, the launchpad and the docs through the agent pipeline; Justin is the security lead, QA and reviewer of the core, and an independent builder at the edge. The July review found its Highs in the services around the contracts rather than in the contracts, and the invariants that failed that month were the off-chain ones, fixed in source, none of the fixes deployed.
I have written down that research agents are summaries because I locked a plan on one, and the plan was wrong. Consultants and dashboards are summaries too; before a decision, someone opens the artifact, the contract or the bank export or the ticket, and checks the field. The agent-written SOP or macro needs a reader with the authority to say no before it touches an invoice. An SOP that names no reader has already left the decision with the agent.
6. Fail closed and bill nothing. In source, the evaluator's production boot refuses to start without real model clients rather than sign mock verdicts with real keys, and it is not hosted anywhere. On npm, the CLI can downgrade to testnet from a flag and never escalate to mainnet. It held through the failed capstone runs on Base Sepolia in July: infrastructure failures, zero inference billed. It did not hold on the block sweep, which asked a free tier for more blocks than its terms allowed and crashed the agent. When the inputs cannot be verified, a system should stop before it spends anything metered. List the four outside services you cannot invoice without, and for each write down its rate limit, its lag, and what your system does when it answers 403. Where the answer is that it crashes, that is this week's work.
Telling a fixed system from a described one
Every tell below was true of our own material at some point this year, which is how I know what they look like. Some still are, and each item says which.
Tells that a system is only described:
- "Audited" with no firm, no date, no scope. Ask a vendor for a page saying what has and has not been done, with a date. The May review was internal and our README calls it external; ours is the page I mean.
- A status word, or a count, without a place and a date. Ask which build a number was counted on. "Live" is a claim about somewhere, and the badge on our README was counted two redeploys ago.
- An open state with no clock and no door. Ask who can move a job out of each of yours without the other side answering. On mainnet a disputed transaction waits for a human with no on-chain deadline, and the artifact is one line of the kernel, "Resolver only". That row is ours.
- A fix in the documentation before it is in the system. Ask to watch the process run rather than read the SOP describing it. Our FAQ described a dispute path the kernel has never had, and it was still up on the date at the top of this page.
- An off switch that is a document. Ask for the flag name and the date of the last dry run. Ours is a February plan with a five-minute activation target, and the flag exists nowhere but the plans.
- A check that cannot fail.
grep PATTERN file | head -1 && echo okprints ok on an empty match: the check passed and checked nothing. Ask when a check in your operation last said no, and what happened next. Our receipt endpoint returned verified: true for a testnet receipt only after a backfill fixed a null hash.
Tells that a fix landed:
- A test named after a bug. Ask a vendor to name their last incident and show the check that runs because of it. Every fixed kernel finding left a regression test, so the bug report is executable; the one that proved a pause could lock the dispute exit is in row four.
- Changes that wait, in public. Ask when your price list last changed and who could have changed it that morning. Fee and penalty changes here are scheduled, wait two days, and anyone may execute them.
- Provenance you can check yourself. Ask who can change a template that touches money, and what record the change leaves. Every npm release since May 19, 2026 carries a sigstore attestation naming the workflow and commit that built it, readable without installing anything.
- A gap list that includes the author. Pair every "what is done" list with a dated "what is not". Most of the fixes in the table are not on mainnet, and it says so.
What to leave
No outside firm has read the bytecode that holds real money, and most of the kernel fixes in the table are still waiting on the redeploy that follows one. Both sit in the list above, dated.
Six decisions come out of the six mechanics: a clock and a door on every state where work or money waits on a person; rules frozen at order time and changed slowly, in public; a guard on every path to a commitment, and then on the second; a ruling that cannot be empty, judged against the delivered file; one named reader who can say no to what an agent wrote; and a system that stops and bills nothing when it cannot verify its inputs. Those six run on the four machines you already have.
Back to the two transactions. One for $3.69 in February that cleared and charged a fee the spec said could not exist. Two for $10 each on a testnet in June that sat in IN_PROGRESS with no way out. Between February and August the kernel gained a deadline floor, a grace period and a pause-proof exit, on testnet, waiting for the redeploy.
Take a sheet of paper. Left column, every state a job can sit in. Right column, who can move it out without the other side answering. A name in the right column is often the right answer, and a judgment call worth paying for should have one. Then ask the three questions the name has to survive: by when, who instead when that person is away for a week, and what happens on its own if neither answers. Wherever a name has no clock, no substitute and no default, the rule is unwritten and the name is carrying it. That is the line item to fix first. The thing that decided both of my transactions is the thing that decides yours: whether the money has a door out that opens on a clock and needs nobody's key.
Mercury Consulting, which publishes this, sells the fixed-fee operational diagnostic this essay argues for ($15,000 to $25,000, four to eight weeks), and deliberately limits concurrent engagements so the senior team that diagnoses is the team that builds. I co-founded AGIRAILS; it is not a Mercury client. Weigh the argument with that in mind.
