Skip to main content

h.work — Client × AI Specialist Interaction Product Documentation

Corrected: 2026-08-05 | Scope: WebChat · Slack Channel · Expert Dashboard

The conversation/runtime contract in ADR-046 is authoritative. Known implementation deviations are listed in its remediation ledger; a legacy code path is not an allowed product alternative.


I. Overall Architecture

Client (org_admin / org_member)
├── WebChat (/client/chat)
└── Slack Channel (DM or Channel @mention)

API (NestJS) — Unified message entry point

Managed Hermes session — canonical Specialist reply

Reply delivered once through the original channel
└── Optional after-delivery Expert observation/correction

Core Principles

  • Messages from all channels remain conversation-scoped and channel-separated
  • Every successful Hermes reply is delivered once; confidence, risk, review, clarification, and approval state never withhold it
  • Humanwork sends only the exact user message and native attachment blocks; Hermes owns history, retrieval, tools, and response behavior
  • Message deduplication and idempotent writes prevent duplicate processing

II. WebChat Module

2.1 Feature Description

After signing in, the Client enters /client/chat and can:

  • View all Specialists assigned to the current org (profile area on the left)
  • Start a new Thread (conversation) with each Specialist
  • Maintain multiple independent Threads for the same Specialist
  • Send text, images, files, and other attachments
  • Receive AI Specialist replies through scoped Socket.io mutation events; reconnect performs one bounded catch-up read and idle time performs no polling

2.2 Current Implementation Status

FeatureStatus
Specialist selection + profile display✅ Implemented
New Thread / Thread list (left sidebar)✅ Implemented
Send messages (text)✅ Implemented
Message attachments (images/files)✅ Implemented
Receive replies in real time via Socket.io✅ Implemented
Rename Thread / Resolve / Reopen✅ Implemented
Unread message badge✅ Implemented
Threads sorted by latest message time, descending✅ Implemented
Thread status display (in_progress / awaiting_client / resolved)✅ Implemented
Channel source indicator (Slack/Email/WhatsApp icon)✅ Implemented

2.3 Message Flow

Client enters message → POST /conversations/:id/messages
↓ Immediate response (201)
Asynchronously in background: runAgentPipeline()
→ Humanwork sends the exact message and real attachment blocks to the existing Hermes session
→ Hermes resumes SessionDB and retrieves or uses tools on demand
→ Every successful canonical reply is stored and pushed once to the Client; a genuine failure remains a failure
→ Expert observation/correction is optional and happens after delivery

2.4 Outstanding Items

#IssuePriority
W-1When creating a new Thread, if the org has multiple Specialists, the Client must explicitly select a Specialist before creationHigh
W-2The Thread list lacks an icon for the native WebChat source when displaying channel origins (only external-channel icons such as email/slack exist)Medium
W-3The Client lacks clear feedback for message status (sending / delivered / failed)Medium
W-4Attachment preview: inline image preview exists, but PDFs/files are displayed only as chips and cannot be previewedLow

III. Slack Channel Module

3.1 Design Goals

Each AI Specialist has a dedicated Slack App. After a Client org installs the App in its Slack Workspace, employees can communicate with that Specialist through:

  • DM: Send a direct message to the Slack App
  • Channel @mention: @mention the App in any channel
  • Bound Channel (opt-in): After binding a channel to a Specialist, all messages in that channel (without requiring an @mention) are routed to that Specialist

3.2 Slack App Activation Flow

SuperAdmin / AM generates a Slack App Manifest for a Specialist in the Ops console

Create an App in the Slack API Console using the Manifest (including bot scopes / Events API / OAuth)

Configure the App's Client ID / Client Secret / Signing Secret in Humanwork

Store the Specialist ↔ Slack App association in IntegrationCredential (encrypted at rest)

Client org administrator clicks "Add to Slack" → OAuth 2.0 authorization flow

oauth.v2.access → Store bot_token in IntegrationCredential (org level)

Activation complete: employees in the org can communicate with the Specialist via DM / @mention

3.3 Message Trigger Strategy (Three Layers, from the PRD)

