Task Pipeline 设计 Brief
Historical design brief(2026-07-23 校准):这是 2026-05 的设计任务书,不是当前 implementation specification。保留用于理解历史问题;当前 Task V2 parity 和 Task V2+ 路线见 工程审计与实施基线,Task V3 设计仍待评估。
这是什么: 给新 session 的设计任务。不是 session 总结,不是 bug 修复清单。 日期: 2026-05-30 前序工作: 2026-05-29 做了 task 生命周期调研(代码 + Neon 数据 + 业界对比),产出了 gap 分析文档和场景覆盖度。细节在材料里,这份 brief 只给方向。
你要做什么
设计 retaintive task pipeline 的架构:代码层和 prompt 层各自负责什么、怎么配合。
这是一个 system design 任务,不是修 bug 或补字段。你的角色:一个精通 AI 技术的 Principal Engineer / AI Engineer——选最贴合这个任务的角色来思考。
Expected Output
新 session 完成后应该交付这些:
- 代码 vs prompt 职责矩阵 — 每个决策点(触发/分类/关闭/没打通/playbook)标清楚谁负责 + 为什么
- 现状 vs 设计后 workflow 图 — 围绕职责划分画,不是围绕数据存储
- architecture recommendation — 基于上下游理解 + 业界校准,给出推荐的 pipeline 设计方案
- gap 分析文档更新 — 把职责划分设计写回
task-lifecycle-gap-analysis.md最上面 - 需要改的代码/prompt 清单 — 具体到文件和改动方向(不是行号级,是设计级)
- API-first / AI-agent-readable 视角 — 反向从未来 API / CLI / OAuth / AI agent 调用方需要什么数据来验证 schema 和 workflow 设计,说明 task / progress / timeline 应该怎么被外部读取和写入
不是写代码。是设计 + Max review 后才执行。
呈现要求: 产出必须让不在这个 session 里的人(Vivian / Oliver / Peter)也能10分钟看懂核心结论。具体:每个交付物先用一句话说结论,再展开细节;用表格和图而不是长段落;技术细节不省略但要有层次(先 what + why,想看 how 再往下读)。不要 over-simplify(丢掉关键 nuance),也不要绕来绕去(读完不知道在说什么)。
Design Acceptance Criteria
设计合格的标准(不满足就不算完成):
- 必须回答:task 到底只是待办清单(还没做的事),还是也兼做业绩记录(当场做成的事也要记),还是一个统一的事项对象(两者都能表达)。不能含糊
- 每个"谁负责"的 recommendation 必须说明:为什么不是放在另一层做
- 必须覆盖至少这些关键场景:lead no answer / intro booked / cancel saved / complaint resolved / DNC / inbound 当场成交 / SMS meaningful reply / 跨门店同号码
- 必须区分Phase 1 必做和 future-compatible 设计(现在不做但架构要兼容的),不要混在一起
Non-goals (这次设计明确不做的)
- ❌ 不设计完整 SMS pipeline — 只定义 task pipeline 预留给 SMS 的接口和触发点
- ❌ 不重做 dashboard 指标体系 — 只定义 task lifecycle 对 metrics 的影响
- ❌ 不设计 AI voice agent 产品 — 只确保 executorType / actor / confidence 等字段能兼容未来 AI 接管
- ❌ 不做 production rollout 方案
- ❌ 不改代码、不跑写入型 DB 操作、不 push、不 PR
必须显式回答的冲突问题
brief 里有几组方向天然有张力。不要默认调和,每个都逐一给出明确结论 + 理由:
- "每个当场办成的事都是 task" vs "业界通常 conversion funnel 不是 completed task" — 兼有可行吗?怎么兼有?
- "只提醒一次" vs "没打通还要回头再试" — 提醒一次是指"不重复建 task"还是"真的只打一次"?
- "AI 判断更灵活 / long term scale" vs "代码状态机必须 deterministic" — 哪些判断给 AI 哪些给代码,边界在哪?
- "SMS 不想触发 AI" vs "有意义 SMS 可能需要即时跟进" — 怎么定义"有意义"?
- "task 是待办" vs "task 是业绩记录" — 一个对象能同时承担两个语义吗?会不会污染其中一个?
- activity(打了电话) vs task progress(联系到了) vs business outcome(签约了) — 这三层是不是不同的概念,该不该压在同一个 task 对象上?
怎么做
Step 1: 先理解整个系统的上下游
不要直接看 task。 先读 architecture 文档,理解:
- 一通电话从进来到最终产生业务结果,整条链怎么走
- 数据从 RingCentral → 转录 → AI 分析 → 写入各表 → 前端展示,每一步谁做的
- task 在这条链里处于什么位置,它的上游(谁触发它)和下游(谁消费它)是什么
- 环境区分: test 环境和 prod 环境不同。test 环境做了全面改造 (DynamoDB → Neon 等),prod 很多功能还没有。以 test 环境为准。
所有代码都在本地 /Users/maxwsy/workspace/retaintive.code-workspace,先读代码再读文档。参考:
docs/architecture/0-system-overview.md— 系统全景docs/architecture/2-backend.md— 后端数据管道(含通话分析)docs/team-ops/repo-overview.md— 所有 repo 职责 + 技术栈callytics-infrastructure/lambda/ai-analysis-processor/src/core/stages/pipeline.ts— per-call AI pipeline 编排(Pre-triage → Triage → Classify → Coaching)callytics-infrastructure/lambda/contacts-analyzer/src/core/prompt-builder.ts— contact analysis prompt(1040 行,SECTION 4 是 task 决策逻辑)
Step 2: 从全局判断 task 的角色
理解了上下游之后,回答:
- task 在这个系统里到底是什么?是”待办清单”还是”业绩记录”还是两者兼有?Max 的初步构思:两者兼有——既是待办清单,也能直接 mark 成完成(比如一通电话当场完成就直接标 closed)成为业绩记录。这个想法不一定对,建议 web search 看 competitors 怎么做,验证后再定。
- 现在 task 的生成/关闭逻辑,放在系统的哪个环节是合理的?当前放置的位置对不对,还是应该重新设计?从正确性出发,不要因为现在是这样就继续这样走。 都在 test 环境,什么都可以改,有 AI 辅助改起来快。
- prompt 和代码各自的能力边界在哪——哪些判断只有 AI 能做(需要理解通话内容),哪些是确定性的规则(代码就能做)?设计要 long term 能 scale:硬编码确定性规则以后改起来复杂。AI 时代要考虑 AI 的 capability(可以搜最新的),未来可能用 AI agent。design 要能 long term scale,不要设计成只适合当下。
Step 3: 设计代码 vs prompt 的职责划分
这是核心交付。要回答的具体问题:
现状的问题:代码和 prompt 的职责混在一起。比如 close.ts:199 用代码硬编码了"没打通 → 关掉重建",但这个判断可能该由 AI 做;prompt 又硬规则禁止了"当场完成建 task",但这可能是产品规则该在代码层控制。这条线要重新划。
Step 4: 画 pipeline workflow 图
画出来的图应该围绕代码 vs prompt 的职责划分,不是围绕"数据存哪个表"。每个节点标清楚:这一步是代码控制还是 prompt 控制。
画两张:现状(代码和 prompt 混着来)vs 设计后(职责清晰)。
Step 5: 从 API / AI agent 视角反推数据模型
除了给前端页面用,task pipeline 最终也要能被外部系统和 AI agent 可靠调用。设计时要从 API contract 反向验证数据模型:
- 未来可能会有 OAuth API、CLI、第三方集成、AI agent(Codex / Claude Code / customer-owned agent)读取或操作 task。
- 不要只问"数据库怎么存",还要问"外部调用方怎么一眼读懂这个 task 现在是什么状态、尝试过几次、下一步该做什么、最终结果是什么"。
- 需要明确
tasks/task progress/contact_timeline各自的职责:tasks: 当前业务事项对象和最终 outcome- task progress / attempt: 每次执行进展(no answer / voicemail / text sent / callback requested 等)
contact_timeline: contact 维度统一时间线和审计
- 如果建议新增
task_progress_events或类似结构,必须说明它和contact_timeline的关系:谁是 source of truth,谁是 projection / audit feed,发生一次 progress update 时两边怎么写。 - 需要草拟 high-level API shape,例如:
GET /tasks/:taskId返回 task snapshotGET /tasks/:taskId/progress返回 task progress historyPOST /tasks/:taskId/progress记录 no-answer / voicemail / text-sent / callback 等进展POST /tasks/:taskId/close只记录 business outcomeGET /contacts/:contactId/timeline返回跨实体时间线GET /contacts/:contactId/work-objects给 AI agent 一次性读取 open/closed objectives + recent progress + next action context
- 对比竞品 API / object model 时,要查官方 API 文档或产品文档,看 HubSpot / Salesforce / Salesloft / Outreach / Mindbody / ABC 等怎么表达 task、activity、call disposition、timeline、outcome。
- 竞品只是校准,不是答案。很多旧 CRM/API 设计来自 AI 不成熟、人工录入、LLM 成本高的时代。要识别他们的历史包袱,再决定 retaintive 在 2026 AI-native 场景下应该怎么做得更清晰。
Step 6: 更新 gap 分析文档
把设计结论写回 docs/product-design/v2/tasks-feature/task-lifecycle-gap-analysis.md。这份文档已有 schema 对照、场景覆盖度、业界对比——需要在最上面加上"代码 vs prompt 职责"这个维度的设计。
思考方式
像一个懂 AI 的 principal engineer 那样思考。 不是在修一个现有系统的 bug,是在设计一个 AI + 代码混合的架构。要考虑:
- AI 和代码各自擅长什么:AI 擅长理解语义/判断意图/处理模糊情况;代码擅长执行确定性规则/保证幂等/控制状态机。把对的事交给对的层。
- 上下游协调:改了 task pipeline 的某个环节,对上游(per-call AI / lead-tracking)和下游(前端展示 / dashboard 指标 / 未来 AI 化)有什么影响?
- 成本:每次调 AI 有 LLM 成本。什么时候值得花钱调 AI 判断,什么时候用代码规则就够了?
- 未来 AI 化:现在前台手动做的事(打电话/选 close result/写 note),以后可能 AI voice agent 来做。现在的架构要给这个过渡留空间,不要设计成只有人能用。
- API-first / agent-readable:未来不只是前端读这些数据,第三方系统、CLI、OAuth API、AI agent 也会读写 task。schema 和 workflow 要能被 API 稳定表达,而不是只适合当前页面或某个 prompt。
- 场景 robust:不是技术上的健壮,是符合真实前台使用场景的健壮——系统行为要对得上前台脑子里"我手头有几件事、办完了没"的心智模型。
已知的核心问题(前序调研发现的)
不展开,只列要点。细节在材料里。不要逐个解决这些小问题——做好顶层设计,这些问题会同时被解决。以面破题,不以点破题。
- 当场完成 = 零 task: prompt 禁止当场建 task,但产品需要每个办成的事都记为 task
- 没打通 = 关掉重建: 代码硬编码的,前台心智不对齐,task 数虚增
- disposition 和 outcome 混在一个字段: close_result 18 值混了"打通没"和"办成没",业界全部分开。disposition 其实已经在 calls.callState 里有了
- 前端 close dropdown 缺 2 个值: booked/cancelled schema 有但 UI 没有,Neon 里 AI 已写入 29 条
- Core Productivity metric 有 bug: denominator 让 rate 恒≈100%
Max 在前序 session 表达的方向
这些是他的想法和倾向,不是 finalized spec:
- 每个当场办成的事都是一个 task(签约/book intro/cancel save/resolve/reschedule)
- 一个任务只提醒一次,不要关掉重建
- 只管打电话 + SMS,不管走进店里的。SMS 还没想好
- 没打通要分情况:lead 更重要
- 店长战绩 = 完成多少 task (superset) → 其中多少签约/挽留 (subset)
- 未来要 AI 化:人做的操作以后 AI 做
- 代码和 prompt 的职责要想清楚再动手
- 整个 flow 对比应该围绕"代码 vs prompt 职责划分"画,不是围绕"数据存哪"
- 要先从 high level 理解整个系统上下游,再看 task 这一块怎么设计
材料清单
只有代码是 source of truth。其余都是不同人在不同时间的想法,不一定对。
A. 代码 (✅ Source of Truth)
B. 架构文档 (读了再开始设计)
C. V1 Task Feature 设计文档 (⚠️ 初版设计,不一定错但不够全,现在要改进)
V1 是最初怎么设计 task feature 的思路。不一定错,可能只是不够完整,现在要做更全面的改进。 读它可以理解最初的设计意图。
D. V2 Task Feature 设计文档 (⚠️ 现版本,schema 对齐后的)
E. 调研产出 (⚠️ AI 产出,Max review 中)
F. 参考材料 (⚠️ 不一定对,当参考不当结论)
G. Neon Test 环境 (✅ 可查真实数据)
- Project:
callytics-test(restless-boat-70724564, us-west-2) - 用 Neon MCP 跑 SELECT 验证假设,不写入
H. AWS (✅ 已登录)
- Account: 237206024479, AdminAccess role
- 可看 Lambda / CloudWatch,用于验证 prompt 实际输出
I. 前序调研成果 — 分三类: Facts / Hypotheses / Calibration
前一个 session 做了大量调研。这些是校准用的,不是替代你自己思考的答案。 按可信度分成三类:
Facts (已用代码/数据验证,可直接信)
Hypotheses (前序 session 的推断,需要你验证后才能采纳)
Calibration (业界校准,不是答案,是参考坐标系)
web search 是校准用的,不替代系统设计结论。最终判断必须回到 retaintive 的前台心智、数据模型和 pipeline 成本。
| SMS 触发 AI 的成本控制 | 业界三层 gate: content gate (regex) → batch gate (debounce) → token-tier gate (小 classifier)。但注意:业界 2024 年的做法基于当时 LLM 贵 + 慢的限制,2026 年成本降了 10-50x、小模型 classifier 成熟了(NVIDIA LLM Router 1.75B)。限制变了,解法可能也该变。 设计时要重新思考:SMS 中什么样的内容值得触发分析,而不是照搬"SMS 一律不触发" | Twilio CI · NVIDIA LLM Router · MindStudio |
| SMS vs Call 合流分析 | 业界写到同一条 contact record,但触发时机不同。同样要考虑:这个做法可能只是当时技术限制下的妥协,不是最优解。 设计时问:如果成本不是问题,理想的 SMS 分析策略是什么?然后再把成本约束加回来做 trade-off | Twilio · Aloware · RingCentral |
| SMS debounce | AWS 原生 MaximumBatchingWindowInSeconds (最长 300 秒),SQS 上设就行 | AWS Lambda batching · n8n |
详细内容在 gap 分析文档的"业界怎么做"段。
前序 session 发现的关键事实(设计时要知道的)
这些不是"要修的 bug 清单",而是你做 system design 时的输入事实——你需要知道系统实际上怎么运作的,才能设计对。
现有 prompt pipeline 怎么触发 task:
- per-call AI (Layer 1) 分析每通电话,产出
fu=yes/no(follow-up needed) +out=success/attempted/...(outcome) - contact analysis (Layer 2, daily batch) 消费 Layer 1 的输出,做跨通话的 contact 级别分析,产出
taskDecisions[](create/close/update) fu=no+out=success的组合在当前 prompt 里 = 不建 task (prompt-builder.ts:812, 611-617)- 这个
fu=信号是 AI 对 AI 的传递——Layer 1 的 AI 告诉 Layer 2 的 AI "要不要跟进"
2026-05-31 note: 这里的 Layer 1 / Layer 2 是旧 task 讨论里对 AI signal chain 的叫法,不等同于 Unified Pipeline Architecture 设计 Brief 里的 Layer 1 Shared Mutation / Layer 2 Processing Capability。
task 创建只有 3 条路径:
- lead-tracking 直接建 (lead_outreach, 不经 AI)
- contact analysis AI 建 (taskDecisions[].create)
- 员工手动建 (studio-api)
- 所有路径都只产 status='pending'。没有"一步建成 closed"的路径
task 关闭有 2 条路径:
- AI auto-close (contact analysis 的 taskDecisions[].close,必须引用已有 taskId)
- 员工 manual-close (studio-api close.ts)
- 但 Neon 实测: manual-close 在 test 环境从未被使用过 (0 条)
没打通的硬编码逻辑 (close.ts:199-218):
- 这段代码不在 prompt 里,是纯代码逻辑
- 员工在前端选 no_answer → 代码关掉旧 task + 自动 INSERT 一个新 pending task (due 明天)
- left_voicemail → 同上,due 2 天后
- 用了
ON CONFLICT DO NOTHING防重复
前台实际怎么看 task:
- tasks 页面 3 段式 flow: Why (为什么有这个 task) → Playbook (怎么做) → Action (Update / Close)
- Update (no answer / voicemail / text sent) 和 Close (converted / not interested / ...) 在 UI 上想分开,但当前后端没有真正的 "status update" 动作——只有 close
- playbook-panel.vue (223 行) 前端已有,但后端 playbook prompt 没接入
disposition 数据已经在 calls 表里:
calls.callState= human_conversation / voicemail / no_answer / busy_signal / system_errorcalls.result= Accepted / Missed / No Answer / Busy / Voicemail (RingCentral 原始值)calls.primaryOutcomeResult= success / attempted / retained / pending_follow_up / cancelled / nacalls.followUpNeeded+calls.followUpReasons= AI 判断的 follow-up 信号- 这些都是 per-call 的,已经有了,不需要在 task 表重复存
contact_timeline 的设计:
- 16 种事件类型,覆盖 task 全生命周期 (task.created / task.status_changed / task.updated / task.due_at_changed / task.note_updated)
- 多态 actor (system / call_analysis / contact_analysis / staff / lead_webhook)
- AI forensic 字段 (aiRunId / aiModelUsed / aiConfidence) — 可追溯 AI 为什么做了这个决策
- 有 entityType + entityId 索引,查某个 task 的事件历史很快
补充维度(设计时别漏)
多门店 / store 级隔离
task 的幂等约束 uq_tasks_pending_contact_category 按 (contactPhone, storeId, typeCategory) 做——同一个客人在不同门店可以有独立的 pending task。contacts 表主键也是 (phone, storeId)。设计 pipeline 时必须考虑:同一个电话号码跨门店的 task 是独立的,不能共享。
前台一天的实际操作流程(场景 robust 的基础)
设计必须对得上前台真实的工作方式,不能只看代码:
- 早上开工: 打开系统看待办清单——"今天有哪些客人要跟进"(新 lead 要联系、有人要取消会籍要挽留、有人试课完没签约要追)。每件事有紧迫度(dueAt)。
- 白天逐个处理: 挑一件 → 打电话/发短信 → 几种结果:
- 打通了,当场办成了(签约/约到试课/挽留住/解决了投诉)→ 一件事了结
- 打通了,没当场办成(客人要考虑/要改时间再打)→ 还没完,记下进展回头来
- 没打通(没人接/留语音信箱)→ 也没完,回头再试
- 客人说别再打了(DNC)→ 结束(但不是办成)
- 当场来的: 客户直接打进来或走进店里,当场就把事办了(当场签约)——这没经过"待办清单"但是实打实的业绩
- 一天结束 / 店长视角: 想知道"今天战绩如何"——完成了几件事、其中几个签约/挽留(superset/subset)
未来 AI agent 的操作流程(设计要兼容)
现在人做的操作以后 AI voice agent 来做。设计时要考虑:
- AI agent 自动外呼 → 自动判断对话结果 → 自动关闭/更新 task
- 需要区分"人做的"和"AI 做的"(executorType)
- 低置信度的 AI 决策需要人工复核(human-in-the-loop)
- 现在人选的 close_result / 写的 note 是未来训练 AI 的 ground truth
SMS 处理方式
现状: message-processor Lambda 只做存储(RC webhook → Neon),不触发 AI 分析。SMS 消息存入后,等 contacts-analyzer 的下一次 batch run(daily cron 06:00 UTC 或 per-call 触发)才被读到(作为 RECENT MESSAGES 注入 prompt)。
Max 的顾虑: 不想让 SMS 不停 trigger AI scan——一条 "thanks" 不值得花 LLM 成本分析。当前设计通过"不直接触发"解决了成本问题,但引入了 delay(SMS 到了要等 batch run 才分析)。
设计时要思考:
- 当前"被动等 batch"的方式够不够?还是需要"有意义的 SMS 才触发即时分析"?
- 如果要即时分析:怎么区分"有意义"(客户回复了有实质内容)vs"无价值"(thanks / ok / emoji / 自动回复)?
- 有没有 debounce 机制(5 分钟内多条合并)?
- 业界 2026 怎么做?small model 做前置过滤?
更深层的设计问题: 当前 SMS 和 Call 都汇入同一个 contact analysis(Layer 2)再统一决定 task。这个"先合流再决策"的模式对不对?Call 和 SMS 的信号密度完全不同(一通 5 分钟的电话 vs 一条 "thanks"),但现在走同一个 1040 行的 prompt + 同样的 LLM 成本。是不是应该 call 和 SMS 各自有不同的判断路径/不同的触发条件?competitors 怎么处理多渠道合流?
注意: SMS 还没有完全想清楚,先 focus 电话。但 pipeline 设计要给 SMS 留位置,不能设计成只支持电话。
API / CLI / AI agent 可读性
这次设计还必须考虑未来对外或内部 API 的形状。Retaintive 以后可能让第三方系统、CLI、客户自己的 AI agent、或 Codex / Claude Code 这样的 agent 通过 OAuth/API 读取和操作 task。
设计时要显式回答:
- 一个外部调用方如何区分:
- task 当前生命周期状态(
pending/closed) - task 执行进展(
no_answer/left_voicemail/text_sent/callback_requested) - 最终业务结果(
converted/booked/cancel_saved/issue_resolved/do_not_contact)
- task 当前生命周期状态(
- 如果有 task progress / attempt 事件,它们和
contact_timeline怎么同步:- 是否需要独立 source-of-truth 表(如
task_progress_events) contact_timeline是否作为 projection / audit feed- 同一次 progress update 是否应在一个 transaction 里同时写 progress event、timeline event、task snapshot
- 是否需要独立 source-of-truth 表(如
- API 返回应该是给机器可读的结构化对象,而不是要求调用方解析 timeline JSONB 或 prompt 文本。
- 竞品 API 的做法只能作为校准:旧 CRM 常把 activity/task/call disposition 混在一起,那可能是历史限制,不一定是 AI-native 系统的最佳设计。
设计时要考虑到(high-level,不需要写具体实现)
- AI 判断失败时的 fallback 策略 — prompt 返回无法解析的结果 / Lambda timeout / Zod 校验不过,代码怎么兜底?这是代码层的核心职责之一
- contacts-analyzer 有 6 个触发路径 — EventBridge cron / on-demand / P1 followUp / Task close / T5 showed / T6 trialed。设计 pipeline 时要覆盖所有入口,不能只改一条路径
- 业界做法是参考不是圣经 — 2026 年的技术限制和 2024 年不同(LLM 成本降 10-50x、小模型 classifier 成熟、边缘推理变快)。不要因为"Twilio 这么做"就照搬,要思考他们当时的限制是什么、现在还在不在、有没有更好的方式
- 并发 / 幂等 / race condition — 这个系统有多条触发路径同时跑:daily batch 和 per-call 可能同时分析同一个 contact;lead-tracking 建 task 的同时 AI 也想建;员工在前端 close 的同时 AI batch 也在 auto-close。设计要说明这些并发场景怎么处理
- API contract / data access pattern — 设计要说明核心读写路径:task list 怎么快读当前状态、task detail 怎么读 progress history、contact detail 怎么读 timeline、manager metrics 怎么聚合 attempts vs completed objectives、external API/AI agent 怎么读懂同一个事项。
- 设计边界:如果需要改,什么都可以改 — per-call pipeline / contact analysis / schema / prompt / 前端,都在 scope 内。这是 test 环境,没有"不能碰"的东西
约束
- 先理解全局再看局部 — 不要直接钻进 task 字段,先把系统上下游走通
- 先设计再写代码 — 画图、确认逻辑、Max review 之后才动手
- Code as source of truth — 每个结论先读代码验证,不信文档 narrative
- 不自动 push/PR — 改完先给 Max review
- 不要以点破题,以面破题 — 不要逐个修小问题,要做好顶层设计让问题自然消解
- 从正确性出发 — 不要因为现在是这样就继续这样走,test 环境什么都可以改
- 保持 high-level — 这是 system design,不是 code review。提"要考虑 error handling / logging",不写具体加在哪行