shubhanshu.cloud
← All writing

Propose, Guard, Approve, Audit: Why an AI Cloud Agent Shouldn't Get to Touch Prod Alone

Every few months another vendor demo shows an AI agent that provisions cloud infrastructure from a plain-English sentence. Type "give me a secure S3 bucket for logs" and watch Terraform appear. It's a good demo. It's also, on its own, a governance incident waiting for a Tuesday afternoon.

I've spent fifteen years on the side of the business that has to live with what infrastructure automation does at 2am — the SWIFT compliance releases, the retail platform migrations, the audits where someone asks "who approved this security group rule" and the honest answer is nobody, exactly, it just got applied. So when I set out to build an AI infrastructure agent as a portfolio piece, the interesting problem was never "can an LLM write Terraform." It's whether you can build a system where an LLM writing Terraform is actually safe to run against a real AWS account. Those are different questions, and most demos only answer the first one.

The shape of the problem

A language model is a good proposer and a bad enforcer. It's genuinely useful at turning "I need somewhere to land application logs" into a first draft of Terraform, and even better at fixing that draft when something's wrong with it. What it shouldn't be trusted to do on its own is decide that the draft is correct — correct meaning compliant with your org's tagging policy, priced within budget, free of the security misconfigurations that show up in a Checkov scan, and something a human actually meant to approve.

The instinct to fix this with a longer, sterner system prompt doesn't hold up. A system prompt is a suggestion the model is statistically likely to follow. A policy you actually need enforced belongs in code that runs independently of the model and fails closed when it can't get a clear answer.

The pipeline: propose, guard, approve, audit

The architecture I landed on splits the work into four stages that don't trust each other by default:

  1. Propose. A ReAct agent takes the plain-language request, retrieves relevant policy and pattern guidance from a small knowledge base — org tagging rules, approved module templates, security standards — and drafts Terraform grounded in that retrieval rather than the model's general training. It has tools to validate its own syntax and re-check itself, so a chunk of the self-correction happens before anything leaves this stage.
  2. Guard. A second, deliberately non-LLM stage re-parses the generated Terraform independently and checks it against the same rules the agent was told to follow — variables, regions, tags, encryption, network exposure, IAM scope — then runs a security scanner and a cost estimator against it. Nothing here asks the model's opinion. It's a deterministic gate that either approves, sends the draft back with specific feedback for another attempt, or drops the request outright. If any check errors instead of returning a clear answer, the default is drop, not proceed — the same fail-closed instinct you'd want from any compliance gate in a regulated pipeline.
  3. Approve. Anything that survives the guard stage still doesn't execute automatically. It pauses for a human to look at the actual Terraform, the cost estimate, and the scan results, and make the call. This is the stage most agent demos skip entirely, and it's the one that matters most the first time an agent is wrong in a way nobody anticipated.
  4. Audit. Every request leaves a record of what happened to it and why — approved, sent back for self-correction, refused by the agent itself, or dropped by the guard — because "the agent didn't do the thing" and "the agent tried to do the thing and was stopped" are different facts, and only one of them tells you your guardrails are working.

What building it actually taught me

The genuinely useful moment in this project wasn't watching the happy path work. It was a run where I asked for infrastructure in a region outside the org's approved list. The agent drafted it, the guard stage caught the region mismatch on its own — no model in the loop for that decision — and dropped the request in a single pass, no retries wasted on a request that was never going to be approved. That's the behavior you actually want from a compliance gate: fast, deterministic, and correct without needing to ask an LLM to grade its own homework.

The second useful moment was messier and more honest: an early draft had invalid HCL, the validation tool caught it, and the agent read the error and fixed its own syntax on retry. That's the ReAct loop doing what it's supposed to do — but it also underlined why that loop can't be the last line of defense. Self-correction is great for syntax. It's not a substitute for a policy check that doesn't care how confident the model sounds.

Where this is headed

The version running today handles the natural-language provisioning path end to end, with the approval step currently a stand-in for what becomes a durable, resumable human-in-the-loop gate — the kind that can pause a request for hours or days and pick back up exactly where it left off, not just a synchronous prompt in a terminal. The same propose-guard-approve-audit shape is designed to extend to two sibling agents I have planned: one focused on FinOps cost advice, one on scanning existing Terraform for security drift. Same pattern, different domain — which is really the point. The pattern is the reusable part; the domain is just where you point it first.

If there's one opinion I'd defend from fifteen years of watching automation meet production: the interesting engineering in AI infrastructure agents isn't getting them to generate correct output. It's building the parts around the model that don't need to trust it to be correct.