XIJIAN DOCS

消息域服务契约 v1.0

消息台深度融入运营台(产品一体、代码服务化):触达动作契约与 shadow-first 纪律 · ← 返回文档中心

目录
1. 总则2. 方向一:server → 消息台3. 方向二:消息台 → server4. 盘点 §6 五项缺口逐项处置5. 配置项清单6. 待裁决事项表(主会话已裁决,2026-08-16)7. 验收判据(P0-6.3/6.4/6.5 共用,qa-acceptor 逐项实证)变更记录

犀见 ↔ 消息工作台 集成契约 v1(P0-6.2)

版本:v1.0 定稿 | 2026-08-16 | 作者:product-owner | 终验:主会话(裁决见 §6 表) 上游:口径基线 v2.1(唯一口径源)| 总纲领 v1.3 §5 | 盘点 docs/dev/message-api-notes.md(下称「盘点」,细节一律引其节号,本文不复述) 下游:P0-6.3(msgbridge 客户端)、P0-6.4(缺口处置)、P1-7/P1-8/P1-11 全部按本文开发。触达类功能的总闸:本文没写的触达场景不许开工。


1. 总则

定位澄清(用户确认 2026-08-16):消息台深度融入统一运营台——对用户是一个产品(主工作面板即消息台形态,总纲领 §5),不是两个独立运行的系统;「集成契约」指的是代码层面的服务间接口(消息台作为企微执行层服务化部署),产品层面无缝一体。

1.1 分工边界(架构级,不可协商)

职责
犀见 server(编排) 圈人(业务条件→名单)、判发不发、文案组装、幂等与去重、审计留痕、批次归因、结果回执
消息工作台(执行) 企微通道本身:发送、限流、设备在线、风控熔断、加人节流、群发分批

犀见 server 绝不自建企微发送通道(盘点 §3「推论对犀见的约束」):消息台的发送限流是单 gunicorn 进程的内存状态,任何绕过它的发送路径都会让两边各限各的、合起来突破企微真实上限,代价是封号(封号=整条触达链全断)。犀见所有主动触达一律经消息台 API。

1.2 通道与身份

1.3 限流继承声明(照录盘点 §3,犀见侧一律只继承不重设)

通道 闸值 归属
单聊 send/reply/forward/card/location 20 条/分、300 条/时(单账号) 消息台 api_ext.py:1500,工程保守取值
群发 broadcast 20 人/批、批间隔 3 秒、≤500 人/次,不过单聊闸 消息台 broadcast.py
批量加人 addfriend 20/号/天、间隔 45~90s、仅 9:00–21:00、单任务 ≤2000 消息台 addfriend.py

犀见侧不设本地限流副本:额度一律实时读 GET /api/send-quota(发送)与 GET /api/addfriend 返回的 quota/config(加人)。理由——把 20/300 抄进犀见 cfg 会制造两份真相且必然漂移;真闸在消息台,犀见只做「发之前先看余量、余量不够就排队」。

1.4 shadow-first 纪律


2. 方向一:server → 消息台

2.1 场景 ②A 一键定向邀约(基线 §3 ②A、§6.9、§6.11)

前置铁律:名单由人工反选拍板(基线 §5「反选永不自动化」);server 只执行已确认名单。名单在发起时快照落库invite_batch_member),运行期不允许扩名单——对应 §6.9 判据「名单外不发」。

A1 未建联/未加好友者 → 批量好友申请(基线 §6.11)

  1. server 取名单手机号(基线 §0:企微只能搜手机号);无手机号者明确列出并提示,不静默跳过(§6.11 判据 2)
  2. POST /api/addfriend body {phones:[...], guids:[...], mode:"balance", verifyText, note:"xijian:<batch_no>"}{ok,id,job}
  3. POST /api/addfriend/<jid>/confirm body {count: len(phones)}(数量原样确认)
  4. POST /api/addfriend/<jid>/start
  5. 轮询 GET /api/addfriend/<jid> 取明细(策略见 §4.3)

  6. 幂等notexijian:<batch_no> 作业务幂等标记;建 job 前先 GET /api/addfriend 按该前缀查重,命中则复用不重建(消息台无幂等键,缺口 4)。

  7. 重试:仅 create 阶段失败可重试(有查重兜底);start 之后不重试。
  8. shadow:跑到步骤 1 + GET /api/addfriend 读余量为止。

