AI Can Prepare a DevOps Change. What Makes It Ready to Approve?
Part 3 of 3 in "Terraform with an AI co-worker: access, testing, review".
An AI agent had prepared a Terraform change: a storage bucket, message queues and an application identity across several environments. The tests showed that the application could use them. Before approving each next step, I asked a separate agent to review the work.
The reviewers found a rollback that would have tried to delete a bucket we hadn't created, a script that could save credentials under the wrong environment's name, and a handover document that promised access which wasn't ready.
These are the details that turn a small infrastructure ticket into extra work for several teams. They also explain why getting an agent to write the code is only part of automating DevOps routines.
Nine reviews ran over one week. Each took between half a minute and four minutes. That was the review runtime, not a measurement of the total effort or time saved. I still had to assess findings, resolve questions and approve the next step.
The reviews also missed a misleading claim in a draft of this series. That failure changed how I brief reviewers.
Part 1 covers access, Part 2 covers testing. This part is about the evidence I needed before accepting the agent's work.
Give the reviewer something it can check
The reviewer was a separate agent with a fresh context. It didn't see the conversation in which the work was done. That gave it some distance from the author's assumptions, but it could still make similar mistakes or inherit those assumptions through its briefing.
I gave it the ticket requirements, the material to review, and read-only access to the real environments where available. The material could be a plan, a code change, a script, a rollout procedure or a handover document. The author's conclusions were claims to verify.
The review instructions were straightforward:
- Read-only review: no deployments or changes, and never print secret values.
- Check relevant vendor documentation rather than relying on memory.
- Rank findings by severity and give a clear verdict, with any conditions or verification gaps.
- Keep the report short enough to use for a decision.
- Account for the actual setting: one operator, a private network and realistic operational risks.
That last point helped keep the reviews useful. A small change doesn't need every control a large organization might operate. It does need someone to notice that its rollback could delete somebody else's bucket.
The rollback would have undone too much
In one test environment, someone had created the bucket by hand before the ticket existed. The agent brought it under Terraform's management through an import, rather than creating a new bucket.
The merge request reviewer spotted the consequence. Terraform tracks the imported bucket just like a resource it created. Removing its resource definition and applying that configuration would normally propose deleting the bucket. Reverting our code wasn't enough to restore the situation before our work.
The bucket still contained an empty folder marker. With force_destroy disabled, that object would normally prevent Terraform from deleting it. But a rollback procedure shouldn't depend on a leftover object blocking a destructive operation.
The procedure gained an explicit step to remove the imported bucket from Terraform's state before applying the reverted configuration. That leaves the bucket itself in place. The resource definition must also be absent from the rollback configuration, or a later plan could try to create it again.
For the person approving the work, the useful question was: does rollback undo our change without undoing somebody else's?
The script accepted an environment name. It didn't use it to select the source.
After deployment, an existing script (that is not created as a part of subj effort) copied Terraform outputs into the secrets store used by build jobs.
The script accepted an environment name as an argument. But it read outputs from whichever environment Terraform currently had selected. If those differed, the script could save one environment's credentials under another environment's name.
The second credentials-and-procedure review found that mismatch by reading the script. A later review found another problem: it reported "saved successfully" even when the secrets store refused the write.
The rollout procedure gained an explicit check that Terraform's selected environment matched the intended deployment. That addressed the environment mismatch at the procedure level. Finding a bug in a helper script and permanently fixing that script are separate pieces of work; a procedure check still depends on being followed.
This is one reason I want automation reviewed beyond the new code. Existing helper scripts are part of the deployment too, including their assumptions and misleading success messages.
A successful plan hadn't proved deployment access
Part 1 described the move to temporary personal logins. In the first credentials review, the reviewer noticed that all the plans had run with state locking disabled.
Terraform's state records which real resources it manages. A deployment needs to update that state, and locking protects it against concurrent changes. The successful plans hadn't demonstrated either the required state writes or the disabled locking operations. Those permissions needed separate examination. Successfully acquiring a lock would not, by itself, prove permission to write the state either.
The read-only access checks described in Part 1 followed from that finding. They provided evidence about permissions without making a test write. They weren't an end-to-end deployment test.
For an approval decision, "the plan ran" and "the deployment has the access it needs" are different claims.
The handover document was ahead of the deployment
The agent also drafted a page for the developers who would upload and consume the files. A reviewer compared it with the live environments and found two must-fix problems.
First, the page said credentials were ready in all four test environments. Only one had them. Following that document would have sent developers looking for access that wasn't available yet.
Second, the page told the consuming application to skip files it had already processed. Elsewhere, it said that re-running an hour meant uploading the same marker file again. An application following both instructions could ignore a deliberate re-run.
Neither problem would have appeared in a test of the infrastructure alone. The handover needed to match both the deployed system and the application's intended behaviour.
A plausible resource count wasn't a verified plan
The merge request description said the production plan would create 13 resources. The final reviewer noted that nobody had run a production plan since the last resources were added. The number was arithmetic, not evidence.
The production procedure then required the saved plan to show exactly 13 creates, 0 changes and 0 deletes, or stop. A final pre-mortem review, prompted with "assume this deployment went wrong; how did it happen?", inspected that saved plan and confirmed the count.
The count was one check, not the whole approval. Thirteen creates can still be the wrong thirteen resources. The review also examined whether the production steps could change or delete existing resources.
Its verdict was "go", with four conditions. One was to record the names of keys already present in the production secret before adding new ones, and confirm that the previous version remained readable for rollback.
Where the nine reviews fitted
The reviews covered different parts of the work. They weren't nine passes over the same code.
| Checkpoint | What was reviewed | Result |
|---|---|---|
| Before writing code | Plan and supporting facts | No critical or major issues; five minor |
| Merge request | Code, scope and rollback | Ready, with caveats |
| Credentials and deployment procedure | Three review rounds | One major issue in each of the first two rounds; both addressed |
| Before test rollout | Rollout steps and helper script | Three major, six minor |
| Handover | Instructions for application teams | Two must-fix items |
| Before production | Final merge request check | Ready, with caveats |
| Before production | Pre-mortem and saved plan | Go, with four conditions |
The credentials and deployment procedure needed three rounds. The first found the unverified state-write access. The second confirmed the response to that finding and caught the environment mismatch in the script. The third found no critical or major issues, only six minor ones.
My default cap is two rounds, with a follow-up justified by a critical or major finding. Each follow-up checks the response to earlier findings before looking for new problems. I allow a third round to verify the response to a major issue from round two when the change involves production, an irreversible operation or a security control. This work qualified because it created production credentials.
The cap limits review effort - it doesn't make an unresolved major issue acceptable. If one remains at the cap, I have to stop the affected work or decide how to resolve it. Minor findings go onto a short list for human judgement rather than triggering another automatic round.
Reviewers can almost always find something else to improve ;) I need a process that ends in an informed decision.
What the reviewers still got wrong
The most revealing miss was in an early draft of Part 2. It said that a full deployment "would have deleted existing stored files". Two rounds of AI review passed that sentence.
The problem was in the briefing. The authoring agent had supplied a summary for reviewers to treat as ground truth. It said the deployment would have "deleted existing storage objects", without identifying the objects. The reviewers checked the article against that summary instead of the actual Terraform plan.
Then I asked: was data loss confirmed, or inferred?
The agent went back to the plan. The deletions were two empty folder markers that a colleague had deliberately removed from the code. Part 2 was corrected to say that.
The reviewers had checked consistency with the author's explanation. They hadn't verified the explanation itself. A fresh context doesn't fix that.
There were other limits too. The production pre-mortem claimed that the year-2000 date used in test filenames would stop a future consumer from treating them as real data. It wouldn't. The date was a naming convention. The relevant safety condition was that no application was reading those queues yet.
One merge request reviewer couldn't reach the real Terraform state and marked the plan numbers as unverifiable. That was a useful result. It told me exactly which part of the evidence was missing.
Some decisions also belonged elsewhere. The reviewers asked for confirmation of the queue visibility timeout, which determines how long a message stays hidden during processing, and whether repeatedly failing messages should go to a separate queue. The application developers needed to settle those questions before production.
I also retained responsibility for exceptions to my own rules. One reviewer flagged a step that required a secrets-store token in the shell. We wrote a small helper to issue a short-lived login for that step. The reviewer identified the problem; it didn't decide which access arrangement I should accept.
What I would automate for a team
This case gives me a practical starting point for helping a company automate DevOps routines: choose one recurring change and work through the whole path from ticket to handover.
I would first identify what the agent can investigate, which evidence it must return, where an independent check adds value, and who approves the next action. The same exercise exposes old scripts, unclear ownership and documentation gaps that can slow down human engineers too.
For this task, the agent investigated access, wrote code, built tests, and prepared and checked the rollout. My work included setting the review conditions, challenging findings, resolving exceptions and deciding whether the evidence supported proceeding. That division of work is the part I would want to make repeatable.
I would measure the total effort before extending it: preparation, reviewing findings, rework and interruptions, as well as agent runtime. Nine quick reviews demonstrate that this extra checking was feasible for this change. They don't establish a time-saving percentage or prove that every ticket needs the same process.
A team trying this should finish with a concrete approval package: the proposed change, the evidence behind it, unresolved questions and a rollback procedure. The reviewer needs access to the underlying plan, diff or live facts, with the author's summary clearly separated from them.
The misleading sentence in Part 2 is why I care about that separation. Adding another agent was easy. Making it check the right evidence took more thought.
This is Part 3 of "Terraform with an AI co-worker: access, testing, review". Part 1 covered access; Part 2 covered testing.
Technical references: removing a resource from Terraform state, S3 backend permissions and locking, S3 bucket force_destroy, and SQS dead-letter queues.
