AI but make it real

DEMO 1 OF 3 · RUNS ENTIRELY IN THIS TAB

A policy gate that fails closed

Multi-agent systems get bought on what they can do and killed on what they cannot prove they refused. This is the governor out of my agent-mesh project, lifted into the browser so you can attack it yourself.

Every delivery between agents is evaluated before it lands. The default is deny. A message goes through because a rule said yes, never because no rule said no. Edit the policy, compose a message, and watch it get refused with a named rule and a receipt.

Try to break it

Each button loads a real attack. The last one is a bug that shipped in my own code and passed review.

The message

The ledger, append only

Nothing evaluated yet.

The policy

The line that carries the whole thing

Load the preset "the bracket typo" above. It changes "mayIntent": ["deliver"] to "mayIntent": "deliver". Two characters, one pair of brackets. The comment in the original source calls it a one character typo, which is wrong by one, and it is corrected here rather than repeated because a page about precision does not get to round its own war story.

An allowlist checked with a plain truthiness test still passes, because in JavaScript "deliver".includes("deliver") is true. The allowlist quietly becomes a substring match, so "request" would also permit the intent "req". That is the exact inversion of the only guarantee the component exists to provide, produced by a config typo, in a file a human edits by hand.

WHAT SHIPPED FIRSTif (!from.mayIntent.includes(intent))
  return deny(...)

Passes. Fails open.
WHAT SHIPS NOWif (!Array.isArray(from.mayIntent))
  return deny('bad-policy', ...)

Denies. Fails closed.

Found by an adversarial review pass, reproduced against the pre-fix code, then pinned by a regression test so it cannot come back. The point of this demo is not that the gate works. It is that I can show you the day it did not.

What is real here and what is not

Real: the evaluation logic is a direct port of src/governor.js from agent-mesh, rule names and refusal messages included. The default-deny ordering, the clearance comparison, and both Array.isArray guards behave exactly as they do in the shipped tool.

Synthetic: the five personas are a sample team, not a real organization. No client data, no employer material, and no personal information appears anywhere in this page.

Not included: the file system layer. The real tool writes each message as a JSON file with atomic write-temp-then-rename, keeps an inbox and an outbox per persona, and appends every decision to a JSONL ledger on disk. A browser tab cannot honestly do that, so it does not pretend to. The ledger above lives in memory and is gone when you close the tab.