A2 已是好友者 → 邀约消息 + 入驻/任务卡片

  1. 身份翻译(§2.5)拿到 (guid,userId)
  2. GET /api/conv-of?guid=&userId=cid;无会话则 POST /api/conv/new {userId,guid}
  3. 文案:POST /api/conv/<cid>/send {text}(模板 cfg,见 §5)
  4. 卡片:POST /api/conv/<cid>/send-miniprogram {pageKey,title,desc,taskId}{ok,wcid,path}
  5. 人数 > msgbridge.urge_batch_threshold 时改走群发:POST /api/broadcast {guid,targets,msgs,sendType,note:"xijian:<batch_no>"}POST /api/broadcast/<bid>/confirm {count}POST /api/broadcast/<bid>/send

  6. 批次归因(§6.9 判据 2「报名意向可关联回邀约批次」):用步骤 4 返回的 wcid 作归因键,server 存 wcid ↔ (batch_id, influencer_id);达人点卡片后 wcid 回流即完成漏斗闭环。不新增任何接口

  7. 审计:每人一条 msgbridge.invite.*,记 scene/batch_id/influencer_id/peer/mode/wcid/消息台返回。

2.2 场景 一键催发(基线 §6.10 人工触发;§4 时效自动触发)

口径红线(契约级断言,api-tester 必测):请求必带 trigger ∈ {manual, auto}。 - scene=urge.underperform(数据不达标催发,§6.10/§7.2)只接受 trigger=manual——「系统绝不自动催发不达标达人,着急的是达人」。trigger=auto + 该 scene → 422。 - scene=urge.sla(时效超时催发,§4)可 auto,对全量达人统一标准(§4 v2.0 口径)。

调用序列(单发):身份翻译(§2.5)→ GET /api/conv-ofPOST /api/conv/<cid>/send {text};需要挂在某条消息下时用 POST /api/conv/<cid>/reply {text,quoteUid}(拼不出结构会 degraded:true 降级成普通发送,server 按成功记但审计标 degraded)。 批量(> 阈值):POST /api/broadcast/confirm {count}/send(≤500 人/次)。

2.3 场景 入驻卡片触达(基线 §6.1)

2.4 场景 会话查看嵌入(P0 明确不做)

可用接口:GET /api/stateGET /api/conv/<cid>GET /api/conv/<cid>/historyGET /api/search——均为整页人工界面设计的重接口(盘点 §6)。 P0 决策:不做嵌入。 北极星判据:只读会话不减少任何达运人工动作(运营已有消息台界面,且总纲领 §5 定调「主工作面板就是消息台」),为它做裁剪接口属镀金(三不原则第 3 条)。P0 只用轻接口 GET /api/conv-ofGET /api/conv/<cid>/binding。P1(随 P2-16 前端融合)再议是否要裁剪版只读接口。

2.5 「业务条件 → 企微身份」翻译链路(催发/邀约共用,唯一正解)

influencer_id →(达人域档案)→ 手机号/抖音号 →(绑定关系)→ peer(guid,userId)GET /api/conv-ofcid

关键:不要试图用手机号在企微侧搜人——企微不给外部联系人手机号/微信号(contactType 2057 实测全空,盘点 §7),GET /api/contacts?kw=<手机号> 对外部联系人基本搜不到。可靠的唯一桥是绑定关系(wcid 回流或人工绑定,盘点 §4)。因此:


3. 方向二:消息台 → server

