Skip to content

Control plane

How the agent is actually constrained

Prompt-injection defense is one line of a much larger system. This page shows the whole stack: what is written down, what is mechanically enforced before a tool runs, what is detected by pattern matching over the wiring itself, what capability is granted, and what gets measured afterwards.

Most "AI agent safety" talk stops at the input filter: catch the bad instruction before the model reads it. That filter matters, but it only protects one moment. The rest of the time the risk is somewhere else — the agent holds a tool, the tool has a name that looks safe, and the model calls it at 3am with nobody reading the transcript.

An instruction asks the model to behave. A control removes the tool.

That is the difference between a rule and a control. A rule is a paragraph the model is asked to read and remember. A control is code that runs whether or not the model cooperates. Everything below is a control, and every control is counted.

Five layers, in the order a request crosses them

Each layer answers a different question, and each one has a measurable size. A stack that only had one layer would be a filter; a stack with five is a control plane.

L1

Written policy

What is always true, whoever asks?

What it is

The constraints exist as text before anything runs. They state what has to hold in every repo, every session, every commit — and they are the spec that the enforcement layer below is checked against, not notes for me to remember.

How it works

Rules are matched by topic and loaded into context automatically, so the same decision gets the same answer whether it arrives from a human instruction, a code comment, or a fresh session with no memory of yesterday.

Evidence

Rule files
108
Rule corpus
809 KB
L2

Wired enforcement

What actually stops a tool from running?

What it is

Checks run at fixed points in the agent lifecycle: before a tool call, after it, at session start, when the context is compacted, when the agent stops. They are wired into the runtime that is actually executing — not into a configuration file somebody remembers to open.

How it works

Each check is a small program that is allowed to refuse. A refusal shows up in the transcript with its reason attached, so the constraint is an event with a timestamp, not a promise with good intentions.

Evidence

Checks wired
36
Lifecycle points
13
Check scripts
88
L3

Verified detection

How do you know a control still works?

What it is

The enforcement layer is itself under test. The suites below each state a condition that must hold — a guard that must be closed, a script that must exist, a failure that must not be swallowed — so the checks are verified rather than assumed.

How it works

The failures that matter are not the ones that crash. They are the ones that look fine: a guard that was never connected, a script that no longer exists, a build step whose exit code is discarded. Those pass every ordinary test, so they are found by pattern matching over the wiring itself.

Evidence

Test suites
18
Assertions
356
L4

Capability, not tools

What is the agent allowed to touch?

What it is

Tool servers are connected to the runtime, and the ones built for this purpose are declared read-only with an explicit statement of what they may and may not do. A server that only reads is not a smaller privilege — it is a different kind of privilege.

How it works

Access is filtered by intent. A read-only pass exposes only the tools that cannot change state, so a stray instruction cannot reach a write path through a read tool. Raising the intent is an explicit, logged act, never a default.

Evidence

Tool servers
17
Built for this
7
L5

What it cost

What did the run actually consume?

What it is

Every request is routed, counted and priced at the upstream boundary: tokens in, tokens out, tokens served from cache, cost, retries, outages. The operations dashboard is live off these counters, and the figures below are the same counters it reads.

How it works

Measurement is what turns "it worked" into an argument. A request that fell back to a second upstream, a prefix that stayed stable across a thousand calls, a limit that was hit and recovered from — each one is a counter with a history, not an anecdote.

Evidence

Requests routed
1,525
Tokens read from cache
127,854,687

Three ways a control fails silently

A control that is wired, tested and documented can still do nothing. These are the three failure modes the scanner knows how to name, explained as the situations they actually are rather than as regex patterns.

The guard that was never connected

hook-not-wired

A guard was written, shipped, documented and reviewed. The script that enforces it existed on disk. But the file that wires the runtime to that script never referenced it, so it never ran — and nobody noticed, because the absence of a guard looks exactly like the presence of one.

What it costs

Any rule that leaned on that guard was decorative. Every action it was supposed to refuse was allowed, while the documentation claimed otherwise.

How it is found

The scanner compares the scripts that exist against the entries that are wired and reports the difference by name. The class is hook-not-wired: present in the filesystem, absent from the runtime.

