
An AI coding agent can produce a working-looking Terraform module in a minute. That speed moves the bottleneck: the scarce resource is no longer writing HCL, it's deciding whether a change is safe. Review is now the job.
This post is a working checklist for that review. It assumes the setup described in our primer on infrastructure as code with AI coding agents: the agent edits code and produces plans, while apply stays behind a human or pipeline approval.
Because it fails differently. A human author writes code that looks like their experience level; weak spots announce themselves. An agent writes uniformly idiomatic HCL whether it's right or wrong, so style tells you nothing. The failure modes hide in places a normal style-and-intent review doesn't look: the execution context the agent assumed, the provider version it trained on versus the one you pinned, and the blast radius of the resulting plan.
There's also a volume problem. Agents make it cheap to open many changes, and reviewer attention doesn't scale the same way. The answer isn't heroic reading. It's moving every mechanical check into automation and spending human time only where judgment is required.
Start outside the diff. Three context checks catch entire categories of failure in under a minute.
Which workspace, backend, account, and region does this change target? An agent can produce a perfect change against the wrong environment. The primer's rule applies to reviewers too: confirm the execution context before interpreting anything else. If the pull request doesn't state workspace and account explicitly, send it back.
Did the dependency lockfile or any module source change? A modified .terraform.lock.hcl, a new module source URL, or a loosened version constraint deserves more scrutiny than any resource block, because planning untrusted code is code execution. HashiCorp's own external data source can run a local program during plan. Treat unexplained dependency changes as a blocker, not a footnote.
Which provider version did the agent assume? Models carry stale defaults from training data. If the code uses arguments that only exist in a newer provider, validate fails loudly, which is the good case. The bad case is code written for a newer pattern that silently behaves differently under your pinned version. Check that the agent actually read required_providers and the lockfile, and that the documentation it cited matches the pinned version.
As of July 2026, these are the patterns worth a dedicated pass:
terraform validate or tofu validate catches these, so a change that arrives without a passing validate run hasn't met the minimum bar.moved blocks. An agent asked to refactor may rename resources or restructure modules. Without moved blocks, that reads to Terraform as destroy-and-recreate. The code diff looks harmless; the plan does not.None of this requires reading suspiciously. It requires knowing where to look, which is exactly what a checklist is for.
The diff shows what changed in text. The plan shows what will change in the world, and only one of those is authoritative.
Require a speculative plan on every agent-authored change, and review it with a short, fixed sequence:
destroy and every replacement gets read and justified. A replacement the author didn't mention in the description is an automatic stop.resource_changes can miss them.A large plan is subagent work on the author's side, but the reviewer should still inspect the human-readable plan for anything destructive rather than trusting a generated summary. Summaries can omit the one attribute that makes a replacement dangerous.
Everything mechanical. A reasonable gate for agent-authored changes, in pipeline order: fmt, validate, a linter such as tflint, a security scanner such as Checkov or Trivy, policy-as-code evaluation, then a speculative plan attached to the pull request. Only after all of that passes should the change consume reviewer attention.
Policy-as-code earns its keep here. Rules like "no security groups open to 0.0.0.0/0", "all resources tagged", or "no IAM wildcards" are precisely the mistakes agents make under pressure to produce something that works. Encoding them in Open Policy Agent means they're enforced identically for human and agent authors, and the agent gets the rejection as feedback it can act on instead of a reviewer comment it can't see.
Platforms in the Terraform automation space (Scalr, Spacelift, env0, HCP Terraform among them) run these checks server-side on every pull request, which matters for agent work because the checks execute with the platform's credentials and configuration rather than whatever the agent's local shell happens to have. In Scalr, OPA policy enforcement and RBAC are available on every tier, so the policy gate doesn't depend on plan level. Atlantis paired with CI linting gets a small team most of the way there too.
Keep three identities distinct: the agent that authored the change, the automation that checked it, and the human who approves the apply. Collapsing any two weakens the review.
Concretely: the agent works with credentials that can plan but not apply. The pipeline runs checks under its own service identity. Approval binds to a specific saved plan or remote run, not to the branch, so what was approved is what gets applied. Our primer covers the safe defaults for that credential split in detail.
Whether your platform can enforce this separation is worth checking before you scale up agent usage. You want workspace-level controls that let an agent's service account create runs but not approve them, with the approval permission held by humans. If the platform can't distinguish those two operations, the separation exists only as convention, and conventions don't survive deadline pressure.
Take one upcoming agent-authored change and run it through this list end to end: context checks, the HCL pass, the plan sequence, then look at what the automation missed. Whatever a human caught that a machine could have caught, encode as a lint rule or OPA policy before the next change. After a few rounds, the human part of the review shrinks to what it should be: blast radius, intent, and the judgment call on whether the plan matches the task.
