Your agents now produce more work in a day than you can review in a week. Drafts, code, research summaries, outbound sends.
So you hit the fork every scaling team hits. Slow everything back down to human reading speed, or let the output through and hope.
There is a third option teams pick without noticing. More AI. A reviewer agent to check the writer agent. A better model. A sharper prompt.
The pile of unverified output just gets taller and more fluent. And fluency is the problem, because a fluent miss looks exactly like a pass.
Why doesn't a better model fix this?
A model can be wrong in a way that reads as right. That is a property of the technology, and it does not go away at the next model tier.
A probabilistic system approximates. When the approximation lands, you get leverage nobody could price a few years ago. When it misses, nothing about the output warns you.
Stacking a second model on top changes the odds. Odds were never the issue.
The issue is that no layer of the stack can say no and mean it. A reviewer agent can be argued with. A prompt can be drifted past.
What the stack is missing is a component that cannot be negotiated with.
So the architecture I run splits the work in two.
Models generate, reason, build, review, and judge. Deterministic software sits at the boundaries and decides whether the output proceeds.
The model does the work. A script decides if the work ships.
What does the architecture look like?
Five boundaries, each one a small public repo. Four are deterministic kernels through and through.
The fifth, the autonomy layer, wraps a probabilistic judge inside deterministic refusal semantics. The rubric thinks, and the wrapper holds the veto.
Each earns its keep the same way, by refusing.
The merge boundary. Agents write code in parallel lanes. An independent reviewer attacks each diff. A zero-dependency gate reads the evidence and decides what merges.
A parked verdict exits non-zero, so a pipeline cannot merge past it. That gate is ship-check.
A measured week running it is in Who decides what your agents may merge?
The autonomy boundary. An agent earns unattended operation with consecutive clean runs, scored by deterministic rules plus an LLM rubric that fails closed.
A scorer that cannot run is treated as a failed check, and the run blocks. Golden trajectories catch the slow decay a spot check misses.
That layer is gtm-agent-evals.
The strategy boundary. Strategy is where fluent nonsense does the most damage, because nobody expects a worksheet to push back.
gtm-architect refuses to advance a decision until its evidence is graded and sufficient.
It exits non-zero naming what is missing.
A model can sit above it through MCP and query it all day. It cannot talk the kernel into anything.
The egress boundary. Anything that carries text out of your process, an LLM call, a webhook, a log line, can carry a client name out with it.
redaction-gate checks outbound text with a matcher deliberately different from the redactor's own.
When redaction missed, it refuses the write.
The design argument for that asymmetry is in Can your redaction check actually fail?
The ingress boundary. Inbound events arrive from senders you do not control.
webhook-engine authenticates raw bytes, bounds replay, and reserves idempotency atomically.
Retries are bounded, and what fails dead-letters into a queue you can actually replay.
Five surfaces, one posture. At every boundary the deterministic side holds a veto the probabilistic side cannot argue with.
What did the boundaries actually catch?
This is the part I would want to read before believing any of it.
In one week of running the architecture on its own construction, the gates caught all of the following before merge.
What matters is the spread. Each one is a different way a green system can still hand you an unsafe answer.
A research-agent rule that green-lit fabricated funding numbers. It pooled every sourced number into one bag.
A made-up fifty million passed whenever the sentence carried an innocent sourced year.
The test suite was green the whole time. The fixtures only used clean integers.
A regression scorer with a blind spot for the worst decay. A quality dimension dropping from nine to seven was flagged. The same dimension vanishing entirely scored as a match.
A dashboard field that was live XSS. Every rendered value was escaped except one, and that one emitted working markup through the public API.
Two hundred forty one green tests coexisted with the hole. No test asserted that field.
A benchmark judge that had been told the answer. The examiner prompt named which arm was the disciplined one, which quietly primes the verdict.
The fix was a blinded, symmetric context, plus a test that greps the composed prompt for condition leaks.
Every one of these was found by an adversarial reviewer whose job was to refute the work, then pinned by a failing test before the fix.
None of them announced themselves. All of them would have shipped.
What did I get wrong building it?
Plenty, and the mistakes are the useful part.
I fixed instances when the defect was a class. A gate failed open on malformed input. I fixed the two code paths that were reported and shipped.
An external review found the same hole in the two paths nobody reported.
The standing rule now, name the class, then enumerate every member. Fixing the reported surface feels complete and is not.
I over-corrected a rule into blocking good work. After the fabricated-numbers catch, the tightened rule demanded a source for every number in a sentence.
It then blocked founding years, list ordinals, phone numbers, and support hours. Legitimate research could not clear the gate.
The durable rule that came out of it. A deterministic check only gets to block on violations it can decide. Judgment calls belong to the rubric layer.
I let one layer's safety depend on a validator two layers away. The dashboard skipped escaping a field because an upstream reader validated it.
True on the shipped path, false for anyone calling the public API directly. Every boundary now escapes and validates at its own edge, whatever upstream promises.
I let the control plane drift while gating everything else. The build queue feeding the whole system accumulated duplicate row IDs and shipped rows still marked launchable.
It was the one surface with no gate on it. The fix was an audit mode that cross-checks the queue against the lane board and refuses on drift.
It found eight problems on its first run, including one a careful human review of the same files had missed.
It caught me again the same evening, minutes after I merged two lanes and forgot to retire their rows.
That last catch is the honest summary of the architecture. The discipline is not that I stopped making mistakes. The mistakes now hit something on the way out.
Doesn't all this gating slow the work down?
The week those catches happened, the same fleet shipped a six-component eval platform, an MCP server, a public benchmark, and hardening waves across four other repos.
Every catch above was converted into a permanent failing-then-passing test, which is where the suites came from. The count matters less than the direction it grew.
Two build agents died mid-run and zero work was lost. The contract requires a commit per test cycle, so the gate decides from committed evidence a dead agent leaves behind.
The gates do add hours. They add them before merge, where a fix costs a failing test, instead of after ship, where it costs an incident.
The benchmark makes the claim falsifiable rather than rhetorical.
A deliberately naive strategy document and a gated one, both examined claim by claim by an adversary demanding the evidence.
The naive arm survives scrutiny 6.3 percent of the time, 1 claim of 16. The gated arm survives 60 percent, 6 of 10.
The committed verdicts were applied by hand from a published rubric, and the repo says so on every run.
Live mode re-judges everything with a blinded model. Grade my homework with your own key.
And the gated arm's four losses are real losses. A firm projection resting on an assumption. A magnitude the evidence supports only as a direction.
The gate improves the odds without guaranteeing them, and the repo prints that limitation on every run.
How do you install one boundary?
Start with your leakiest boundary, never with all five. Each repo runs from a clean clone with zero dependencies, and the deterministic layers need no API key.
| If this is the risk | Start here |
|---|---|
| Agent code merging on vibes | ship-check, with --ci so a parked verdict blocks |
| Sensitive text leaving your process | redaction-gate |
| Strategy claims without evidence | gtm-architect |
| Inbound events trusted on arrival | webhook-engine |
| Agents running unattended | gtm-agent-evals, and the streak decides autonomy |
If you build your own boundary instead, carry the four properties that did the work here.
It refuses instead of warning. It fails closed when its own machinery breaks. Its refusals name what is missing and how to repair it.
And something adversarial reviews it. Every catch above came from a reviewer paid to refute. The suite that was already green found none of them.
FAQ
Is this just writing tests for your AI? Unit tests tell you whether known behavior still works. These boundaries decide whether a new, previously unseen output is allowed to cross an operational boundary.
The autonomy gate and golden trajectories exist precisely because agent output changes after your tests go green.
Why deterministic? An LLM judge is more flexible. An LLM judge is one more probabilistic layer, so it belongs inside the boundary. The rubric scores, and the script around it holds the veto.
When the judge itself fails, the deterministic wrapper turns that failure into a block instead of a silent pass.
Does this replace human review? It concentrates it. Humans review refusals and park decisions, a small auditable surface, instead of skimming everything and approving from fatigue.
Where should a GTM team start? Egress. A leaked client name in an agent-drafted email is the cheapest catastrophe to prevent, and redaction-gate installs in a minute.