Get started

HITL & Inbox

Human-in-the-Loop brings human oversight to automated systems. The inbox system manages approvals, tasks, and notifications that need human attention.

What is Human-in-the-Loop (HITL)?

Human-in-the-Loop is a pattern where automated systems pause and wait for human input before proceeding. This ensures critical decisions have human oversight.

In simple terms: When an AI agent or workflow needs approval, clarification, or a decision, it creates an "inbox item" and waits. A human reviews it, takes action, and the system continues.

Why HITL matters

BenefitDescription
SafetyPrevent automated systems from taking irreversible actions
ComplianceEnsure human approval for regulated processes
QualityAdd human judgment to AI-generated content
AccountabilityCreate audit trails of who approved what

The inbox system

What is an Inbox?

An inbox is a queue of items waiting for human attention. Inboxes can be:

TypeDescription
OrganisationItems for the entire organisation
DivisionItems scoped to a division
DepartmentItems scoped to a department
TeamItems for a specific team
UserPersonal inbox for individual user

Inbox items

Items represent work waiting for human action:

TypePurposeExample
approvalBinary approve/reject decision"Deploy to production?"
questionFree-form response needed"What timeout value?"
taskWork to be completed"Review this PR"
alertInformational notification"Build completed"
reviewContent review request"Check AI response"
escalationEscalated from another item"Unhandled for 2 hours"

Item lifecycle

pending → in_progress → approved/rejected/resolved
                     ↘ escalated (on timeout)
                     ↘ expired (if not handled)
StatusDescription
pendingAwaiting action
in_progressBeing worked on
approvedApproved (for approval type)
rejectedRejected (for approval type)
resolvedCompleted
escalatedMoved to higher authority
expiredTimeout reached, no action taken

Routing rules

Routing rules determine how items are assigned to inboxes and users.

Rule components

FieldDescription
condition_typeType of item to match
condition_scope_typeScope to match (org, division, team)
action_typeWhat to do (assign_inbox, assign_user, escalate)
target_idWhere to route the item
priorityRule ordering (higher = first)

Example rules

Route approvals to the Security team:

json
{
  "name": "Security Approvals",
  "condition_type": "approval",
  "condition_scope_type": "org",
  "action_type": "assign_inbox",
  "target_id": "<security-team-inbox-id>",
  "priority": 100
}

The SLA runner

Escalation is not just a routing rule shape, it is a live server-side runner. A background job polls open items (default every 60 seconds, configurable via HITL_SLA_POLL_INTERVAL_MS) and fires staged actions as deadlines pass:

StageWhat it does
notifyReminds the assignee an item is waiting
escalateMoves the item to the next inbox or authority
reassignHands the item to a different user
auto_expireMarks an untouched item expired
auto_denyAutomatically denies the item

auto_approve is blocked by default. The runner will never approve an item on your behalf unless you explicitly opt in with HITL_SLA_ALLOW_AUTO_APPROVE=true. Left unset, an auto-approve stage is logged loudly and left untriggered rather than silently skipped.


API reference

Inbox endpoints

MethodEndpointDescription
POST/api/orgs/:orgId/inboxesCreate inbox
GET/api/orgs/:orgId/inboxesList inboxes
GET/api/orgs/:orgId/inboxes/:inboxIdGet inbox
PATCH/api/orgs/:orgId/inboxes/:inboxIdUpdate inbox
DELETE/api/orgs/:orgId/inboxes/:inboxIdDelete inbox

Item endpoints

MethodEndpointDescription
POST/api/orgs/:orgId/inbox-itemsCreate item
GET/api/orgs/:orgId/inbox-itemsList items (with filters)
GET/api/orgs/:orgId/inbox-items/:itemIdGet item
PATCH/api/orgs/:orgId/inbox-items/:itemIdUpdate item status

Routing rule endpoints

MethodEndpointDescription
POST/api/orgs/:orgId/routing-rulesCreate rule
GET/api/orgs/:orgId/routing-rulesList rules
PATCH/api/orgs/:orgId/routing-rules/:ruleIdUpdate rule
DELETE/api/orgs/:orgId/routing-rules/:ruleIdDelete rule

Create inbox item

