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) ANDautoReplyMode = 'none'(Issue #346) for new orgs. All AI responses queue for Expert review until the AM explicitly opts the org intosystem_replyoragent_replyand (ifagent_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.mdfor 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
| Status | Meaning |
|---|---|
unread | New item; Expert has not opened it |
in_review | Expert has opened the item |
resolved | Expert has sent a response or the item was auto-resolved |
Expert Actions
From the queue item detail view (/workspace/queue/[id]), an Expert can:
| Action | Endpoint | Description |
|---|---|---|
| Approve & Send | POST /expert-queue/:id/respond | Send the AI draft verbatim as Specialist |
| Edit & Send | POST /expert-queue/:id/respond | Modify draft, then send as Specialist |
| Write & Send | POST /expert-queue/:id/respond | Discard draft, write own response |
| Resolve | POST /expert-queue/:id/resolve | Mark resolved with optional satisfaction score |
| Defer | POST /expert-queue/:id/defer | Defer the item by X hours |
| Add Note | POST /expert-queue/:id/add-note | Add internal note (never visible to client) |
| Get AI suggestion | POST /expert-queue/:id/suggest | Re-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_id ↔ org_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:
| Value | Behavior |
|---|---|
0 | Always auto-send (any agent score ≥ 0 qualifies) |
1–100 | Auto-send if agent confidence ≥ threshold |
101 | Never 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 Level | Auto-Send Eligible? |
|---|---|
low | Yes (if confidence ≥ threshold) |
medium | Yes (if confidence ≥ threshold) |
high | No — always routes to Expert |
critical | No — 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
- Room
- 8-second polling (fallback): frontend polls when WebSocket is unavailable
PR #244 (2026-05-07):
ExpertQueueService.respond()now emitsagent_message_sentafter 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 approvalPOST /agentic/tasks/:id/steps/:stepId/approvePOST /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
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /expert-queue | Expert | List queue items (status, orgId filters) |
| GET | /expert/orgs | Expert | Get Expert's available orgs |
| GET | /expert-queue/:id | Expert | Fetch single queue item |
| POST | /expert-queue/:id/suggest | Expert | Get fresh AI suggestion |
| POST | /expert-queue/:id/respond | Expert | Send response (approve/edit/write) |
| POST | /expert-queue/:id/resolve | Expert | Resolve with satisfaction score |
| PATCH | /expert-queue/:id/status | Expert | Update status |
| POST | /expert-queue/:id/defer | Expert | Defer X hours |
| POST | /expert-queue/:id/add-note | Expert | Add internal note |
| POST | /expert-queue/:id/corrections | Expert | Submit correction |