Human-in-the-Loop (HITL)
Require human approval before your AI agent takes action.
What is HITL?
Human-in-the-Loop (HITL) is a governance pattern where agent actions are paused and queued for human approval before execution. This is the strictest form of oversight, ideal for high-risk or irreversible actions.
When to Use HITL
- Financial transactions - Payments, transfers, refunds
- Data modifications - Deletes, updates to critical data
- External communications - Emails, messages to customers
- System changes - Configuration updates, deployments
- Compliance-sensitive - Actions requiring audit trails
⚠️
Latency Impact
HITL blocks execution until approval. Only use for actions where the delay is acceptable.
Enabling HITL
Via SDK
hitl_agent.py
from turingpulse import instrument, GovernanceDirective
@instrument(
agent_id="financial-agent",
governance=GovernanceDirective(
hitl=True,
reviewers=["finance@company.com", "compliance@company.com"],
escalation_timeout=3600, # Escalate after 1 hour
auto_reject_after=86400, # Auto-reject after 24 hours
)
)
def process_refund(user_id: str, amount: float, reason: str):
"""This function will pause for approval before executing."""
return payment_service.refund(user_id, amount, reason)Via UI
- Navigate to Governance → Policies
- Click Create Policy
- Select Human-in-the-Loop (HITL)
- Choose the workflow to apply
- Configure reviewers and timeouts
- Save and enable
Conditional HITL
Apply HITL only when certain conditions are met:
conditional_hitl.py
from turingpulse import instrument, GovernanceDirective
@instrument(
agent_id="financial-agent",
governance=GovernanceDirective(
hitl=True,
# Only require approval for high-value transactions
hitl_condition=lambda ctx: (
ctx.metadata.get("amount", 0) > 10000 or
ctx.metadata.get("action") == "delete" or
ctx.metadata.get("risk_score", 0) > 0.8
),
reviewers=["finance@company.com"],
)
)
def process_transaction(action: str, amount: float):
# Small transactions proceed automatically
# Large transactions wait for approval
return execute_transaction(action, amount)HITL Workflow
1. Action Triggered
When an instrumented function is called with HITL enabled:
- Execution pauses before the function body runs
- A review request is created in TuringPulse
- Reviewers are notified via configured channels
2. Review Queue
Reviewers see the pending action in the Review Queue:
- Action Details - Function name, arguments, metadata
- Context - User info, session history, risk indicators
- Workflow Info - Which agent/workflow triggered
3. Review Actions
- Approve - Allow the action to proceed
- Reject - Block the action (raises exception)
- Modify - Edit parameters and approve
- Escalate - Forward to another reviewer
4. Execution Resumes
After approval, the function executes normally. After rejection, a HITLRejectedException is raised.
Handling Rejections
handle_rejection.py
from turingpulse import instrument, GovernanceDirective
from turingpulse.exceptions import HITLRejectedException
@instrument(
agent_id="financial-agent",
governance=GovernanceDirective(hitl=True, reviewers=["admin@company.com"])
)
def process_refund(user_id: str, amount: float):
return payment_service.refund(user_id, amount)
# Handle rejection gracefully
try:
result = process_refund("user-123", 500.00)
print(f"Refund processed: {result}")
except HITLRejectedException as e:
print(f"Refund rejected: {e.reason}")
print(f"Rejected by: {e.reviewer}")
# Notify user, log, etc.Timeouts and Escalation
Escalation
If a review isn't completed within the timeout, escalate to additional reviewers:
governance = GovernanceDirective(
hitl=True,
reviewers=["level1@company.com"],
escalation_timeout=1800, # 30 minutes
escalation_reviewers=["level2@company.com", "manager@company.com"],
escalation_channels=["pagerduty://critical"],
)Auto-Approve/Reject
Prevent indefinite blocking with automatic resolution:
governance = GovernanceDirective(
hitl=True,
reviewers=["admin@company.com"],
# Auto-approve after 4 hours (for low-risk actions)
auto_approve_after=14400,
# Or auto-reject after 24 hours (for time-sensitive actions)
auto_reject_after=86400,
)⚠️
Use Carefully
Auto-approve should only be used for lower-risk actions where the cost of delay exceeds the risk of the action.
HITL Configuration
| Option | Type | Description |
|---|---|---|
hitl | bool | Enable HITL governance |
hitl_condition | callable | Function to determine if HITL applies |
reviewers | list[str] | Email addresses of reviewers |
escalation_timeout | int | Seconds before escalation |
escalation_reviewers | list[str] | Reviewers for escalation |
escalation_channels | list[str] | Alert channels for escalation |
auto_approve_after | int | Seconds before auto-approval |
auto_reject_after | int | Seconds before auto-rejection |
Best Practices
- Use conditions - Apply HITL conditionally to avoid overwhelming reviewers with low-risk actions.
- Set appropriate timeouts - Balance urgency with reviewer availability.
- Configure escalation - Ensure actions don't get stuck if primary reviewers are unavailable.
- Provide context - Include relevant metadata to help reviewers make informed decisions.
- Monitor queue depth - Track review queue size to ensure adequate reviewer capacity.