Governance as Code: Encoding Permissions and Approvals Into AI Workflows
“Only approved reviewers can let an agent deploy to production” is a rule that exists in most companies — usually as a paragraph in an onboarding doc nobody re-reads after their first week. When an autonomous agent is the one taking the action, a rule that lives in a document isn’t a control, it’s a suggestion the agent has no way to know about. Governance as code means the permission, the approval requirement, and the policy check are executable artifacts that the system enforces automatically, not documentation that depends on someone remembering to follow it.
Why This Has to Move Into Code
A human engineer who’s unsure whether they’re allowed to deploy on a Friday afternoon will usually ask. An agent doesn’t have that instinct unless the system is built to stop it — the policy has to be a gate the agent’s action physically cannot pass, not a norm it’s expected to intuit from context.
What Governance as Code Looks Like
A policy expressed as code, versioned alongside the rest of the system:
policy: production_deployapplies_to: agent_actions: ["deploy", "database_migration"]rules: - require_approval: true approvers: ["team:platform-leads"] min_approvals: 1 - require_passing_checks: ["unit_tests", "security_scan", "integration_tests"] - deny_if: time_window: "friday 15:00-23:59" unless: "override_approved_by: incident-commander" - max_blast_radius: files_changed: 50 services_affected: 1This isn’t pseudocode for illustration — policy engines like Open Policy Agent (OPA) let you write exactly this kind of rule and enforce it at the point an agent’s action is about to execute, returning an allow/deny decision the orchestration layer must respect.
The Permission Matrix an Agent Actually Needs
| Action class | Example | Default policy |
|---|---|---|
| Read-only | Search code, read logs, run analysis | Auto-allowed |
| Reversible write | Open a PR, comment, create a draft | Auto-allowed, logged |
| Irreversible write, low risk | Merge a small, well-tested change | Auto-allowed with passing gates |
| Irreversible write, high risk | Deploy to prod, run a migration, delete data | Requires explicit human approval |
| Cross-boundary action | Access a different team’s repo or environment | Requires elevated approval + audit log |
Codifying this table — not describing it in a wiki — is the actual deliverable of governance as code. The table becomes the input to a policy engine, and the policy engine becomes a mandatory step in the agent’s action pipeline, tying directly into human-in-the-loop control for anything that lands in the bottom two rows.
Auditability Is Governance’s Other Half
A policy that’s enforced but not logged is unverifiable after the fact. Every governance decision — allowed, denied, or escalated — should produce an immutable audit record: what action was attempted, what policy evaluated it, what the outcome was, and who (human or agent) initiated it. This is what turns “we have a policy” into “we can prove compliance during an audit,” which matters a great deal more once agents are taking actions that used to require a human to click a button and implicitly accept accountability.
Getting Started Without a Full Policy Engine
You don’t need OPA on day one. Start by hardcoding the two or three policies that would cause real damage if violated — no unattended production deploys, no agent access to customer PII without logging — as explicit checks in your orchestration layer. Move to a real policy engine once you have more than a handful of rules, because policies-as-if-statements scattered through code become exactly the kind of undocumented, unenforceable governance this pattern exists to replace.