The build that could not fail

silent-failure

A build chain ended with a construct that discards the exit code of everything before it. The build was broken. The gate in front of the deploy reported success anyway. The deploy shipped the previous artifact, and the logs said everything was fine.

What it costs

The failure was invisible at the exact moment it mattered most — the gate that existed to stop the deploy passed instead of blocking it.

How it is found

The scanner parses the command chain and flags the shape where an error-swallowing step sits in front of a gate. The class is silent-failure: the script is syntactically valid, and it always reports success.

The door to an empty room

declared-but-absent

The runtime was told to run a check at a certain moment, and named the check. The script it points to does not exist — it was renamed, moved, or never committed. The wiring is intact and resolves to nothing.

What it costs

A whole class of checks stopped running without removing any line of configuration. The count of active guards fell, and the dashboard did not say so, because the dashboard was counting declarations rather than executions.

How it is found

The scanner resolves every declared path and reports the ones that cannot be resolved. The class is declared-but-absent: the runtime believes it is protected, and it is not.

The system auditing itself

The control plane scans its own wiring on a schedule and publishes what it finds — including the findings that are still open, including the one that blocks. A system that lists its own gaps is a different proposition from one that claims to have none.

1 blocking3 warnings1 informational5 open findings

A declared check has no script

blocker

The runtime references a check whose script does not exist, so that check can never run. It is the highest-severity class because it removes protection without removing the appearance of protection.

A guard exists but is not connected

warn

The script is present and executable, but the runtime does not reference it. The protection is written, reviewed and shipped — and it is not active.

A background service is not running

warn

A long-lived helper that other checks depend on is in a failed state. It is not blocking anything today, but anything relying on it is relying on a service that is down.

A proposed check has no wiring recipe

info

A note proposes a new check but does not record how to install it. Proposals like that are easy to write and easy to forget; the fix is to keep the recipe next to the proposal.

What a run actually costs

Every request that enters the routing layer is counted at the upstream boundary. These are the live counters behind the operations dashboard, read at the same moment as the corpus snapshot above.

Cache read per fresh token

3.27×

Requests served from a cached prefix

92.5%

Tokens handled in total

167,933,880

Blended cost per million tokens

$0.061669

Requests routed
1,525Every call that entered the router, whichever upstream took it.
Routing decisions
1,525How many times the router chose an upstream for a request.
Requests with a cached prefix
1,411Calls where a reusable prefix was found, so the upstream did not have to recompute it.
Tokens read from cache
127,854,687Context served from a stored prefix instead of being recomputed from scratch.
Fresh input tokens
39,051,470The part of the prompt that had to be processed cold.
Output tokens
1,027,723What the model wrote back.
Prefixes left stable
679Calls whose context prefix was already in the order that makes it cacheable.
Prefixes reordered
846Calls whose prefix had to be reshuffled before it could be cached.
Limit hits
10Times a request hit a provider limit and was retried against another upstream.
Recovered after a limit
10Of those retries, how many ended in a successful answer.
Circuit breaker opens
0Times an upstream was taken out of rotation after failing repeatedly.
Total outages
0Times no upstream was available and the request could not be served.
Blended cost
$10.356380Total spend across all upstreams, after any failover.

The corpus behind it

The size of the system doing the enforcing: how much is written down, how many checks exist, how many of them are connected, and how much of the whole thing is under test.

Rule files
108
Rule corpus
809 KB
Checks wired
36
Lifecycle points
13
Check scripts
88
Tool servers
17
Built for this
7
Test suites
18
Assertions
356
Source files
174
Lines of code
45,338
Breakdown by lifecycle event
  • PreToolUse13
  • PostToolUse4
  • SessionStart4
  • PostCompact3
  • PermissionRequest2
  • PreCompact2
  • Stop2
  • Notification1
  • PostToolUseFailure1
  • SessionEnd1
  • SubagentStart1
  • SubagentStop1
  • UserPromptSubmit1

Every figure on this page is generated by a measurement script and committed as a dated snapshot — none of them typed by hand. Corpus measured on 2026-10-24.