The first generation of agent guardrails was copied from traditional security and it did not survive contact with agents. Block `rm -rf /` and the model writes a Python one-liner. Block `curl` and it pushes to an external git remote. Every blocklist closes one path and opens three.
The second generation replaced blocklists with a judge model that reviews each tool call before it runs. This is better and still structurally broken. Two October 2026 launches on Hacker News's front page — OpenAPPA and ai-rete-RAG — approach the problem from a direction that explains why both earlier attempts keep failing.
Why judge models cannot track data flow
A judge model reads a tool call and decides whether it looks acceptable. That works right up to the moment the dangerous behaviour spans calls.
Consider the ordinary sequence: read a private repository, then read an unvetted web page, then write to a public paste site. No single call is obviously an attack. The leak is the *combination*, and it only exists as a relationship between calls. A per-call judge has no representation for it.
There is a second, worse problem. Classifiers are themselves models, which means they are prompt-injectable. The standard mitigation is to hide tool outputs from the judge — so the judge never sees the data it is supposed to be protecting. You cannot audit what you refuse to show.
And probabilistic defences have a ceiling. Even a 99.3% accurate injection detector leaks at millions of calls; 0.7% of a large number is a lot of breaches. This is not a tuning problem. It is arithmetic.
The alternative: labels that only tighten
The deterministic approach, as implemented by OpenAPPA, moves the guardrail entirely outside the agent's prompt and execution loop. The model cannot see it, negotiate with it or manipulate it, because there is no prompt surface to inject into. You cannot prompt-inject an algebra.
Instead of allowed and blocked tools, you write one declarative contract describing data sources, audiences, trust levels and authorities. Every trajectory carries a security label of audience times trust. Reading a private repo narrows the audience. Reading an unvetted web page lowers trust. The label only ever gets more restrictive, and each decision is derived from it algebraically rather than judged.
The engineering consequence is that coverage becomes checkable. Because the config is data, you can validate in CI that your entire tool graph is covered — something nobody can do with a regex list. And because it is declarative, the same contract scales to millions of agents without changing.
Two design choices are worth stealing regardless of whether you adopt the tool.
Remedies instead of refusals. A bare "forbidden" makes an agent stall, retry and fail. OpenAPPA returns a machine-readable remedy plan describing how the agent may legally proceed: sanitizers that transform the payload so it can flow to a wider audience, authorities that approve one specific action without lifting the session's restrictions, and subagents that isolate an untrusted read in a disposable branch. The project reports this lifting task completion from 37% to 90% on its benchmarks. Strictness that breaks the agent is not security — it is an outage.
Subagent isolation for untrusted reads. If one input is untrusted, give it its own branch and let the parent trajectory continue unpoisoned. This is the same instinct behind sandboxing a build step, applied to a model turn.
The project publishes benchmark comparisons against auto-mode judges and is MIT licensed with a NeurIPS-accepted paper behind it. Its own launch numbers were modest — 25 points and 12 comments — so treat the community as thin and verify against your own workload before committing.
When determinism is the point, not the defence
A second October launch, ai-rete-RAG, reaches the same conclusion from the compliance side. It pairs a Rete rule engine with retrieval-augmented generation: rules decide the *what* and produce an auditable trace, and retrieval is invoked only to narrate the *why* in plain language from your own documents.
This is the right split for regulated decisions. In loan underwriting or fraud screening you do not want a language model producing the verdict — you want the verdict to be a deterministic function of stated facts, with a natural-language explanation attached for the human. Three composition patterns are live: rules acting as retrieval filters so a cardiac case only fetches cardiology sources; documents parsed into facts and asserted into working memory for rules to fire on; and post-hoc explanation where the engine fires first and retrieval only writes the narrative.
Two features matter more than the demo domains. Every decision links back to the exact rules that fired *and the ones that nearly did*, down to the value that missed the threshold — which is what an auditor actually asks for. And static conflict analysis flags when two rules with different verdicts could both match the same case, before it becomes a production surprise.
The trade is honest: you must bring your own rules and policies, so the domain modelling is on you. A rule engine does not remove the work of deciding what your policy is. It removes the ambiguity of whether it was applied.
Context is a third attack surface
There is a failure mode neither tool fully covers, and it is worth naming because it is common. An agent's context degrades silently. A stale assumption, an outdated branch, a conclusion nobody remembers the basis for — none of it trips a guardrail because none of it is a tool call.
ThoughtDAG makes context a first-class, inspectable object: a graph where each edge is a route into the next request, with a preview of exactly what the model will receive before you send. Its published pilot found that removing a contaminated subgraph repaired 162 of 162 derailed cases, versus 152 of 162 when only the source was deleted. Most "the model forgot" incidents are context contamination, not model failure, and they need visibility rather than a rule.
A practical starting order
If you are adding guardrails to an existing agent stack, this sequence tends to work.
- Inventory what data each tool can touch. You cannot write a contract before you know your sources and audiences. This step alone usually surfaces a tool that can read far more than anyone remembered.
- Separate untrusted from trusted inputs. Web pages, user uploads and third-party APIs are untrusted. Your own repositories are trusted. Make that boundary explicit in the config.
- Run the guardrail outside the loop. If the model can see the guard, it can be manipulated by the guard.
- Return remedies, not refusals. An agent that stalls is an outage. Give it a legal path forward.
- Validate coverage in CI. The single biggest advantage of a declarative contract over a blocklist is that you can prove it covers your tool graph.
For regulated decision paths, invert the usual architecture: let a deterministic engine decide and let retrieval explain. The explanation is the part that benefits from fluency. The decision is the part that must not have any.
FAQ
Do I need guardrails if my agent only reads?
Yes, if it reads anything untrusted and then writes or acts on what it read. Read-then-write across a trust boundary is the classic exfiltration path, and no single call looks wrong.
Is a blocklist ever the right answer?
As a cheap supplementary layer, sometimes. As your primary control, no — it gives zero visibility into coverage and cannot express relationships between calls.
How much overhead does running outside the loop add?
It is a separate process making an algebraic decision from a label, not a model call, so it is fast. The real cost is authoring the contract, which is a one-time design exercise.
Can I use this with Claude Code or Codex?
The deterministic engines are vendor-agnostic and plug into an existing agent loop at a single point. Check the integration docs for your harness; the pattern is the same regardless of which agent you run.