Agent control · Analysis

Human in the loop for AI agents: approval gates that hold

Human in the loop AI agents need durable approval gates. Learn when to pause, what reviewers need, and how to resume one authorized action safely.

A proposed agent action pauses at a locked gate while an authorized reviewer binds a decision to the exact payload before one execution resumes
The short answer

Human in the loop for AI agents means that application code, not the model, pauses a consequential action until an authorized person makes a recorded decision. The system should persist the run, present the actual tool and normalized arguments, bind the approval to that immutable proposal, and recheck identity, policy, expiry, and business preconditions before execution. Rejection, editing, timeout, and escalation need explicit states. Use approval for actions whose impact, reversibility, data exposure, or uncertainty exceeds policy. Low-risk calls can run under standing rules, while high-impact actions may need one or more reviewers. A chat prompt that tells the agent to ask first is guidance, not an enforcement boundary.

Human in the loop AI agents need a real stop between a model's proposal and an external side effect. If the same model that chooses refund_order can also decide that approval happened, the person is present in the conversation but absent from the control path.

A production approval gate has a narrower job. It captures one proposed action, saves enough state to survive a long wait, routes the request to someone with authority, and refuses to execute until a decision is recorded. Approval applies to the exact action shown. If the recipient, amount, command, destination, or data changes, the old decision no longer applies.

This distinction turns human oversight from a reassuring label into an engineering contract. The person must be able to understand the material facts, reject or change the proposal, and stop the workflow without relying on the agent's cooperation. The runtime must be able to resume after a browser closes, a worker restarts, or the approval sits overnight.

The pattern is useful for payments, external messages, production changes, data disclosure, account actions, and other consequential work. It is less useful when a deterministic policy can safely decide, or when a reviewer sees so little evidence that clicking Approve adds no control.

Define the control boundary

Human in the loop, often shortened to HITL, covers several different interactions. Mixing them creates vague requirements. A team says that an agent "has HITL," while one product means a confirmation before a tool call and another means that someone samples completed transcripts each week.

For runtime agent control, separate four patterns:

Pattern When the person acts What the system must allow
Approval gate Before a specified action Approve, reject, edit through a new proposal, or request more information
Input handoff When the agent lacks a required fact or judgment Supply bounded input and return the task to the runtime
Live supervision While work is running Inspect progress, pause, redirect, cancel, or take over
Post-action review After an output or action Label, correct, appeal, investigate, or change future policy

Only the first pattern authorizes a pending action. Input is not approval unless the interface and policy say that it is. Monitoring after an action is useful, but it cannot prevent that action. Training-time feedback, data labeling, and reinforcement learning from human feedback are also outside this runtime boundary.

NIST's AI RMF Appendix C treats human roles as a design choice that can range from autonomous operation to manual decision making. It asks organizations to define who decides, who oversees performance, and how people receive enough information to act. That is a better starting point than adding a generic approval button after the agent workflow is already built.

Legal obligations depend on the system and jurisdiction. Article 14 of the EU Artificial Intelligence Act applies human oversight requirements to high-risk AI systems as the regulation defines them. It calls for measures proportionate to risk, autonomy, and context, and for people to understand limitations, avoid automatic over-reliance, disregard or reverse outputs, and safely stop operation. Those are specific requirements for regulated high-risk systems, not a claim that every agent needs the same approval design. They still offer a useful test: can the assigned person actually intervene, or can they only watch?

The control boundary belongs outside the model. The model may propose an action and explain its evidence. Application code should decide whether the tool is available, which policy applies, whether approval is required, and which identities may decide. The action service should reject execution without a valid decision. A prompt such as "always ask before sending" can improve behavior, but it cannot enforce the rule against prompt injection, model error, or a later code path.

Choose when a person intervenes

Approval should follow risk, not a blanket rule that all tool calls are dangerous or that read operations are harmless. A read can expose payroll data to an external model. A write to an isolated draft can be reversible and low impact. Evaluate what the action does in its actual context.

A policy engine can consider:

  • impact on money, people, production, reputation, access, or legal rights;
  • reversibility and the time available to reverse the effect;
  • data sensitivity, destination, and whether information crosses a trust boundary;
  • the requesting principal's authority and the agent's delegated scope;
  • novelty, ambiguity, policy exceptions, and signs that the workflow is outside its tested operating range;
  • cumulative effect, since 5,000 individually small changes may be material;
  • evidence quality and disagreement between independent checks.

