Where to Put the Approval: Human-in-the-Loop Is a Design, Not a Checkbox
A confirm dialog nobody reads has all the latency of oversight and none of the protection. Four placements, a routing rule based on reversibility, and the metric that tells you your gate has become a rubber stamp.
"Human-in-the-loop" gets written into agent designs as though it were a single feature. In practice it's a placement decision, and the same approval step is either a real control or theatre depending on where in the run it sits and what it shows.
The failure to avoid is the one that looks compliant: a confirmation dialog that appears so often, so late, and with so little context that approving becomes reflex. That system has all the latency cost of oversight and none of the protection.
Four places the human can go
Before the plan. The agent proposes what it intends to do; a person authorizes the whole sequence. Cheap — one interruption per run — and it's the right shape when steps are interdependent and the risk is in the strategy rather than any single action.
Weakness: plans change during execution, and an approval granted against the original plan doesn't cover what the agent actually did. Only workable if plan revision re-triggers approval.
Before each consequential action. Approval at the tool call, for a named subset of tools. Precise, and the human sees exactly what will happen with real arguments.
Weakness: interruption count scales with the work. This is where approval fatigue is manufactured — and an approval nobody reads is worse than none, because it launders responsibility.
After the action, before it takes effect. The agent acts into a staging state: the email is drafted but not sent, the PR is opened but not merged, the record is written with pending status. Review happens on the real artifact, asynchronously.
This is the most underused placement and often the best. The human reviews something concrete rather than a proposal, the agent isn't blocked, and the batch of pending items can be reviewed in one sitting rather than one interruption at a time.
After the fact, with undo. No gate. Everything is reversible and audited, and a person reviews a digest. Correct when actions are genuinely cheap to reverse and volume is high — and it beats a gate nobody reads, because at least the digest gets read.
The placement rule
Route by two properties of the action: reversibility and blast radius.
- Reversible, small radius → after the fact, with undo. Don't gate it.
- Reversible, large radius (mass email, bulk update) → staged. Review the artifact before it takes effect.
- Irreversible, small radius (a single refund within a limit) → policy check in code. A rule the agent can't exceed beats a human approving each one.
- Irreversible, large radius → gate at the action, every time, no batching, no defaults.
⚠️ Notice how much of this is not asking a human. Approval is expensive attention; spend it only where a code-level policy can't do the job.
What the approval screen must show
A gate is only as good as what it displays. The failure mode is a dialog saying "The agent wants to run send_bulk_email. Approve?"
Show, always:
- The exact arguments, not a paraphrase. Recipient count and the actual list. The real amount. The specific record IDs.
- What led here — the request that started the run, and the tool results that informed this call. Approval without provenance is a coin flip.
- What happens if declined. Does the run stop, skip, or take an alternative path? Reviewers approve out of uncertainty when refusal has unclear consequences.
- The irreversibility, stated plainly. "This cannot be undone" changes reading behavior more than any amount of styling.
✅ And make declining productive: let the reviewer supply a reason that goes back into the context. "No — this customer is on the enterprise plan, use the escalation path" both stops the action and teaches the run. A bare rejection often just produces the same call again.
🔍 Detecting approval fatigue before it costs you
Instrument the gate:
- Time-to-decision. A median under a couple of seconds means nobody is reading. That's the number to watch, and it's trivial to collect.
- Approval rate. Consistently near 100% means the gate isn't discriminating — either it's in the wrong place, or the policy behind it should be code.
- Rejections per reviewer. If one person catches everything, the gate depends on that person, and their vacation is an incident.
The takeaway
Human-in-the-loop is a routing problem: which actions get gated, at which point in the run, with what shown. Put policy in code wherever a rule can express the limit, stage what's reviewable as an artifact, gate only the irreversible and wide-reaching, and measure whether your reviewers are actually reading. A dialog that everyone approves in under a second isn't oversight — it's a receipt.