Human-in-the-Loop (HITL)
Supervision Patterns for Safe and Reliable AI Agents
What is Human-in-the-Loop?
Human-in-the-Loop (HITL) refers to patterns where human oversight is integrated into AI agent workflows. Instead of fully autonomous operation, agents pause at critical decision points to request human review, approval, or input before proceeding.
HITL is essential for high-stakes applications where errors have significant consequencesβ financial transactions, medical decisions, legal actions, or any irreversible operations.
Why Human-in-the-Loop?
π‘οΈ Risk Mitigation
Catch errors before they cause harm. Human review prevents catastrophic failures from hallucinations or misunderstandings.
βοΈ Compliance
Many regulations require human oversight for automated decisions, especially in finance, healthcare, and HR.
π― Edge Cases
Humans handle ambiguous situations, novel scenarios, and cases outside the agent's training distribution.
π Continuous Learning
Human corrections provide training data for improving the agent and reducing future intervention needs.
Common HITL Patterns
1. Approval Gates
Agent pauses and waits for explicit human approval before executing high-impact actions like sending emails, making purchases, or modifying data.
# LangGraph interrupt pattern
from langgraph.graph import StateGraph
from langgraph.checkpoint.memory import MemorySaver
def execute_action(state):
# This node only runs after human approval
action = state["pending_action"]
result = perform_action(action)
return {"result": result, "pending_action": None}
# Create graph with interrupt
graph = StateGraph(AgentState)
graph.add_node("plan", plan_action)
graph.add_node("execute", execute_action)
# Interrupt BEFORE execute for human review
app = graph.compile(
checkpointer=MemorySaver(),
interrupt_before=["execute"]
)
# First run: agent plans, then pauses
result = app.invoke({"input": "Send email to client"}, config)
# β Returns with pending_action for review
# Human reviews and approves...
# Resume execution
result = app.invoke(None, config) # Continue from checkpoint
2. Confidence-Based Escalation
Agent self-assesses confidence. Low-confidence decisions automatically escalate to humans; high-confidence ones proceed autonomously.
def process_request(request):
# Agent generates response with confidence
result = agent.analyze(request)
if result.confidence >= 0.85:
# High confidence: auto-approve
return execute(result.action)
elif result.confidence >= 0.60:
# Medium confidence: flag for review
queue_for_review(result, priority="normal")
return {"status": "pending_review", "eta": "1 hour"}
else:
# Low confidence: immediate escalation
alert_human(result, priority="urgent")
return {"status": "escalated", "reason": result.uncertainty_reason}
3. Async Review Queue
Agent completes work and queues results for batch human review. Humans can approve, reject, or edit before final delivery.
# Async review workflow
class ReviewQueue:
def submit_for_review(self, item):
"""Agent submits work for human review"""
review_item = {
"id": uuid4(),
"content": item.output,
"agent_confidence": item.confidence,
"context": item.input,
"status": "pending",
"created_at": datetime.now()
}
self.db.insert(review_item)
return review_item["id"]
def human_reviews(self, item_id, decision, edits=None):
"""Human provides feedback"""
item = self.db.get(item_id)
if decision == "approve":
self.finalize(item)
elif decision == "reject":
self.reject_with_reason(item)
elif decision == "edit":
item["content"] = edits
self.finalize(item)
# Log for agent improvement
self.log_feedback(item, decision, edits)
4. Collaborative Editing
Human and agent work together in real-time. Agent suggests, human refines, agent incorporates feedback iteratively.
Example: Code review assistant suggests changes, developer accepts some, modifies others. Agent learns from the edits for future suggestions.
When to Require Human Approval
| Action Type | Risk Level | HITL Recommended? |
|---|---|---|
| Reading data | π’ Low | No - proceed autonomously |
| Generating drafts | π’ Low | No - human reviews output anyway |
| Sending internal messages | π‘ Medium | Optional - depends on content |
| Modifying database records | π Medium-High | Yes - require approval |
| Sending external emails | π Medium-High | Yes - review before send |
| Financial transactions | π΄ High | Always - mandatory approval |
| Deleting data | π΄ High | Always - irreversible action |
| Legal/HR decisions | π΄ Critical | Always - regulatory requirement |
Implementation Considerations
β±οΈ Timeout Handling
What happens if the human doesn't respond? Set timeouts with fallback actions (auto-reject, escalate, or safe default).
π± Notification Channels
How do humans get notified? Slack, email, SMS, in-app. Match urgency to channel (SMS for critical, email for routine).
π₯ Reviewer Assignment
Who reviews what? Route by expertise, workload, or hierarchy. Avoid bottlenecks with round-robin or skill-based routing.
π Feedback Loop
Track approval rates, common rejections, and edit patterns. Use this data to improve agent performance and reduce HITL frequency over time.
Tools & Frameworks
- LangGraph: Built-in interrupt_before/after for approval gates
- Temporal: Workflow orchestration with human task support
- Inngest: Durable functions with wait-for-event patterns
- Retool Workflows: Visual HITL workflow builder
- Slack/Teams Integrations: Interactive approval buttons in chat
Best Practices
- Clear context: Show humans exactly what the agent wants to do and why
- Easy actions: One-click approve/reject, not complex forms
- Audit trail: Log who approved what, when, with what modifications
- Graceful degradation: Handle reviewer unavailability
- Reduce friction over time: As confidence grows, reduce HITL requirements
- Batch similar items: Group related decisions to reduce context-switching