Human approvals for AI agents without approval fatigue
Require a person only where the action is irreversible or expensive, hold that action and nothing else, and record the approval next to the policy decision that asked for it.
A human approval for an AI agent is a hold on one specific action until a named person accepts it. The design question is which actions deserve that hold, because an approval on every action trains people to click through, and a click-through is worse than no approval at all: it looks like a control and behaves like a rubber stamp.
Which actions deserve an approval
Apply five tests. Is it irreversible? Is it visible outside the company? Does it spend money? Does it change production? Does it grant access to data or credentials? An action that fails all five is not an approval case, and pretending otherwise is how a program loses its approvers.
| Action | Reversible | Visible outside | What it needs |
|---|---|---|---|
| Edit a file in a worktree | Yes | No | A record, nothing more |
| Push to a feature branch | Yes | No | A sequence gate, no approval |
| Open a pull request | Yes | No | A record |
| Merge to main | Mostly | No | A gate plus review |
| Force push to a protected branch | No | Possibly | A deny, not an approval |
| Deploy to production | No | Yes | An approval |
| Turn on a production flag | Yes, if caught | Yes | An approval for the switch-on |
| Read customer records at volume | Yes | No | A gate on volume, an approval on export |
| Send an email to a customer | No | Yes | An approval |
| Place an order or issue a refund | No | Yes | An approval above a threshold |
| Grant a role or mint a token | No | No | An approval |
Scope the approval to the action
Approving a session is the mistake to avoid. The hold should name the exact action with a digest: github.pr.create for a repository, base and head commit; git.push to main at a given commit; a deploy of one revision to one environment. If the action changes, the approval does not carry over.
Three properties do most of the work. Single use, so one acceptance releases one action. An expiry, so a hold from yesterday cannot release a change today. And a question the approver can answer without reading a transcript, because an approval that requires twenty minutes of context will be given without any.
Write the rule so it carries all three, in words a person can answer: "Before a pull request is created against main, the ticket owner approves this diff, once, and the approval expires after 24 hours." If the policy engine in front of the action can also answer questions on its own, keep those answers out of the approval path. The acceptance that releases the action has to come from a named person, and a model's confidence is not a person. Anything the rule does not settle goes to a person instead of to a default.
Approve at the boundary, not inside the loop
A session can issue a few hundred tool calls. That is a few hundred prompts, and the only rational human response is to press yes. Put the hold where the action crosses a line that can wait: opening the pull request, pushing to a protected branch, deploying, sending, paying.
In-loop prompts still have a place for actions that must not proceed at all. Those are better expressed as a deny with a clear error than as a question, because a deny is deterministic and a question needs a person who may be asleep. A hold nobody answers is a policy outcome nobody chose on purpose.
Where the vendors stand matters here. Claude Code has a PermissionRequest hook event that fires when a tool call needs a permission decision, and its permission rules can ask (hooks reference, permissions). Cursor's hooks accept permission: "ask" for beforeShellExecution and beforeMCPExecution, while the same field is accepted and not enforced for preToolUse in its current docs (hooks reference). Codex pauses through approval_policy, and administrators can restrict which values a machine may run (sandbox and approvals). All three ask inside one vendor's client, and the answer is recorded there. Claude Code can also export it: its OpenTelemetry events include claude_code.tool_decision, with accept or reject, the source of the decision and the tool_use_id that joins it to the tool call (monitoring). What you do not get from any one vendor is one approval record across three vendors, tied to the commit and to the release, with integrity you can check later.
Record the approval with the decision
The approval belongs in the same chain as the policy decision that asked for it: the rule id, the question as shown, what the approver could see (the diff digest, the command, the target, the revision), who approved, when, what they decided, and when it expires. The record then says that a rule held this action and that this person released it, which is what an auditor actually wants to read. An approval that lives in a chat channel proves that someone typed "ok" somewhere.
Monitor first, then enforce
Approvals fail on human throughput, so measure before enforcing. Run the rule in monitor mode, where Alyria Beacon records what it would have held without holding anything (rollout), and read four numbers for a week:
- Holds per engineer per day. Low single digits is a program. Thirty is a formality.
- Share approved without a change. If it approaches 100 percent, the rule is either wrong or should be a gate instead.
- Median time to answer. Compare it with how long an agent session waits before it gives up.
- Holds still unanswered at the end of the day. Each one is a blocked agent and a person who did not see it.
Promote one rule at a time, starting with the action that would hurt most if it went wrong once.
Practices that keep it honest
- Name a backup approver and an escalation path, so a hold does not silently become a deny because the owner was on leave.
- Do not let the agent choose the approver. The rule names the role or the person.
- Do not allow self-approval. If the reviewer started the agent, the approval is theatre, so route it to someone else.
- Do not route approvals to a shared mailbox. An approval needs one accountable name.
- Expire approvals quickly and keep them single use, so an approval for revision one cannot release revision two.
- Keep routine work free of human gates, or the first busy week will remove the rule for you.
A reasonable first set
Three rules, one per risk class, all in monitor mode to begin with: a deploy to production needs the service owner, sending anything to a customer needs the account owner, and granting a role or minting a token needs a security reviewer. Everything else is a gate or a record. That set produces a manageable number of holds, covers the actions you cannot undo, and gives you evidence from the first week.
That is the approvals layer of governing agents across the SDLC, alongside the evidence to keep and where the gates go. The vendor approval behaviour comes from their own docs, read in November 2026, and the properties above are what an approval needs in order to mean anything, whichever console shows it.