Manage AI agent policies as code the same way you manage infrastructure: Rego in git, plan before apply, attach by UUID.

Authorize with OPA proved a deny rule locally. This post puts that rule on an agent with the StackGen Terraform/OpenTofu provider. Background on why agent config moved to a provider lives in Terraform for agent configuration.

Key takeaways

  • sg_policy creates Rego; sg_agent_policy_attachment binds it to an agent.
  • Prefer type = "logic" / "intervention" over stale tool_call examples.
  • Test with opa test, then tofu plan, then attach.

Managing AI agent policies as code with Terraform from Rego to StackGen enforcement

opa test locally, declare sg_policy and sg_agent_policy_attachment, tofu plan / apply, then Aiden enforces allow or deny on tool calls.

Architecture: control plane vs enforce path

Terraform (and the Guild API) own the control plane:

Resource Stores Runtime effect
sg_policy Rego text, type (logic / intervention / …), UUID Available for evaluation
sg_agent Agent identity and config Target for attachment
sg_agent_policy_attachment (agent_name, policy_id, enabled) PEP includes that Rego for that agent

Nothing in this path runs the LLM. tofu apply only mutates stored policy and links. The data plane (factsheet → OPA → allow/deny/ask → tool) is unchanged until a live tool call happens. That split is why you can opa test offline, tofu plan the attach, and only then enable enforcement.

Provider docs: terraform-provider-stackgen (pin v0.1.48). Prefer workspace_id on the provider; org_id / project_id are deprecated aliases.

Why policy as code for agents?

HashiCorp’s line for AI-driven infrastructure is “agent proposes, control plane governs.” Same split here: the model proposes a tool call; the platform policy decides. Putting Rego only in a UI click means the next incident has no PR to blame and no plan output to review.

OpenShell and gateway products roll rules in audit then enforce. Aiden’s practical equivalent: prove the rule with opa test, create it on a lab agent first, then enable the attachment on production agents.

Provider setup

You can exercise create/attach for free:

  1. Create a free account at app.stackgen.com.
  2. Open Personal access tokens and mint a token. That value is stackgen_token. Never commit it.
  3. Set stackgen_url to https://app.stackgen.com and stackgen_workspace_id to your workspace UUID from the app.

Without URL, token, and workspace id, tofu apply has nowhere to create resources. Same bar as Aiden the Hard Way. Pin the provider to 0.1.48 (docs).

terraform {
  required_version = ">= 1.5"
  required_providers {
    sg = {
      source  = "releases.stackgen.com/stackgen/stackgen"
      version = "0.1.48"
    }
  }
}

provider "sg" {
  stackgen_url   = var.stackgen_url   # https://app.stackgen.com
  stackgen_token = var.stackgen_token # personal access token; never commit
  workspace_id   = var.stackgen_workspace_id
}

Docs: terraform-provider-stackgen · sg_policy.

Create the policy from a file

Keep Rego on disk. Terraform loads it with file().

resource "sg_policy" "deny_secret_write" {
  name        = "lab-deny-secret-write"
  description = "Deny gh secret set (teaching lab)"
  type        = "logic"
  rego_source = file("${path.module}/policies/deny-secret-write.rego")
}

Honest note on types: provider HTML examples still show type = "tool_call" and decision := "deny". Solutions and Hard Way use package policy with allow / approval_required and types logic / intervention. Teach the live shape.

Create a minimal agent and attach

The lab creates a bare sg_agent, then attaches the policy by UUID:

resource "sg_agent" "lab" {
  name        = var.agent_name
  description = "Teaching lab agent for OPA policy attach"
  persona     = "You are a lab agent used only to demonstrate policy attachment."
}

resource "sg_agent_policy_attachment" "deny_secret_write" {
  agent_name = sg_agent.lab.name
  policy_id  = sg_policy.deny_secret_write.id
  enabled    = true
}

For a full agent plus workflows in one module, use Aiden the Easy Way.

Lab step

Full teaching root:

samples/aiden-opa-policies/02-terraform-attach/

cd samples/aiden-opa-policies/02-terraform-attach
cp terraform.tfvars.example terraform.tfvars
# stackgen_url = https://app.stackgen.com
# stackgen_token = from Personal access tokens
# stackgen_workspace_id = your workspace UUID
tofu init
tofu plan
# tofu apply only when you intend to mutate the tenant

Next: clock-based rules. Time-based AI agent policies with OPA.


Policy reviews belong in PRs. Create a free account, mint a personal access token, then run the attach lab.

Free to try: create an account, then create a personal access token for Terraform. StackGen / Aiden: app.stackgen.com.

Previous: Authorize AI agent tool calls with OPA. Next: Time-based AI agent policies with OPA.

FAQ

How do you manage AI agent policies with Terraform?

Declare sg_policy with rego_source, then sg_agent_policy_attachment with agent_name and policy_id. Review with tofu plan before apply.

What is the StackGen Terraform provider source?

releases.stackgen.com/stackgen/stackgen at version 0.1.48. You need a tenant URL, personal access token, and workspace_id. Tokens never belong in git.

Should policy type be tool_call or logic?

Use logic for allow/deny and intervention for approval_required. Older provider examples still show tool_call; solutions modules use logic and intervention.

Does the Terraform attachment support priority?

The REST attach API accepts priority. The sg_agent_policy_attachment resource today exposes agent_name, policy_id, and enabled.