Skip to main content

Feature: Expert Queue (HITL)

The Expert Queue is the core human-in-the-loop review surface. When an AI Agent's confidence falls below the Confidence Threshold, the draft response is routed to the queue for an Expert to review before it is sent to the client.

Default behavior: autoRespondThreshold = 101 (Never auto-send) AND autoReplyMode = 'none' (Issue #346) for new orgs. All AI responses queue for Expert review until the AM explicitly opts the org into system_reply or agent_reply and (if agent_reply) lowers the threshold. This ensures no AI draft or template is delivered to a client without explicit AM/SuperAdmin opt-in.

See docs/features/auto-reply.md for the full auto-reply mode matrix.

Conversation Lifecycle

Client sends message (via Email, WhatsApp, Slack, or portal)


Channel adapter normalizes → POST /conversations/:id/messages


ConversationsService calls Agent Service (POST /v1/chat → Hermes CLI)


Agent returns { reply, confidence, flag_for_review, risk_level }

├── confidence >= threshold AND risk_level NOT in (HIGH, CRITICAL)
│ → Auto-send reply as Specialist
│ (default threshold 101 means this path is never taken)

└── confidence < threshold OR flag_for_review OR risk_level HIGH/CRITICAL
→ Create ExpertQueueItem (status: unread)
→ Emit expert_queue_item_added via WebSocket
→ 8s polling fallback on the frontend

Queue Item Lifecycle

unread → in_review → resolved
StatusMeaning
unreadNew item; Expert has not opened it
in_reviewExpert has opened the item
resolvedExpert has sent a response or the item was auto-resolved

Expert Actions

From the queue item detail view (/workspace/queue/[id]), an Expert can:

ActionEndpointDescription
Approve & SendPOST /expert-queue/:id/respondSend the AI draft verbatim as Specialist
Edit & SendPOST /expert-queue/:id/respondModify draft, then send as Specialist
Write & SendPOST /expert-queue/:id/respondDiscard draft, write own response
ResolvePOST /expert-queue/:id/resolveMark resolved with optional satisfaction score
DeferPOST /expert-queue/:id/deferDefer the item by X hours
Add NotePOST /expert-queue/:id/add-noteAdd internal note (never visible to client)
Get AI suggestionPOST /expert-queue/:id/suggestRe-fetch AI draft on demand

Reassign: previously routed to an expert pool. Pool model was removed 2026-05-03. Reassign UI is currently disabled pending redesign on the new direct Expert ↔ Org model.

Expert ↔ Org Assignment

Expert routing is direct: each Expert is assigned to one or more orgs via the org_experts table (org_id, expert_id, assigned_at, assigned_by). Queue items are routed based on conversation.org_idorg_experts.org_id.

Expert pools have been removed. The previous expert_pools and pool_memberships tables and all pool-based routing have been deleted. Do not re-implement pool routing.

Assignment is managed by SuperAdmin via /ops/team and the org detail /ops/clients/[id].

Confidence Threshold

Each Specialist has a confidenceThreshold (integer 0–101) set per Org via OrgSpecialistAssignment:

ValueBehavior
0Always auto-send (any agent score ≥ 0 qualifies)
1–100Auto-send if agent confidence ≥ threshold
101Never auto-send — every response routes to Expert

Default is 101 (Never autoreply) until the AM explicitly changes it. AM configures this in wizard Step 2; Experts can adjust it post-onboarding. Clients never see or configure the threshold.

Risk Classification

The agent service classifies every response with a risk level. HIGH and CRITICAL override the confidence threshold — the item always routes to Expert review regardless of confidence score.

Risk LevelAuto-Send Eligible?
lowYes (if confidence ≥ threshold)
mediumYes (if confidence ≥ threshold)
highNo — always routes to Expert
criticalNo — always routes to Expert

Current implementation: keyword heuristic classifier. Finance/IR roles have elevated base risk. LLM-based classification is planned for P2.

Real-Time Updates

  • WebSocket (primary): Socket.io NotificationsGateway
    • Room experts — all experts platform-wide
    • Room org:<id> — per-org experts
    • Events: expert_queue_item_added, queue_item_resolved, agent_message_sent
  • 8-second polling (fallback): frontend polls when WebSocket is unavailable

PR #244 (2026-05-07): ExpertQueueService.respond() now emits agent_message_sent after saving the expert reply, so the client portal receives the message in real-time without waiting for the 8s poll cycle.

Queue Filtering

Experts can filter the queue by:

  • Status: pending / in_progress / resolved
  • Risk: critical / high / medium / low
  • Org: specific client org
  • Sort: Newest first (no toggle — always newest-first)

Agentic Task Approval

For multi-step agentic tasks, Experts must approve each step before execution. See agentic-tasks.md.

Endpoints:

  • GET /agentic/tasks — list tasks pending approval
  • POST /agentic/tasks/:id/steps/:stepId/approve
  • POST /agentic/tasks/:id/steps/:stepId/reject

Correction Capture

When an Expert sends a corrected response:

POST /expert-queue/:id/corrections
{
"correctionType": "factual_error | tone | missing_step | wrong_action",
"originalResponse": "...",
"correctedResponse": "...",
"notes": "..."
}

Stored in corrections table. Reviewed by SuperAdmin via GET /learning/corrections.

API Reference

MethodPathAuthDescription
GET/expert-queueExpertList queue items (status, orgId filters)
GET/expert/orgsExpertGet Expert's available orgs
GET/expert-queue/:idExpertFetch single queue item
POST/expert-queue/:id/suggestExpertGet fresh AI suggestion
POST/expert-queue/:id/respondExpertSend response (approve/edit/write)
POST/expert-queue/:id/resolveExpertResolve with satisfaction score
PATCH/expert-queue/:id/statusExpertUpdate status
POST/expert-queue/:id/deferExpertDefer X hours
POST/expert-queue/:id/add-noteExpertAdd internal note
POST/expert-queue/:id/correctionsExpertSubmit correction