Voice Agent 可行性

作者: Max + AI (Claude Opus 4.7) + Codex 日期: 2026-05-25 状态: 调研报告 — 非 implementation plan, 不给时间表 读者: retaintive 团队 (含 non-technical 成员)

这份提到 "tenant-scoped tool API" / "capability token" / "control plane" 等架构概念。如果不熟悉 layered vs hexagonal 分层 / ports & adapters / Dependency Inversion / SOLID, 先看 Backend 架构 Pattern


这份文档要回答什么

Max 看到 Chowbus / Toast 在做 AI 接电话, 想知道:

  1. 市面上 AI 接打电话产品是怎么做的, 自研还是接第三方
  2. retaintive 未来从 "AI 帮员工建任务" 演进到 "AI 自己打 / 接电话", 难度多大
  3. 多店运营时怎么保证数据不串
  4. 现有 backend 够不够, 缺什么
  5. 晚上下班场景具体怎么跑

一句话结论

有条件推荐做, 但不是马上做。

retaintive 起步比绝大多数 SaaS 容易。多租户隔离 / Deepgram + LLM pipeline / 21 张 Neon 表 / 权威 phone→store 映射这些底子已经跑生产, 同档对手是 Chowbus (cloud-native + 数据 pipeline 完备, $209M Series E), 不是 ABCPOS 那种 legacy POS。

工程上中等不难 — 接 Vapi 或 Retell + 暴露 tenant-scoped tool API + 加一张 session 表 + 改 calling hours 引擎。不需要重写 backend, 不需要造新 pipeline。

合规上真的难。TCPA (FCC 2024 把 AI 合成语音明确纳入监管) + FTC click-cancel rule + 两方录音同意州法。这部分不能跳, 不能事后补, 必须从一开始进架构设计。

产品上风险中等。第一次上线 AI 接电话, 店主对品牌第一接触点的信任度容易被一次翻车毁掉。必须 1 店试点 + 老板能开关 + 通话可 review。

什么时候做: 前端展示阶段做完后再启动。现在不动代码。

定位接受重新 framing — 第一阶段不做 booking / sales / outbound, 只做 AI 接电话 + 留信息 + 合规路由。当成 "替员工值夜班接电话留信息", 不是 "AI receptionist 自主决策"。


市场全景

按层分谁在做这件事

底层 voice 基础设施 — Twilio, LiveKit, Deepgram, ElevenLabs, Cartesia, OpenAI Realtime API

中层通用 platform (帮你把底层拼起来, 给开发者用) — Vapi, Bland AI, Retell AI, Synthflow, Pipecat

上层垂直 app —

  • 餐厅: Loman, Bite Buddy, Slang.ai, NeverClosed, SoundHound (drive-thru), PolyAI (enterprise)
  • 健身房: CallSphere, Dograh, Whippy, JustCall, Capture Client
  • POS 巨头自带: Toast IQ (Toast POS), Chowbus AI Digital Worker

几乎没人自研底层

自己造一个生产级 voice agent 要 $800K-2M, 12-24 个月。接第三方 platform 是 $0.05-0.20/min, 数天上线。2024 年 42% 的企业 AI 项目放弃 (2023 是 17%), 主因低估自研复杂度。

垂直 SaaS (餐厅 / 健身房 / 医疗) 100% 站在中层 platform 之上, 只控制行业 prompt + 集成 + workflow。retaintive 没理由例外。

Retell 不是最强

标价 $0.07/min 是钓鱼, 全套配齐实际 $0.25-0.33/min。没有 visual builder, 改流程要工程师。没有 RBAC / audit trail / ISO 27001。非企业用户只有 Discord / email 支持。

按 retaintive 场景选不同 trade-off:

  • 最快上线试水选 Vapi (最 dev-friendly, free tier 够 POC)
  • 跑量 outbound 选 Bland AI (per-minute 价格便宜 30-50%)
  • 低延迟做预约选 Retell (600ms latency 行业最低)
  • no-code 让运营改选 Synthflow

