glitchfix

18 Feb 2026 · 2 min

Guardrails that compile

Securing an AI agent deployment splits into two worlds that rarely talk. Above the model: prompt injection, jailbreaks, exfiltration through tool calls. Below it: what the serving process may touch, execute, and connect to. The above-world ships as classifiers and filters; the below-world ships as AppArmor profiles and network policy. Two vocabularies, two files, two review processes, and the drift between them is exactly where incidents live.

The design I converged on this winter: one policy source, compiled twice.

policy:
  name: agent-serving
  allow_tools: [search, calculator]
  deny_topics: [credentials, lateral-movement]
  filesystem:
    read: [/models, /config]
    write: [/tmp/scratch]
  network:
    egress: [inference-gateway:8443]

From this single document, one emitter generates the runtime guard configuration: which tool calls pass, which topic classifiers run on which routes, what the injection filters scan for. A second emitter generates the matching AppArmor profile and egress rules for the pod. The classifiers themselves are the heavy lifting (SID and phishing detection models, plus an LLM-based classifier with prompt caching so the judge does not cost more than the workload), but the architecture point is independent of any given detector.

Why compile rather than configure

Because the failure mode of two hand-maintained configs is silent disagreement. The filter layer believes the agent cannot write files, the profile still allows /data from a debugging session two months ago, and the gap surfaces in an incident review. When both artifacts derive from one source, the review question collapses from “are these two files consistent?” to “is this one policy right?”, which humans are far better at answering.

The deeper lesson generalizes past security: whenever two systems must agree and both are generated by people, they eventually will not. Make one of them a compilation target. I first learned this pattern from infrastructure-as-code; watching it apply cleanly to model guardrails convinced me it is a load-bearing principle, not a devops fashion.