Skip to main content

PRD:WhatsApp 渠道 — Specialist ↔ 号码 1:1 绑定(号码池模式)+ 配对准入

English: whatsapp-per-specialist-number-prd.md

状态Draft — 待评审
OwnerFranky(产品)
日期2026-07-08
架构依据ADR-002(Twilio + 号码池 + 配对码,现行实现)· ADR-030 WhatsApp 子文档(Draft,per-OSA endpoint 方向)· WhatsApp 官方限制
姊妹方案Slack per-Specialist App PRD(同一模式:1:1 渠道身份 + 按状态门控的 Profile 入口)
关联#1471(ADR-030)、#3630(渠道配置 UX)、#3541/#3542(渠道指标族)

0. 术语澄清(先说清"绑定对象是谁")

客户门户里的 "Specialist" 是该 org 的运行实例(catalog 原型物化出的克隆,即 OSA 对应的 live Specialist)。因此本 PRD 的「Specialist ↔ 号码 1:1」实际是 每个 (Org × Specialist) 一个专属号码 —— 同一个原型 Kai 服务两个客户时,两个客户各得一个不同的号码。这与 ADR-030 WhatsApp 子文档的不变量 I-2(每 OSA 一个专属号)完全一致。

1. 问题陈述

当前 WhatsApp 渠道(ADR-002)虽有号码池与配对码机制,但存在三个产品缺口:

  1. 路由塌缩:一个 org 一份 WhatsApp 凭证,多 Specialist 的 org 在 WhatsApp 上回落到 primary OSA——号码与 Specialist 没有严格的 1:1 关系,客户无法"发消息给特定的 Specialist"。
  2. 配置不可见、容量不设防:管理员没有按 Specialist 的 WhatsApp 开关;号码池余量对配置流程完全无感——池子空了也能"配置",结果静默失败。
  3. 准入不明确:配对(HW-XXXX 码)存在但埋在设置页里;谁能和 Specialist 对话、未配对的人发消息会怎样,无统一规则(今天未知发件人会收到配对提示自动回复,行为未经产品确认)。

本 PRD 将现有机制收紧为:严格 1:1 号码绑定 + 池容量门控 + 配对白名单准入 + Profile 对话入口

2. 目标

  • G1 — 确定性归属:每个启用 WhatsApp 的 Specialist 拥有一个专属号码;发到该号码的消息只会进入该 Specialist 的会话。度量:入站按 To 号码单查表命中率 100%,primary-OSA 回落命中 = 0。
  • G2 — 容量诚实:管理员在开关处即可看到能否启用;绝不出现"打开了却没有号码"的静默失败。度量:因无号码导致的配置失败工单 = 0。
  • G3 — 准入可控:只有完成配对的用户 WhatsApp 账号能与 Specialist 会话;未配对号码来信不响应(不回复、不建会话)。度量:未配对来信触发的会话数 = 0。
  • G4 — 自助配对:客户成员从 Specialist Profile 入口自助完成配对管理(查看/新增/删除),无需管理员或 AM 介入。度量:配对完成率 ≥ 80%,配对后首条消息成功率 ≥ 95%。
  • G5 — 号码可回收:Specialist 被回收/删除后号码自动释放回池,经冷却后可复用;释放过程不产生跨客户消息串扰。

3. 非目标(v1)

  • 按需购号(Twilio API 动态采购)——v1 只消费预置号码池;池子的扩容走运营流程(见 §8 容量阶梯)。
  • ADR-030 完整 endpoint/persona 架构落地——v1 在现有 whatsapp_number_pool + whatsapp_linked_numbers 上收紧语义;osa_channel_endpoints 迁移是后续架构阶段(设计需与其兼容,见 §6 R1 技术注记)。
  • WABA-per-Specialist 身份容器与发信人资料同步——每号码的 sender display name / 头像同步(ADR-030 §2/§6)推后;v1 号码无个性化资料。
  • Org 前门模式(一个 org 一个号 + 话题路由)——ADR-028,明确推迟。
  • 对未配对来信的引导回复——按产品要求 v1 为静默不响应;一次性配对提示作为开放问题(O2)另议。
  • 群聊支持——仅 1:1 私聊。