典型技术栈

绝大多数 2026 垂直 AI voice 产品的组合:

Telephony            STT              LLM                   TTS                  Orchestration
─────────           ───────          ──────                ──────────           ──────────────
Twilio          →   Deepgram     →   GPT-5 / Claude   →   ElevenLabs       →   Vapi
ConversationRelay   Nova-3           OpenAI Realtime      Cartesia Sonic-3      或 Retell
                                                          OpenAI TTS            或 LiveKit Agents
                                                                                或 Pipecat

latency 标杆:

  • 700ms 以下 — 听感对话流畅
  • 700-900ms — 用户察觉延迟
  • 900ms 以上 — 用户挂电话

retaintive 走外呼必须打到 700ms 以内。


retaintive 现有代码现状

系统架构 (现在长这样)

RingCentral → ringcentralSubscriptionService (webhook receiver)
            → SQS (telephony + message queue)
            → callytics-infrastructure (Lambda factory)
                ├── transcribe-processor → Deepgram nova-2-phonecall + Whisper batch
                ├── ai-analysis-processor → LLM (triage / classify / coaching)
                ├── contacts-analyzer → contact-level aggregation
                ├── neon-sync → DynamoDB → Neon
                └── lead-processor / message-processor
            → DynamoDB (call-analysis, call-events, MessageStore, LeadTracking-v2)
            → Neon PostgreSQL (21 张表)
            → studio-website-monorepo (Hono API + Vue 3 frontend)
            → Cloudflare Pages (studio.retaintive.ai)

Store-level 隔离已落地

