Core Concept

Human-in-the-Loop (HITL)

Protocol-level human oversight for autonomous agent decisions

What is HITL?

Human-in-the-Loop enables AI agents to request explicit human approval before executing critical actions. The approval workflow is managed at the protocol level, making it:

  • Channel-agnostic - Works with SMS, email, voice, push notifications, or any communication method
  • LLM-managed - AI interprets natural language responses for approval/rejection
  • Auditable - All decisions logged with timestamps and user IDs
  • Time-bounded - Approvals expire after a configurable timeout

When to Use HITL

Recommended

  • • High-value transactions ($100+)
  • • Personal data sharing
  • • Irreversible actions
  • • Regulatory compliance
  • • First-time services

Consider Carefully

  • • Low-value routine tasks
  • • Time-sensitive operations
  • • Fully autonomous agents
  • • Public information queries

How It Works

  1. 1
    Agent Negotiation - Your agent negotiates with a service provider
  2. 2
    Create Approval - Agent creates approval request in Amorce
  3. 3
    Notify Human - Your app notifies the user via their preferred channel
  4. 4
    Human Response - User responds with natural language (e.g., "yes", "sounds good")
  5. 5
    LLM Interpretation - AI interprets the response as approve/reject
  6. 6
    Submit Decision - Decision submitted to Amorce protocol
  7. 7
    Agent Proceeds - Agent completes or cancels the transaction

Channel Options

HITL is protocol-level, meaning the Amorce SDK doesn't send notifications directly. You choose how to communicate with humans:

📱SMS (Twilio)

"Sarah needs approval: Book table for 4. Reply YES/NO"

📧Email

One-click approve/reject links in email body

🎙️Voice (Vapi.ai)

"Say approve or decline to continue"

📲Push Notifications

Native mobile app notifications with actions

Code Example (Python)

from amorce import AmorceClient

# 1. Agent negotiates with service
response = client.transact(
    service_contract={"service_id": "srv_restaurant"},
    payload={"intent": "book_table", "guests": 4}
)

# 2. Request human approval
approval_id = client.request_approval(
    transaction_id=response['transaction_id'],
    summary="Book table for 4 guests at Le Petit Bistro",
    details=response['result'],
    timeout_seconds=300
)

# 3. Your app notifies human (SMS/email/push/etc.)
notify_user_via_sms(
    message=f"Approve booking? {approval_id}"
)

# 4. Check approval status
status = client.check_approval(approval_id)

if status['status'] == 'approved':
    # 5. Finalize transaction
    client.transact(
        service_contract={"service_id": "srv_restaurant"},
        payload={"intent": "confirm"}
    )

LLM Interpretation

HITL supports natural language responses instead of rigid YES/NO:

import google.generativeai as genai

# Human responds: "sounds good to me!"
human_response = "sounds good to me!"

# LLM interprets intent
interpretation = genai.GenerativeModel('gemini-pro').generate_content(
    f'Is this approving or rejecting? "{human_response}"'
    'Answer: APPROVE or REJECT'
).text

decision = "approve" if "APPROVE" in interpretation else "reject"

client.submit_approval(
    approval_id=approval_id,
    decision=decision,
    approved_by="user@example.com",
    comments=human_response
)

Security & Audit Trail

All approval decisions are permanently logged in Amorce with:

Approval ID
Unique identifier
Transaction ID
Links to the original transaction
Decision
approve/reject/expired
Approved By
User identifier
Timestamp
When decision was made
Comments
Original human response

Best Practices

Do's

  • ✓ Use clear, concise approval summaries
  • ✓ Set appropriate timeout periods (consider time zones!)
  • ✓ Provide context in the details field
  • ✓ Handle expired approvals gracefully
  • ✓ Verify human identity before submitting decisions

Don'ts

  • ✗ Don't use HITL for every minor decision
  • ✗ Don't set timeouts too short (<60 seconds)
  • ✗ Don't expose approval IDs publicly
  • ✗ Don't assume approvals will always complete
  • ✗ Don't proceed on 'rejected' or 'expired' status

API Reference

Create Approval

POST /api/v1/approvals

Get Approval Status

GET /api/v1/approvals/:approval_id

Submit Decision

POST /api/v1/approvals/:approval_id/submit

For detailed API documentation, see the API Reference.