Model confidence can be one input, but it is a weak gate by itself. Models may be confident when wrong, and confidence values are not necessarily calibrated across tasks or releases. A known high-impact operation should still require its policy control even when the agent reports certainty. Likewise, a low-confidence label does not automatically mean that a human can resolve the problem. The reviewer may need a specialist, a deterministic validation, or a refusal path.

A simple risk policy might produce four outcomes:

allow             low impact, within scope, validated, reversible
deny              prohibited action or missing authority
require_approval  a named reviewer can authorize this exact action
require_step_up   stronger identity, extra evidence, or multiple reviewers

The boundaries should be written as policy rules with versions, not improvised by the agent. For example:

Proposed action Possible default Reason
Search public documentation Allow and log Read-only, public source, bounded cost
Read one customer's private record Allow only within delegated account scope Sensitive data, but no external disclosure
Send a draft to an internal review queue Allow with destination restrictions Reversible workflow state, limited audience
Email a customer or publish content Require approval of recipient and final body External communication and reputation impact
Delete data, move money, change access, or deploy to production Step-up or deny by default High impact, hard recovery, or privilege change

Standing approval can reduce friction for repetitive low-risk work, but it needs a narrow scope. Bind it to the principal, tool, argument constraints, data class, environment, time window, and maximum volume. "Always allow this tool" is too broad when the same tool can address different tenants or destinations. A standing grant should be revocable and visible in the decision record.

Human intervention also has a cost. Review queues add latency and operational load. Repeated harmless prompts train people to accept the next request without reading it. Use automatic policy for clear low-risk cases, denial for clear prohibited cases, and people where judgment or accountable authorization can change the result.

Model approval as durable state

An approval wait is a workflow state, not a blocked HTTP request. The reviewer may respond in seconds, hours, or never. The initiating client can disconnect. A new software version may deploy while the request is pending. The runtime needs an explicit lifecycle that survives all of those events.

One useful state model is:

State Allowed next states Meaning
proposed awaiting_review, denied The normalized action exists and policy has evaluated it
awaiting_review approved, rejected, expired, superseded No protected side effect may run
approved executing, expired, superseded A valid decision exists, but execution has not settled
executing succeeded, failed, unknown The downstream action has started
rejected or expired terminal The proposal cannot execute
succeeded or failed terminal The authoritative service returned a known outcome
unknown succeeded, failed, manual reconciliation A request may have committed but its response was lost

Keep rejected distinct from denied. Policy denial means the proposal was never eligible for human authorization. Reviewer rejection means an eligible proposal reached a person who declined it. The difference matters for user messages, metrics, and incident review.

Editing should normally create a new proposal and mark the old one superseded. If an approver changes $500 to $50, the system can display that convenience in one screen, but the resulting payload needs a new digest and decision. Quietly mutating an approved object destroys the link between what the person saw and what the service executed.

Each pending item should have its own ID. Parallel tool calls need independent decisions unless a policy deliberately creates a batch with a fixed manifest. Approving one email should not release every email that the agent proposed in the same model turn. A batch approval should list every member, define whether partial approval is allowed, and become invalid when the membership changes.

Timeout is also a decision. High-impact requests should usually expire closed, which means no action occurs. The workflow can notify the requester, escalate to another queue, or create a fresh proposal. Silent auto-approval after a timer turns a human gate into a delay mechanism. If a business process has an explicit default action at a deadline, document it as policy and show that consequence to the reviewer before the timer starts.

Bind the decision to one action

The approval object should reference a canonical proposal envelope. Do not authorize a natural-language summary while leaving executable arguments elsewhere. The summary can omit a hidden recipient, a shell flag, a changed tenant, or a data attachment.

A framework-neutral envelope can contain:

proposal_id       pr_7f2a
task_id           task_2841
principal_id      user_913
agent_version     support-agent@17
tool              send_refund_notice
schema_version    4
arguments         canonical JSON object
argument_digest   sha256:...
policy_version    refund-policy@12
created_at        2026-08-03T12:30:00Z
expires_at        2026-08-03T14:30:00Z

Canonicalization must be deterministic. Normalize field ordering, amounts, currencies, identifiers, paths, destinations, and defaults before computing the digest. Validate the arguments against the current schema and business rules before routing the request. An approver should not spend time on an action that the service would reject anyway.