4. 用户故事

客户管理员(org_admin)

  1. 作为客户管理员,我想为某个 Specialist 打开 WhatsApp,让团队能在 WhatsApp 上直接找到该 Specialist。
  2. 作为客户管理员,当号码池没有空闲号码时,我希望开关直接不可用并说明原因,而不是打开后出错。
  3. 作为客户管理员,我想在配置框里看到该 Specialist 的专属号码和已配对的用户列表,随时掌握谁在使用这个渠道。

客户成员 4. 作为客户成员,我想在 Specialist Profile 上看到 WhatsApp 入口,点进去就能完成配对并开始对话。 5. 作为客户成员,我想查看/新增/删除我自己的配对号码,换手机号时能自助处理。 6. 作为客户成员,配对完成后我希望直接在 WhatsApp 里和 Specialist 对话,体验与其它渠道一致(AI 起草 + Expert 审核)。

Ops(SuperAdmin / AM) 7. 作为 SuperAdmin,我需要维护号码池(添加号码、查看占用/空闲/冷却状态),并在池余量低时收到告警。 8. 作为 AM,我想看到我负责客户的 WhatsApp 启用与配对情况,便于推动采用。

Expert — 工作流不变:入站消息进队列时已归属正确 Specialist;回复经该 Specialist 的专属号码发回。

5. UX 流程

5.1 管理员配置(客户门户 → Settings → Channels → WhatsApp)

WhatsApp 卡片改为按 Specialist 列表,每行:Specialist 头像/名称 + 开关 + 状态。

池有空闲号码:
开关可用 → 打开 → 系统从池中随机取一个空闲号码,与该 Specialist 绑定
→ [已启用] 显示专属号码 +15551000001 · 已配对用户 N 人 · [配置▸]

池无空闲号码:
开关置灰,提示:「暂时没有可用 WhatsApp 号码,不能启用 WhatsApp 渠道」
(SuperAdmin 侧同步看到池余量告警)

关闭开关(有活跃绑定):
确认弹窗 → 解绑 → 号码进入冷却 → 该 Specialist 的入口隐藏、配对失效

5.2 配置框(点开某 Specialist 的 [配置▸])

  • 号码信息:专属 WhatsApp 号码(含复制按钮)。
  • 已配对用户列表:org 内每个已配对成员一行 —— 用户名 · 配对的 WhatsApp 号码(脱敏显示,如 +86 138****1234)· 配对时间;管理员可移除任一配对(用户可重新配对)。
  • 管理员不能代替用户新增配对(配对必须由本人完成占有验证,见 5.3)。

5.3 用户使用流程(Specialist Profile 的 WhatsApp 入口)

  1. 客户成员点击 Specialist Profile 上的 「Chat on WhatsApp」 入口(渠道未启用则不展示/置灰——与 Slack PRD 的门控入口同一模式)。
  2. 弹出我的配对面板
    • 已配对:列出我的已配对 WhatsApp 号码(可删除);主按钮 「打开 WhatsApp 对话」wa.me/{专属号码} 深链直接进入与该 Specialist 的聊天。
    • 未配对:引导新增配对 ——「新增配对」生成一次性配对码 HW-XXXX(15 分钟有效,沿用现机制),并给出预填了配对码的 wa.me/{专属号码}?text=HW-XXXX 深链;用户在 WhatsApp 里点发送即完成占有验证式配对(必须从本人手机发出,杜绝替他人绑号)。
    • 配对成功后面板即时刷新(webhook 驱动),主按钮变为「打开 WhatsApp 对话」。
  3. 会话准入:配对号码发来的消息 → 正常进入 该 Specialist 的会话(入站 → agent 起草 → Expert 审核 → 回复)。未配对号码发来的消息 → 不响应:不自动回复、不创建会话;仅内部隔离记录(见 R7)。

5.4 文案(v1)

