On this page · 10 sections
- Why does the pop-up fail?
- Make the decision visible
- Bind the approval to what executes
- Why is confirmation not approval?
- Decide in the system what needs a gate
- Give people more than “allow” or “deny”
- Keep the path resumable
- Design the record with care
- Approvals are also a measurement surface
- Frequently asked questions
A human approval workflow for AI agents is the part of a run where a consequential action stops, a person sees what is proposed, and the agent continues from their answer. Frameworks often call it a human-in-the-loop approval. It is a handoff, and it deserves the same design attention as any other. A useful approval names the action, its scope, and its consequence; shows what information the agent used; offers more than allow or deny; is bound to the exact operation that later runs; keeps the task resumable afterwards; and records what happened without over-collecting. A confirmation dialog does none of that, and a confirmation is not an approval unless your system can tell that a person gave it. Encode which actions require a gate in the system rather than trusting the model to decide, because descriptive metadata is not a security boundary.
A person needs to understand what the agent proposes to do, what will change, what information it used, and which choices remain available. The agent needs a clear way to pause, receive a response, and continue without losing the thread.
Why does the pop-up fail?
A modal that says “The agent wants to run send_invoice. Allow / Deny?” fails for four separable reasons.
It shows a decision without its basis. The person cannot see which customer, which amount, which source document, or which prior step produced the proposal. They are being asked to underwrite a conclusion whose evidence is hidden.
It offers the wrong choices. Real work rarely comes down to yes or no. The right answer is often “yes, but to a narrower scope”, “not until you check X”, or “no, use the other path”.
It spends attention the reviewer does not have. A gate that appears for every action, consequential or not, soon becomes a keystroke. Anthropic gives one vendor figure for how fast this happens. In an engineering post of 25 May 2026, How we contain Claude across products, it reports that its telemetry showed users approving roughly 93% of Claude Code permission prompts, and that the more approvals a person sees, the less attention they pay to each. That is a vendor’s measurement of its own product and its own, mostly developer, users, with no published method, so read it as one company’s report rather than a rate for other products. Anthropic’s response was fewer prompts rather than more: a sandbox at the operating-system level, and an auto mode in which a classifier decides which commands to approve. A June 2026 preprint by Emre Turan, Oversight Has a Capacity, puts that concern on firmer ground. On a hand-labelled set of 125 agent actions, reviewers agreed only moderately about which ones were risky (a Fleiss’ kappa of 0.52), so a gate often has no single correct label to aim at. When the paper then models a reviewer who tires as escalations accumulate, realised safety rises and then falls as the escalation rate grows: past a point, sending more to a person makes the system less safe, and a flood of requests can carry a harmful one past a worn-out reviewer. The author presents the fatigue results as a model that motivates a study with people, and they should be read that way. Either way, human attention is finite, so decide deliberately which actions spend it.
It costs the workflow its state. If denying means the agent starts over, people learn to approve rather than pay the restart cost, which defeats the point of the gate.
The Model Context Protocol points the same way. Its tools specification says there should always be a human in the loop with the ability to deny tool invocations, and its security best practices warn that broad scopes granted up front widen the damage a stolen token can do and lead people to decline consent screens that ask for too much. So put friction where the consequence is, instead of adding as much as possible.
Make the decision visible
A useful approval names the action, its scope, and its consequence. It should distinguish a harmless read from an action that changes data, reaches an external system, or commits a customer-facing result.
Five elements make an approval readable:
- The action, in the user’s language. “Email the September invoice to Acme Ltd”, rather than
POST /v2/invoices/send. - The exact scope. Which record, which recipient, which amount, which time window. Specifics are what let a person review the action instead of rubber-stamping it.
- The consequence and its reversibility. “This sends an email immediately. It cannot be recalled.” This sentence sets how careful the person needs to be.
- The basis. The two or three inputs the agent used to reach this proposal, with links to them.
- The alternatives. What the agent will do if refused, and what other paths exist.
An approval payload with that shape is easy to specify. The example below is illustrative, and the API it describes is invented:
{
"action": "send_invoice",
"summary": "Email invoice INV-2291 (£4,320.00) to billing@acme.example",
"effect": "external",
"reversible": false,
"scope": { "invoice_id": "INV-2291", "recipient": "billing@acme.example" },
"basis": [
{ "label": "Ledger entry", "ref": "ledger/2026-08/acme" },
{ "label": "Approved quote", "ref": "quotes/Q-1180" }
],
"options": ["approve", "approve_with_changes", "request_info", "reject"],
"expires_at": "2026-09-02T09:00:00Z"
}
effect and reversible are structural fields. They determine whether this action needs a gate at all, and your system should make that decision, not the model.
Bind the approval to what executes
An approval is a control only if the operation the person approved is the operation that runs. Two recent preprints show how easily that link breaks, and what it takes to keep it.
The first, Loopjacking: Hijacking Human-in-the-Loop Approval by Adithyan Arun Kumar (September 2026), names the failure in which a person approves what they understand as one operation while the system uses that decision for a materially different one. The paper separates two variants:
- Representation mismatch. The different operation is already encoded when the request is shown, but the approval screen leaves it out or misdescribes it. The person reviews an accurate-looking summary of something else.
- Substitution after approval. The person sees the correct operation, and mutable workflow state, such as a pending call or its stored arguments, is replaced between the decision and the execution.
The author tested a purposive set of released agent products, and the paper names each product and the exact versions tested. It reports substitution after approval reproduced in specific released versions of two agent frameworks, and representation mismatch in one release of a third agent product, whose following release rejected the mismatched request. An agent SDK served as a negative control: it serialised each pending call, kept an exact per-call binding and rejected the altered operation. The paper states plainly that these results do not estimate how common the problem is. Read it as a demonstration that the binding can fail in shipped software, limited to the versions it names, and as no statement about any product’s current releases. The defences it reports are structural: render the complete, canonical operation at approval time and compare it exactly at use time, or stop pending state from being changed without authorisation.
The second, What You Approve Is What Executes by Xiaoqi Weng (June 2026), starts from the observation that a coding agent’s approval dialog is often narrated by the agent itself, so the person approves a summary the agent wrote. It names the missing property Consent Integrity, adapting the “What You See Is What You Sign” idea from electronic signatures: the action shown to the person should be rendered by a trusted mediator from the real action at the system boundary, over a path the agent cannot spoof, and bound to the exact action that executes. The prototype also shows the cost. On an independent corpus of 1,330 known misuses of trusted command-line tools it silently passed 10.0%, and on 28,798 ordinary commands it marked 87.0% as uninspectable rather than approving them unseen. The author presents this as an open trade-off rather than a finished defence.
Two further preprints from September 2026 widen what “the operation” has to include.
Agent Approval Laundering by Jinqian Zhang and colleagues (23 September 2026) looks at what an approved command sets off. A person approves a package install, but installing a package can run the package’s own scripts and write files, and one MCP call can reach the network. The approval record names the command the person saw and leaves out these further effects, which the authors call approval laundering. On 111 fixed pairs of approval records and execution traces from coding-agent tools, the records that still left out an effect fell from 40 with explicit fields, to 17 when the command’s meaning was used, to 13 with the details available at decision time (the paper’s figures, on its own benchmark). The authors propose predicting, before the decision, what the workflow behind a call will touch, and storing that prediction with the approval.
When Consent Outlives Context by Zhihao Zhang and colleagues (27 September 2026) looks at approvals that persist across tasks or sessions. An attacker first arranges harmless requests that earn a standing approval, then reuses that leftover authority for something the person never agreed to. On 508 attack cases from the AgentDojo benchmark, across six families of models, leftover authority raised attack success by up to 35.1 percentage points compared with a fresh start, and by 24.9 points on average in live tests on 55 Terminal-Bench tasks with three production coding agents. Those are the paper’s figures, for the models and agent versions it tested.
Seven rules follow for an approval you design:
- Render the request from the call. The component that will execute the operation should produce the summary the person sees, from the same structured arguments it will send. The agent’s explanation can sit beside it, labelled as the agent’s.
- Store the approved operation with the decision. Keep a canonical copy or digest of the call that was approved, and compare the call against it at execution time. Any difference goes back for approval.
- Freeze pending requests. While a request waits for a decision, only the reviewer’s own edit should be able to change it.
- Bind edits too. When someone approves with changes, the edited call becomes the approved operation, and it is the one compared at execution.
- Say when the system cannot tell. If the harness cannot work out what an action will do, show that plainly instead of a confident summary.
- Show what the call sets off. If an approved command runs other things, such as install scripts, hooks or further network calls, name them in the request or treat them as separate actions with their own decision.
- Let approvals lapse. Tie an approval to the task it was given for and let it expire, rather than keeping it as a standing grant that a later task can reuse.
Why is confirmation not approval?
A confirmation is any “yes” that reaches your system. An approval is a decision a person made, with the facts in front of them, about the exact action that will run. The two can look identical in a log, which is the problem. A confirmation counts as an approval only when your system can tell that a person gave it.
Take the invoice from earlier. Five different things can arrive at the server that sends it, and only some of them are a person’s decision:
| What reaches your server | What it shows | Treat it as |
|---|---|---|
The agent’s call carries "user_confirmed": true |
The model wrote a field | Not approval. Anything the agent can write, it can write wrongly. |
| A confirmation form answered through the person’s client | The client returned “accept” | A guardrail. Some clients answer these forms automatically. |
| A click in your own signed-in interface, or on a link bound to the account | This account acted | Not enough alone. An agent driving a browser signed in as the person can click it too. |
| A decision by a route the agent cannot operate, such as your app on the person’s phone, from someone your policy allows to approve | A person decided on this request | Approval, if the request they saw is the one that runs and it has not expired. |
| A standing rule the person set earlier, such as “allow invoices to existing customers” | A person decided in advance, in general | Approval only inside the rule’s scope, recorded as a rule rather than a fresh decision. |
The table is this guide’s working vocabulary, not a standard. Each row can be seen in products shipping now.
Supabase says plainly that its confirmations are guardrails. Supabase’s MCP server documentation, as retrieved on 8 October 2026, uses MCP elicitation (a way for a server to pause a tool call and ask the person for input) for two kinds of risk. Before create_project or create_branch adds a charge, the client shows the resource, the standard rate and the billing interval, and the call goes ahead only if the person accepts. The confirmation is valid for a short time, and the cost is checked again just before creation. Before execute_sql or apply_migration runs SQL that it detects as destructive, it asks again. The documentation then adds a caveat: “Treat elicitations as a guardrail, not a guarantee of human review or approval. Some clients support hooks or rules that answer elicitations automatically.” A skip_elicitations setting can also turn the forms off for named tools. The server knows that a client said yes. It cannot know that a person did, and it says so.
Secrets should never pass through the model. The same server takes a different route for secrets. Its create_edge_function_secret tool asks only for the secret’s name, and the person types the value into the Supabase Dashboard, “never in chat, model input, or MCP tool arguments”. This follows the MCP elicitation specification (2026-07-28), which forbids servers from using form mode to ask for passwords, API keys, access tokens or payment credentials and requires URL mode instead, so that the value never enters the model’s context or the client. In URL mode the server must also tie the request to the user’s identity and check who opens the link, usually through a session cookie. That tells the server which user opened it, not that a person rather than an agent in their browser did; clients should, not must, offer approval controls. OpenAI’s computer-use documentation for its Agents API makes the same separation for signing in: sign-in values, verification codes included, go through a separate event that keeps them out of the model’s input and saved history.
Only the right person can approve. Vercel’s open-source agent framework, eve, changed its default in release 0.72.0 (7 October 2026). An approval without its own response policy can now be granted or cancelled only by the person whose turn requested the call, so in a shared thread someone else can no longer run a tool under another person’s turn. A tool that genuinely needs a different approver has to say so in its own policy.
Approving access is not approving an action. In OpenAI’s computer use for the Agents API (documentation retrieved 8 October 2026), the person approves each new website the agent’s browser may open. The documentation warns that this origin approval “does not enforce confirmation before individual actions”, and that asking for confirmation through a function tool “relies on the agent calling that function”. Where a purchase or a destructive change must be confirmed, it advises limiting what the browser can reach, or running a browser you control.
Approval can live in the service that moves the money. Stripe’s Link wallet for agents (announced 29 September 2026; documentation retrieved 8 October 2026) puts the decision in Stripe’s own app. The agent creates a spend request with the amount, the seller and a description of at least 100 characters, which is what the customer reads. The customer approves it on the Link website or in the Link app, and only then does the agent receive a one-time payment credential. The customer has 10 minutes to answer, and raising the amount means asking again. Approval in the Link app is the table’s fourth row, apart from the agent’s session; approval on the Link website holds only if the agent’s browser cannot reach it.
Decide in the system what needs a gate
The most common design error is leaving “is this consequential?” to the agent’s judgement.
The Model Context Protocol specification (2026-07-28) is explicit that tool annotations, such as read-only, destructive and open-world hints, are untrusted unless the server providing them is trusted, and that the client and server must still validate and authorise. Those hints are useful for selection and for shaping the interface, but they are not a boundary. The model reasons over metadata, and the harness enforces execution.
So classify actions server-side, by effect. The table below is a suggested default treatment rather than a standard or a compliance requirement:
| Effect class | Examples | Default treatment |
|---|---|---|
| Read, contained | Search, fetch a record, summarise | No gate; sample in review |
| Write, internal, reversible | Draft, tag, create a private note | No gate; visible in history |
| Write, internal, irreversible | Delete, overwrite, close | Gate, with an undo window where possible |
| External or customer-visible | Send, publish, pay, provision | Gate, always |
| Scope escalation | New permission, wider access, new system | Gate, with step-up authentication |
That last row has a standards answer. OAuth’s step-up authentication challenge (RFC 9470) exists for the case where an in-progress session’s authentication level is insufficient for what is now being requested, and Rich Authorization Requests (RFC 9396) allow a grant to carry fine-grained authorization_details rather than a coarse scope. The broader OAuth 2.0 Security Best Current Practice (RFC 9700) is the baseline. Where a delegated grant is involved, it should answer four questions plainly: who, for which resource, for what scope, and for how long.
An approval cannot repair an over-broad grant. WorkOS, which sells an authorisation product, describes a confused-deputy case in which an agent holding permission to read secrets posts one into a shared channel at the request of a developer who had no such access: each party acted within its own permissions, and nothing checked the intersection. Its argument is that an agent acting for a person should hold a subset of that person’s permissions. A gate placed on top of a grant that is already too wide asks the reviewer to catch what the permission model should have prevented.
Standing rules are a tempting way to cut the number of prompts: the person decides once, in advance, which kinds of action to allow, which to ask about and which never to allow. A preprint by Ting Yan, Do User-Authored Permission Policies Improve Protection Against AI Agent Overreach? (27 August 2026), tested this with 113 participants without software backgrounds. Each supervised a scripted, simulated day of 18 agent actions, seven of which went beyond what the person had asked for. People who wrote allow, ask and never rules let through more of those seven than people who approved every action one by one: the rules blocked 20.1 percentage points less of this overreach than per-action approval (95% confidence interval 8.1 to 32.1 points less), and 14.5 points less than automated review by a model. Participants chose “ask” for 114 of their 140 rules, so most decisions came back at run time anyway, and of the 148 overreach actions that ran under rules, 133 ran because a person approved them when asked. The author names the limits: one scripted day, no real consequences, four broad categories, and no live model in the sessions. The design lesson is narrow. A rule does not settle a decision that people still want to make case by case, and an approval request should say plainly when an action goes beyond what the person originally asked for.
There is a further case that deserves an automatic gate: any consequential action taken after the agent has ingested untrusted content. Indirect prompt injection is a demonstrated attack (Greshake et al., 2023), a 2026 in-the-wild study documented injections that were hidden across many models and page representations, and design-pattern work by Beurer-Kellner et al. (2025) argues the reliable mitigation is to narrow the consequential actions available once untrusted input has entered. In approval terms: reading a stranger’s document should change what the agent is allowed to do next without asking.
Give people more than “allow” or “deny”
Real work often needs a third option: revise the request, choose a narrower scope, supply missing information, or send the task back for a different path. With them, the handoff becomes part of the workflow instead of an interruption to it.
Four responses cover most situations:
- Approve. Proceed as proposed.
- Approve with changes. The reviewer edits the scope or the parameters, and the agent proceeds with the edited version. This is the option most systems omit and most reviewers want.
- Request information. The reviewer asks a bounded question; the agent answers and re-proposes. The MCP tools specification supports multi-round-trip flows for exactly this shape, where a tool needs more input before it can complete.
- Reject with a reason. The reason is the valuable part, because it is a product signal about a workflow that proposed the wrong thing.
People who use agents every day ask for the same distinctions. A study by Larissa Salerno and colleagues, Let the Agent Do It? (preprint, 5 October 2026), interviewed 18 software practitioners and then surveyed 115 about how they decide what an agent may do. Its recommendations for permission systems are to make consequential actions easier to review, to separate what an agent is allowed to do from what the person intended, to make reversibility clearer, not to treat repeated approvals as a stable preference, and to tell rejecting one action apart from rejecting the whole approach. The last point is a reason to keep “reject this step” and “try a different path” as separate answers.
Approvals also need an expiry. An approval request that sits unanswered for two days can lapse cleanly rather than execute later against stale state. Products already do this. Supabase’s cost confirmations are valid only for a short time, and Stripe gives the customer 10 minutes to answer a spend request before it expires. The residual-authority preprint above shows the risk from the other side: an approval that outlives its task becomes authority that someone else can reuse.
Keep the path resumable
After someone responds, the system should know what was approved, what changed, and what still needs to happen. Neither the person nor the agent should have to rebuild the whole task from scratch.
Resumability requires three things. The agent’s working state must survive the pause: the goal, the steps already completed, the artefacts produced. The reviewer’s decision must be attached to the specific proposal, including any edits they made. And the resumed run must be able to detect that the world moved while it waited: an approval granted against a record that has since changed should re-verify rather than proceed.
Two recent products make the pause a named state rather than an error. Browserbase (changelog, 24 September 2026) lets a run say in plain language when it should stop for a person, such as “an MFA or verification code is required”. The run enters a PAUSED state and later resumes in the same browser session with a follow-up task. In Browserbase’s own example the code travels back inside that follow-up task, so it passes through the model and stays in its transcript and logs after it expires. This guide recommends protected entry instead, as in OpenAI’s computer use above. Stripe’s spend requests return a next_action when something needs attention, with a resolution that tells the agent what to do next and, where the step belongs to the customer, an action_url to send them to. A 3D Secure check resumes the same request on its own once the customer completes it, while a declined card means a new request after the customer picks another card. The agent is told which part is its own job and which part is the person’s.
This is the same discipline as any handoff between actors. An agent context handoff should carry the reason for the work covers the general case; approvals are the version where the receiving actor is a person with limited time and no context.
When the answer is “no”, resumability matters just as much. A rejection should leave the agent with a usable next state (a narrower plan, a question to ask, or a clean stop) rather than an abandoned run. That is the recovery argument in Agent error recovery belongs on the main path.
Design the record with care
Teams should be able to understand what happened later without exposing more information than the task requires.
A defensible record answers: what was proposed, on what basis, who decided, what they changed, when, and what happened next. NIST’s AI Risk Management Framework frames trustworthy AI as balancing accountability and transparency with security and privacy in context, rather than maximising any one of them, so more logging is not automatically better governance. Provenance work in adjacent fields makes the same trade explicit: too little provenance is useless, and too much leaks internals.
Two practical rules follow. Redact by default at write time, not at read time, because a log that contains a customer’s payment details is a liability whoever can currently see it. And keep the approval record legible to the person who will read it under pressure, who is usually a support engineer at an awkward hour rather than an auditor with a week.
Approvals are also a measurement surface
A well-designed approval queue tells you where your workflow is weakest. Approvals granted almost every time suggest the gate is not earning its interruption and the action could be scoped smaller and automated; Anthropic’s figure of roughly 93% for Claude Code prompts is that signal at the scale of a whole product. Frequent rejections suggest the agent is proposing the wrong thing, which is a description or context problem upstream. Long response times suggest the request is not readable enough to answer quickly.
Feed those patterns back through Evaluate the decisions in an agent workflow rather than treating the queue as pure operational overhead.
Frequently asked questions
What is a human approval workflow for AI agents? A human approval workflow for AI agents is the designed path a consequential action takes when it reaches a person: the agent pauses, states what it proposes to do and on what basis, the person approves it, narrows it, asks a question or refuses it, and the run resumes from that answer without losing its state. It is a workflow rather than a dialog because it has a before, a decision and an after, and each of those can be designed. Which actions enter it is settled by the system, by effect class, rather than by the model at run time.
What is human-in-the-loop approval for AI agents? Human-in-the-loop approval is a checkpoint at which an AI agent must stop before a consequential action and wait for a person to approve, change, question or refuse it. The Model Context Protocol tools specification (2026-07-28) says there should always be a human in the loop with the ability to deny tool invocations, and that applications should present confirmation prompts. The design work lies in what the person is shown, which actions reach them, and how the run continues after their answer.
What is human-in-the-loop authorisation for AI agents? Human-in-the-loop authorisation means that a person, not the agent, grants the permission for a consequential action, and that the service can tell the grant came from that person. Knowing which account approved is not enough: an agent driving a browser signed in as the person can press the same button. The decision should arrive by a route the agent cannot operate, such as the service’s app on the person’s phone, from someone the service’s policy allows to approve, tied to the exact action and expiring. A yes the agent wrote, or a form a client can answer automatically, does not meet that bar.
What is the difference between confirmation and approval for AI agents? A confirmation is any yes that reaches your system. An approval is a decision a person made, with the facts in front of them, about the exact action that will run. A confirmation counts as an approval only when your system can tell that a person gave it. Supabase’s MCP documentation makes the distinction itself: it calls its confirmation forms a guardrail rather than a guarantee of human approval, because some clients answer them automatically.
When should an AI agent ask a human for approval? When the action is hard to reverse, externally visible, or outside the scope the person originally delegated. Reads, drafts, and searches rarely need a gate. Payments, deletions, outbound messages, published content, and permission escalations do. Encode the rule in the system rather than leaving it to the model’s judgement.
Do allow, ask and never rules replace approving each action? Not on their own. In a 2026 preprint study of 113 people without software backgrounds, supervising a simulated day of agent actions, those who wrote allow, ask and never rules let through more actions that went beyond their request than those who approved each action, partly because they chose ask for most rules and then approved what they were asked about. Rules can cut the number of prompts, but an approval request still needs to show when an action goes beyond what the person asked for.
Can an approval step be bypassed? Yes, when the approval is not bound to the operation that runs. A 2026 preprint on Loopjacking describes two routes: the approval screen omits or misdescribes an operation that is already encoded, or pending state is changed after the person has approved the correct one. Render the request from the real call through a component the agent cannot control, store the approved call with the decision, compare it exactly at execution time, and block changes to pending requests. A 2026 preprint on approval laundering adds a quieter route, in which an approved command sets off effects the request never showed, and a 2026 modelling study adds another: a flood of low-value requests that wears a reviewer down until a harmful one slips through.
Why is a confirmation dialog not a real approval? Because it usually shows a decision without its context. A person needs to know what will change, what information the agent used, what scope is being granted, and what alternatives exist. A dialog offering only allow or deny converts a design problem into a habit: people click through it, and the gate stops functioning as a control.
Do tool safety annotations make an approval unnecessary? No. The MCP specification (2026-07-28) states that tool annotations such as read-only or destructive hints are untrusted unless they come from a trusted server, and that the client and server must still validate. Annotations help selection and interface design. They are not enforcement.
How do we keep an approval from blocking the whole workflow? Make the pause resumable and the request specific. The MCP tools specification supports multi-round-trip flows for when a tool needs more human input, and OAuth step-up authentication (RFC 9470) exists for tasks that become sensitive partway through. Design the pause so the agent keeps its state and the person answers one bounded question, rather than restarting the task.
A good approval gives people control without turning every useful workflow into a dead end.