bash
curl -X POST /api/orgs/<orgId>/inbox-items \
  -H "Authorization: Bearer <token>" \
  -d '{
    "inbox_id": "<inbox_id>",
    "type": "approval",
    "title": "Deploy to production",
    "description": "Release v2.1.0 to production servers",
    "priority": "high",
    "metadata": {"version": "2.1.0", "commit": "abc123"}
  }'

Update item status

bash
curl -X PATCH /api/orgs/<orgId>/inbox-items/<itemId> \
  -H "Authorization: Bearer <token>" \
  -d '{"status": "approved", "resolution_note": "LGTM"}'

Frontend implementation

Components

ComponentLocationPurpose
InboxView/src/pages/views/InboxView.jsxMain inbox UI

InboxView features

  • Search - Full-text search across item titles, descriptions, and workflow names with debounced input
  • Assignee filters - Quick tabs: All, Assigned to Me, Unassigned, Urgent
  • Status tabs - Quick filter by item status (open, in progress, waiting, resolved)
  • Priority badges - Visual priority indicators with urgent pulse animation in sidebar
  • Bulk actions - Select multiple items, then Approve All, Deny All, or Clear selection
  • Inline approve/deny - Quick action buttons on approval items without opening the detail modal
  • Keyboard shortcuts - j/k to navigate items, Enter to open, Escape to clear
  • Pagination - 25 items per page with Load More for large inboxes
  • Item detail sidebar - View and action items with full history
  • Create/resolve/reopen - Full item lifecycle
  • MCP integration - Agents can create inbox items via the create_inbox_item tool

Routes

jsx
<Route path="/inbox" element={<InboxView />} />

Database schema

Tables

sql
-- Inboxes
CREATE TABLE inboxes (
  id TEXT PRIMARY KEY,
  org_id TEXT NOT NULL REFERENCES orgs(id),
  inbox_type TEXT NOT NULL, -- org, division, department, team, user
  owner_id TEXT NOT NULL,   -- ID of the owning entity
  name TEXT NOT NULL,
  description TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Inbox items
CREATE TABLE inbox_items (
  id TEXT PRIMARY KEY,
  org_id TEXT NOT NULL REFERENCES orgs(id),
  inbox_id TEXT REFERENCES inboxes(id),
  scope_id TEXT REFERENCES scopes(id),
  type TEXT NOT NULL,       -- approval, question, task, alert, review, escalation
  status TEXT DEFAULT 'pending',
  priority TEXT DEFAULT 'medium',
  title TEXT NOT NULL,
  description TEXT,
  source_type TEXT,         -- agent, workflow, manual
  source_id TEXT,
  assignee_type TEXT,       -- user, team
  assignee_id TEXT,
  metadata_json TEXT,
  resolution_note TEXT,
  expires_at DATETIME,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Routing rules
CREATE TABLE routing_rules (
  id TEXT PRIMARY KEY,
  org_id TEXT NOT NULL REFERENCES orgs(id),
  name TEXT NOT NULL,
  condition_type TEXT,       -- Item type to match
  condition_scope_type TEXT, -- Scope type to match
  condition_scope_id TEXT,
  action_type TEXT NOT NULL, -- assign_inbox, assign_user, escalate
  target_id TEXT NOT NULL,
  priority INTEGER DEFAULT 0,
  is_active INTEGER DEFAULT 1,
  escalation_timeout INTEGER,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Integration with workflows

Workflow wait states

Workflows can pause for human input:

javascript
// Create approval request and wait
const item = await createInboxItem({
  type: 'approval',
  title: 'Approve deployment',
  source_type: 'workflow',
  source_id: workflowRunId
});

// Workflow pauses here until item is resolved
await waitForResolution(item.id);

// Check result
if (item.status === 'approved') {
  // Continue with deployment
} else {
  // Handle rejection
}

Best practices

Inbox organisation

  • Create focused inboxes - Don't dump everything in one place
  • Use meaningful names - "Production Approvals" not "Inbox 1"
  • Set up routing rules - Automate item distribution
  • Monitor queue depth - Watch for backlogs

Item management

  • Set appropriate priorities - Reserve "critical" for truly urgent items
  • Add context - Include enough detail to make decisions
  • Use expiration wisely - Set deadlines for time-sensitive items
  • Document resolutions - Add notes explaining decisions

Escalation

  • Define escalation paths - Know where items go when unhandled
  • Set reasonable timeouts - Balance urgency with workload
  • Notify on escalation - Alert the escalation target

Last updated: 2026-01-22