Area 03 // AI AgentsLesson 59 / 14013 min read
Human in the loop
Human in the loop means the agent pauses at important moments (before a risky action, when it's unsure, or to get missing information) so a person can approve, edit or reject, and the agent resumes from exactly where it stopped.
Think of it like this
Analogy
A junior accountant prepares payments all day, but anything over £1,000 sits in a "waiting for sign-off" tray until the finance manager approves it, edits the amount, or sends it back with a note. The accountant then carries on exactly where they left off. The tray holds the paperwork overnight if needed.
Human in the loop is that sign-off tray for agents.
The problem it solves
Agents make mistakes and can be manipulated (prompt injection). For many actions (sending money, emailing customers, deleting records, merging code) a mistake is costly or irreversible. On the other hand, asking for approval at every step makes an agent slower than doing the work by hand.
You need to pause at the right moments, show people exactly what's about to happen, and resume reliably, even if the answer comes the next morning.
How it works, step by step
- Choose pause points for human in the loop:
- Before irreversible or high-impact actions (payments, deletions, external emails, production changes).
- When confidence is low or a check failed.
- For policy-sensitive topics (legal, medical, HR).
- When the agent needs information only a person has.
- Pause with an interrupt: the agent stops before the action and saves its full state (checkpoints).
- Show a clear request in an approval flow: what the agent wants to do, with which arguments, why, and the consequences. Route it to the right person (the user, a manager, a reviewer queue).
- Let the human respond: approve, edit (change arguments or the draft), reject with a reason, or answer a question.
- Resume the agent with the response; it continues from the saved state, using the human's input.
- Handle timeouts: if nobody answers, expire, escalate or cancel safely.
- Log everything (who approved what, when) for audit, and use approval data to tune where pauses are needed.
See it in code
- Install
pip install langgraph- Needs
- Python 3.10+. Runs offline.
A LangGraph agent that pauses for refund approval, saves its state, and resumes when a person answers.
from typing import TypedDict
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.types import Command, interrupt
class State(TypedDict):
order_id: str
refund: float
status: str
def check_order(state: State) -> dict:
return {"refund": 129.0} # a real app would look the order up
def approve(state: State) -> dict:
# Pause the graph and wait for a human. The state is saved by the checkpointer.
decision = interrupt({"question": f"Refund {state['refund']} GBP for {state['order_id']}?"})
return {"status": "approved" if decision == "yes" else "rejected"}
graph = StateGraph(State)
graph.add_node("check_order", check_order)
graph.add_node("approve", approve)
graph.add_edge(START, "check_order")
graph.add_edge("check_order", "approve")
graph.add_edge("approve", END)
app = graph.compile(checkpointer=InMemorySaver()) # checkpoints after every step
config = {"configurable": {"thread_id": "ticket-42"}} # one thread = one saved conversation
first = app.invoke({"order_id": "A1234", "refund": 0, "status": "new"}, config)
print("paused, asking:", first["__interrupt__"][0].value["question"])
print("saved state :", app.get_state(config).values)
final = app.invoke(Command(resume="yes"), config) # later, maybe from another server
print("after resume :", final)paused, asking: Refund 129.0 GBP for A1234?
saved state : {'order_id': 'A1234', 'refund': 129.0, 'status': 'new'}
after resume : {'order_id': 'A1234', 'refund': 129.0, 'status': 'approved'}In production the checkpointer is a database, the question goes to a review UI or Slack, and the reviewer's click calls invoke(Command(resume=...)) for that thread. Other frameworks offer the same idea (approval callbacks in tool runners, tool_confirmation events in hosted agent platforms).
A real example
Example
An accounts-payable agent with a sign-off threshold
A company's AP agent matches invoices to purchase orders and schedules payments. Rules: payments under £500 to known suppliers run automatically; anything over £500, any new supplier, or any changed bank details pauses for a finance manager, who sees the invoice, the PO match, the bank details diff and the agent's reasoning, and can approve, edit the amount, or reject.
In the first month, managers rejected 3% of flagged payments, including one invoice from a fraudster who had changed a supplier's bank details by email. The agent would have paid it; the pause caught it.
The easy way
Start here
Wrap your riskiest tool in a confirmation step: before running it, show the user the action and arguments with "Approve / Cancel" buttons. For short waits that's enough. For long waits, use a framework with durable checkpoints.
When you grow: the production setup
Production approval systems define risk tiers per action, route requests to the right approver with context, support edits and comments, enforce timeouts and escalation, persist state durably, write audit logs, and review approval statistics regularly to move low-risk actions to automatic and add pauses where incidents happened (human approval for actions).
Trade-offs
What you gain
What it costs you
- Slower: tasks wait for people.
- Approval fatigue: people start clicking "approve" without reading.
- Needs durable state, review UIs and routing.
When not to use it
- Low-risk, reversible, high-volume actions where review adds little and slows everything.
Common mistakes
- Approving everything (fatigue) or nothing (risk) instead of tiering by risk.
- Approval prompts that don't show the actual arguments.
- Pausing in memory, so a restart loses the pending action.
- No timeout or escalation, leaving tasks stuck forever.
- Not logging who approved what.
Interview questions
Try answering out loud first, then open the model answer.
How would you add human approval to an agent that can issue refunds?
Model answer
Classify refund actions by risk (amount, customer history, policy match). For risky ones, interrupt before executing: persist state with a checkpointer, send a review request with the order, amount, reason and policy evidence to the right queue, allow approve/edit/reject, resume with the decision, enforce timeouts and escalation, and audit-log every decision. Low-risk refunds within policy can be automatic, monitored by sampling.
What makes a good approval UX for agent actions?
Model answer
It shows exactly what will happen (action, arguments, target, amount), why the agent wants to do it (evidence, reasoning), the consequences and reversibility, and offers approve, edit and reject with a comment. It's routed to someone qualified, has a deadline, is fast to act on, and records the decision. It should be rare enough to avoid rubber-stamping.
Why do human-in-the-loop systems need checkpointing?
Model answer
Human responses can take minutes to days, during which processes restart, deploy or scale. Without durable state the pending action and context would be lost or need recomputation (possibly differently). Checkpoints persist the exact state at the pause so the agent resumes deterministically with the human's input.
Quiz
Pick an answer to see whether it’s right and why.
0 of 5 answered
Key terms
- Human in the loop
- Designing an AI system to pause for a person to approve, edit, reject or add information at important moments.
- Interrupt
- Pausing an agent run at a specific step, saving its state, until a person or system provides input to resume it.
- Checkpoint
- A saved snapshot of an agent's state after a step, so it can pause, resume, recover from crashes or be inspected.
- Approval flow
- The process and UI by which a person reviews a proposed agent action and approves, edits or rejects it.
Before and after
Progress is saved in this browser only.