The decision record should add the decision, reviewer identity, authentication strength, role or authority, time, proposal digest, optional reason, and the policy path that accepted the reviewer. Store it in a service the agent cannot rewrite. The agent may summarize why it proposed the action, but that summary is model output, not proof of the underlying facts.

Approval and authorization remain separate checks. A manager might approve the business purpose but lack permission to access the customer's account. A user might have account access but lack authority to approve a large refund. At execution time, verify both the decision and the current service authorization. Do not hand an approval token to the model or expose a tool that can approve its own later call.

Use three identifiers for three jobs:

Identifier Purpose
proposal_id Names the frozen action that reached review
approval_id Names the recorded human decision
idempotency_key Prevents duplicate downstream effects during retry

They may be related, but they should not be treated as synonyms. One proposal can collect two required approvals. A denied proposal has a decision but no execution key. An execution retry reuses its idempotency key without creating a new approval.

This action-level evidence connects naturally to AI agent observability. Trace the proposal, policy check, approval wait, decision, execution attempt, and authoritative result as separate events. Keep the proposal digest, approval ID, and transaction ID in a protected evidence packet even if routine traces are sampled.

Give reviewers useful evidence

An approval screen must answer what will happen if the reviewer accepts. "Allow agent to use email?" is not enough. Show the operation in domain terms and make the exact machine request inspectable.

For a material tool call, the reviewer may need:

  • the initiating person, tenant, agent, and task purpose;
  • the tool or business operation and the exact target;
  • important arguments, with a diff from the current state when possible;
  • the data that will leave a boundary and its destination;
  • expected side effects, cost, reversibility, and recovery option;
  • evidence references and validation results that support the proposal;
  • which policy triggered review and why this reviewer has authority;
  • expiry, escalation path, and whether other approvals are still pending.

Redact fields the reviewer does not need, but do not redact the fact that sensitive data will be sent. A digest can bind a protected payload while the UI shows a controlled representation. The system needs a tested way to prove that the representation and executable payload describe the same action.

Offer decisions that have clear semantics: approve this proposal, reject it, request specified information, or edit into a new proposal. Free-form chat can accompany those actions, but prose alone should not change state. "Looks fine except use the other account" is ambiguous until the system resolves the account, creates a replacement payload, and obtains approval for that payload.

Reviewer assignment is part of the control. Route by domain, amount, geography, tenant, separation-of-duties rule, and current availability. Require stronger authentication for sensitive operations. Delegation should be recorded, bounded, and revocable. If two reviewers are required, define whether order matters and whether either decision expires when the other role changes.

Design for attention. Put the consequence and changed fields first. Avoid a wall of model reasoning that encourages reviewers to accept the agent's narrative. Provide source records or test results that a person can check. Make Reject as available as Approve, and avoid color or button placement that treats approval as the normal answer.

A 2026 exploratory interview study of 17 experienced developers found four forms of oversight in software-agent use: a priori control, co-planning, real-time monitoring, and post hoc review. Participants also used practical shortcuts because exhaustive review was difficult. The sample was small, largely situated within one technology company, and the authors do not claim a complete taxonomy. The useful design lesson is modest: adding more output to review does not make oversight effective. Reviewers need bounded evidence, time, authority, and a clear consequence for their decision.

Measure the queue as a product surface. Track wait time, expiry, reassignment, approval and rejection rates by policy, edits, reviewer disagreement, decision reversals, and incidents after approval. A 99.9 percent approval rate may mean the policy is routing harmless work, the interface hides risk, or reviewers are overloaded. It is not automatically evidence that the agent is safe.

Resume without changing the deal

The runtime should persist the task before notifying a reviewer. At minimum, store the proposal, normalized arguments or protected reference, state, workflow and tool versions, policy result, reviewer requirements, and continuation pointer. A process-local promise or open browser connection will not survive ordinary production failures.

On approval, resume through an execution guard:

  1. Load the task and confirm that it is still awaiting_review or approved under the expected version.
  2. Authenticate the decision source and verify that the reviewer still has the required role.
  3. Check the approval signature or protected record, proposal digest, scope, expiry, and single-use status.
  4. Re-evaluate hard policy constraints and current business preconditions, such as account status, inventory, exchange rate bounds, or target existence.
  5. Acquire a lease or use an atomic state transition so two workers cannot execute the same proposal.
  6. Move to executing, call the downstream service with the stable idempotency key, and record its transaction ID.
  7. Store the authoritative result before asking the model to produce a user-facing explanation.