位置文案
开关置灰提示暂时没有可用 WhatsApp 号码,不能启用 WhatsApp 渠道
Profile 入口Chat on WhatsApp
入口(渠道未启用,成员视角)tooltip:该 Specialist 尚未开通 WhatsApp——请联系你的管理员
配对引导发送配对码 HW-XXXX 到 {号码} 即可完成绑定(15 分钟内有效)
配对成功配对成功!现在可以在 WhatsApp 上与 {Specialist} 对话了

6. 需求

Must-have(P0)

R1 — 号码池与 1:1 绑定。 维护 WhatsApp 号码池(现有 whatsapp_number_pool 收紧语义):号码状态机 空闲 available → 已绑定 bound(specialist_id) → 冷却 cooling → 空闲。一个号码同一时刻至多绑定一个 Specialist(DB 唯一约束);一个 Specialist 至多一个号码。

  • Given 号码已绑定 Specialist A,then 任何将其绑定到 B 的尝试都被拒绝(约束层,非仅应用层)。
  • 技术注记:绑定关系的读写路径按 ADR-030 osa_channel_endpoints 的形状设计(number = external_id),后续迁移平滑。

R2 — 池容量门控开关。 管理员渠道配置中,WhatsApp 开关可用性 = 池中 available 号码数 > 0。

  • Given 池空,when 管理员查看渠道配置,then 开关置灰 + 提示文案(§5.4),且后端拒绝启用请求(UI 置灰非安全边界)。
  • Given 池空且有 org 想启用,then SuperAdmin 池面板显示待满足需求(低余量告警见 P1)。

R3 — 激活即随机绑定(并发安全、幂等)。 打开开关 → 从池中随机选一个 available 号码原子绑定(UPDATE … WHERE status='available' … LIMIT 1 RETURNING,遵循 active-active 规则,无进程内锁)。

  • Given 两个管理员同时为两个 Specialist 开启且池中仅剩 1 个号码,then 恰好一个成功、另一个得到池空提示——绝不双绑同一号码。
  • 重复开关不泄漏号码:同一 Specialist 重复激活是幂等的(已有绑定直接返回)。

R4 — 配置框可见性。 配置框展示:专属号码 + 已配对用户列表(用户 · 脱敏号码 · 配对时间),管理员可移除配对(写审计日志)。

R5 — 门控的 Profile 入口。 Specialist Profile 展示 WhatsApp 入口,状态如实:渠道启用 → 可用;未启用 → 不展示或置灰附提示(与 Slack PRD R3 同模式)。点击进入我的配对面板(§5.3)。

R6 — 自助配对管理(占有验证)。 用户在配对面板查看/新增/删除自己的配对:新增 = 生成 HW-XXXX 码(15 分钟 TTL、限速沿用现机制:5 次/小时)+ 预填 wa.me 深链,从本人 WhatsApp 发码完成验证(复用 whatsapp_pairing_codes / whatsapp_linked_numbers);删除即时生效。

  • Given 配对码过期或错误,then 该来信按未配对处理(R7),不消耗会话。
  • 配对归属 (用户, org) 层级:一次配对即可与该 org 内所有已启用 WhatsApp 的 Specialist 对话(按 To 号码路由到具体 Specialist)——按 Specialist 粒度的准入见开放问题 O3。

R7 — 入站准入(核心规则)。 入站消息路由:To 号码 → 绑定的 Specialist(org+specialist 确定)From 号码 → 配对表 → 用户两者同 org 且配对有效 → 进入该 Specialist 会话。否则(未配对 / 配对已删 / 跨 org)→ 不响应:不回复、不建会话、不进队列;写内部隔离记录(unresolved_ingress,reason=unpaired_sender,含脱敏 From/To)供 ops 排查与滥用监控。

  • 不变量测试:会话的 specialist_id/org_id 恒等于号码绑定的 Specialist/org;未配对来信产生 0 条 conversations/messages 记录。
  • 配对码消息(HW-XXXX)是唯一例外:走配对流程,不算会话消息。

R8 — 出站与会话语义。 Expert 放行的回复经该 Specialist 的专属号码发出(Twilio,3 层派发:熔断 → 重试 → DLQ);会话按 (用户, Specialist) 维度隔离;HITL 默认阈值等既有语义不变。24h 客服窗口外的回复需模板消息(计费见 whatsapp-limits §三)。