Layer 1 — Hard Triggers (Must Respond)

  • Direct message to the Slack App
  • Direct @mention of the Bot
  • Follow-up messages in a previously engaged Thread (Thread continuation)

Layer 2 — Contextual Scoring (Intelligent Evaluation, Phase 2)

composite_score = channel_weight × (keyword_match + question_intent)

score > relevance threshold → Deliver the real message to Hermes
else → Store silently (silent ingest)

Layer 3 — Implicit Relevance (Semantic Vector Matching, Phase 3)

  • Embedding similarity matching
  • Cold start requires labeled data

3.4 Message Processing Flow

Slack Events API → POST /channels/slack/events
↓ Verify HMAC-SHA256 signature → Immediately return 200

BullMQ channels-inbound queue (asynchronous)

handleRuntimeEvent()
├─ Resolve orgId through team_id → IntegrationCredential
├─ Dedup: event_ts / event_id already processed? → Skip
├─ Determine Trigger type: DM / @mention / Bound Channel / Thread continuation
│ └─ silent ingest (trigger conditions not met) → Store in channel_context_messages

findOrCreateConversation() (Slack user → customer mapping)

conversationsService.sendMessage() [Synchronously await Agent]

Hermes resumes SessionDB and generates the canonical reply

BullMQ channels-outbound

slack.chat.postMessage(channel, text, thread_ts) Reply in the original thread

3.5 Current Implementation Status

FeatureStatus
Slack App Manifest generation (SlackManifestSuggester)✅ Implemented
OAuth 2.0 installation flow (Add to Slack)✅ Implemented
HMAC-SHA256 signature verification✅ Implemented
DM message receipt + routing✅ Implemented
@mention message receipt + routing✅ Implemented
Thread continuation tracking (slack_engaged_threads)✅ Implemented
Bound Channel (opt-in, no @mention required)✅ Implemented
Message Dedup (Redis NX + event_ts)✅ Implemented
Silent ingest (channel_context_messages)✅ Implemented
Send Expert replies back to Slack thread✅ Implemented
Dedicated Slack App for each Specialist⚠️ Supported by the architecture, but the current OAuth configuration is globally shared (single SLACK_CLIENT_ID)
Layer 2 Contextual Scoring🔲 Not implemented (Phase 2)
Layer 3 semantic vector matching🔲 Not implemented (Phase 3)

3.6 Outstanding Items

#IssuePriority
S-1Dedicated Slack App for each Specialist: OAuth currently uses global SLACK_CLIENT_ID/SECRET; per-Specialist App credential configuration and installation flows are requiredHigh
S-2Client-side Slack connection management UI: display connected workspaces and bound channels, with disconnect/reconnect actionsHigh
S-3Bound Channel binding UI (currently back-office only; client admins need self-service access)Medium
S-4Implement the Layer 2 Contextual Scoring engineMedium
S-5Forward image/file attachments in Slack messages to the Expert DashboardMedium
S-6Support rich-text formatting in Expert replies (Slack mrkdwn)Low

IV. Expert Dashboard Module

4.1 Feature Description

After signing in, the Expert enters /workspace/queue and can:

  • Handle explicit human requests and genuine failures from WebChat + Slack + Email + WhatsApp; ordinary successful deliveries create no work item
  • View the canonical Specialist reply and real tool/failure evidence available for audit
  • Correct the canonical reply or author a genuine follow-up when needed
  • View canonical SessionDB history plus recorded Expert follow-ups
  • Sort by multiple dimensions (risk level / creation time / SLA)

4.2 Current Implementation Status

