Give an agent real capabilities, the ability to send, spend, delete, and deploy, and the question stops being whether it can act and becomes whether it should act unsupervised. Human-in-the-loop is the answer most production teams converge on: let the agent run autonomously through the routine work, and make it stop and ask at the points where a wrong action is expensive.
Why agents need a human in the loop
Four reasons recur across every serious deployment:
- Irreversible actions. Sending an email, moving money, deleting records, merging code. A model’s confidence is not the same as correctness, and some mistakes cannot be undone. A gate before the action converts a catastrophic failure mode into a rejected proposal.
- Judgment calls. Some decisions depend on context the agent does not have: organizational politics, customer relationships, taste, risk appetite. The agent can assemble the decision; only the human can make it.
- Trust. Users adopt agents they can supervise. An agent that shows its proposed action and waits earns the autonomy it is later granted; an agent that acts silently gets switched off after its first visible mistake.
- Compliance. Regulated industries often require a named, accountable human behind specific decisions, plus an audit trail showing who approved what and when. An interrupt with a recorded response is that audit trail.
The point is not to slow the agent down everywhere. It is to place a small number of deliberate gates exactly where the cost of error is highest, and let the agent move at full speed between them.
The interrupt patterns
Nearly every human-in-the-loop interaction is one of five patterns. Each one pauses the run, puts a decision in front of a person, and resumes with the response.
- Approve or reject. The agent proposes a complete action and the human gates it. “Send this refund confirmation to the customer?” Yes executes it; no stops it or sends the agent back to revise.
- Edit, then continue. The human corrects the proposal before it executes. The agent drafts a $500 refund; the reviewer changes it to $50 and approves; the agent executes the edited version, not the original. The edit replaces the proposed arguments outright, so there is no ambiguity about what ran.
- Choose among options. The agent presents alternatives instead of a single answer: three flight itineraries, two architectural approaches, a shortlist of candidates. The human picks, and the agent proceeds with the selection.
- Provide missing input. The agent hits a fact only the human knows. “Which cost center should this invoice bill to?” The run waits for a structured answer, then continues with it.
- Retry with guidance. The human rejects and says why. “Wrong tone, make it more formal.” The agent regenerates with the correction applied, and the loop repeats until the proposal passes.
What the interface has to do
Most writing about human-in-the-loop covers the policy half: which actions to gate and who approves them. The other half is what the interface must actually do when the agent pauses, and it decomposes into three jobs.
Render the interrupt. A raw text prompt in a chat window is the floor, not the pattern. A real interrupt carries structure: the tool being called, its arguments, the options on offer, the schema of the expected response. The interface should render that structure as purpose-built UI: an editable diff of the proposed arguments, option cards for a choice, a form for missing input. A reviewer who can see exactly what will execute makes faster and better decisions than one parsing a paragraph.
Collect the response. The response must be validated against what the agent expects and correlated with the right interrupt, because a run can raise more than one. A free-text reply is not a response; an approval, an edited payload, or a selection is.
Resume the run. This is the hard part, and it is a transport problem before it is a UI problem. The paused run lives on a server; the decision happens in a browser, possibly hours later, possibly after the user closed the laptop. The connection between agent and interface must be bi-directional, the agent’s state must be checkpointed at the pause, and the response must reach the paused run and continue it exactly where it stopped. Plain request-response cannot do this, which is a specific case of why agents break the request-response paradigm in general.
Human-in-the-loop vs. human-on-the-loop
The two terms describe different supervision postures. In the loop means the agent waits: the human decision is a blocking step in the run, and nothing consequential happens without it. On the loop means the agent proceeds on its own while a human monitors with the power to intervene: dashboards, alerts, and a halt button rather than a gate. In-the-loop fits low-volume, high-consequence actions; on-the-loop fits high-volume work where per-action approval would not scale and errors are recoverable.
Both are distinct from agent steering, where the human volunteers direction mid-run without being asked. In human-in-the-loop the agent initiates the pause; in steering the user initiates the correction. Mature agent interfaces support both.
The other meaning: HITL in model training
The same phrase names an older machine-learning practice: humans inside the training pipeline. Data labelers annotate examples, domain experts review edge cases the model is unsure about (active learning), and raters rank model outputs to train the reward models behind RLHF, reinforcement learning from human feedback.
Same words, different loop. Training-time HITL improves the model in general, before deployment, across all future users. Run-time HITL, the subject of this article, governs one specific action in one specific run at execution time. The two are complementary rather than competing: a team can fine-tune a model with human feedback and still gate its deployed agent’s irreversible actions.
How protocols carry interrupts
Because the pause spans a server-side run and a client-side decision, human-in-the-loop needs support from the protocol connecting them, the agent-user connectivity layer. AG-UI, the Agent-User Interaction protocol, treats interrupts as first-class run outcomes: a run ends with an interrupt outcome instead of a completion, and each interrupt carries an id, a reason (a tool call awaiting approval, required input, or a confirmation), a human-readable message, and optionally a schema describing the expected response and an expiry timestamp. The client resumes by starting a new run on the same thread with a response for every open interrupt.
Splitting the interaction across two runs is what makes the pause durable: the interrupted run has already checkpointed its state, so the decision can arrive seconds or days later, from the same device or a different one, and the audit trail records the proposal, the human’s response, and the executed result as separate entries. Agent frameworks map their own pause mechanisms onto this contract (LangGraph’s interrupt function is one example), and CopilotKit’s frontend hooks render the interrupt and collect the response on the application side of the same protocol.
