Contact Context Smoke
0. 这份 smoke 要回答什么
Call Input Smoke 检查单次 calls row 是否准确。Contact Context Smoke 检查的是下一层:
contacts-analyzer看到的 contact-level context 是否够准、够完整、够可解释。
如果 task 错了,可能不是 task decision policy 本身错,而是 contact context 已经缺关键事实:
- Contact snapshot 没带
doNotContact/lifecycleStage/leadStatus。 - Message 只有
VoiceMail (no transcript),AI 根本没看到客户留言内容。 - Lead record 没带 booking 相关事实,AI 不知道这是不是已经预约。
- Open task 没带
attemptCount/dueAt,AI 不知道该record_progress还是close unable_to_reach。 - Recently closed task 没进入 context,AI 可能重复创建同类 task。
这不是完整的 Contact Accuracy Foundation。它是 demo 前的 lightweight upstream sanity check:确认 Task Accuracy 的 contact input 没有明显歪掉。
1. 它在 pipeline 里的位置
这份 smoke 覆盖的是:
它不测试 raw audio transcription 质量,也不测试 Vapi。它直接假设 call/message/lead/task facts 已经落库,然后检查 context builder 是否把必要字段喂给 AI。
2. 当前 production context 已经喂了什么
当前 contacts-analyzer 的 user message 不是只喂一段 text。它会把多张表压成半结构化 context:
Contact Context Smoke 重点看 RECENT CALLS 以外的部分:current snapshot、messages、leads、open tasks、progress state、recently closed tasks 和 playbook guidance。
3. Smoke 的 review 原则
不要做所有全排列。这里按 contact decision point 覆盖:
- Source identity:这是 call、SMS、voicemail、lead record,还是 existing task?
- Recency:发生时间、当前时间、store timezone、last activity。
- Safety/context:
doNotContact、terminal lifecycle、recently closed task、existing duplicate task。 - Process state:open task、
attemptCount、dueAt、progress history。 - Lead facts:lead source、lead type、received time、booking facts。
- Message facts:SMS body、voicemail transcription、DNC keywords、callback timing。
- UI explainability:task timeline、customer summary、related open tasks 是否让 staff 能 30 秒看懂。
这个 smoke 不是看模型“会不会编一个合理故事”,而是看 production contact context 是否足够支撑正确判断。
4. 第一批 smoke scenario set
每个 scenario 至少检查三件事:
DB facts:上游表里字段是否写对。Prompt context:contacts-analyzeruser message 是否带到了这些字段。Expected implication:这些 facts 是否足够支持后续 contact / task decision。
CT-01 Existing lead books intro
业务状态
Lead 接通电话并确认预约 intro / first class。
必须看到的 contact context
- Lead record 存在。
CONTACTsnapshot 能显示当前 lifecycle / lead status。- Open task 如果是
lead_outreach/lead_follow_up,要出现在OPEN TASKS。 OPEN TASKS里的taskRef、typeCategory、attemptCount、dueAt必须可见。
Expected implication
已有 lead task 应该 close as booked。不要因为已经 booked 再创建 intake、waiver、arrival logistics task。
CT-02 Trial completed but not converted
业务状态
Lead 已经完成 trial / first class,但还没购买 membership。
必须看到的 contact context
- 有可靠 attendance / post-trial 证据,不只是 generic SMS。
- Contact stage 仍是
lead。 leadStatus可以是showed/trialed。PREVIOUS SUMMARY或 recent facts 说明 trial 体验和未转化原因。
Expected implication
后续 task 才能走 booked_not_converted。如果只是 booked upcoming class,不应该提前创建。
CT-03 Outbound no-answer on existing open task
业务状态
员工对一个 open task 打电话,没人接。
必须看到的 contact context
OPEN TASKS里有对应 open task。attemptCount和dueAt出现在OPEN TASKS。- 最新 call facts 能证明 outbound no-answer。
- 没有客户新表达的 objection / DNC / close outcome。
Expected implication
通常是 record_progress,不是 create new task,也不是随便 close。若 attemptCount 达到 policy threshold,再按 Task Accuracy policy 判断是否 close unable_to_reach。
CT-04 Voicemail callback request
业务状态
客户留 voicemail,说希望明天回电或指定时间 follow up。
必须看到的 contact context
messages.type = VoiceMailvoicemailTranscription有内容- Prompt 显示
VoiceMail (transcribed) - 文本里能看出 callback timing
- Store timezone / local time 存在,方便生成 UTC
nextDueAt
Expected implication
如果有 existing task,应该 record_progress with callback_requested / follow_up_scheduled。如果没有 existing task,而且是清晰 unresolved objective,才考虑 create task。
CT-05 SMS STOP / DNC
业务状态
客户回复 STOP / unsubscribe / do not contact。
必须看到的 contact context
RECENT MESSAGES显示 SMS body。- Contact snapshot 的
doNotContact如果已是 true,必须传给 AI。 - Writer / policy 仍要 sticky enforce,不能只靠模型。
Expected implication
AI 不应该创建普通 outreach task。DNC 是 safety gate,应该阻断 proactive call/SMS/email。
CT-06 Wrong number / non-customer business inquiry
业务状态
来电或消息是 wrong number、vendor、corporate sponsorship、partner、marketing pitch,和健身 customer lifecycle 无关。
必须看到的 contact context
- Current snapshot 能允许
lifecycleStage = unknown - Recent call/message summary 保存有用事实,但不要伪造成 lead/member
- 如果已有 open fitness task,要能在
OPEN TASKS看到它,方便 close invalid existing task
Expected implication
lifecycleStage 应该是 unknown,普通 fitness task 应该 no-op 或 close invalid existing task。
CT-07 Unresolved complaint
业务状态
会员投诉 billing、staff、facility、policy 或 app issue,且没有明确解决。
必须看到的 contact context
- call/message summary 里有 complaint evidence
followUpNeeded = yeswhen unresolved- Contact profile 要能设置或保留
hasOpenComplaint = true - 如果已有 retention/cancellation task,prompt 里必须能看到 existing task context
Expected implication
这类通常进入 retention 或 cancellation_risk,取决于是否有 churn/cancel risk。不能只当成普通 history summary。
CT-08 Referral / bring-a-friend opportunity with existing task
业务状态
现有会员主动说要带朋友、问 guest pass、推荐家人,或留下 referral opportunity;同一个 contact 可能还有 renewal / cancellation / retention task。
必须看到的 contact context
- Recent call/message 明确提 referral / guest / friend
- Contact identity 明确是 member 或 known customer
- Existing open tasks 全部进入 context,不要只显示一个 objective
- UI 能显示 same contact 的 related open tasks,避免 staff 误以为只生成一个 objective
Expected implication
这可以产生 referral task。若同一个 contact 还有另一个 open task,Task UI 要能让 staff 看见 related open tasks。
CT-09 Churned member asks to rejoin
业务状态
前会员主动来电或发消息,说想重新加入或回来上课。
必须看到的 contact context
- Contact snapshot 已是
churned,或 recent call facts 显示former_member - inbound customer-initiated re-engagement evidence
- 如果 interaction 当场完成 rejoin,outcome 要能显示 success;否则 follow-up remains open
Expected implication
后续 task 应该偏向 win_back。这不是 cold outbound win-back;是 customer-initiated reactivation。
5. 当前已发现的 contact context 风险
5.1 Lead facts 可能不够
当前 prompt 里的 LEAD RECORDS 主要展示:
但 leads schema 还有 booking/source/raw email 相关字段。对于“lead 是否已经 booked / trialed / needs follow-up”的判断,v1 smoke 应该验证现有字段是否够用。
如果不够,下一步不是马上把 rawBody 全塞进 prompt,而是先加 targeted context:
- booking date/time
- lead source / email subject
- parsed class time if available
- ingestion source when helpful
5.2 Store isolation 的 prompt 输入要继续验证
Open tasks 当前按 phone + storeId 取,这是对的,因为 task mutation 必须 store-scoped。
Recent calls / messages / leads 当前更像 phone + franchise scoped context。demo 前 smoke 要验证同一个 phone 在多 store 下不会把另一个 store 的 facts 喂给 AI。若发现风险,应该优先把 recent calls/messages/leads context 也收敛到 store-scoped 或 source-store-aware。
5.3 Playbook guidance 只在 open task 存在时注入
当前 PLAYBOOK GUIDANCE 是按 open task categories 注入的。这个对 progress / close / update 很有用。
但 create case 没有 existing open task 时,AI 主要靠 task taxonomy 和 call/contact facts 创建新 task。后续如果要让 create 的 suggestedActions 更稳定,可以考虑给 create candidate category 注入轻量 playbook guidance,但不要在 demo 前强行扩 scope。
5.4 Contact Accuracy Foundation v1 的长期形态
Contact Accuracy 不是让 AI 读一堆历史后自由发挥“这个人是什么状态”。更稳的形态是:
这和 AI Agent Foundation 的关系是:
Facts:多张表的历史事实,不是一段自由文本。Context Builder:决定 AI 到底看见什么;如果这里漏字段,下游 task 再聪明也会错。Structured Output Schema:让 contact state 和taskDecisions[]可验证、可 replay。Policy Guard:DNC、duplicate、store mismatch 不能只靠模型自觉。Eval / Replay:Contact Accuracy smoke 先验证 input 是否喂对,完整 foundation 再验证 lifecycle / intent / safety state 是否稳定。
6. Demo 前怎么用这份 smoke
每个 demo candidate 至少检查这一条链:
建议最小操作:
- 从 8-12 个 demo candidate 里选 3 个真实端到端 case。
- 对每个 case 保存一份 prompt context 或 OpenRouter log。
- 在 DB 里确认 contact/message/lead/task 的关键字段。
- 在 UI 里确认 task card、timeline、customer summary、related open tasks 能解释发生了什么。
- 如果错了,先归因:contact context 错、prompt contract 错、task decision 错、writer/policy 错,还是 UI 隐藏了正确结果。
一句话:
Demo 要讲的是 Task 准 + 写库安全 + UI 可解释;Contact Context Smoke 确保“Task 准”不是建立在看错 contact context 的基础上。