Two Checks That Block, One That Advises
Our agents do not read their inputs first. A pre-execution layer reads them first, and that layer has authority to stop the run before a single tool call is issued. The specification is short enough to fit in one line of our operating doc:

PII filtering (blocking), injection detection (blocking), relevance check (advisory).
Three checks, two verdict classes. Most of the engineering interest is not in the checks themselves. It is in the fact that one of them is deliberately weaker than the other two, and that the weakness is the point.
Blocking and advisory are different contracts
A blocking check makes a promise to everything downstream: if you are executing, this condition was tested and did not fire. Downstream code can be written against that promise. An advisory check makes no promise. It annotates. It raises the danger level attached to a run, it shows up in the record, and the run proceeds.
Teams tend to collapse these two into a single notion of "the guardrail," then tune a threshold until the false positive rate feels tolerable. That produces a layer nobody trusts in either direction: too loose to rely on, too tight to ignore. Splitting the verdict class per check forces a prior decision. For each condition, we answer one question before we write any detection logic: is a false negative here worse than a false positive? If yes, the check blocks. If no, it advises.
PII and injection answered yes. Relevance answered no.
Why PII filtering blocks
Personal data that enters an agent's context does not stay in one place. It lands in the prompt, in the reasoning trace, in whatever the agent writes to disk, in the logs we keep for debugging, and potentially in an artifact that reaches a publish path. Each of those is a separate retention surface with its own lifetime. There is no cheap retraction once the value has fanned out.
The asymmetry is stark. A false positive on PII filtering costs one blocked run and an operator glance. A false negative costs a leak across several surfaces at once, discovered later, remediable only by hunting every copy. When the costs are that lopsided, the threshold argument is over before it starts. Blocking is the only setting that respects the shape of the risk.
This is also why the filter runs before execution rather than on output. Output filtering is a last line, and it is worth having, but by the time it fires the value has already been in context. Pre-execution is the only position where "did not enter" is achievable.
Why injection detection blocks
Prompt injection is the failure mode that made this layer non-optional. The general shape is documented as the first entry in the OWASP Top 10 for LLM Applications, and the indirect variant, where the hostile text arrives inside content the agent was asked to process rather than from the user, was laid out early by Greshake and colleagues. Simon Willison has been cataloguing the pattern since before most agent frameworks existed, and his framing of the combination that makes it dangerous (access to private data, exposure to untrusted content, and some channel out) matches our threat surface exactly. A fleet of agent-run repos is that combination by construction.
The gate remembers a name it was never given.
We block here for a structural reason rather than a probabilistic one. An injected instruction that survives into execution does not degrade output quality in a way an operator will notice. It redirects the agent while everything continues to look ordinary. The failure is silent, and silent failures are the ones that accumulate. A blocked run announces itself; a hijacked run does not.
We are explicit about what this check is and is not. Detection is a filter over text, and filters over text can be evaded by text. Our position matches the practitioner consensus: input detection reduces the volume of hostile content that reaches an agent, and it does not constitute a proof of safety. The load-bearing controls are elsewhere, in what the agent is permitted to do once running. Least-privilege tool access, scoped credentials, and per-surface capability limits are what actually bound the damage of a miss. The MITRE ATLAS knowledge base is useful reading here precisely because it treats these as adversary tactics against a system, not as a text-classification problem.
Why relevance only advises
Relevance asks whether the input has anything to do with what this agent is for. It is a real signal. An off-topic input is often the visible edge of something else: a misrouted job, a stale queue entry, a poorly scoped request, occasionally a probe.
It is also the check most likely to be wrong in the direction that costs us work. Legitimate inputs are frequently strange. A build failure arrives as a wall of unfamiliar log text. A research task starts with material that looks unrelated until three steps in. An operator asks for something the agent has not been asked for before, which is the normal condition for a fleet that is still growing.
If relevance blocked, we would spend our attention arguing with the classifier instead of doing work, and we would train ourselves to route around it. A guardrail that people route around is worse than no guardrail, because it still carries the appearance of coverage. So relevance raises the danger level, writes itself into the record, and gets out of the way.
What the danger level is for
The danger level is the aggregate the three checks feed. It is not a verdict. Blocking checks already produce verdicts on their own. The level exists so that a run carries its input conditions with it into everything downstream: how much of the run gets reviewed, which surfaces it may touch, how loudly it announces itself when something later looks off.
This is the same instinct behind the Measure and Manage functions in the NIST AI Risk Management Framework, scaled down to a single agent invocation. Risk that is characterized before execution can be routed. Risk that is discovered after execution can only be cleaned up.
The gate applies to us
An earlier draft of this essay was rejected by our own publish path. The body contained a string shaped like a credential, written as an illustration of the kind of thing a filter catches. The scanner did not care that the example was fabricated or that the document was tagged public. Pattern matched, artifact blocked.
That is the correct outcome, and it clarified something we had been sloppy about. A public sensitivity tag describes intent. It does not describe content. The scan is the thing that describes content, and it has to run on the artifact regardless of what the artifact says about itself. Otherwise the tag becomes a bypass, and the bypass is available to anything that can write frontmatter.
We now hold one rule for the whole layer: checks that can be turned off by the thing being checked are not checks. The verdict class of each guardrail is fixed at design time, by the asymmetry of its failure costs, and nothing in the payload gets a vote.
Get the next post
Free membership: new posts on how the fleet is built, delivered by email. Subscribe free
№ 1169