Prompts are not policy
The usual way teams control AI coding agents is a prompt — an AGENTS.md, a system preamble, a paragraph of standards. A prompt is a request, evaluated probabilistically, and it cannot be versioned into evidence, tested, signed, or proven to have gotten stricter. A policy bundle can be all four. The distinction is the difference between hoping and enforcing.
Ask a platform team how they keep AI agents on rails and you will almost
always get the same answer: there is a file. An AGENTS.md, a system
prompt, a block of standards pasted into the agent's configuration. It lists
the frameworks the team uses, the patterns it prefers, the things it would
rather the agent not do.
That file is doing real work, and it is not a control.
It is a request. It is read by a model, weighed against everything else in the context window, and followed most of the time. Which sounds fine until you write down what "most of the time" means at the volume agents now produce, and until someone outside your team asks you to prove it.
Four questions
There is a simple test for whether something is governance or guidance. Ask four questions about it.
Can you version it into evidence? A prompt lives in a repo, so technically yes — there is a diff. But the diff tells you the text changed, not that the behavior did. Two prompts that read almost identically can produce materially different output, and the same prompt produces different output across model versions. The artifact you can point at is not the artifact that decided.
Can you test it? Write a test that fails when the prompt is violated. You cannot, in any meaningful sense. You can sample outputs and grade them, which is evaluation, not a gate — it tells you a rate, after the fact, on a sample. The build does not go red.
Can you sign it? You can sign the file. That establishes the text has not been tampered with, which is worth something. It establishes nothing about what the model did with it.
Can you prove this quarter's version is stricter than last quarter's? This is the one that tends to end the conversation. Regulated teams get asked to demonstrate that controls tightened after an incident. With a prompt, the honest answer is that the words got firmer. Nobody can prove the constraint did.
A prompt fails all four. Not because it is written badly — because a paragraph of natural language is the wrong kind of object to ask these questions of.
A prompt
A policy rule
Can you version it into evidence?
A prompt
Partly
There is a diff. It tells you the text changed, not that the behaviour did — and the same prompt produces different output across model versions.
A policy rule
Yes
The rule is the artifact that decided. Its version is the version that was enforced.
Can you test it?
A prompt
No
You can sample outputs and grade them. That is evaluation — a rate, after the fact, on a sample. The build does not go red.
A policy rule
Yes
A rule is code, so a test asserts it denies what it should deny. The build goes red.
Can you sign it?
A prompt
Partly
You can sign the file, which proves the text was not tampered with. It establishes nothing about what the model did with it.
A policy rule
Yes
The bundle is signed and verified before the runtime starts, and what was signed is what evaluated.
Can you prove this quarter's version is stricter than last quarter's?
A prompt
No
The words got firmer. Nobody can prove the constraint did. This is the question that tends to end the conversation.
A policy rule
Yes
Layers may only tighten. A rule that tries to loosen a baseline fails to compile, and the linter names it.
The left column is not a badly written prompt. It is the best a paragraph of natural language can do against these four questions, which is why writing a firmer one does not move any of the answers.
The auditor version of the same problem
Auditors do not ask whether you have good intentions. They ask what the control is, how you know it operated, and what happens when it fails.
"We instruct the agent not to do that" answers none of those. It is the compliance equivalent of a sign asking people to be considerate. The follow-up question — how do you know it complied? — has no answer that is not a manual sample of pull requests, which is exactly the work everyone adopted agents to avoid.
This matters more than it used to, because the thing being instructed is now producing code at a rate no sampling process keeps up with.
What the alternative actually looks like
Here is the same intent expressed both ways.
The prompt:
Please make sure any service that handles cardholder data
uses a pinned image digest rather than a floating tag.
The rule:
deny contains msg if {
input.service.scope == "cardholder_data"
not input.image.digest_pinned
msg := "cardholder-data services must pin an image digest"
}
Both express the same requirement. Only one of them is an object you can reason about.
| The prompt | The rule | |
|---|---|---|
| Evaluated by | A model, probabilistically | An engine, deterministically |
| Outcome when violated | Usually complied with | Build fails |
| Testable | Only by sampling outputs | trustacks rule test — red or green |
| Signed | The file, maybe | The bundle, with the decision it produced |
| Varies by model version | Yes | No |
| Provably stricter than last quarter | No | Yes, by construction |
The second column is not better because Rego is a nicer language than English. It is better because it is code, and code is the kind of thing you can put a test around, sign, and diff for meaning rather than for wording.
Ratchet-only, and the linter that proves it
The part that surprises people is not that the rules are code. It is what layering them makes possible.
TruStacks rules come in three layers. The constitution — a signed Rego bundle we author, free at every tier, non-waivable. Community packs for frameworks and runtimes. And your overlay, written by your own architects and compliance people, encoding the things that are true about your organization and nobody else's.
Each layer can only tighten the one above it. Your overlay can require more than the constitution does. It cannot require less. And this is not a convention or a code-review norm we ask people to respect — a linter checks it at compile time and rejects the bundle if it tries to loosen anything.
That property is what makes the whole thing hold. A rule that can be quietly relaxed under deadline pressure is a rule that will be, and the relaxation will not be in anyone's evidence binder. A rule that cannot be relaxed, where the attempt is a compile error with your name on the commit, is a different kind of object entirely.
You author it with a CLI that looks like the rest of your toolchain:
trustacks rule new # scaffold a rule
trustacks rule test # run it against fixtures
trustacks rule lint # prove it only ratchets stricter
trustacks rule sign # sign the bundle
new, test, lint, sign. There is no step where the rule works because
everyone agreed it should.
Where prompts are still the right tool
The honest version of this argument concedes something, because a policy engine is bad at most of what a prompt is good at.
Prompts are how you convey taste. House style, naming conventions, which of three reasonable approaches your team prefers, the tone of a commit message, the fact that this codebase does things a slightly unusual way for a reason. Encoding that as deny rules would be miserable and mostly wrong, because it is guidance, and guidance is what prompts are for.
The mistake is not using prompts. It is using only prompts, and assuming that the subset of instructions that genuinely must not be optional is safe there alongside the rest. Those requirements need a different instrument.
Ask for it in the prompt. Require it in the policy. If the answer to "what happens if the agent ignores this?" is "we would probably catch it in review," it was never a control.
The uncomfortable part
Most AI-governance tooling being sold right now is prompt governance with better packaging — a console where you manage the instructions, version the personas, and approve which agents may run. That is genuinely useful. It is also a management layer on top of requests, and the thing underneath is still being asked rather than required.
The question worth putting to any vendor, including us: when the model ignores the instruction, what stops the change? If the answer is a better instruction, a stricter model, or a human who will hopefully notice, there is no control in the system. There is a very well-organized hope.
Ours is a signed bundle that fails the build, that your architects can tighten and nobody can loosen, and that produces the same answer at 5pm on a Friday as it does at 10am on a Tuesday.
Agents propose. Policy decides. Humans approve.
The constitution, customer overlay authoring, the ratchet-only linter, and the
trustacks rule CLI are shipped today — see the facts page for what
is live versus roadmap, each entry with a verification date. The policy model
is described in more detail on /product/policy.
- policy as code
- AI governance
- AI delivery governance
- Rego