$ myla ~/how-its-built
The AI explains.
It never decides.
A control you can’t reproduce isn’t a control. Myla’s verdict is a pure function of the agent, the tool and the arguments — the same inputs give the same answer every time, and no language model is consulted to reach it. Every claim on this page is checkable against the code, and where something doesn’t hold yet, it says so.
The decision path
An agent asks
tool + arguments
evaluatePolicy
a pure function
A verdict
allow · ask · block
The ledger
append-only
The model
Receives the verdict after it is decided, and writes the plain-words explanation. Read-only to everything above it.
There is no arrow from the model back into the verdict.
Prompt injection can change what Myla says; it cannot change what Myla allows.
$ myla ~/verdict
01 · The verdict
evaluatePolicy takes the agent, the tool and the arguments and returns allow, ask or block. It reads no network, no database and no model — the reasons it records are fixed strings in that one file. Three properties hold by construction:
Deny by default.
A tool that is not in the agent’s allowed list is blocked (NOT_ALLOWED). A newly issued agent has an empty list, so it is allowed nothing until you widen it — access is something you grant, never something you forget to remove.
A safety property the code enforces, not one it remembers.
The config-block door is observe-only today. The one place a fail-open “allow” is minted runs this assertion first, so “enforcement on, yet allowing on failure” cannot be expressed — the day enforcement ships, the same code throws, which the editor adapters read as a block. Fail closed, by a line that raises, not by someone remembering to.
export const OBSERVE_ONLY_FAIL_OPEN = true
export function assertObserveFailOpen(observeOnly: boolean): void {
if (!observeOnly) throw new Error(
'gate hook fail-open reached with enforcement on — refusing to allow')
}$ myla ~/context
02 · What the model sees
The model is used to explain, so it is given context — but a bounded, allow-listed context, every value passed through a sanitizer and an injection scan first. The sent column below is generated at build time from the exact allow-list the code uses (EV_ALLOW), so it cannot drift from what actually ships.
SENT (per finding)
- repo
- path
- package
- dev_dependency
- osv
- aliases
- commit
- committed_at
- still_in_current_code
- deleted_but_in_history
- redacted
- secret_type
- org
- setting
- value
- job
- trigger
- category
- count
- scope
- first_safe_version
- affected_range
- advisories_matched
NEVER SENT
- file contents
- the value of a secret — only its redacted first 4 chars + type
- database rows
- message bodies, subjects or attachments
- anything, ever, for training
Myla is held to her own Gate: an action tool is offered only when your latest message asks for that kind of action, and anything that changes state produces a signed, short-lived confirmation you tap — nothing runs until you do. She drafts; you decide.
$ myla ~/credentials
03 · Credentials
Myla holds the keys so it does not have to hope the agent behaves. Four properties, each in the code:
- 01A token that cannot write. Every permission the installation has is downscoped to read, the token is minted fresh for one scan, and it is held in memory only — never stored, logged, or sent to the browser.
- 02Write only on your tap. Opening a fix mints a separate token with exactly the permissions that fix needs, restricted to the one named repository — never the default branch, never a force-update.
- 03Bound to the exact call. An approval is bound to a hash of the agent, the tool and the canonicalised arguments, so an “allow” for one action can’t be replayed against a different one.
- 04Consumed once, atomically. The retry that spends an approval flips its row from approved to consumed in a single compare-and-set; only the update that wins grants the allow, so it can be used exactly once even under concurrent retries.
args_hash = sha256( agent.id + "\n" + tool + "\n" + canonicalJSON(args) )
$ myla --ledger
04 · Evidence
Every verdict, approval and fix lands in an append-only ledger. Each entry carries a hash that is the SHA-256 of the previous entry’s hash plus this entry’s own fields — so the entries are chained, and any edit, insertion or deletion anywhere changes every hash after it.
“Chain verified” is not a badge we print. It recomputes the whole chain from the first entry and reports the first entry whose hash no longer matches — or confirms there is none. You can run it; so can an auditor you hand the export to.
$ myla ~/measurement
05 · Measurement
The scanner is scored against a fixed set of known cases every release, and the most recent run, on November 11, 2026, found 91.4% of the planted issues at 100.0% precision. That number is read from the same file the benchmark page renders — never retyped here. See how we measure, including what we miss →
$ myla ~/limits
06 · What this does not do
This is the part that makes the rest believable. None of it is softened.
The config-block door watches; it does not block.
For Claude Code, Codex and Cursor the Gate records what it would have stopped and never interrupts the agent. Enforcement on that door is not shipped. The evaluate door (one HTTP call) returns a real verdict it can act on; the config-block door does not, yet.
Determinism is not omniscience.
A fixed rule gives the same answer every time — about the things the rules cover. It does not know an attack no rule describes. The untrusted-action tripwire catches the obvious command and misses a determined evader by design.
A scan describes the set it scanned.
Findings are about the code, history, dependencies and config Myla could read at that moment — not a guarantee that nothing else is open.
No SOC 2, and we won’t imply one.
We are in beta. What we can tell you instead is exactly what Myla holds and for how long — in plain words, on the privacy page.
Why it’s built this way
A verdict you can reproduce is one you can check. A chain you can recompute is one an auditor can trust without trusting us. Nothing in the Gate core knows which agent is asking, so the same rules apply to a tool we’ve never heard of. And Myla holds the credential rather than hoping the agent behaves. None of that is a feature we added on top — it is what the architecture is for.