3.1 wcid 绑定回流(归属决策,待裁决 D1

PO 推荐方案:沿用消息台协议签发与兑现,犀见 server 只做镜像。 - 犀见新 miniapp 拿到 wcid 后仍调 POST /api/wcid/redeem(公网固定入口 api.lynoxi.com/qiwe/wcid/redeem,无鉴权、HMAC 自证、30 天 TTL); - redeem 成功后 miniapp 调犀见 POST /api/miniapp/binding/redeemed {wcid, influencerId, openId},server 写 binding_mirror 并触发 P0-3.1 建联入档。 - 推荐理由:① WCID_SECRET 只在消息台,犀见自签需复制密钥跨服务,双签发一旦密钥不同步即全链断;② 绑定权威表 peer_binding 在消息台(人工绑定也写那里),双写会造出两份真相;③ 卡片由消息台发出,token 由发卡方签发天然内聚;④ 犀见真正需要的只是「绑定发生了」这一事实,镜像足够。 - 风险与缓解:miniapp 需连调两个后端 → 顺序固定「先 redeem(权威)后通知犀见」;通知犀见失败不阻塞达人流程,靠 §4.3 的绑定对账轮询兜底补齐。 - 备选(若主会话裁定犀见自签):需下发 WCID_SECRET、复刻 bind.make_wcid(约 30 行,盘点 §5),消息台 verify 侧不变——代价是密钥同步与两处生成逻辑必须永远一致。

3.2 绑定状态查询

GET/POST/DELETE /api/conv/<cid>/binding(单会话 CRUD,POST body {influencerId,taskId,note}source=manual 优先级高于 wcid 自动绑定,不被覆盖);GET /api/binding/stats(总数+来源分布,看板用);按 influencer_id 反查见 §2.5 镜像方案。

3.3 议价落库(基线 §6.2,实现排 P1-11.1,v1 只定形状)

3.4 阶段状态与档案(犀见供给侧,实现排 P1,AI 回复 9-10 里程碑)

业务阶段(基线 §3 的 12+2)权威在犀见,消息台侧的 handling(auto/escalated/taken/done)是会话处理态,两者不是一回事,禁止互相映射。犀见对外只读接口形状: GET /api/msgbridge/stage?douyin_id=|phone=|influencer_id= → 当前阶段 + 关联商单;GET /api/msgbridge/influencer?douyin_id=|phone= → 档案(§6.8 判据)。

3.5 反向鉴权(待裁决 D7

建议:同机回环 + 犀见侧固定 X-Msgbridge-Token(放 server .env,非业务 cfg)。v1 不实现。


4. 盘点 §6 五项缺口逐项处置

# 缺口 处置 理由
1 无服务间认证 契约内解决 固定身份头 + 127.0.0.1 回环边界(§1.2);改消息台加凭证 = 动老服务,风险与收益不匹配;跨机升级钩子已留
2 无按 influencer_id 反查绑定 犀见侧自解 binding_mirror 本地镜像(§2.5):反查是犀见的读需求,缓存在犀见侧最自然,零改动老服务
3 无事件推送/webhook 接受现状轮询(策略见 §4.3) 加 webhook 需改老服务且要处理投递重试;受控轮询在本量级(5 个企微号、百级会话)足够
4 发送无客户端幂等键 犀见侧自解 touch_log 先占后发 + 超时不自动重试(§2.2);notexijian:<batch_no> 供批量类回查。「每人每场景每日至多一次」本就是业务口径层的事,放犀见侧比改协议更贴切
5 「项目」三源不一致 契约内解决(约束式) v1 禁止跨系统传递 projectId 语义:犀见→消息台不传 projectId;归因一律用 wcid + 犀见自己的 batch_id。主键体系对齐留 P0-4(待裁决 D2)

4.3 轮询三原则(缺口 3 的落地纪律,工程铁律 3:轮询按实体去重,防 binlog 洪水)

  1. 受控集合:只轮与「运行中的 addfriend job / 活跃邀约批次 / 活跃商单」关联的实体,永不全量扫 GET /api/state
  2. 变更才写:每轮对 (scene, entity_id, fingerprint) 比对,值未变零写入、零事件(消息台 store.set_handling() 是同一纪律的先例,盘点 §3)。
  3. 水位/游标:addfriend 用 job 状态 + 已处理明细序号;price 用 latest.ts 水位;binding 用 synced_at 对账时间戳。
  4. 频率(全部 cfg):addfriend job 30s(仅任务运行中,终态即停);binding 对账 60 分钟;price 5 分钟(仅活跃商单)。任务无活跃实体时轮询器空转不发请求。

5. 配置项清单

A. 走犀见配置中心(cfg,判定/开关;键名规范 域.蛇形名,需补入基线 §12A —— 补入动作待主会话批准,本次未改基线)

默认值 出处
msgbridge.mode off 总纲领 P0-6「shadow 先行」;三态语义对齐盘点 §3
msgbridge.scene_mode.<scene> 空(继承全局,取更保守档) 同上
msgbridge.dedupe_window_hours 24 无基线出处,待业务确认(D3)
msgbridge.urge_batch_threshold 30 工程取值(20 条/分反推),非业务口径(D4)
msgbridge.broadcast_max_targets 500 消息台硬限(盘点 §2.6),只读镜像不得调大
msgbridge.retry_max 2 工程取值
msgbridge.rate_limited_backoff_minutes 5 工程取值
msgbridge.poll.addfriend_job_seconds 30 工程取值(§4.3)
msgbridge.poll.binding_reconcile_minutes 60 工程取值(§4.3)
msgbridge.poll.price_minutes 5 工程取值(§4.3)
msgbridge.tpl.invite_text 待确认 基线 §6.9;话术由犀见/运营提供(基线 §3 五要素说明),不编默认文案
msgbridge.tpl.urge_underperform_text 待确认 基线 §6.10,同上(D5)
msgbridge.tpl.urge_sla_link_fill_text 待确认 基线 §4/§6.10,同上(D5)
msgbridge.tpl.card_onboarding_title / _desc 待确认 基线 §6.1(欢迎话术已配企微后台,卡片文案待核)

B. 走 server 环境配置(.env,部署事实非业务口径,不进配置中心) MSGBRIDGE_BASE_URL=http://127.0.0.1:5040MSGBRIDGE_AUTH_MODE=headerMSGBRIDGE_AUTH_USER=xijian-serverMSGBRIDGE_AUTH_OID=system-xijianMSGBRIDGE_TIMEOUT_READ=10MSGBRIDGE_TIMEOUT_WRITE=30

C. 明确不设本地副本:发送限流 20/分·300/时、加人 20/号/天 —— 见 §1.3,实时读消息台接口,禁止抄进 cfg。


6. 待裁决事项表(主会话已裁决,2026-08-16)

# 事项 PO 建议倾向 裁决
D1 wcid 归属:沿用消息台签发 vs 犀见 server 自签 沿用消息台签发 + 犀见镜像(理由见 §3.1 四条) ✅ 采纳——密钥不跨服务、权威表单一,是唯一低险解
D2 「项目」主键三源(lynoxi.task / 中台 project / 经营环 card)对齐 v1 契约内回避(不传 projectId);主键体系在 P0-4 项目与计划域定案 ✅ 采纳
D3 同场景同人去重窗口 24h 基线无此口径,建议按 24h 先跑并交业务确认后补入 §12A 用户定案(二批-1):每日至多 5 次msgbridge.daily_touch_limit=5 可配),touch_log 改计数制;已入基线 §12A
D4 单发/群发切换阈值 30 人 工程取值,允许开发期按实测调;不属业务口径 ✅ 采纳
D5 邀约/催发/卡片文案模板 待运营出话术;不编默认文案 用户定案(二批-2):全部可配,系统生成默认文案(运营后台可改)——tpl 键已填默认值
D6 send-miniprogramtaskId 语义(消息台 make_wcid 存 task_id,疑为 lynoxi.task.id) P0-6.3 实测确认;确认前留空,归因靠 wcid ✅ 采纳
D7 反向接口(阶段/档案/议价)鉴权形式 同机回环 + 固定 X-Msgbridge-Token,P1 实现 ✅ 采纳
D8 议价落库:犀见轮询拉 vs 消息台推 v1 轮询拉(老代码不动不管);若日后允许改消息台,推送更省资源 ✅ 采纳——与用户定案「老代码不动不管」一致
D9 会话查看嵌入是否做 P0 不做(镀金,§2.4);随 P2-16 前端融合再议 ✅ 采纳——与「主工作面板即消息台」定调一致,运营直接用消息台界面

7. 验收判据(P0-6.3/6.4/6.5 共用,qa-acceptor 逐项实证)


变更记录

日期 版本 变更
2026-08-16 v1 草案 首版:总则/双向场景/五缺口处置/配置清单/9 项待裁决。基于盘点 v1 + 主会话核实的部署事实(无 FEISHU_APP_ID、回环监听、同机部署、WCID_SECRET 与 XIJIAN_WELCOME_CARD 已配置)
2026-08-16 v1.0 定稿 主会话终验:D1–D9 全部裁决(§6 表),D3/D5 转用户确认清单;契约生效,P0-6.3/6.4/6.5 按此开发
2026-08-17 v1.1 追加 scene:order.visitor_invite / order.group_pull(商单触发器场景,P0-5.1 S13);§2.5 注实现表名(S6)