Version-Controlling Agent Policy Like You Version-Control Code
If your guardrail config is a live setting someone edits in place, you can't answer 'what was the policy last Tuesday' — and eventually someone will ask.
Every engineering team version-controls its code as a matter of course, without debate — nobody argues for editing production source files directly on a server anymore. Ask the same teams how their agent's guardrail policy is managed, and a surprising number will describe something closer to a live config: a threshold in an admin panel, a rule someone updates when a new edge case comes up, a value that lives in a database row with no history attached to it. The policy that determines what the agent is and isn't allowed to do gets treated with less rigor than the code that implements the agent itself — which is backwards, because the policy is often the part doing the actual safety work.
The fix is not complicated in principle: treat agent policy exactly like code. Store it in version control, require review before a change ships, keep a full history of what changed and why, and make it possible to answer, with certainty, what the policy was at any point in the past. The reason this matters isn't process purism. It's that policy-as-a-live-value makes several things that production agents actually need — rollback, audit, and controlled experimentation — either very hard or outright impossible.
The rollback problem
When a guardrail change makes things worse — too permissive, too restrictive, or subtly wrong in a way that only shows up under real traffic — the obvious fix is to revert to the previous version while you figure out what went wrong. That's trivial with version control: one command, a known-good state restored immediately. It's much harder with a live config, because "the previous version" often isn't a preserved artifact at all — it's whatever the value was before someone typed over it, which nobody necessarily wrote down.
This gap becomes acute during exactly the moment it matters most: containment, in the middle of an active incident. If tightening a guardrail is straightforward but reverting a bad change is not, teams under pressure end up making further live edits on top of an already-uncertain state, compounding the problem instead of resolving it. A policy under version control turns containment into "deploy the last known-good version," which is fast and low-risk. A policy that's just a mutable value turns containment into "try to remember what it used to be," which is neither.
The audit problem
An audit log that records what an agent did is only half the story if it can't also say, definitively, what policy was governing that action at the time. "The agent processed this refund under a policy that allowed it" is a meaningful statement only if you can point to the exact policy version in effect on that date — not the policy as it exists today, which may have been tightened since, quietly making the historical action look worse than it was under the rules that actually applied, or loosened, making it look more permissible than it should have been evaluated as.
This is the connective tissue behind why audit logs for autonomous systems need to reference specific, immutable policy versions rather than "the current policy." A regulator or auditor asking about a decision from three months ago is asking about the policy as it stood three months ago. If that policy was a live value with no history, the honest answer is "we don't know, precisely" — which is a very different position to be in than producing the exact diff, the exact commit, and the exact reviewer who approved it.
The experimentation problem
There's also a purely practical cost to not version-controlling policy: it makes careful, incremental change harder than it needs to be. Version-controlled policy supports the same workflow engineering teams take for granted with code — a proposed change goes through review, gets tested against a suite of known scenarios before it ships, and merges only once someone with the authority to approve it has actually looked at the diff and understood what's changing and why.
A live config supports none of that by default. Changes happen in place, often by whoever has access at the moment a problem needs fixing, frequently under time pressure, with no forcing function requiring a second set of eyes before the change takes effect. That's a reasonable way to patch a minor bug in a low-stakes internal tool. It's a genuinely risky way to change the rules governing what an autonomous system is allowed to do to real customers or real data — the exact category of decision that blast-radius gates exist to keep bounded, and a policy change that loosens a gate without review is precisely the kind of silent, unreviewed risk that gates are meant to prevent everywhere else in the system.
What "policy as code" actually looks like
In practice, this doesn't require exotic tooling — it requires applying tooling teams already use for application code to a different artifact. Guardrail rules, blast-radius limits, escalation thresholds, and tool-permission lists live as structured files in the same repository (or a clearly linked one) as the agent's other configuration, reviewed through the same pull-request process as any other change. Each change carries a commit message explaining the why, not just the diff — because six months later, "why did we tighten this threshold" is exactly the question someone will need answered, and a bare diff without context answers "what changed" but not "what problem this was solving."
Deploys of policy changes go through the same staged rollout discipline as code deploys where the stakes justify it — a change to a high-risk guardrail probably shouldn't go straight to 100% of traffic any more than a risky code change would. And critically, the deployed, in-production version is always traceable back to an exact commit, so that any audit-log entry referencing "policy in effect at time T" can be resolved to an actual, inspectable artifact, not a best guess about what a database value probably contained on that date.
The organizational shift this forces
The reason teams resist this, even when they understand the argument, is usually that policy changes have historically been owned by a different group than code changes — a trust and safety team, a compliance function, an ops lead — and that group doesn't necessarily have git in their existing workflow. That's a real friction, but it's a process problem, not a reason to avoid the underlying discipline. The people who own policy don't need to become software engineers; they need a review workflow — even a lightweight one, a pull request with a plain-language description reviewed by someone with the context to approve it — that produces the same artifact: a versioned, reviewable, revertible history of what the rules were and when they changed.
Once that history exists, several other pieces of the production-agent stack get meaningfully easier: incident containment has a known-good state to roll back to, audits have a precise record to point to instead of a reconstruction exercise, and the organization has an honest answer, backed by evidence, to the question that eventually gets asked whether or not anyone was prepared for it: what was the policy, exactly, on the day this happened — and who approved it.
Part of the "Running Agents in Production" series on aiskill.market.