h.work — Client × AI Specialist 交互产品文档
版本:2026-06-08 | 范围:WebChat · Slack Channel · Expert Dashboard
一、整体架构概述
Client(org_admin / org_member)
├── WebChat(/client/chat)
└── Slack Channel(DM 或 Channel @mention)
↓
API(NestJS)— 消息统一入口
↓
Agent Service(Python)— AI 生成回复
↓
Expert Dashboard(/workspace/queue)
├─ ─ Expert 审阅 AI 草稿
└── 修改/确认 → 原渠道发回 Client
核心原则
- 所有 channel 的消息统一汇聚到 Expert Dashboard,不混渠道
- 默认 HITL(Human-in-the-Loop):
autoRespondThreshold = 101,AI 回复必须经 Expert 确认后才发送 - 消息 dedup + 幂等写入,防止重复处理
二、WebChat 模块
2.1 功能描述
Client 登录后进入 /client/chat,可以:
- 查看当前 org 下所有已分配的 Specialist 列表(左侧 profile 区)
- 针对每个 Specialist 发起新的 Thread(对话)
- 在同一个 Specialist 下维护多个独立 Thread
- 发送文本、图片、文件等附件
- 实时接收 AI Specialist 回复(Socket.io,8s 轮询兜底)
2.2 当前实现状态
| 功能 | 状态 |
|---|---|
| Specialist 选择 + 简介展示 | ✅ 已实现 |
| 新建 Thread / Thread 列表(左侧) | ✅ 已实现 |
| 消息发送(文本) | ✅ 已实现 |
| 消息附件(图片/文件) | ✅ 已实现 |
| Socket.io 实时接收回复 | ✅ 已实现 |
| Thread 重命名 / Resolve / Reopen | ✅ 已实现 |
| 未读消息角标 | ✅ 已实现 |
| Thread 按最后消息时间倒序排列 | ✅ 已实现 |
| Thread 状态展示(in_progress / awaiting_client / resolved) | ✅ 已实现 |
| Channel 来源标识(Slack/Email/WhatsApp 图标) | ✅ 已实现 |
2.3 消息流程
Client 输入消息 → POST /conversations/:id/messages
↓ 立即返回(201)
后台异步:runAgentPipeline()
→ Python Agent 生成回复(含 confidence / risk_level)
→ 默认进入 Expert Queue(threshold=101)
→ Expert 审核确认后:Socket.io 推送给 Client
2.4 待完善事项
| # | 问题 | 优先级 |
|---|---|---|
| W-1 | 新建 Thread 时,若 org 有多个 Specialist,需明确选择哪个 Specialist 再创建 | 高 |
| W-2 | Thread 列表展示 channel 来源时,webchat 自身的渠道图标缺失(仅有 email/slack 等外渠道 icon) | 中 |
| W-3 | Client 侧消息状态(发送中 / 已送达 / 专家已读)缺少明确反馈 | 中 |
| W-4 | 附件预览:图片内联预览已有,PDF/文件仅 chip 展示,无法预览内容 | 低 |
三、Slack Channel 模块
3.1 设计目标
每个 AI Specialist 对应一个独立的 Slack App。Client org 将该 App 安装到自己的 Slack Workspace 后,员工可以通过以下方式与该 Specialist 沟通:
- DM:直接私信 Slack App
- Channel @mention:在任意频道 @mention 该 App
- Bound Channel(opt-in):将频道绑定给某 Specialist 后,频道内所有消息(无需 @mention)都会被路由到该 Specialist
3.2 Slack App 激活流程
SuperAdmin / AM 在 Ops 后台,为某 Specialist 生成 Slack App Manifest
↓
在 Slack API Console 用 Manifest 创建 App(含 bot scopes / Events API / OAuth)
↓
将 App 的 Client ID / Client Secret / Signing Secret 配置回 Humanwork
↓
Specialist ↔ Slack App 关联关系存入 IntegrationCredential(加密存储)
↓
Client org 管理员点击「Add to Slack」→ OAuth 2.0 授权流程
↓
oauth.v2.access → bot_token 存入 IntegrationCredential(org 级别)
↓
激活完成:该 org 的员工可通过 DM / @mention 与 Specialist 沟通
3.3 消息触发策略(三层,来自 PRD)
Layer 1 — Hard Triggers(必须响应)
- DM 私信 Slack App
- @mention 直接提到 Bot
- 已参与过的 Thread 中的后续消息(Thread continuation)
Layer 2 — Contextual Scoring(智能判断,Phase 2)
composite_score = channel_weight × (keyword_match + question_intent)
score > threshold_high → 立即响应
score > threshold_low → 进入 Expert 审核队列
else → 静默存储(silent ingest)
Layer 3 — Implicit Relevance(语义向量匹配,Phase 3)
- Embedding 相似度匹配
- 冷启动需要标注数据
3.4 消息处理流程
Slack Events API → POST /channels/slack/events
↓ HMAC-SHA256 验签 → 立即返回 200
↓
BullMQ channels-inbound 队列(异步)
↓
handleRuntimeEvent()
├─ 通过 team_id → IntegrationCredential → 找到 orgId
├─ Dedup:event_ts / event_id 已处理?→ 跳过
├─ 判断 Trigger 类型:DM / @mention / Bound Channel / Thread continuation
│ └─ silent ingest(不满足触发条件)→ 存入 channel_context_messages
↓
findOrCreateConversation() (Slack user → customer 映射)
↓
conversationsService.sendMessage() 【同步等待 Agent】
↓
Agent 生成回复 → Expert Queue
↓
Expert 确认 → BullMQ channels-outbound
↓
slack.chat.postMessage(channel, text, thread_ts) 回复到原 thread
3.5 当前实现状态
| 功能 | 状态 |
|---|---|
| Slack App Manifest 生成(SlackManifestSuggester) | ✅ 已实现 |
| OAuth 2.0 安装流程(Add to Slack) | ✅ 已实现 |
| HMAC-SHA256 签名验证 | ✅ 已实现 |
| DM 消息接收 + 路由 | ✅ 已实现 |
| @mention 消息接收 + 路由 | ✅ 已实现 |
| Thread continuation 追踪(slack_engaged_threads) | ✅ 已实现 |
| Bound Channel(opt-in,无需 @mention) | ✅ 已实现 |
| 消息 Dedup(Redis NX + event_ts) | ✅ 已实现 |
| Silent ingest(channel_context_messages) | ✅ 已实现 |
| Expert 回复后发回 Slack thread | ✅ 已实现 |
| 每个 Specialist 对应独立 Slack App | ⚠️ 架构设计支持,但当前 OAuth 配置是全局共享(单一 SLACK_CLIENT_ID) |
| Layer 2 Contextual Scoring | 🔲 未实现(Phase 2) |
| Layer 3 语义向量匹配 | 🔲 未实现(Phase 3) |
3.6 待完善事项
| # | 问题 | 优先级 |
|---|---|---|
| S-1 | 每个 Specialist 对应独立 Slack App:当前 OAuth 使用全局 SLACK_CLIENT_ID/SECRET,需要支持 per-Specialist 的 App 凭证配置和安装流程 | 高 |
| S-2 | Client 端 Slack 连接管理 UI:展示已连接 workspace、已绑定 channel、断开/重连操作 | 高 |
| S-3 | Bound Channel 绑定操作 UI(当前仅后台,需要 client admin 可自助操作) | 中 |
| S-4 | Layer 2 Contextual Scoring 评分引擎实现 | 中 |
| S-5 | Slack 消息中的图片/文件附件透传到 Expert Dashboard | 中 |
| S-6 | Expert 回复支持富文本格式(Slack mrkdwn) | 低 |
四、Expert Dashboard 模块
4.1 功能描述
Expert 登 录后进入 /workspace/queue,可以:
- 查看所有待审核的对话(来自 WebChat + Slack + Email + WhatsApp)
- 查看 AI 自动生成的草稿(含 confidence 分数 + risk level 标识)
- 修改草稿后确认发送(通过原渠道回复)
- 查看完整的对话历史(Client 侧消息 + AI 草稿 + Expert 历史回复)
- 多维度排序(风险级别 / 创建时间 / SLA)
4.2 当前实现状态
| 功能 | 状态 |
|---|---|
| Queue 列表(待审核会话) | ✅ 已实现 |
| AI 草稿展示 + confidence 分数 | ✅ 已实现 |
| Risk Level 标识(low/medium/high/critical) | ✅ 已实现 |
| Expert 修改草稿 + 确认发送 | ✅ 已实现 |
| 发送后通过原渠道(webchat/slack/email)回复 | ✅ 已实现 |
| 会话历史(完整消息列表) | ✅ 已实现 |
| Channel 来源标识(email/slack 等) | ✅ 已实现(email 有 badge,其他渠道待完善) |
| SLA 计时器 | ✅ 已实现 |
| 键盘快捷键 | ✅ 已实现 |
| Socket.io 实时新消息通知 | ✅ 已实现 |
| 未读消息角标 | ✅ 已实现 |
| 会话排序(风险/时间/SLA) | ✅ 已实现 |
| 消息附件展示(图片/文件) | ✅ 已实现(webchat 附件;Slack 附件透传待做) |
| 多 Specialist 过滤视图 | ⚠️ 当前按 expert_access 权限过滤,无 UI 切换 |
| 未读条数展示(per-conversation) | ⚠️ 全局 unreadCount 有,per-conversation 计数待确认 |
| 会话状态管理 | ⚠️ 状态值已有(pending/awaiting_client/resolved),状态含义和流转规则待明确 |
4.3 待完善事项
| # | 问题 | 优先级 |
|---|---|---|
| E-1 | Channel 来源标识统一:所有渠道(webchat/slack/whatsapp/email)在 Queue 列表和会话详情中均显示来源 badge | 高 |
| E-2 | Slack 附件透传:Slack 消息中的图片/文件应透传到 Expert Dashboard 可查看 | 高 |
| E-3 | 会话状态定义明确化:明确 pending / open / awaiting_client / resolved 各状态的含义、流转条件、UI 展示规则 | 高 |
| E-4 | per-Specialist 视图:当 Expert 有多个 Specialist 访问权限时,支持按 Specialist 筛选会话 | 中 |
| E-5 | 未读消息数 per-conversation:Thread 列表中每条会话显示精确未读条数 | 中 |
| E-6 | 消息富文本渲染:Slack mrkdwn、Markdown、链接预览等格式化展示 | 中 |
| E-7 | Internal Note:Expert 之间的内部沟通消息(已有 API,UI 完整性待核查) | 低 |