Do not send the approved proposal back to the model and ask it what to do next. That creates a new planning step after authorization. Execute the frozen operation through typed application code. If a fresh model call is required to produce new arguments, those arguments form a new proposal.

Rechecking policy does not mean silently broadening the approval. If the policy became stricter, stop or request a new review. If it became looser, the existing approval may still execute while valid, but record which policy governed proposal and execution. A changed tool schema, agent definition, or workflow can make serialized state incompatible. The OpenAI Agents SDK HITL guide supports serialized RunState for long waits and recommends storing a version marker with pending tasks so they can resume on a compatible code path.

Resumption semantics vary by framework. LangGraph interrupts persist graph state and resume from a thread checkpoint, but the interrupted node restarts from its beginning. Code that ran before interrupt() can run again. Its documentation therefore recommends putting non-idempotent side effects after the interrupt or in a separate node. This is a concrete example of a general rule: know whether the runtime resumes at a line, replays a node, retries a task, or reconstructs the run from events.

Idempotency covers the case where execution repeats. It does not resolve every unknown outcome. If a payment API accepts a request and the response is lost, the workflow should query by idempotency key or transaction reference before retrying. Keep the task in unknown until the authoritative service settles it. Asking another human to approve the same payment does not answer whether the first one already happened.

Pending state contains sensitive material. The OpenAI guide notes that serialized state can include application context, approvals, tool input, nested resumptions, and trace metadata. Apply encryption, access control, retention, and secret minimization to checkpoints. Durable should not mean permanent or broadly readable.

Map the pattern to current stacks

Agent libraries expose different names, but the same control questions apply: what pauses, what is persisted, what the decision binds, and how execution resumes.

Stack Native mechanism What the application still owns
OpenAI Agents SDK Tools can require approval; runs surface interruptions and resume from RunState Risk policy, reviewer identity, durable storage, business authorization, expiry, UI, and downstream idempotency
LangGraph interrupt() saves graph state through a checkpointer and resumes with a command Proposal binding, reviewer routing, replay-safe nodes, business policy, and action service controls
A2A 1.0 A Task can enter TASK_STATE_AUTH_REQUIRED or TASK_STATE_INPUT_REQUIRED Meaning, scope, validity, credential delivery, and enforcement of the authorization
MCP Hosts can expose and confirm model-controlled tool calls Trust policy, accurate action display, argument validation, approval scope, and server-side authorization

The A2A 1.0 specification is explicit about the boundary. An agent may move a Task to TASK_STATE_AUTH_REQUIRED when it needs authorization, including human approval before a destructive action. The state transition does not grant permission by itself. The implementation or credential issuer must define the operation, scope, validity, revocation, and checks. The A2A tasks vs messages guide explains why work that pauses for authorization needs a durable Task rather than a direct Message.

The fixed MCP tools specification recommends a human ability to deny tool calls, clear indicators of tool use, and confirmation prompts. It also says clients must treat tool annotations as untrusted unless they come from trusted servers. A readOnlyHint or friendly tool description can inform policy and UI, but an untrusted server cannot declare itself safe. The host and action service still enforce scope and validate the real operation. The broader MCP security architecture covers installation, sessions, OAuth, and downstream service boundaries around this approval point.

Protocols transport state and requests. They do not know that a refund over $500 needs a finance manager, that two people must confirm a biometric match, or that a customer email expires after the case changes. Keep those domain rules in a versioned policy and approval service that can work across agent frameworks.

Avoid approval theater

