Coding agents on infrastructure code: Terraform, pipelines and the blast radius
Application code has a test suite and a staging environment between a mistake and a customer. Infrastructure code has a plan command and a production account. That asymmetry is why coding agents on infrastructure code need a different setup from the application side. The agent writes Terraform with the same confidence it writes Python, and the review that catches a wrong block has to be stronger because nothing downstream will. Our recommendation, from the platform teams where we have set this up: agents may write and plan, humans apply, and the credentials in the agent’s environment cannot do anything else.
What changes when the code is infrastructure
Three properties of infrastructure code make an agent’s mistakes more expensive. The blast radius: a wrong line in a service file breaks one feature, a wrong line in a security group opens a database to the internet, and a renamed Terraform resource means destroy and recreate, data included. Drift: declared state in the repository and real state in the account diverge through console changes and failed applies, so the agent reasons from a file that is partly fiction, and the plan output is the only accurate picture. Secrets: the agent’s environment holds cloud credentials, and what they can do is the same question we ask before any agent gets write access to a business system. No unit test tells you an IAM policy is too broad, and a destroyed database does not come back on revert. The structure below compensates for that.
Agents write and plan, humans apply
The agent gets a branch, the module in scope and the plan command (terraform plan, kubectl diff, a dry run of the pipeline). It never runs apply. A human reads the plan, compares it with the stated intent of the task, and applies from CI with their own credentials. The agent’s environment holds read-only credentials: enough to run a plan against the real state, nothing that changes it. Scoped tokens, a separate role, no admin session in a shell history file the agent can read. Treat the MCP servers wired to your cloud provider the same way, since a server with write scope on your account is an apply command with extra steps.
For experiments, give agents their own workspace or account: a sandbox subscription, a dedicated Terraform workspace, a namespace in a non-production cluster. There the agent can apply, break things and learn inside a boundary you drew on purpose.
Policy as code and plan checks in CI
Human review of a plan is the last gate, so put mechanical gates in front of it. Policy-as-code tools (OPA, Sentinel, Checkov, tfsec) run on every plan in the pipeline and reject the changes you never want to see without a named human attached: public ingress on a data store, a wildcard IAM action, a resource deletion, an unencrypted volume. A check that blocks any plan with resources to destroy, unless the pull request carries an explicit label, catches the renamed-resource trap on its own. These gates are the infrastructure version of the guardrails that belong in CI for application code, and they apply to humans and agents alike.
Small changes, explicit scope, and a review checklist
Size infrastructure tasks smaller than application tasks. One module, one environment, one concern. "Upgrade the RDS module to the new provider version in staging" is a task; "clean up the networking" is a week of incidents. State the scope in the task: which directories, which workspace, which resources must not appear in the plan.
When the pull request arrives, the reviewer reads the plan before the diff. The checklist we give teams fits on a card:
- IAM: new actions, principals or wildcards
- Networking: ingress rules, public IPs, peering
- Deletion: everything destroyed or replaced, and its data
- Data stores: encryption, backups, retention, deletion protection
- Pipelines: steps that gained credentials or lost a check
Anything that trips a line gets a second reviewer. The checklist exists because the postmortem after an AI-written change breaks production almost always finds a gate that said yes without reading.
Where agents help most on infrastructure, and where they should not go
The high-return work is the tedious kind. Provider and module upgrades, with changelogs read and deprecations listed. Refactoring copy-pasted Terraform into modules with variables, with an empty plan as the acceptance test. Documenting a legacy stack nobody fully understands, from the code and the live state, the first task we hand an agent on an inherited account, as on any legacy codebase. Drafting incident write-ups from logs and timelines.
Where they should not be: anything that applies to production unattended, rotation of secrets, changes to the identity provider, and emergency fixes during an incident, when nobody has time to read a plan and the temptation to let the agent "just fix it" is strongest.
The setup is a day or two of work: a read-only role, a sandbox workspace, a policy check in the pipeline and a checklist on the review template. After that, infrastructure becomes one of the better places to delegate, because the plan tells you what the agent intends before anything happens. Setting this up with a platform team is part of our work with engineering teams, usually right after the application side is running.