npm run v2
The policy, compiled from what the agent actually did.
An accounts-payable agent ran for six months under a wide policy. Its intent trail was read back from the chain, the first 80% went through the nyaya synthesiser, and the result was written to a fresh key. Below: the policy as sentences, the 20% it never saw replayed through it, and ten attacks. Switch a rule off and see what gets through.
Two numbers, with their denominators.
A policy that cannot state these is a guess. Coverage is measured on calls the compiler never saw. Both numbers were computed on chain by simulate(), and every refusal was cross-checked against execute() reverting with the same code.
The catch rate needs a denominator, so here it is. Eight of the ten attacks are refused by the wide hand-written policy the agent ran under during shadow mode, before the compiler does anything at all — an unknown payee, an approval over the cap, a call into the account itself. Those were caught by an allowlist, not by learning. Two of the ten are attributable to compiling the policy: the 100,000 USDT payment the learned ceiling refuses, and the router function the agent never used. The demo prints both figures on every run.
honest held-out calls allowed. Every refusal of an honest call is a cost the owner pays in a human being paged.
attacks refused before any gas was spent, with the reason in words.
calls compiled from, calls held out. Six simulated months, seeded, so the run is the same every time.
And every one of those ten attacks crosses a line. None of them stays inside the policy, which is the case worth testing — so the demo tests it too. A payment to a payee the policy already trusts, just under the hourly ceiling, at the permitted rate, timed to miss the learned habits (which is easy, because the habits are published on this page for a person to read) moves 208,000 USDT in 52 calls over four days. Every call allowed. The guardian flags none of them. Nothing there is a bypass; it is the policy working exactly as written. A bound over who, what and how much per hour cannot tell an honest hour from a dishonest one, and that is the boundary of what compiling behaviour into bounds can buy.
Every rule, the evidence that earned it, and what enforces it.
Bounds are what the agent never exceeded, with 25% headroom, and they map one-to-one onto the account's on-chain policy. Learned sentences are habits the synthesiser found that the contract cannot enforce today; they are what a guardian watches for. Click a bound to switch it off; the two numbers above are recomputed by a mirror of the contract's evaluation, in this page.
Ten attacks, and what the compiled policy said.
Each is a call the agent, once hijacked, genuinely wants to make. The verdict column follows the switches above.
| attack | the call | instruction | verdict |
|---|
The held-out calls, replayed.
The last 20% of the trail, in order, through the policy compiled from the first 80%.
| when | the call | instruction | verdict |
|---|
The habits the contract cannot enforce, and who watches them.
Learned sentences are monitor-only. A guardian key reads every call against them with client/monitor.js, the same bands the compiler used, and can stop the agent but never spend. The run below is that guardian at work.
How the run works, and how to run it.
Shadow
The agent pays three suppliers, funds payroll on the first, and tops up USDC through a router on the fifth, for 182 simulated days, under a policy wide enough to let it work. Every call lands on chain through the account with a hash of the instruction behind it.
Export
The intent trail is read back from the chain's
IntentExecutedevents, each transaction decoded, and the prompt log joined to it on the intent hash. Nothing in the compiler sees the agent's code.Compile
Bounds come from what the agent never exceeded. Habits come from the nyaya synthesiser, the same search that learns game rules and phone-message rules, pointed at (context, payee) and (payee, amount). A rule survives only with at least four cases and 90% precision, re-scored against everything.
Apply and measure
The policy is written to a fresh agent key with owner-only calls. The held-out calls are replayed at their original spacing, then ten attacks. Coverage and catch rate come from the chain, not from the compiler's opinion of itself.
What this run does not show.
- The trail is simulated. Seeded, regular, and friendlier than a real ledger. A real agent's six months will have exceptions the bounds would refuse, and coverage below 100% is the expected result there, not a defect.
- Shadow mode is not zero policy. Rein needs a payee list to run at all, so the owner listed everyone the agent might pay. The compiler still had to find the list, the ceilings and the habits on its own.
- Learned habits are monitor-only. Time of day and per-payee amounts are not in the contract today. Putting them there is the v2 contract work, and it is not done.
- Headroom is a choice. 25% above the observed hourly maximum. Less headroom, more refusals of honest calls; more headroom, a larger loss when the payee list is wrong. The number is a dial, and it is printed, not hidden.
- Local chain. This run is on the in-process Hardhat network. The account contract is the same bytecode that is verified on Base Sepolia and Whitechain Sepolia.