Many HITL designs pause visibly but fail to control execution. Check for these patterns:

  1. A model that polices itself leaves the tool callable when the prompt says to ask permission. Put enforcement between proposal and execution.
  2. A summary such as "update customer" can hide the record and fields that will change. Bind the decision to canonical arguments and show the material values.
  3. If a reviewer or model edits the payload after approval, create a new proposal and invalidate the old decision.
  4. A wait held only in memory disappears on restart or can resume incorrectly. Persist it before notification, then test recovery on another worker.
  5. Some runtimes replay a node that has already sent a message or created a record. Move effects after the checkpoint and use idempotency.
  6. A signed-in user may still lack business authority. Check the role, tenant, amount limit, separation-of-duties rule, and current status.
  7. A timer must not turn silence into permission. Expire closed unless a documented policy names another default.
  8. One transaction approval must not become blanket permission for later calls. Scope standing grants explicitly and evaluate every call against them.
  9. After rejection, an agent may try an equivalent tool or slightly altered arguments. Where feasible, policy should block the restricted effect or require a newly evaluated proposal.
  10. A network error can hide an action that already committed. Reconcile with the downstream service before retrying.
  11. Model reasoning without a target, diff, source, or consequence gives the reviewer little to verify. Present the facts and exact action instead.
  12. The control itself also needs review. Policies drift, queues overload, and nearly all requests may be approved. Monitor decisions and test the gate with each release.

Human review cannot compensate for unlimited agent permissions. Keep least privilege, schema validation, sandboxing, egress controls, deterministic business checks, rate limits, and rollback mechanisms. Approval is one control at a specific boundary.

Test the complete control path

Treat approval as an adversarial state machine. A successful UI click covers too little. Use a fake downstream service that records idempotency keys and can simulate accepted requests with lost responses.

  1. Propose a low-risk action that policy should allow. Confirm that no unnecessary review item appears.
  2. Propose a prohibited action. Confirm that a reviewer cannot override a hard denial unless a separate, documented exception path exists.
  3. Change one material argument after the approval screen renders. The old approval must fail digest validation.
  4. Submit two decisions for the same proposal at the same time. Only one atomic transition may win.
  5. Resume the same approved task on two workers. The downstream service should observe one logical effect.
  6. Restart the worker, queue, and reviewer client during the wait. The request should remain pending with the same proposal ID and expiry.
  7. Deploy a new agent, tool schema, and policy version while an old proposal waits. Route it to compatible code or expire it safely.
  8. Remove the reviewer's role after notification but before decision. The later approval attempt must fail authorization.
  9. Let the request expire, then submit a delayed approval. It must not reopen or execute the proposal.
  10. Reject a request and let the agent propose a semantically equivalent action through another tool. Policy should detect the same restricted effect where feasible.
  11. Make the downstream service commit and drop the response. The task should enter unknown, reconcile, and avoid a duplicate call.
  12. Verify that logs and traces connect the principal, task, proposal digest, policy version, reviewer, approval, idempotency key, transaction, and final outcome without storing unnecessary secrets.

Measure the system after release. Useful rates include approvals requested per task, policy denials, human rejections, edits that created new proposals, expiry, median and tail wait time, duplicate effects prevented, unknown outcomes, reversals, and incidents after approval. Break them down by action class and policy version without putting personal identifiers into metric labels.

Review sampled approval screens with the people who carry the responsibility. Ask whether they could identify the consequence, verify the evidence, understand why the request reached them, and safely reject it. Track whether the queue gives them enough time. A nominal human checkpoint fails when the organization rewards fast acceptance or gives the reviewer no workable alternative.

In implementation terms, the path is: propose, normalize, evaluate, persist, route, decide, revalidate, execute once, and record the outcome. Every step has an owner and an observable state. The person can change what happens, while the agent cannot manufacture its own permission. If an incident reviewer cannot pair the executed transaction with the displayed payload and decision record, the gate did not hold.

Sources and methodology

This article draws on the primary documentation and research listed below. An editor reviewed the technical claims and wording before publication.

  1. OpenAI Agents SDK: Human-in-the-loop — official tool approval, interruption, serialized run state, rejection, resume, and pending-task versioning behavior
  2. LangGraph Interrupts — official durable checkpoint, resume, replay, serializable payload, and idempotent side-effect guidance
  3. NIST AI RMF Appendix C: AI Risk Management and Human-AI Interaction — human role definition, oversight configurations, bias, reviewer information, and deployed override analysis
  4. EU Artificial Intelligence Act, Article 14 — official requirements for proportionate and effective human oversight of high-risk AI systems
  5. Agent2Agent Protocol Specification 1.0.0 — interrupted task states, in-task authorization responsibilities, and limits on what an authorization state means
  6. Model Context Protocol: Tools — official user-interaction guidance for tool visibility, denial, and confirmation, plus the trust limit of tool annotations
  7. Human oversight of agentic systems in practice — 2026 exploratory interview study of oversight work and review constraints among 17 experienced software developers