Plan-and-Apply for AI Agents
Plan-and-apply is the pattern of splitting a change into two steps: first a plan is computed, an exact and reviewable description of what will change, and then, only after a person approves that specific plan, an apply step carries it out. The pattern was made familiar by infrastructure tools, above all HashiCorp's Terraform, whose plan and apply commands became the standard way to change cloud infrastructure. As of October 2026 it has become one of the main ways to let AI agents act on real systems without giving them unchecked write access: the agent proposes, a person disposes, and the system guarantees that what gets applied is exactly what was approved.
Where the Pattern Comes From
In Terraform, terraform plan compares the desired configuration with the recorded state of real infrastructure and prints every resource it would create, change or destroy. With -out, the plan is saved to a file, and terraform apply given that file carries out exactly the saved plan without asking again; HashiCorp's documentation puts it plainly: "Terraform interprets the act of passing the plan file as the approval." If the infrastructure's state changed after the plan was made, Terraform refuses the saved plan as stale rather than applying it to a world it no longer describes. HashiCorp's hosted service turned this into a pipeline: a run plans, passes through policy checks and a cost estimate, and then waits in a "Needs Confirmation" state until someone approves it.
Other infrastructure tools converged on the same split. Atlantis runs Terraform's plan and apply from pull-request comments, and can require the pull request to be approved before an apply is allowed. Pulumi previews every update before running it and, as an experimental feature, can save a preview as a plan that the update must not go beyond. Kubernetes offers kubectl diff and server-side dry runs, which pass a change through validation and admission without saving it, and rejects writes made against an out-of-date resource version. Ansible's check mode simulates a playbook and, with --diff, shows what would change. The common idea is that a dry run must be both accurate (it shows what will really happen) and binding (what happens afterwards can't silently differ from it).
Why Agents Need It
An agent can take actions far faster than a person can watch them, and its account of what it did is generated text, not a measurement. Supervising every step doesn't scale, and trusting the agent's summary isn't safe. Plan-and-apply moves the human in the loop to the one point where judgment is cheapest and most useful: a concrete, complete proposal, before anything irreversible happens. It fits the "calibrated autonomy" approach that production agent harnesses use, in which reads and reversible actions run freely and consequential writes are gated.
It also changes what the agent is good for. Instead of asking a model to be right every time, the system asks it to produce a good proposal and to explain it, which is a task models do well, and leaves acceptance to a person or a policy.
Anatomy of a Safe Plan
A dry run on its own is not enough. The approval has to be tied to the exact plan, or an agent (or a bug) can approve one change and apply another. Robust implementations share six properties:
- The plan is computed, not narrated. The system, not the model, resolves the proposed change into a concrete diff. A model's prose summary can be shown alongside it, but the diff is what gets approved.
- It is bound to a base state. The plan records the version it was computed against. If anything changed since, the apply is refused or the plan is recomputed, the same optimistic-concurrency check (compare-and-swap) that databases and version control use.
- Approval is bound to the plan's identity. The confirmation is tied to a hash of the plan, typically with a keyed signature such as an HMAC, so approving plan A can't be replayed to apply plan B.
- Approval expires. A confirmation that stays valid forever invites stale applies; a short expiry forces a fresh look.
- Approval rights are separate. The agent can request a change but can't approve it. Some actions, such as publishing or approving a final version, are reserved for people altogether.
- The result is recorded. Each apply produces an immutable record of what was applied, against which base, and who approved it, so the history can be audited and reversed.
Implementations in Agent Tooling
Agent frameworks have built the same split into their primitives. Claude Code's plan mode lets the agent research and propose without editing anything until the person approves the plan. The OpenAI Agents SDK lets a developer mark a tool as needing approval; the run pauses with an interruption, and resumes only after the call is approved or rejected. LangGraph's interrupt saves the graph's state at a checkpoint and waits for a human response before continuing. The Model Context Protocol's specification says that "there SHOULD always be a human in the loop with the ability to deny tool invocations," and that clients should ask for confirmation on sensitive operations.
These primitives give a person the chance to say no. They don't, on their own, guarantee that what was approved is what runs: that depends on how the plan is bound to the apply, which is where the properties above come in. The web has long had the binding half of the pattern: HTTP's If-Match header ties an update to the exact version the client saw and fails with "412 Precondition Failed" if it changed, and payment APIs such as Stripe's use idempotency keys so that a retried request runs only once, and a reused key with different parameters is rejected.
Creative tools are adopting the same structure. In agentic video editing, a proposed cut is checked and previewed before it is saved as a new revision. One AI video harness binds each confirmation to the exact plan's hash: its check step returns a confirm token bound by HMAC to the plan hash, the base revision and a 30-minute expiry, and its apply step refuses to save without that token. Approving a finished revision is reserved for a person. Because the edit is stored as data, as in video as code, the "plan" is a precise diff of shots, trims and levels rather than a description of intent.
How It Fails
- Rubber-stamping. If every action needs approval, people stop reading. Gate only consequential changes, and make plans short enough to review.
- Plans that are too abstract. "Update the configuration" is not a plan. The reviewer needs to see the actual changes, with the risky ones called out.
- A narrated plan that diverges from the real one. If the model writes the summary and the system computes the diff, the two can disagree; the diff must win.
- Dry runs with side effects. A "check" that quietly writes, sends or spends breaks the whole contract.
- Replayable approvals. A token that isn't bound to one plan, one base and one time window can be reused for a change no one saw.
Where It's Headed
The direction is toward policy-graded plans: low-risk plans approved automatically by rules, with people reviewing only exceptions and high-impact changes. That keeps the guarantee, that nothing is applied which was not planned and checked, while reducing the review burden that causes rubber-stamping. It connects plan-and-apply to agent reliability and agent evals: the plan is also the natural unit to log, score and audit.
Further Reading
- terraform plan and terraform apply — HashiCorp's documentation of the original pattern
- Plan mode — Claude Code documentation
- Human in the loop — OpenAI Agents SDK documentation on tool approvals
- Tools — Model Context Protocol specification, including its human-in-the-loop guidance
- RFC 9110, If-Match — the HTTP mechanism for preventing lost updates