Skip to main content

Feature: Expert Workspace

Last updated: 2026-06-05 (response-templates feature deprecated and removed end-to-end; see "Deprecated" section below)

The Expert Workspace is the surface where Humanity Protocol Experts actually do the human-in-the-loop review work โ€” picking up queued items, reading the client thread + AI-drafted reply, editing/approving, and shipping the response back out to the client. It is served under /workspace/* (the getRoleRedirect() destination for users with the expert platform role).

This doc covers the workspace UX layer โ€” the pieces an Expert touches while triaging a queue item. For the queue's lifecycle, SLA, and access rules, read expert-queue.md. For how new Experts arrive on the platform in the first place, see expert-application.md.

Two productivity primitives shipped on 2026-06-03 and are the focus of this doc:

  1. Customer history timeline โ€” prior conversations with this customer in the same Org ร— Specialist scope, rendered alongside the active ticket.
  2. KB search panel โ€” Org-scoped Haystack search with citation insertion, so the Expert can ground edits in the team's documented answers.

A third piece โ€” a dedicated notifications drawer โ€” shipped on the same day but for the client portal (/client/*), not the Expert workspace. It's listed here for cross-reference because the same notification primitive will plug into /workspace/* once the Expert-side drawer ships (currently not implemented โ€” see "Speculative / not yet wired" below).

The Expert's primary draft surface remains the AI-generated draft attached to every queue item. The agent produces it; the Expert reviews/edits; corrections feed back into the agent over time. See expert-queue.md for the draft contract and correction-capture loop.

What shippedโ€‹

PRChangeDate
#1530Customer history timeline โ€” backend service (ConversationsService.getCustomerHistory()) returning prior conversations scoped by Org ร— Specialist (ADR-020 isolation)2026-06-03
#1533Customer history timeline โ€” frontend UI (CustomerHistoryTimeline component on the queue item detail page)2026-06-03
#1526KB search panel โ€” backend endpoint GET /api/workspace/kb/search (Haystack RAG with ADR-020 OSA scoping; top-5 results)2026-06-04
#1528KB search panel โ€” UI in the queue item detail page with citation insertion into the reply draft2026-06-03
#1549Dedicated client-portal notifications drawer with categorization (All / Mentions / Assignments / System). Closes #1474. Client-side; not yet ported to /workspace.2026-06-03

Workspace layoutโ€‹

/workspace/queue           โ€” queue list (filters, SLA badges, pickup)
/workspace/queue/[id] โ€” queue item detail (the main work surface)
/workspace/approvals โ€” agentic-task approval queue (see agentic-tasks.md)
/workspace/tasks โ€” long-running task list
/workspace/analytics โ€” Expert performance + correction-capture rollups
/workspace/settings โ€” per-Expert preferences

> **`/workspace/pools` removed** โ€” the Expert pool model was retired
> (`expert_pools` + `pool_memberships` tables dropped; PR #1711 PR 4 also
> dropped `org_experts` on 2026-06-05). Expertโ†”data assignment is now via
> `expert_access` (dual-scope: `scope='specialist'` or `scope='org'` โ€”
> see ADR-007). The pool route was deleted alongside.

The queue-item detail page (frontend/src/app/workspace/queue/[id]/page.tsx) is the surface that mounts both productivity primitives:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ TicketDetail โ”‚
โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚ โ”‚ Client thread โ”‚ AI draft + Expert reply editor โ”‚ โ”‚
โ”‚ โ”‚ (ClientViewPane) โ”‚ (ExpertWorkspacePane) โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ โ–ธ KBSearchPanel.tsx (#1526/ โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ #1528) โ€” Haystack search + โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ "Insert citation" button โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ โ–ธ Submit / Edit + Send โ”‚ โ”‚
โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚ โ”‚ CustomerHistoryTimeline (#1533) โ”‚ โ”‚
โ”‚ โ”‚ โ”€ prior conversations with this customer in this OSA โ”‚ โ”‚
โ”‚ โ”‚ โ”€ fetched via getCustomerHistory(customerId) โ†’ #1530 โ”‚ โ”‚
โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Customer history timelineโ€‹

Why: When triaging a queue item, the Expert needs to know whether this customer has asked the same question before (or has a known escalation history) to avoid repeat-question whiplash and to pattern-match against prior resolutions.

Backend (#1530): ConversationsService.getCustomerHistory(customerId) in api/src/conversations/conversations.service.ts (line 3129). Returns the customer's prior conversations within the current Org ร— Specialist scope (ADR-020 isolation enforced โ€” cross-Specialist history is filtered out by the service-layer query in addition to the OrgRlsInterceptor GUCs). Used by the API client via getCustomerHistory() in frontend/src/lib/api.ts.

Frontend (#1533): CustomerHistoryTimeline โ€” frontend/src/app/workspace/queue/[id]/CustomerHistoryTimeline.tsx. Mounted below the active ticket on the queue item detail page; renders the timeline chronologically with conversation snippets and status badges.

KB search panelโ€‹

Why: Experts need to ground edits in the team's documented answers, not their own memory. Inline KB search (without leaving the queue item) is the shortest path from "I'm not sure" to "here's the answer with a citation."

Backend (#1526): GET /api/workspace/kb/search?q=<query> in api/src/workspace/workspace.controller.ts. Wraps the Haystack RAG service (post the ADR-024 RAGflowโ†’Haystack migration โ€” see docs/decisions/024-haystack-migration.md). Returns top-5 results scoped to the Expert's current OSA per ADR-020 row 2 (KB documents = Org-wide default with optional Specialist scope; retrieval filters cross-Specialist documents out). The endpoint is behind JwtAuthGuard + Expert role.

Frontend (#1528): KBSearchPanel.tsx โ€” frontend/src/app/workspace/queue/KBSearchPanel.tsx with tests under frontend/src/app/workspace/queue/__tests__/KBSearchPanel.test.tsx. Renders a search input + result list with "Insert citation" buttons that splice a citation marker into the reply-editor draft state in ExpertWorkspacePane.

Notifications drawer (cross-reference)โ€‹

PR #1549 (closing #1474) shipped a dedicated client-portal notifications drawer with All / Mentions / Assignments / System tabs, NotificationProvider, and a /client/settings/notifications preferences page backed by localStorage.

2026-06-06 update: The original NotificationBell + drawer for the client portal was subsequently replaced by a dedicated /client/inbox route (PR #1866, commit b20b36c0). Notification primitives still live under frontend/src/components/client/notifications/ but the bell-icon surface is no longer the entry point for clients.

The drawer/inbox is not in the Expert workspace yet. The Expert workspace continues to rely on Socket.io live updates + the queue refresh poll for in-app signalling. Porting an inbox-shaped surface to /workspace/* is a natural follow-up โ€” the useNotifications hook + NotificationProvider are generic โ€” but no PR is open for it as of 2026-06-04.

Module locationsโ€‹

Backend (NestJS)โ€‹

ModulePurpose
api/src/conversations/conversations.service.ts (getCustomerHistory)Customer history backend โ€” #1530
api/src/workspace/workspace.controller.ts (GET /api/workspace/kb/search)KB search endpoint โ€” #1526
api/src/kb/kb.service.tsHaystack-backed KB retrieval (consumed by the workspace KB search endpoint)

Frontend (Next.js)โ€‹

PathPurpose
frontend/src/app/workspace/layout.tsxWorkspace shell (Expert role only)
frontend/src/app/workspace/queue/page.tsxQueue list
frontend/src/app/workspace/queue/[id]/page.tsxQueue item detail โ€” mounts CustomerHistoryTimeline
frontend/src/app/workspace/queue/[id]/CustomerHistoryTimeline.tsxCustomer history UI โ€” #1533
frontend/src/app/workspace/queue/KBSearchPanel.tsxKB search panel UI โ€” #1528
frontend/src/app/workspace/queue/ExpertWorkspacePane.tsxThe Expert reply editor that hosts the KB-citation insertion entry point
frontend/src/app/workspace/queue/TicketDetail.tsxTwo-pane (client view + Expert pane) layout for the active ticket

The customer-history and KB-search work didn't require new schema โ€” they read from existing conversations / org_documents tables, with isolation enforced via the existing ADR-020 columns (specialist_id, RLS GUCs).

Deprecatedโ€‹

Response templates (removed 2026-06-05)โ€‹

Response templates โ€” Org-scoped reusable reply snippets with {{var}} interpolation โ€” were briefly part of the Expert workspace tooling v1 effort (epic #1361). They shipped to dev on 2026-06-03/05 via PRs #1532 (schema + seed), #1535 (backend CRUD + interpolation engine), #1536 (admin CRUD UI at /ops/clients/:id/templates), and #1618 (workspace picker modal).

They were removed end-to-end on 2026-06-05 (issue #1518 closed as not-planned):

  • The agent already generates a draft for every queue item. That is the primary draft surface โ€” a parallel human-template system creates two competing draft sources and a UX surface Experts have to keep in sync with model improvements.
  • The agent learns from Expert edits/corrections over time (correction embeddings, fine-tuning loop). Improvements should land in the model, not in static templates.
  • The optimisation goal was never "sub-15s template insertion"; it is "agent produces the right draft directly" โ†’ Expert effort goes into reviewing/correcting, which feeds the loop.

A follow-up cleanup is pending: drop the response_templates table (migration 1788500000002-DropResponseTemplates.ts), remove api/src/templates/, the admin CRUD UI at /ops/clients/[id]/templates/, the workspace TemplatePickerModal, and the Templates button on the client/internal-chat composers. Documentation references in this doc, the ops manual, and the implementation-status changelog will be scrubbed alongside that cleanup. An earlier attempt at this scrub (PR #1868) was reverted; the next attempt is owned by @ethumanity.

Speculative / not yet wiredโ€‹

  • Notifications drawer in /workspace/*. Client-portal drawer is live (#1549); workspace port is not. The provider is generic and could be lifted into the workspace layout when the use case justifies it.
  • docs/features/expert-queue.md โ€” queue lifecycle, SLA policy, confidence threshold, queue-item state machine. The work productivity primitives in this doc operate inside a queue item that the Expert has already picked up.
  • docs/specs/tavus-integration.md โ€” Tavus reporting (post-call transcript summary + conversation links) surfaces in the workspace ticket detail when the originating message thread came via a Tavus call. Expert workspace consumes it read-only.
  • docs/decisions/020-isolation-classification.md โ€” the matrix that says customer_history is Org ร— Specialist scoped, and KB retrieval filters cross-Specialist content. Every endpoint listed above is in that matrix.
  • docs/decisions/024-haystack-migration.md โ€” Haystack is the RAG backend behind /api/workspace/kb/search.
  • docs/features/agentic-tasks.md โ€” /workspace/approvals is a sibling surface that handles agentic-task approvals (distinct from queue-item review).