R9 — 回收与释放。 以下事件触发号码释放:Specialist 被解除分配(OSA 终止)、Specialist 删除/归档、org 停用、管理员关闭开关。释放动作(事务性):

  1. 解绑(号码 → cooling);
  2. 吊销该绑定下的全部配对(防止旧配对用户的来信到达"下一个主人");
  3. 冷却期(默认 30 天,可配)后回到 available;冷却期内来信按未配对静默处理;
  4. 全程审计(谁、何时、为何释放)。
  • Given 号码冷却结束被绑到新 Specialist,then 任何旧配对都无法与新 Specialist 对话(配对已在步骤 2 吊销)。
  • 注意 Twilio 号码保留在平台账户内(池模式),不做 Twilio 侧 release——避免 63051 类重新注册成本与号码丢失。

R10 — 埋点与审计(服务端)。 与渠道指标族(#3541/#3542)一致:whatsapp_pool_size{status}(gauge)、whatsapp_binding_total{outcome}whatsapp_pairing_total{outcome}whatsapp_unpaired_inbound_total;审计:开关开/关、绑定/释放、配对增/删(操作者 + org + specialist)。§11 每个指标可直接算出。

Nice-to-have(P1)

  • SuperAdmin 号码池面板:池列表(号码 · 状态 · 绑定对象 · 冷却剩余)、手动添加号码、低余量阈值告警(Slack 通知 AM/ops)。
  • 管理员通知:绑定成功 / 池空被拒 / 配对异常波动。
  • 配对面板显示二维码(扫码打开 wa.me 深链,桌面端体验)。
  • 未配对来信的滥用监控:同一 From 高频撞号告警。

Future(P2)

  • 按 Specialist 粒度的配对准入(当前为 org 级,见 O3)。
  • Twilio API 按需购号自动补池(池水位线自动维持)。
  • 迁移到 ADR-030 完整 osa_channel_endpoints + WABA-per-Specialist persona、发信人资料同步。
  • 未配对来信的一次性配对引导回复(若 O2 改变决策)。
  • Org 前门模式(ADR-028)。

7. 现状基线(改什么)

维度今天(ADR-002 现状)v1 之后
号码 ↔ Specialist池存在但无严格 1:1;路由回落 primary OSA严格 1:1(约束层保证);按 To 号码确定性路由
管理员配置无按 Specialist 开关;池容量无感按 Specialist 开关 + 池容量门控 + 配置框(号码 + 配对列表)
配对HW-XXXX 码存在,埋在设置页;发码即绑保留占有验证机制,升级为 Profile 入口内的自助配对面板(查/增/删)
未配对来信隔离 + 自动回复配对提示静默不响应(仅内部隔离记录)——行为变更!
旧白名单(whatsapp_sender_whitelist遗留回退路由v1 不再参与准入(只认配对),保留只读待清理
号码回收无产品化流程R9 全生命周期(释放 → 吊销配对 → 冷却 → 复用)
Profile 入口门控的「Chat on WhatsApp」+ 配对面板

8. 平台约束(务必正视)

  1. 池的天花板是 Meta portfolio 上限:未验证 2 个号、验证后 20 个、再往上人工工单(whatsapp-limits §二/§七 容量阶梯)。启用 WhatsApp 的 Specialist 总数 ≤ 池上限——Business Verification 是本功能规模化的硬前置;池扩容按容量阶梯走(工单 → ISV per-client portfolio)。
  2. 触达限额按 portfolio 共享:所有池号码共享同一 messaging limit(250 → 2,000 → …);某个 Specialist 的高流量会挤占全池的主动触达额度。窗口内回复不受限——本功能以用户主动发起为主,风险可控,但需监控。
  3. 模板计费:客服窗口(24h)外的回复按模板逐条计费(2025-07 起);成本随 osa_id 归集。
  4. 63051 闲置锁:池中长期 available 的号码 30 天无活动会被 Meta 锁定——池维护任务需周期性保活或接受重激活成本(工程确认,O4)。

9. 安全与隐私

  1. 配对 = 占有验证:必须从本人手机发码,UI 不允许直接录入任意号码(防冒绑他人号码)。配对码 15 分钟 TTL + 5 次/小时限速(现机制)。
  2. 权限:开关/配置框 = org_admin;配对面板 = 成员本人(只能管理自己的配对);管理员可移除任何配对但不能代加。后端 Guard 是权威边界。
  3. 号码复用串扰:R9 的"吊销配对 + 冷却期"是防串扰的核心;冷却期内来信静默丢弃并记录。
  4. 脱敏:配对列表与日志中的手机号一律脱敏展示;完整号码仅路由层使用。
  5. 租户隔离:ADR-020 不变量——会话按 (org, specialist) 双过滤;未配对来信绝不产生任何跨租户可见痕迹。

10. 发布与回滚

  • Feature flag 按 org 白名单:1 个内部测试 org + 1–2 个友好客户试点,漏斗指标(R10)干净运行 2 周后放开。
  • 回滚 = 关 flag:UI 回到现状;已绑定号码保持绑定(不自动释放),入站准入回退到现行为(含配对提示自动回复)。
  • 行为变更提示:「未配对静默」上线时,对已有 WhatsApp 使用的试点 org 需在发布说明中明示(今天会收到配对提示的用户将改为收不到任何回复)。

11. 成功指标

领先(上线 2 周):启用成功率(开关打开→绑定成功)≥ 99%;配对完成率(发起→成功)≥ 80%;配对后首条消息进入队列成功率 ≥ 95%;未配对来信静默处理率 100%(0 响应、0 会话);池空导致的启用被拒次数(用于扩容决策)。

滞后(季度):WhatsApp 会话量/org;启用 WhatsApp 的 Specialist 数与池利用率;配对用户留存(配对后 30 天仍活跃对话);WhatsApp 相关支持工单下降。

度量方法:全部来自 R10 计数器 + 审计日志;无需人工拉数。

12. 开放问题

#问题Owner阻塞?
O1池的初始规模与扩容触发线(结合 Meta 上限 2→20:验证前只有 2 个号,试点即受限——Business Verification 是否作为上线前置?)产品 + ops
O2未配对来信"完全静默"的 UX 风险:真实客户手输错号/换号后发消息石沉大海。是否给首次未配对来信一条一次性配对引导(之后静默)?产品(Franky)是 — 决定 R7 最终形态
O3配对粒度:v1 为 org 级(配对一次可与该 org 全部已启用 Specialist 对话)。是否需要按 Specialist 粒度准入(用户 A 只许和 Kai 聊、不许和 Mei 聊)?产品否 — P2 预留
O463051 闲置锁对池中空闲号码的实际影响与保活方案(定期自发保活消息?接受重激活?)工程
O5冷却期时长(建议默认 30 天)与是否允许 SuperAdmin 手动提前解冻产品 + ops
O6同一用户手机号在多个 org 都配对时的路由确认(现 whatsapp_linked_numbers 含 orgId,To 号码已定 org——需确认多 org 同号无歧义)工程
O7Profile 入口与 Slack 入口的统一设计(「Contact via …」多渠道组件,见 Slack PRD §5.2 设计说明)设计UI 开发前需定

13. 阶段划分与依赖

  • v1(本 PRD):R1–R10 全量 + P1 的池面板(SuperAdmin 没有池面板则 R2 无法运营)。前置:Meta Business Verification(O1,决定池 ≤2 还是 ≤20);号码池预置(Twilio 采购 + 入池)。
  • v1.1:P1 余项(告警、二维码、滥用监控)+ O2/O3 决策落地。
  • v2:ADR-030 endpoint/persona 迁移、按需购号、发信人资料同步、按 Specialist 配对粒度。

依赖:Twilio 号码采购(ops);Meta Business Verification(ops,建议立即启动——审核周期数天到数周);与 Slack per-Specialist PRD 的 Profile 入口组件复用(O7)。

14. 参考