来源: docs/system-design/store-level-isolation.md (2026-04-14 定稿, PR #277 2026-04-28 切换完成, ~99.7% 填充率)

概念角色
store_idUUID, retaintive 生成唯一隔离键, 所有查询 WHERE store_id = ?
account_idRC OAuth ownerId性能分区 + 安全网, 不做隔离
franchise_id硬编码 ("orangeTheory")品牌标识, 无隔离价值
store_phoneE.164 phone审计字段, 不做隔离

加了 store_id NOT NULL 的表: calls / contacts / leads / tasks / phone_numbers / operating_schedules / messages / staff / contact_timeline。

rc_store_phones 是 phone → store_id 的权威映射。Prod 数据 2026-05-25 query 结果: 78 phone / 78 distinct / 13 store / 0 dup。每个 phone 唯一映射一个 store。

现有数据可以直接喂给 voice agent

读完 schema 后, voice agent 需要的 "店内 context" retaintive 几乎都有现成:

Voice agent 要回答数据已在哪
会员价多少store_config.pricing (JSONB, 支持 intro offers / class packs / membership tiers)
营业时间operating_schedules.schedule (per-day open/close + effective_date)
明天 10am 有空吗operating_schedules + blackout_periods (节假日 / 特殊关店)
你们是哪家店rc_stores.name + store_config.alias
我之前打过电话吗contacts 表 (WHERE phone AND store_id)
我是 lead 吗leads
我有过失约吗tasks

voice agent 主要工作不是写新业务逻辑, 而是: 拼一个 store context bundle endpoint 聚合上面 6-7 个数据源 + 把 system prompt 模板化 + 暴露 3-5 个 tool 给 voice 平台调。

studio-api 已有 multi-tenant 基础

apps/api/src/utils/store-authorization-neon.tsgetAuthorizedStoreNeon(userId, storeId) 用一个 SQL 验证用户对 store 的权限。21 个 route 模块全部按 store scope 设计。JWT auth + tracing + error-handler 三层 middleware 就位。

voice agent 拿 storeId 调 studio-api 现有 endpoint = 0 重构。但当前 endpoint 都是 JWT-scoped 给前端用, voice partner 不能直接用 — 见 §endpoint 现状。

retaintive 的 CI 数据是真正护城河。voice agent 拿到的不是 "通用健身房 prompt", 是 "Devon 店今晚营业到 10pm + intro offer $49 + 这个号码上周打过电话问过价 + Sarah 是 manager + 明早 9-11am 空" 这种 store-specific live context。CallSphere / Dograh / Whippy 这些通用 voice 平台拿不到这层。


多租户隔离设计

Max 最关心的问题。retaintive 已有 store_id 隔离是基础, voice agent 加一层。

Inbound 解析链路

客户拨 +16104403480 (Devon 店的号码)

RC 接通 + 录音 + webhook 到 ringcentralSubscriptionService

voice agent gateway 接到 inbound call (RC SIP forward 或 Twilio bridge)

voice agent 启动前调 retaintive API:
  POST /v3/voice-agent/inbound-context
  body: { calledNumber: "+16104403480", callerNumber: "+12125559999" }

retaintive API 执行:
  1. resolvePhoneIdentity → 查 rc_store_phones 拿 storeId
  2. 查 store_config (timezone / business hours / pricing)
  3. 查 callerNumber 是不是已知 lead/contact (WHERE store_id = ?)
  4. 返回 tenant-scoped context bundle

voice agent 用 context 开始对话, 后续所有 tool call 必须带 storeId

通话结束 → 录音 + 转录 → 进入现有 call-analytics-pipeline

Outbound 链路

触发: lead 表新增一行 (store_id NOT NULL 已填好)

触发器 (EventBridge): 5min 后员工没接 → 触发 AI 外呼

retaintive 调 voice 平台 API:
  POST https://api.vapi.ai/call/phone
  body:
    phoneNumberId: <Devon 店的 vapi phone resource>
    customer: { number: "+12125559999" }
    assistant:
      systemPrompt: <retaintive 拼好, 注入 store 信息>
      tools:
        - checkSchedule  → studio-api /v3/voice-agent/schedule
        - bookAppointment → studio-api /v3/voice-agent/book
        - escalateToHuman → studio-api /v3/voice-agent/escalate
      metadata: { storeId, leadId }

voice agent 拨号 → AI 用 store-scoped prompt 对话

每次 tool call 打到 retaintive API:
  - 验证 capability token (绑 storeId / leadId / allowed tools / expiry / nonce)
  - 强制 WHERE store_id = $tenant
  - 跨 store 查询直接 403

通话结束 → webhook 回到 retaintive → 进入现有 pipeline

数据串店的三层防护

Phone routing 层

Devon 客户拨错号到 White Plains: rc_store_phones 查到 storeId = WP, AI 自报 "Hi this is White Plains", 客户自己挂电话。

两店共用号码: schema 当前允许但 prod 没出现 (见 §schema 加固)。

号码移店 (Devon → WP): UI 改 phone-store-assignment 之后, 新通话 routing 到 WP, 旧数据留 Devon (TCPA 合规要求)。

API 调用层 (voice agent 调 retaintive)

每个 tool endpoint 五道关:

  1. 验证 capability token (server-side 发的 session token, 不信任 header 中的 storeId)
  2. storeId 从 token 解出, 不允许 caller 自己 declare
  3. SQL 层强制 WHERE store_id = $tenant
  4. Tool response schema 校验
  5. Audit log (storeId / tool / input / output 全记)

token 设计借鉴 OAuth2 capability pattern: voice_agent_session_id → 一次性服务端 token, 绑 storeId / leadId / allowed tools / expiry / nonce / call vendor id。token 失效后 voice agent 调用直接 403。

Voice 平台层

平台多租户方式retaintive 怎么用
Vapiper-tenant phoneNumberId + per-call assistant override一个 vapi phone resource = 一个 store, dynamic prompt 注入
Retellweighted agent lists + dynamic variables类似
Twilio Programmable Voice完全自管每个 store 一个 phone, callbackUrl 带 storeId

POC 选 Vapi (dev-friendly + per-call dynamic prompt + 便宜)。但 vendor 拥有 call state / latency path / prompt runtime / recordings / phone resources / failure modes / pricing — voice 平台是 disposable POC 工具, 不该成为 system of record。retaintive 长期边界应该是: 自有 policy engine / session ledger / consent-DNC / prompt-script versions / audit / outcome scoring, 只 buy media + orchestration。

Schema 加固

rc_store_phones 的 unique index 是 (store_id, phone_number) 组合, phone_number 单独不 unique:

// callytics-common/src/db/schema/rc-stores.ts
uniqueIndex('uq_rc_store_phones_store_phone').on(table.storeId, table.phoneNumber),
index('idx_rc_store_phones_number').on(table.phoneNumber),  // NOT UNIQUE

意味着 schema 允许同一个号码出现在多个 store 行。resolvePhoneIdentityWHERE phone_number = $1 LIMIT 1, 如果真出现 dup, routing 是 nondeterministic。

Prod query 2026-05-25 验证: 78 phone / 0 dup, 不是 active bug, 是 latent risk。仍要加 unique 约束兜底 — voice agent 上线后 outbound 是新 write path, dup 风险概率上升。

修法: schema 加 UNIQUE(phone_number) (或 partial unique on active rows) + 写入前 application-level invariant check + CloudWatch alarm 监控 dup count 持续为 0。voice agent 之前要做, 不阻塞 voice agent 启动。

隔离的非数据维度 (容易漏)

数据库层 store_id WHERE 不够, 还有几个 boundary 也要 store-scoped:

  • Voice 平台 vendor logs / recordings / debug payload (per-store DPA + retention 配置)
  • Vendor 端 webhook payload 验证 (不能信任 vendor 发来的 metadata.storeId, 用本地 session_id 双向校验)
  • Human escalation 链路: 转接号码 / staff assignment / SMS 通知 / task owner / manager mobile phone 全部 store-scoped
  • 复用现有 call-analytics-pipeline 时, contacts 表 phone-only dedupe 可能把多 store caller 的历史串起来 — 要 verify

voice_agent_sessions 新表的 store_id 字段必须 uuid 类型 (跟 rc_stores.id 一致), 别在新表降级为 text


晚上下班场景具体怎么跑

第一阶段定位接受重新 framing: AI 不直接 booking, 不直接报 cancellation outcome, 不报 approved snippets 之外的 pricing。

Inbound (客户主动打来)

22:00 客户拨 Devon 店主线 +16104403480

RC 转 voice agent gateway (RC SIP forward)

Voice agent 接起 (3 秒内):
  "Hi, this is Devon OrangeTheory. We're closed for the night
   but I'm here to help. Are you looking to try a class,
   ask about pricing, or something else?"

分支 A: "I want to try a class"
   → AI 留 name + phone + 建 task "Lead inquiry from after-hours"
   → 发 SMS "Got it! Our team will call you tomorrow before 11am."

分支 B: "Pricing?"
   → AI 报价 (从 store_config.pricing 拉 approved snippet)
   → 建 task 跟进

分支 C: "I want to cancel my membership"
   → 必须立刻 acknowledge + 时间戳锁死 + 创建合规可追溯的 cancellation event
   → 不能 "tomorrow team will follow up" (FTC 2025-08 已起诉 LA Fitness cancellation friction)
   → AI 仅 capture, 实际 cancellation 处理走员工 SOP

分支 D: 沉默 / 挂电话
   → AI 留 voicemail 记录, 建 missed_lead task

所有路径 → 现有 call-analytics-pipeline → 老板早上看 dashboard

Outbound (新 lead 凌晨提交表单)

01:00 AM 有人填了 Devon 店的体验课表单
        → lead-tracking poller 写入 lead 表 (store_id = Devon)

EventBridge rule 看 lead.calling_hours_window:
  TCPA 8am-9pm 是 called party local time (不是 store 时区!)
  推 called party 时区的策略:
    1. 优先用 lead capture 时收集的辅助信号 (IP geo / zip code) — 最准
    2. fallback 用电话区号推时区 — 不可靠 (携号转网 / 跨州迁移)
    3. 保守策略: 区号时区 ∩ store 时区, 两个时区都在 8am-9pm 才拨
       (e.g. lead 是 NYC 区号但实际在 CA, ET 8am 拨 = PT 5am = 违规)
  → defer 到下一个安全窗口

执行时间到, 还要 re-check:
  - consent 还有效?
  - phone 在 DNC list?
  - phone 在 FCC reassigned number database?
  - lead 还属于这个 store?
  - 现在是 called party 的 8am-9pm?

全过 → voice agent 拨过去:
  "Hi <name>, this is Sarah from Devon OrangeTheory.
   You inquired about a free class. Did I catch you at a good time?
   Takes 1 minute."

分支 A: "yes" → 资格初筛 → 约时间 → 建 task confirm
分支 B: "not now" → "When's a good time today?" → 改 task dueAt
分支 C: "wrong number" → mark lead invalid + DNC list 加号
分支 D: 没接 → leave voicemail (注意: voicemail 不是 TCPA loophole) + SMS follow-up
分支 E: "stop calling" / "remove me" → 立刻停, 写 DNC + 取消所有 queued retries/SMS

全部 → pipeline

Risk

维度做了会怎样不做会怎样
客户体验gym 行业 first-call-no-answer 流失 40-60%, AI 接住转化率显著高晚上 lead 第二天员工才看到, 转化掉 60%
数据隔离三层防护 + capability token + audit log 兜底n/a (现在没 outbound)
合规TCPA + FCC AI voice + FTC click-cancel 必须做对联邦 / 集体诉讼风险 (单条 $500-1500, 集体诉讼上千万)
成本Vapi 标价 $0.10-0.20/min, all-in 实际 2-3x markup (含 STT/LLM/TTS/recording/SMS/retries/monitoring)员工漏接 lead 机会成本
店主信任1 店试点 + 老板能开关 + 通话可 review直接全店上线翻车 = 失去信任

AI 能说什么 — approved claim library

AI 能说什么不应该由 prompt 自由发挥, 而是由 retaintive 拥有的 approved claim library 控制:

话题第一阶段边界
Pricing只说 store_config.pricing 中批准过的 snippet。不做临时折扣, 不承诺特殊价格
Booking收集偏好时间, 创建 task。除非接真实 availability + writeback, 否则不说 "you are booked"
Cancellation立刻记录 request, 不给用户增加阻力, 不承诺法律结论
Health / injury / pregnancy / disability少问、少存、必要时转人工
Minors保守转人工
Angry customer / refund转人工, 保留 transcript
Wrong number立即停止, 标记 suppression

真实成本由这些组成

不要用 platform 标价 $0.10-0.20/min 直接做财务承诺。真实成本:

成本项说明
telephony minutesinbound / outbound / transfer 都可能计费
STTstreaming 比 batch 更贵, 计费方式也不同
LLMlatency 和 model 选择影响成本
TTSElevenLabs / Cartesia / OpenAI TTS 成本不同
recording storage录音存储 + retention policy
SMSfollow-up / confirmation / handoff
failed calls未接 / 重试 / 超时也可能产生成本
monitoringSentry / Datadog / logs
vendor marginVapi / Retell 打包后的加价
human review店主和内部 review workflow 的人力成本

POC 阶段按真实账单算每通 after-hours call 的 cost, 再对比 missed lead 的机会成本。


Build vs Buy

Max 原问: 我们对接另外一个像 Deepgram 这样的东西, 把 prompt 给他们吗? 还是它能访问我们的数据库?

都不是。是 tool-based integration:

谁负责retaintive 怎么接入
Telephony (打电话本身)Twilio 或 Vapi 内嵌API call
STT (语音转文字)Deepgram (已用) 升级到 streamingAPI key, 已熟
LLM (理解 + 回答)Claude (已用) / GPT通过 voice 平台配置
TTS (文字转语音)ElevenLabs / Cartesiavoice 平台配置
OrchestrationVapi 或 Retell, 不自研API + webhook
业务逻辑 (查 lead / 排 schedule / 建 task)retaintive 自己暴露 HTTP tools, voice 平台调
Storageretaintive Neonvoice 平台不直连, 通过 retaintive API

不只把 prompt 给他们 — 还要把 retaintive API 当 tool 给 voice 平台调用。绝对不给 DB access — 必须经 retaintive API, 才能强制 tenant scoping。

判定 Buy vs Build 三问 (ABCPOS framework):

  1. 行业有成熟 partner SaaS? 有 → buy
  2. retaintive 拥有独特数据? 有 → build
  3. ROI break-even 在 12 个月以内? 超过 → buy

应用到 voice agent: 行业有 Vapi/Retell/Slang.ai → buy 底层。retaintive 独特数据是 CI + lead funnel + tasks → build prompt + tool API 接入。ROI: 自建 $800K-2M / 12-24 个月, 接 Vapi 数天上线 → 明确 buy。

结论: voice 底层 buy partner, 业务逻辑 + tenant-scoped tool API + consent ledger build 自己。

长期 vendor lock-in 边界

POC 用 Vapi 可以快速验证, 但 Vapi / Retell 不是 durable architecture。Vendor 拥有 call state / latency path / prompt runtime / recordings / phone resources / failure modes / pricing。长期 retaintive 必须自有什么 / 可以买什么:

retaintive 必须拥有可以先买
policy enginemedia transport
session ledgerorchestration runtime
consent / DNC ledgerSTT / TTS
prompt and script versionstelephony routing
approved claim libraryvendor dashboard
audit logslow-level latency tuning
outcome scoringvoice model selection

volume 上来后再评估是否从 Vapi / Retell 迁到 LiveKit Agents / Pipecat / Twilio 自管。POC 阶段不要为未来迁移提前造完整平台, 但 API 边界要干净。


上线前必须当 test cases 处理的 edge cases

这些不是边角料, 全部要在 POC 阶段就跑过:

Edge case需要的处理
consent 是 phone + person + store/seller + channel + purpose + source不把 per-lead 当成万能 consent
outbound 排队后状态变化执行时 re-check consent / DNC / phone assignment / lead ownership / store config / calling window
Lead 从 Devon 移到 White Plains取消旧 session, 按新 store policy 重新创建
客户换号码旧 consent 不自动跟新号
reassigned number老 lead 外呼前查 FCC reassigned number database 或采用保守策略
推 called party 时区区号不可靠, 优先用 lead capture 时收的 IP/zip; fallback 用区号时区 ∩ store 时区双交集 (任一在 8am-9pm 外就 defer)
mid-call revocation ("stop calling" / "don't call me")立即停止, 不能继续问 "one more question"
duplicate triggers (form submit + IMAP lead + CRM import)需要 idempotency key
voicemail仍受 TCPA 监管, 不是 loophole
call recording disclosure按州处理 two-party consent, 不能全美一个模板
tool timeout不让 AI 编答案, 转人工或安全结束
vendor webhook retrywebhook receiver 必须幂等, 双向校验不信 vendor metadata
phone mapping duplicateschema unique + monitoring
prompt hallucinated offerapproved claim library + adversarial evals
Devon 客户拨错号到 White Plainsrc_store_phones 解析为 WP, AI 自报 "Hi this is White Plains", 客户挂电话

Endpoint 现状 + 缺什么

AI partner 接入必须经公开 API + OAuth

ABCPOS 调研报告 (Max 引用) 核心架构判断: AI partner 不能直连数据库, 必须经公开 read-only API + OAuth。理由对 retaintive 一样成立:

  • 安全 / 性能 / 抽象 / 多租户隔离, 全靠 API 层兜底
  • 每个 partner 单独定制 endpoint 不可扩展, 第二个 partner 接进来工程量翻倍
  • partner 是独立公司, 不应该共享 retaintive 工程师的内部 secret, 必须 OAuth (或同级别 capability token)

7 个 voice agent tool 的 endpoint 现状

Voice agent tool干啥现状
getStore(storeId)店名 / timezone / 营业状态已有 GET /v3/setup + GET /v3/stores
getStoreContext(storeId)pricing / intro offers / lead_emails已有 GET /v3/setup (返 store_config.pricing JSONB)
getOperatingHours(storeId, date)那天营业? 几点空?表数据在 (operating_schedules + blackouts), 没现成语义 endpoint, 要新建
lookupContact(storeId, phone)这号码是谁 / 历史通话 / lead status已有 GET /v3/contacts + GET /v3/conversations
lookupLead(storeId, leadId)lead 来源 / 状态 / 之前问过啥已有 GET /v3/leads + GET /v3/leads/pipeline
createTask(storeId, contactPhone, body)建 task 给店长POST /tasks/*, voice 触发的 task 创建要新建
escalateToHuman(storeId, sessionId, reason)转人工 / voicemail / 通知店长完全没有

新建 3 个 endpoint: GET /v3/operating-hours/effective, POST /v3/voice/create-task, POST /v3/voice/escalate

4 个可复用 endpoint 必须加内部 token 或 OAuth scope — 现在的 v3 路由都是 JWT-scoped 给前端用, voice partner 不是用户。

缺什么完整清单

后端工作:

  1. 修复 rc_store_phones schema (加 unique 索引兜底)
  2. 公开 API + OAuth 改造 — AI partner 接入硬前提
  3. 3 个新 endpoint
  4. 4 个现有 endpoint 加内部 token / OAuth scope
  5. Voice control plane: session ledger / capability token / kill switches / policy engine
  6. voice_agent_sessions Neon 表 + Drizzle migration (store_id 必须 uuid 类型)
  7. Outbound trigger Lambda: EventBridge + 执行时 re-check consent / DNC / calling-hours
  8. TCPA consent ledger (维度: phone + person + store + channel + purpose + source, 不是 per-lead)
  9. DNC list + FCC reassigned number database 检查
  10. Calling hours engine — per called-party timezone, 不复用 operating_schedules
  11. Voice 平台 webhook receiver (Vapi end-of-call event, 幂等 + 双向校验, 不信任 vendor metadata)
  12. Observability 改造 — Sentry + Datadog APM (AI 出错 1 分钟内要看到, 不然单一事故损害品牌信任)
  13. 复用现有 call-analytics-pipeline 分析 AI 通话录音 (0 工作量)

Voice 平台层:

  • Vapi 账号 + per-store phone resource provision (RC SIP forward 或 Twilio bridge)
  • system prompt 设计 + call replay evals + adversarial tests + per-brand approval
  • Fallback / 异常处理 (AI 卡住转人工)

前端:

  • 老板看 voice agent 通话记录 (复用 calls 列表 UI, 加 source filter)
  • 老板开关 voice agent (per-store)
  • AI 出错通话 review + flagging + redaction + 退款 / 投诉处理 workflow
  • Outbound consent 管理 UI

合规 + 法律 (独立工作流, 早期介入, 不是 launch checklist):

  • TCPA — AI voice 属 artificial/prerecorded voice, telemarketing 需要 prior express written consent (FCC 2024 ruling)
  • FCC AI voice ruling 强化 AI 合成语音监管
  • FCC reassigned number database lookup
  • FTC click-cancel rule — recurring membership 取消必须跟 signup 一样容易
  • FTC v. LA Fitness (2025-08) — phone cancellation friction 已有判例
  • State-level robocall (CA AB 1132 / FL FDUTPA / 各州差异)
  • Two-party consent recording (12 个州, CA / FL / IL / NY 等)
  • HIPAA 一般不直接适用, 但 injuries / pregnancy / disability / health goals / minors / biometric 触发 state privacy + discrimination 风险

工程量我猜不准, 不给周数。可以确定的复杂度量级:

  • 改 schema + 加 unique 约束: 小
  • 公开 API + OAuth 改造: 中等偏大, 是硬前提
  • voice control plane + session ledger + tool endpoints: 中等
  • TCPA consent + DNC + calling hours engine: 中等偏大 (含合规咨询)
  • Observability + 前端 review UI: 中等

ABCPOS framework 关键洞察对 retaintive 也成立: 不要 "先 foundation 再 AI" 顺序执行, 而是用具体 AI feature 反向倒逼基础设施改造。voice agent 这件事本身就是反向倒逼公开 API + observability + idempotent write + consent ledger 的最好契机。这是 Shopify 当年走过的 vertical SaaS 升级套路。

失败 scenario (不能让它发生)

ABCPOS 调研报告 §4.3 列了 4 个失败模式, 翻译到健身房直接成立:

  1. AI 接电话, 客户说 "I want two memberships", STT 把 "two" 听成 "twenty", 系统下了 20 个 Stripe charge, 次日客户发现, 18 个退款
  2. 缺少 Sentry, 工程团队不知道哪些电话失败, 半个月后才发现这是系统性 bug
  3. Outbound trigger API 不幂等, 网络抖动触发 retry, 同一个 lead 拨两次, 双倍 SMS, 触发 TCPA 投诉
  4. 健身房老板在小红书 / Reddit 发声 "retaintive 的 AI is BS", 行业社区病毒传播

恢复成本 $50 万 + 6 个月, 远超 partner Vapi 总成本。这是 Observability 必须在 ship 前做扎实的原因。


需要决定的事

不给时间表, 不猜。下面是要决定的内容:

立刻 (这周内):

  • Neon query 验证 rc_store_phones (已跑 2026-05-25, prod 0 dup)
  • schema 加 unique 索引这件事独立 PR, 不等 voice agent
  • 这份 spec 给 Peter / 陈栋 / non-tech 成员 review, 看读不读得懂

前端展示阶段做完后, 决定 voice agent 启动时:

  • 试点店选哪个 (建议 Devon, 数据量大)
  • Voice 平台先 POC 哪个 (推荐 Vapi)
  • 公开 API + OAuth 改造怎么做: 走独立工作流 (AI 之前必修) 还是借 voice agent 反向倒逼
  • TCPA consent 怎么收集: 现有 lead form 加 checkbox, IMAP 来的 lead 怎么办
  • AI 出错 / 卡壳怎么 escalate: 转店长手机 / 留 voicemail / SMS
  • 商业模式: 现有 seat-based 加 AI minute 包 / per-call surcharge (留到看真实数据再定)

不应该现在决定 (防被动 commit):

  • 不承诺具体开发周数
  • 不承诺全店 rollout 时间
  • 不承诺 autonomous outbound 做不做
  • 不承诺 booking 或 closed-loop sales
  • 不承诺把 Vapi / Retell 当作长期最终架构

来源

retaintive 内部代码 (verified):

  • callytics-common/src/phone-identity/phone-identity.ts
  • callytics-common/src/db/schema/rc-stores.ts
  • callytics-common/src/db/schema/operating-schedules.ts
  • callytics-common/src/db/schema/store-config.ts
  • studio-website-monorepo/apps/api/src/utils/store-authorization-neon.ts
  • studio-website-monorepo/apps/api/src/routes/v3/ 全部 route 文件
  • docs/system-design/store-level-isolation.md
  • docs/architecture/0-system-overview.md

Neon prod query (2026-05-25 via Neon MCP):

  • callytics-prod project (red-math-38447173) — rc_store_phones isolation 验证

市场调研:

合规 (FCC + FTC 官方源):

外部调研对照:

  • ABCPOS PDF "AI 战略评估与十二个月路线建议" (Max 引用, 微信文档)
  • Codex adversarial review (2026-05-25 跑, 跑了 FCC + FTC docs 校准, 完整 output session-archived)