FeatureStatus
Attention list (explicit human requests and genuine failures only)✅ Implemented
Canonical reply / failure evidence display✅ Implemented
Compatibility confidence/risk metadata (observability only)✅ Implemented
Expert correction and genuine follow-up✅ Implemented
Corrected/follow-up reply through original channel (webchat/slack/email)✅ Implemented
Conversation history (complete message list)✅ Implemented
Channel source indicator (email/slack, etc.)✅ Implemented (email has a badge; other channels need improvement)
SLA timer✅ Implemented
Keyboard shortcuts✅ Implemented
Real-time new-message notifications via Socket.io✅ Implemented
Unread message badge✅ Implemented
Conversation sorting (risk/time/SLA)✅ Implemented
Message attachment display (images/files)✅ Implemented (WebChat attachments; Slack attachment forwarding remains outstanding)
Multi-Specialist filtered view⚠️ Currently filtered by expert_access permissions; no UI switcher
Unread count display (per-conversation)⚠️ A global unreadCount exists; per-conversation counts require confirmation
Conversation status management⚠️ Status values exist (pending/awaiting_client/resolved), but their semantics and transition rules need clarification

4.3 Outstanding Items

#IssuePriority
E-1Standardize Channel source indicators: display a source badge for every channel (webchat/slack/whatsapp/email) in the Queue list and conversation detailsHigh
E-2Forward Slack attachments: images/files in Slack messages must be forwarded for viewing in the Expert DashboardHigh
E-3Clarify conversation status definitions: define the semantics, transition conditions, and UI display rules for pending / open / awaiting_client / resolvedHigh
E-4per-Specialist view: when an Expert can access multiple Specialists, support filtering conversations by SpecialistMedium
E-5Unread message count per-conversation: display the exact unread count for each conversation in the Thread listMedium
E-6Rich-text message rendering: formatted display of Slack mrkdwn, Markdown, link previews, and related contentMedium
E-7Internal Note: internal communication messages between Experts (API exists; UI completeness requires review)Low

V. Consolidated Task List

Module 1: Expert Dashboard

Task IDTask DescriptionPriorityDependency
E-1Standardize source badges for all channels in the Queue list (webchat/slack/email/whatsapp)P0
E-2Forward Slack attachments: storage + display (Slack images/files viewable in the Expert Dashboard)P0S-5
E-3Define and implement conversation status transition rules (including UI status labels)P0
E-4per-Specialist filtered viewP1
E-5Exact per-conversation unread message countsP1
E-6Rich-text message rendering (Markdown + Slack mrkdwn)P2
E-7Internal Note UI completeness acceptanceP2

Module 2: Slack Channel

Task IDTask DescriptionPriorityDependency
S-1Support independent per-Specialist Slack App credentials (separate Client ID/Secret/Signing Secret for each)P0
S-2Client Admin Slack connection management UI (display connected workspaces / disconnect / reconnect)P0S-1
S-3Self-service Bound Channel binding UI (available to Client Admin)P1S-2
S-4Layer 2 Contextual Scoring engine (PRD Phase 2)P1
S-5Forward image/file attachments in Slack messages to the Expert DashboardP1
S-6Support Slack mrkdwn in Expert repliesP2E-6

Module 3: WebChat

Task IDTask DescriptionPriorityDependency
W-1Support selecting a target Specialist when creating a new Thread (multi-Specialist org scenario)P0
W-2Client-side message sending status feedback (sending / delivered / failed)P1
W-3Add the missing WebChat source icon (channel dot)P2
W-4PDF/document attachment preview (currently displayed only as a chip)P2

VI. Key Data Models

EntityDescription
conversationsEach Thread, including channel / status / agentName / orgId
messagesCanonical message records, including role (user/ai/expert) and real attachments; compatibility review fields cannot gate delivery
expert_queue_itemsOptional Expert observation/correction work records, never a prerequisite for a successful Hermes reply
integration_credentialsSlack/Email/WhatsApp tokens, encrypted at rest, at org level
slack_channel_bindingsChannel opt-in binding: channel_id → Specialist
slack_engaged_threadsThread continuation tracking (sliding engaged_at TTL window)
channel_context_messagesSilent ingest context storage (FTS index)
expert_accessExpert ↔ (Org × Specialist) access authorization (ADR-007)

Based on impact scope and dependency order, begin with:

  1. S-1 — Independent per-Specialist Slack App credentials (unblocks the complete multi-Specialist Slack flow)
  2. E-1 — Standardize channel source badges (small change, high visibility)
  3. E-3 — Define conversation statuses (blocks several downstream UI decisions)