P0-1 migration: detect the same-named stage-3 execution_stage CHECK by sqltext (must contain rework + manager_review), SQLite rebuild / PG-MySQL drop+add, PG boolean default TRUE, validate_schema checks constraint content + seat_tasks status CHECK/unique/FKs; tests start from a real stage-3 schema. P0-2: a missing/invalid manager review (timeout/exception/empty/invalid JSON/missing per-seat decision) is never an acceptance - system rework under the cap, contract fallback (reassign/controlled_gap/ask_user) afterwards, source=system events. P0-3: unaccepted deliveries are isolated from the fact ledger, cross-review and final report (deferred merge, delivery_json envelope, accepted_task_results in checkpoint, accepted-only synthesis, no turn_results fallback). P0-4: seat-task init is atomic get-or-create over the full expected set; recovery fills missing tasks without overwriting frozen contracts; quality gate blocks missing required tasks. P1: zero config values honoured; duplicate detection persists SHA-256 conclusion digests in history (survives restarts); findings never satisfy evidence, evidence_refs must resolve to trusted ledger refs (unverified_evidence_ref); conversation SSE projection tests added and manager/finalizer messages are no longer mislabelled as seat.delivery.submitted.
49 KiB
MAF 多智能体会商升级版实施计划(V2:保留原会商体验,替换底层编排)
文档状态:V2 重写,待按本计划重新实施 更新时间:2026-08-02 本轮决策:原
/page/maf/*的「会话列表 + run 详情 + 前端轮询」原型不再作为目标产品继续扩展。 产品目标:新 MAF 会商是原多智能体会商页面的底层升级版,不是另造一套会商产品。
1. 本次重新确认的产品目标
用户认可的是现有多智能体会商的视觉语言和交互链路:左侧历史会话、中心对话流、输入框发问、意图理解、总控派活、席位发言、过程卡片、澄清与审批、最终结论。
本次升级只替换以下“看不见的发动机”:
- 旧的前端驱动编排、多个前端可见线程和旧会商作业,替换为 MAF Workflow + DeerFlow Agent Adapter;
- 浏览器定时轮询,替换为一条可恢复的 SSE 对话事件流;
- 用户手动创建/管理多个智能体线程,收敛为服务端按需创建和持久化的内部执行线程;
- 保留现有工具、技能、MCP、沙箱、WriteGuard、审批和审计能力,并让它们在原有会商体验中自然出现。
不能接受的结果: 新页面没有对话列表、没有输入框、让用户先创建 session/run、需要用户选择或理解多个内部线程、靠多个定时 GET 拼出实时效果,或把审批/流程图做成脱离聊天主链路的独立后台页。
1.1 必须保留的用户体验
| 原会商能力 | 升级版要求 |
|---|---|
| 左侧会商历史、新建会商 | 保留。一个条目就是一个用户可见会商,不暴露 MAF session/run/thread。 |
| 中央连续对话流 | 保留。用户消息、总控消息、席位发言、工具进度、澄清、审批、最终报告按时间顺序呈现。 |
| 底部对话输入框 | 保留。用户可在首轮发起任务、在澄清时回答、在会商结束后追问/继续会商。 |
| 意图理解 | 保留并服务端化。先识别“可直接会商 / 需要澄清 / 只回答问题 / 需要工具或写入”。 |
| 总控智能体派活 | 保留。总控是唯一能选择席位、分派任务、收束轮次和生成结论的主体。 |
| 业务链、席位与过程可视化 | 保留其信息架构和交互,不复用旧业务状态;数据改由 MAF 事件驱动。 |
| 澄清、取消、恢复、审批 | 保留,并成为对话流中的卡片,而不是跳转到 run 管理页。 |
1.2 明确不保留的实现方式
- 不在浏览器端
setInterval轮询 run、events、actions、approvals; - 不让浏览器创建或维护 seat thread、manager thread、thread map;
- 不让用户先填写“经理、席位、模式、最大轮数”才能开始一次正常会商;
- 不把
MafSessionsPage/MafRunDetailPage当作新产品主界面继续堆功能; - 不调用旧的
/api/roundtable-*、/api/multi-agent/*、roundtable_jobs、旧草稿或旧会商状态; - 不修改旧
RoundtablePlanningPage的业务状态机、历史数据和对外行为。
2. 总体架构与边界
flowchart LR
U[用户:会商对话页] -->|POST 新建/发送消息| API[MAF Conversation API]
API --> C[(MAF Conversation / Message)]
API --> D[MAF Dispatcher]
D --> W[MAF Workflow]
W --> M[总控:意图、派活、收束]
M --> S[服务端按需创建席位执行线程]
S --> A[DeerFlow Agent Adapter]
A --> T[工具 / 技能 / MCP / 沙箱]
T --> G[WriteGuard + 审批]
W --> E[(持久化会商事件)]
E --> H[SSE Hub:重放 + 实时推送]
H -->|一条 SSE 流| U
2.1 前后端职责
| 层 | 职责 | 禁止事项 |
|---|---|---|
| 前端 | 呈现会商、发送用户消息、消费 SSE、执行用户明确点击的取消/审批/重试 | 编排席位、决定下一位发言者、创建内部线程、轮询事件。 |
| MAF Conversation Service | 会话聚合、消息持久化、运行创建、SSE 重放、所有权校验 | 让浏览器传入 user_id、工具能力快照、目标键或内部幂等键。 |
| MAF Workflow | 意图判断、总控派活、席位协作、交叉审查、结论、恢复 | 把模型输出直接当作可写外部系统的授权。 |
| DeerFlow Adapter | 为总控/席位提供既有模型、工具、技能、MCP、沙箱和用户上下文 | 从 packages/harness/deerflow/** 导入 app.*。 |
| WriteGuard | 风险识别、审批、目标租约、一次执行、审计 | 将密钥、target_key、idempotency_key 回传给浏览器或模型。 |
2.2 新旧隔离规则
- 旧会商继续运行,旧路由、旧 API、旧数据表、旧任务深链全部不变。
- 新页面独立使用
/api/maf-roundtable/*和maf_roundtable_*表;只允许参考旧页面的布局、文案、交互和通用视觉规范。 - 旧
roundtable-planning/**中的业务 hook、草稿、Job、SSE 消费器和状态类型不能被新页面直接 import。 - 若需要复用旧组件的视觉效果,必须复制/迁移为
maf-roundtable/legacy-compatible/**中的新组件,替换为 MAF view model;或抽到无业务依赖的公共展示组件。旧页面不得因此改变行为。 - 新旧页面都只能使用仓库本地依赖;UI 基础组件统一采用
tdesign-react,不接远程 UI、CDN 或外部运行时。
3. 用户可见的新版会商流程
3.1 首次进入
- 用户点击独立菜单“MAF 会商(升级版)”,进入与旧会商相同层级的页面壳。
- 左侧显示自己的 MAF 会商历史和“新建会商”。新建只创建一个用户可见会商,不显示 session/run/thread 表单。
- 中心区域显示欢迎语、业务链/任务上下文入口和对话输入框。
- 用户输入任务后,前端立即插入本地的用户气泡,调用一次
POST /messages,然后消费同一会商的 SSE 流。
3.2 一次会商轮次
- SSE 推送“正在理解任务”事件;页面以旧会商的过程卡/总控气泡表现。
- 若信息不足,推送
clarification.required,页面显示可回复的澄清卡;用户回答后仍通过输入框或卡片提交。 - 若可以执行,总控输出“派活计划”;页面以旧的席位条、派活卡和消息气泡展示。
- 每个席位的可见发言、工具进度、技能过程、交叉审查和总控收束都写入同一条时间线。
- 出现外部写操作时,SSE 推送审批卡。用户批准/拒绝后,后端恢复工作流,SSE 继续推送;前端不手工轮询 run 状态。
- 最终结论、事实账本、执行动作和报告作为对话流中的结果卡呈现;用户可以继续在同一会商输入追问。
3.3 “一个会商”与内部线程的关系
- 用户只认识
conversation_id;左侧历史、URL 和前端状态都以它为主键。 - 一个 conversation 可以有多轮用户消息,每轮消息产生一个内部
maf_run。 maf_session、manager/seat thread、seat run 都是服务端内部执行身份。服务端使用既有ExecutionPrincipal绑定当前用户,并在真正需要某席位执行时懒创建/复用线程。- 浏览器只收到经过脱敏的消息和事件,不会收到内部 thread id、能力快照、目标键、幂等键、密钥或原始工具结果。
3.4 总控质量闸门:派活不是“发出即完成”
当前旧会商的问题不是没有派活,而是席位只说一两句话、格式和证据都不合格时,总控仍把它当作完成并直接进入下一步。新版 MAF 必须把总控从“消息转发者”升级为每项席位交付的验收责任人。
每一个由总控发布的席位任务都必须有服务端持久化的 task_contract:
| 字段 | 含义 |
|---|---|
objective |
本席位要回答的具体问题,不能只写泛泛角色描述。 |
expected_deliverable |
交付类型和结构,例如“风险清单 + 依据 + 优先级 + 建议”。 |
acceptance_criteria |
由总控给出的可验收标准:覆盖范围、最少关键点、证据/工具依据、格式与约束。 |
required |
是否为本阶段必需交付;必需项不能被静默跳过。 |
max_rework_attempts |
同一席位最多返工次数,默认 2(初稿之外最多两次返工),服务端配置且写入快照。 |
fallback_policy |
到达返工上限后的策略:改派、请求用户澄清,或带缺口受控推进。 |
3.4.1 席位交付与总控验收状态机
stateDiagram-v2
[*] --> assigned
assigned --> delivering
delivering --> submitted
submitted --> manager_review
manager_review --> accepted: 达到合同标准
manager_review --> rework: 不合格且未到返工上限
rework --> delivering: 带明确退回意见
manager_review --> reassigned: 达到上限且可改派
reassigned --> delivering
manager_review --> exhausted: 达到上限且无合适改派
exhausted --> controlled_gap: 记录缺口、风险与原因
accepted --> [*]
controlled_gap --> [*]
验收规则如下:
- 席位先提交结构化
delivery,至少包含结论、依据/证据、未解决项、自检结果;不能只输出“已完成”或一两句空泛结论。 - 进入
manager_review前先执行确定性检查:空内容、最小有效长度、必须章节、必填字段、所需证据/工具引用、重复文本、错误 schema。确定性不通过时不允许直接 accepted。 - 总控随后根据
task_contract做结构化审查,决策只能是accept、return_for_rework、reassign、ask_user、controlled_gap,并必须写明reason和针对性修改要求。 - 总控的模型自评不是验收证据。 席位自评分只作为参考;验收由确定性规则 + 总控审查 + 必要时交叉审查共同决定。
- 对同一席位,默认最多两次返工。每次打回都必须把“缺什么、怎样补、哪些原结论不可用”带入下一次任务上下文。
- 到达上限后绝不把不合格结果伪装成合格:总控应优先改派给一个合适备用席位(默认最多一次改派);仍无法满足时生成
controlled_gap,明确标记未覆盖问题、风险和对最终结论的影响,再受控进入下一阶段。 - 一个阶段的所有
required任务必须处于accepted或controlled_gap等明确终态,阶段闸门才可通过。总控不能因为“轮数到了”或“已有部分回答”跳过未决必需项。 - 最终报告不得将
controlled_gap的内容写成已验证事实;它必须在结论中的风险/待补信息部分可追溯显示。
这既满足“打回几次后不要死循环”的要求,也避免“超过次数就把垃圾答案强行推进”的错误行为。
3.4.2 对话页必须可见的质量反馈
- 总控派活卡展示任务目标、交付要求和当前第几次尝试;
- 席位提交后显示“总控审核中”,而不是立即标为完成;
- 打回时以总控消息卡显示具体退回理由和补充要求;
- 改派时显示原席位未通过和新席位承接范围,但不羞辱性展示内部评分;
- 受控降级时显示“存在未解决缺口”,并在最终结果卡中保留风险提示;
- 右侧席位条区分“执行中、待返工、已验收、已改派、存在缺口”,不能只显示“发过言”。
4. API 与 SSE 契约(必须先定,前端不得猜测)
4.1 Conversation API
以下接口全部位于 /api/maf-roundtable,身份只从服务端鉴权上下文读取。
| 接口 | 用途 | 前端调用时机 |
|---|---|---|
GET /conversations |
左侧历史列表(分页) | 首次进入、用户显式刷新、创建/删除后失效刷新;无定时轮询。 |
POST /conversations |
创建空白用户会商 | 点击“新建会商”。只接收 title、任务上下文等安全字段。 |
GET /conversations/{id} |
获取会商快照、权限和当前状态 | 进入会商或浏览器刷新时。 |
GET /conversations/{id}/messages |
获取历史消息分页 | 进入会商、向上滚动加载历史。 |
POST /conversations/{id}/messages |
原子写入用户消息并启动 MAF run | 用户点击发送或提交澄清。返回 message_id、run_id、conversation_id。 |
POST /conversations/{id}/cancel |
取消当前活跃 run | 用户显式点击取消。 |
POST /approvals/{id}/decision |
批准/拒绝写入动作 | 审批卡点击;成功后由后端恢复 workflow。 |
POST /conversations/{id}/recover |
显式恢复异常中断的活跃会商 | 仅在后端判定可恢复时展示。 |
不再让页面以“创建 session → 创建 run → GET events 循环”的方式驱动会商。原有低层 session/run 接口可以作为内部诊断 API 暂时保留,但从用户页面和导航移除。
4.2 SSE:唯一的实时通道
GET /api/maf-roundtable/conversations/{conversation_id}/stream?after_seq={last_seen_seq}
Accept: text/event-stream
Authorization: 与现有 fetch 客户端一致
- 前端在进入一个 conversation 后只建立一条 fetch-reader SSE 连接;切换会商、卸载页面、权限失效时 Abort。
- 浏览器不能用定时 GET 代替 SSE。连接断开后采用指数退避重连,并携带最后已确认的
after_seq;不产生全量重复气泡。 after_seq是 conversation 维度、服务端单调递增的序号,不能复用每个 run 独立的seq。- 首次连接先由
GET messages加载历史,再从该历史的最大seq订阅 SSE;服务端也必须支持重放,避免“历史请求和订阅之间”丢事件。 - SSE 使用
fetch+ReadableStream解析,以复用项目鉴权头;响应必须带Content-Type: text/event-stream、Cache-Control: no-cache、X-Accel-Buffering: no,并每 15 秒发送心跳。 - 服务端负责等待和推送。单 worker 可用进程内 conversation event hub;生产多 worker 部署前必须接入 Redis Pub/Sub 或等价分布式广播,不能退回浏览器轮询。
4.3 SSE 事件信封
所有事件统一为:
{
"seq": 42,
"event_id": "evt_...",
"conversation_id": "conv_...",
"run_id": "run_...",
"type": "agent.message.delta",
"occurred_at": "2026-08-02T12:00:00Z",
"data": {}
}
允许的首批 type:
| 类型 | 对话页表现 |
|---|---|
conversation.snapshot |
首帧状态同步,不重复插入消息。 |
user.message.created |
刷新/多标签同步时补齐用户气泡。 |
manager.intent |
总控“正在理解/已理解”的过程卡。 |
clarification.required / clarification.resolved |
澄清卡及其回答状态。 |
manager.dispatch |
总控派活卡、席位条状态更新。 |
seat.delivery.submitted |
席位提交交付,进入总控审核而非直接完成。 |
manager.review.decision |
展示验收、打回、改派或受控降级及其安全摘要。 |
seat.rework.assigned / seat.reassigned |
更新第几次返工、原/新席位和新的任务要求。 |
stage.quality_gate |
阶段质量闸门通过、阻塞或带缺口推进。 |
agent.message.start / delta / complete |
席位或总控流式气泡。 |
tool.started / tool.progress / tool.completed |
现有步骤卡/工具过程,不显示敏感参数。 |
approval.required / approval.decided |
嵌入对话流的审批卡。 |
fact.confirmed / review.completed |
事实/交叉审查摘要卡。 |
run.status / run.error / run.completed |
顶部状态、失败重试与最终结果。 |
事件 data 必须先经过现有 MAF 安全规范化和二次展示脱敏;前端不负责猜测工具风险或修复敏感数据。
5. 后端改造计划
MAF-R0:冻结错误原型并建立旧会商基线
难度:D2(中低)|负责人:前端/测试各 1 人|前置:无
- 将现有
/page/maf/*标记为“实验原型”,从正式菜单移除;不得在其上继续新增业务功能。 - 记录旧会商的页面状态:空会商、发送后、意图澄清、总控派活、席位流式发言、审批、完成、失败恢复、历史切换。
- 为每种状态保存可复现的测试数据与截图基线;截图只作为视觉验收参考,不作为数据契约。
- 输出旧组件到新 MAF view-model 的映射清单,禁止直接搬旧 hook。
验收: 旧会商无行为回归;团队对“复制体验、替换编排”有书面映射表。
MAF-R1:Conversation 聚合与消息持久化
难度:D5(高)|负责人:后端资深 1 人|前置:R0
新增/迁移 MAF 专用持久化模型:
maf_roundtable_conversations:用户可见会商,至少包含 id、owner_user_id、title、task_context、安全状态、active_run_id、created_at、updated_at;maf_roundtable_messages:用户消息、总控/席位消息、澄清/审批/结果卡的稳定历史表示;maf_roundtable_conversation_events:conversation 维度严格递增的seq、event_id、run_id、type、安全 data、created_at;- 现有
maf_roundtable_sessions/runs/events/seat_runs/actions/approvals保留为底层执行与审计记录;conversation 与内部 session/run 显式关联。
要求:
- 发送用户消息、创建/占用 run、写入首个用户消息事件必须在清晰的事务边界内完成;失败不留“消息已显示但未运行”的孤儿状态。
- 消息历史必须可在刷新后重建对话;不能只依赖内存或 SSE 临时帧。
- 所有读写继续 owner-only;管理员诊断只读不扩大写权限。
- 新迁移必须 SQLite/PostgreSQL/MySQL 可重复执行;旧 MAF 原型数据可保留,不强制伪造为新对话历史。
验收: 会话创建、连续发消息、刷新恢复、并发发送冲突、跨用户隔离、迁移幂等都有 API 和存储测试。
MAF-R2:服务端 SSE Hub 与断线续传
难度:D5(高)|负责人:后端流式/并发经验者 1 人|前置:R1
- 新增 conversation stream 路由和
ConversationEventHub;Workflow/Dispatcher 的规范化事件落库后再发布,顺序是“先持久化、后通知”。 - SSE 连接先按
after_seq重放,再订阅实时事件;重放和订阅切换期间必须有序、不丢帧、不重复。 - workflow 终态、审批等待、审批恢复、取消、失败重试都必须通过同一流通知。
- 不允许每个 SSE 客户端创建数据库轮询循环。服务端可以阻塞等待 hub 通知,事件重放只在连接/重连时发生。
- 写出单 worker 与多 worker 的实现边界;若部署配置多 worker,未接入分布式广播时健康检查必须明确告警并禁止该模式上线。
验收: 测试覆盖慢客户端、断线重连、after_seq 重放、同时打开两个标签、切换会商、取消、审批后恢复、进程内 hub 异常和终态自动关流。
MAF-R3:总控意图理解与派活语义对齐
难度:D5(高)|负责人:MAF/Agent 负责人 1 人|前置:R1,可与 R2 并行
在现有 MAF Workflow 上增加用户对话入口状态,而不是让前端预先填 manager/seat/run:
- 总控首先进行意图判断:普通问答、需要澄清、单席位任务、并行专家会商、链式业务会商、需要工具/写入。
- 总控产出受 schema 校验的派活计划;只有服务端可将计划转成实际席位执行。
- 每个计划项必须生成并冻结
task_contract(目标、交付结构、验收标准、必需性、返工上限和降级策略),席位的发言不等于交付完成。 - 席位完成后先做确定性完整性检查,再由总控做结构化验收;总控可接受、打回同一席位、改派、请求用户补充或记录受控缺口。所有决策、次数和理由持久化到 checkpoint 与审计事件。
- 默认初稿后最多两次同席位返工;到达上限优先改派一次,仍失败才以带风险标记的
controlled_gap结束。严禁自动把不合格交付推进为合格事实。 - 阶段迁移需经过质量闸门:所有必需任务均有
accepted或受控缺口终态;最终总结只能消费已验收事实,缺口必须显式传入风险章节。 - 席位集合来自业务链、可信能力快照和上下文;前端可呈现“建议/已参与席位”,但不能提交任意工具权限或 thread id。
- 总控每轮应吸收已确认事实、验收结果、退回原因和用户追问;弱模型无效派活、重复派活、无收敛时走确定性纠偏/终止策略。
- 已有 structured/group_chat、事实账本、交叉审查、审批 checkpoint、执行阶段身份均继续复用;只重构其输入输出为 conversation event。
验收: 用同一任务对照旧会商的意图澄清、总控派活、席位协作、打回/改派和收束结论;弱模型的短答、空答、错误 schema、缺证据、重复派活、非法席位、超轮次、返工上限和受控降级都有确定性保护测试。
R3 当前实施记录(2026-08-03)
后端已先完成 R3 的服务端核心骨架,作为 R1/R2 Conversation API/SSE 的后续:
app/maf_roundtable/dispatch_contracts.py提供确定性意图分类、服务端业务路线解析、schema 校验的MafDispatchPlan和弱模型防护;请求、模型输出都不能提供 agent id、thread id、tool metadata 或能力快照。MafRoundtableConfig增加default_manager_agent_id、default_seat_agent_ids、business_routes和max_seats_per_run。仓库配置保持空路线;上线前必须由部署配置填入实际 agent catalog 中的精确 id,未知业务路线失败关闭。- 首条消息在同一事务内创建内部 session、服务端选定的 manager/seat participants 和冻结能力快照;澄清意图进入
waiting_input,不创建 run,用户补充信息后才允许重新 claim。 - Conversation service 已接入现有
MafRunDispatcher/WorkflowRunner,持久化manager.intent、manager.dispatch和 run 状态桥接事件;现有结构化工作流的席位集合仍只来自服务端 participants,manager 文本不能扩席或改派非法席位。 - V2
POST /conversations/{id}/messages只返回message_id、conversation_id、seq;run_id仍是持久层/服务端内部关联字段,不返回给浏览器。 - 新增
tests/test_maf_phase3_conversation_dispatch.py,覆盖未知业务路线、默认路线、澄清、完成状态桥接、重复/越权派发计划等确定性用例。R3 尚未整体验收完成:仍需完成新页面、完整真实 MAF Workflow E2E、质量门禁和与旧会商体验的浏览器对照验收。
MAF-R4:将审批和外部写入嵌回对话主链路
难度:D4(较高)|负责人:后端安全 + 前端各 1 人|前置:R2、R3
- 保留 Phase 5 的 WriteGuard、能力快照、HMAC 目标键、租约、加密参数、一次执行和审计;不得为了 SSE 改弱任何安全边界。
approval.required只携带白名单展示字段和安全摘要。审批决定后由后端自动续跑,前端只等待同一 SSE 流中的新事件。- 拒绝、过期、执行失败、unknown 均形成清晰对话卡和可恢复状态;不得把“未知结果”伪装成成功。
- 行为审计可在最终结果区展开查看,但不能替代对话中的关键用户反馈。
验收: HTTP → MAF → ToolNode/outbox → 审批 → SSE → 前端卡片 的端到端测试;确保 target_key、idempotency_key、internal_canary、密钥和原始工具结果从不进入消息/API/SSE。
6. 前端改造计划:复刻体验,替换状态源
MAF-R5:新会商页面壳与历史列表
难度:D4(较高)|负责人:熟悉旧会商的前端 1 人|前置:R0、R1
新建 src/maf-roundtable/conversation/**,建议结构:
maf-roundtable/conversation/
pages/MafRoundtableConversationPage.tsx
components/
ConversationSidebar.tsx
ConversationTimeline.tsx
ConversationComposer.tsx
ManagerDispatchCard.tsx
SeatMessageBubble.tsx
ToolProgressCard.tsx
ClarificationCard.tsx
ApprovalMessageCard.tsx
FinalResultCard.tsx
ParticipantStrip.tsx
hooks/
use-maf-conversations.ts
use-maf-conversation-stream.ts
use-maf-conversation-reducer.ts
api/conversations.ts
lib/event-reducer.ts
styles/maf-roundtable-legacy-compatible.css
页面要求:
- 左侧
ConversationSidebar的层级、历史列表、新建、激活态、删除/重命名交互对齐旧会商; - 中间
ConversationTimeline使用连续消息流,保留旧会商的用户气泡、总控气泡、席位气泡和时间锚点; ConversationComposer常驻底部;发送、停止、澄清回答、追问都在该入口完成;- 右侧仅保留旧体验中真正有用的参与席位、当前阶段和业务链摘要,不再摆放 run/session 管理后台;
- 使用本地
tdesign-react组件实现按钮、输入、Dialog、Tag、Tabs 等基础交互,同时通过 scoped CSS 对齐旧视觉; - 视觉相似不等于 import 旧业务组件。旧组件仅作参考,数据类型、hook 和 API 必须是 MAF 专用实现。
验收: 不连接后端时,使用固定 MAF 事件样本可完整演示旧会商同等的 8 种关键状态;没有 session/run/thread 表单。
MAF-R6:SSE 客户端、事件 reducer 与刷新恢复
难度:D5(高)|负责人:前端流式经验者 1 人|前置:R2、R5
use-maf-conversation-stream只维护一个连接、一个 cursor、一个 AbortController;不得含setInterval、refetchInterval或轮询 fallback。- reducer 以
(conversation_id, seq)去重并排序,将原始事件转为稳定 view model;流式 delta 必须按message_id合并,不能用数组下标。 - 切换会商时先 abort 旧流并增加 generation;旧 SSE 帧永远不能污染新会商。
- 刷新时先加载消息历史,再以最后 seq 订阅;网络断开显示“正在重连”,重连成功不重复气泡。
- 只有历史列表等非实时资源可在用户主动操作后调用 GET;不能靠后台刷新伪装实时性。
验收: 模拟 1 万条历史、跨页加载、慢旧流切换、新流先到、断线重连、重复帧、乱序帧、终态关流和多标签同步;所有案例必须组件级测试。
MAF-R7:意图/派活/审批卡的旧体验兼容
难度:D4(较高)|负责人:前端业务负责人 1 人|前置:R3、R4、R6
- 用旧
IntentClarificationCard、MessageStepsCard、ParallelSeatStrip、MessageBubble的交互作为视觉和信息架构参照,重新实现 MAF 版本。 - 总控派活计划必须先显示“将由谁做什么”,席位开始/结束、工具过程和交叉审查要回到原有对话叙事中。
- 席位“发言结束”只能显示为“已提交,待总控审核”;只有收到
manager.review.decision=accept才能显示“已验收”。打回次数、改派和缺口必须清楚可见。 - 审批卡需要同步防双击锁、二次脱敏、拒绝/通过后的“等待工作流继续”状态;不可另外跳转到 action 审计页。
- 最终结论卡要区分“建议动作”“审批中动作”“已执行动作”“失败/未知动作”。
- 继续追问时,页面不新建多个用户可见线程;后端根据 conversation 上下文决定是否创建新 run 或继续恢复。
验收: 产品人员可在不看技术术语的情况下完成“发起会商 → 澄清 → 观察派活 → 审批 → 查看结论 → 追问”全链路。
7. 测试、上线与回滚
7.1 必须新增的自动化测试
| 类别 | 核心用例 |
|---|---|
| 后端事务 | 发消息/创建 run 原子性、并发发送、跨用户隔离、迁移幂等。 |
| SSE 服务端 | 重放、顺序、心跳、取消、断线、审批恢复、多订阅者、终态关流。 |
| Workflow | 意图澄清、总控派活、弱模型格式错误、重复派活、最大轮次、恢复。 |
| 质量闸门 | 短答/空答、缺少必填章节、无证据、总控打回、两次返工上限、一次改派、受控缺口、阶段阻塞和最终报告不把缺口伪装成事实。 |
| 安全 | SSE/API/历史消息不泄露敏感键和值;审批和一次写入仍保持现有 Phase 5 保证。 |
| 前端 reducer | delta 合并、去重、乱序、切换代次隔离、重连 cursor。 |
| 前端组件 | 输入发送、澄清、派活、审批锁、取消、失败恢复、历史切换、无轮询断言。 |
| E2E | 从用户输入到真实 MAF Workflow、ToolNode/outbox、审批、最终结果的 SSE 全链路。 |
| 回归 | 旧 roundtable-planning、旧 DeerFlow、AI 写作以及既有 MAF Phase 1–5 用例全部通过。 |
7.2 人工视觉验收
在同一浏览器尺寸下对照旧会商,至少核对:
- 空白页和新建会商;
- 左侧历史/当前会商切换;
- 用户输入、流式总控消息、席位消息;
- 意图澄清和总控派活;
- 工具过程、审批、取消、失败恢复;
- 最终结论和连续追问;
- 窄屏滚动、长内容、断线重连和页面刷新。
7.3 灰度与回滚
- 新入口使用独立 feature flag,例如
maf_roundtable.conversation_ui_enabled;旧会商不受该开关影响。 - 先仅向内部账号开放,记录连接数、重连率、事件延迟、工作流失败率、审批耗时和前端异常。
- 出现问题时关闭新入口即可;不迁移或删除旧会商数据,也不需要回滚旧页面。
- 当前错误原型可保留为仅开发者诊断路由,或在新版稳定后删除;它不应继续出现在用户菜单。
8. 分阶段任务分配、难度与交付顺序
本节是分工的唯一依据。难度定义:D1=很低(局部文案/样式),D2=低(明确边界的小模块),D3=中(跨 2–3 个模块),D4=较高(跨前后端或需回归),D5=高(并发、状态机、安全或 Agent 行为,必须由有经验者负责)。
阶段 0:冻结错误原型,提取旧会商交互基线(R0)
难度:D2|建议人员:1 名熟悉旧会商的前端 + 1 名测试|依赖:无
具体要做:
- 将现有
/page/maf/*的 session/run 详情原型从正式菜单隐藏,标注为开发诊断原型,停止继续加功能。 - 逐一记录旧会商的 8 类页面状态:空白/新建、历史切换、用户提问、意图澄清、总控派活、席位发言、审批、完成/失败恢复。
- 给每种状态保留可复现 mock 数据、页面截图和操作步骤;梳理旧组件到新 MAF view-model 的映射。
- 明确哪些只能参考视觉和交互,哪些旧业务 hook/API/状态禁止复用。
交付物:旧会商交互地图、截图基线、组件映射表、被隐藏的原型入口说明。
验收:旧会商没有代码行为变化;任何人可以根据基线判断新版是否“像原页面”。
阶段 1:建立用户可见 Conversation 与消息历史(R1)
难度:D5|建议人员:1 名资深后端|依赖:阶段 0
具体要做:
- 新增
maf_roundtable_conversations、maf_roundtable_messages、maf_roundtable_conversation_events,设计 owner、标题、消息、conversation 全局序号、活跃 run 和安全状态字段。 - 建立 conversation 与现有 MAF session/run/seat-run 的内部关联;用户只得到 conversation id,不能看到内部 thread id。
- 实现会商历史列表、创建空白会商、读取会商快照、读取消息分页、发送用户消息五类 API。
- 发送消息时,用户消息持久化、run 创建/占用和首个事件必须有明确事务边界;并发发送、重复请求、失败回滚都要处理。
- 完成 SQLite/PostgreSQL/MySQL 迁移与 owner-only 权限测试。
交付物:迁移脚本、repository/service/router、API schema、后端事务与隔离测试。
验收:刷新后能从消息历史恢复完整会商;跨用户不可读写;失败不会留下“已显示但没有实际运行”的孤儿消息。
阶段 2:服务端 SSE 对话流、事件 Hub 与断线续传(R2)
难度:D5|建议人员:1 名熟悉 FastAPI 异步流与并发的后端|依赖:阶段 1
具体要做:
- 实现
GET /conversations/{id}/stream?after_seq=,按 conversation 全局 seq 先重放、后订阅实时事件。 - 新建
ConversationEventHub;所有 workflow 事件先安全落库,再按顺序广播。禁止 SSE 客户端通过定时查库等待更新。 - SSE 实现心跳、连接取消、权限校验、终态关流、异常帧和断线后的 cursor 续传。
- 明确多 worker 部署方案:单 worker 可进程内广播;多 worker 必须 Redis Pub/Sub 或等价方案,未满足时不能灰度上线。
- 把 run 状态、总控派活、席位消息 delta、工具过程、审批、质量审核、最终结论全部映射为统一事件信封。
交付物:SSE router/hub、事件发布适配器、集成测试、部署说明。
验收:慢连接、断线重连、乱序/重复防护、多标签订阅、审批后续跑、取消和终态均不丢事件;前端不需要轮询任何实时资源。
阶段 3:总控意图理解、业务链选择与服务端派活(R3)
难度:D5|建议人员:1 名 MAF/Agent 工程师|依赖:阶段 1;可与阶段 2 并行
具体要做:
- 将旧会商的意图理解能力迁到 MAF 总控入口:识别直接问答、需澄清、单席位、并行会商、链式业务会商、工具/写入请求。
- 总控根据业务链、用户上下文、可信能力快照选择席位,生成 schema 校验的派活计划;前端只展示,不参与编排。
- Dispatcher 在服务端按需创建/复用 manager 和 seat 的内部执行线程,并由
ExecutionPrincipal绑定当前用户。 - 对弱模型增加确定性保护:非法席位、空派活、重复派活、无效 schema、超轮次、无法收束必须被拒绝、纠偏或终止。
- 保持既有工具、技能、MCP、沙箱、事实账本、交叉审查和 checkpoint 恢复可用。
交付物:总控状态 schema、workflow executor、派活事件、弱模型测试矩阵。
验收:用户只输入任务,就能看到“意图理解 → 总控派活 → 席位执行”;浏览器没有 thread map 和派活决策代码。
阶段 4:席位任务合同、总控验收、打回与强制收束(R3-Q)
难度:D5|建议人员:1 名 Agent/MAF 工程师 + 1 名后端状态机工程师|依赖:阶段 3
具体要做:
- 总控发布任务时冻结
task_contract:具体目标、交付格式、验收标准、必需性、返工次数、改派与降级策略。 - 为每项席位任务持久化状态机:
assigned → delivering → submitted → manager_review → accepted/rework/reassigned/controlled_gap。 - 席位提交后先做确定性质量检查:空答、过短、必填章节缺失、格式错、无证据、重复内容等均不能自动完成。
- 总控必须生成结构化验收决定和原因;不合格时打回并带精确补充要求。默认最多两次同席位返工,之后最多一次改派。
- 改派仍失败时只能产生
controlled_gap,标记风险、缺失项和最终报告影响;严禁伪装为成功。 - 增加阶段质量闸门:所有必需任务处于
accepted或controlled_gap,才允许进入交叉审查/下一阶段/最终总结。 - 将尝试次数、退回理由、验收结果和缺口写入 checkpoint、审计和 SSE。
交付物:任务合同模型、持久化表/迁移、质量状态机、总控审查 prompt/schema、事件和测试。
验收:席位只说一两句话、无依据或内容垃圾时会被明确打回;达到上限不会死循环,也不会被当作合格产出;最终报告可追溯所有缺口。
阶段 5:审批、WriteGuard 与外部动作嵌入对话流(R4)
难度:D4|建议人员:1 名安全后端 + 1 名前端|依赖:阶段 2、3、4
具体要做:
- 保留现有 Phase 5 的可信能力快照、WriteGuard、目标租约、HMAC、加密参数、一次执行与审计,不允许为新页面降低安全性。
- 将工具开始、审批请求、批准/拒绝、执行成功/失败/unknown 变成安全 SSE 事件和对话卡。
- 审批点击只调用明确决策 API;后端负责恢复 checkpoint/workflow,浏览器只等待 SSE。
- 安全展示统一二次脱敏,禁止 target_key、idempotency_key、internal_canary、密钥、凭据和原始工具结果进入 API、消息、SSE 或 DOM。
交付物:事件映射、审批消息卡契约、端到端 ToolNode/outbox 测试。
验收:一次真实测试写入能在对话里经历“申请 → 审批 → 继续 → 结果”;重复点击或断线都不会重复外部写入。
阶段 6:复刻旧会商页面壳、历史列表和输入框(R5)
难度:D4|建议人员:1 名熟悉旧会商代码的前端|依赖:阶段 0、1
具体要做:
- 新建 MAF 专用 conversation 页面、路由和独立 feature flag;不修改旧
RoundtablePlanningPage。 - 依据阶段 0 的映射,复刻左侧历史会话、新建会商、中心时间线、常驻输入框、参与席位区和业务链摘要的视觉与交互层级。
- 基础组件使用本地
tdesign-react,旧页面仅参考;需要的视觉组件在 MAF 目录重写或抽无业务依赖公共组件。 - 接上 Conversation API:创建、历史、切换、消息分页。此阶段不允许先做任何轮询实时逻辑。
- 删除新页面中暴露给用户的 manager/seat/max round/session/run 创建表单。
交付物:新页面壳、MAF 专用 view model、静态/接口 mock 组件测试、视觉对照截图。
验收:即使 SSE 未接通,用户也能看到与旧会商同类的历史、对话与输入体验;新旧业务状态零耦合。
阶段 7:前端 SSE 消费、对话 reducer 与过程交互(R6 + R7)
难度:D5|建议人员:1 名前端流式工程师 + 1 名前端业务工程师|依赖:阶段 2、4、5、6
具体要做:
- 实现单连接
use-maf-conversation-stream:fetch-reader SSE、cursor、AbortController、指数退避重连和会商切换 generation 隔离。 - 实现 event reducer:按
conversation_id + seq去重排序;按 message_id 合并 delta;刷新后历史与 SSE 无缝衔接。 - 重写旧会商对应的 MAF 版组件:总控意图卡、派活卡、席位条、席位气泡、工具步骤、澄清卡、审批卡、质量审核/打回卡、结果卡。
- 所有卡片在时间线内叙事,不另开 run/session 管理后台;继续追问仍使用同一输入框。
- 页面必须显示待审核、已验收、返工次数、改派、受控缺口和恢复状态,不能把“发过言”显示为“已完成”。
- 代码审查和测试中检查不存在
setInterval、refetchInterval或事件轮询 fallback。
交付物:SSE hook、reducer、对话组件、组件/API mock 测试、无轮询静态检查。
验收:切换会商、断线重连、审批续跑、慢旧流回包、长会话翻页均不污染、不丢消息、不重复;整个会商过程只依赖 SSE 实时更新。
阶段 8:端到端验收、灰度和回滚演练(R8)
难度:D4|建议人员:1 名测试/集成人 + 各阶段负责人配合|依赖:阶段 1–7
具体要做:
- 跑完后端事务/SSE/Workflow/质量闸门/WriteGuard 测试、前端 reducer/组件测试、旧会商与 DeerFlow 回归。
- 在真实浏览器按阶段 0 截图基线逐项对照,并完成用户任务:发起、澄清、派活、短答打回、两次返工、改派、审批、受控缺口、结论和追问。
- 内部账号灰度,观测 SSE 建连/重连、事件时延、派活/验收/返工次数、workflow 失败率、审批耗时和前端错误。
- 验证关闭 feature flag 后立即回到旧会商入口,旧数据和旧任务不受影响。
- 若需生产外部写入,补齐 UAT 系统、最小权限凭据、核验 API、补偿联系人和生产
MAF_ACTION_SECRET_KEY。
交付物:自动化结果、人工验收记录、灰度指标面板、回滚演练记录、上线清单。
验收:满足第 9 节全部条件后才允许标记开发完成。
8.1 可并行边界
- 阶段 2 与阶段 3 可在阶段 1 的 schema/API 定稿后并行,但二者必须共用同一事件信封。
- 阶段 6 可在阶段 1 的 API mock 契约定稿后提前开始;不得自行发明事件字段。
- 阶段 5 必须等待阶段 2、3、4 的安全事件与状态机定稿。
- 阶段 7 必须等待阶段 2、4、6,不能以轮询临时替代 SSE。
- 阶段 8 只做集成、验收和上线准备,不补写前面阶段缺失的核心设计。
建议主顺序:阶段 0 → 阶段 1 → (阶段 2 + 阶段 3 + 阶段 6) → 阶段 4 → 阶段 5 → 阶段 7 → 阶段 8。
9. 最终验收定义
只有同时满足以下条件,才可以说“本次 MAF 会商升级开发完成”:
- 新页面在视觉和主交互上可被用户认作原多智能体会商的升级版;
- 页面具备历史会话、连续对话流、输入框、意图理解、总控派活、席位协作、澄清、审批、结果和追问;
- 每个必需席位任务都有任务合同、总控验收、有限返工和改派/受控缺口处理;席位短答或垃圾产出不能自动被当作完成;
- 浏览器没有会商事件/run/approval 的定时轮询;实时交互通过可重连 SSE 完成;
- 用户不需要创建或管理多个智能体线程,内部线程由服务端按用户身份安全创建和恢复;
- 新页面未调用旧会商业务 API/状态,旧会商零回归;
- 工具、技能、MCP、沙箱、审批、WriteGuard、一次写入和审计都仍可用;
- 自动化测试、SSE 故障测试、真实浏览器人工验收和旧功能回归全部通过;
- 真实 UAT 写入系统、最小权限凭据、外部核验 API、补偿协议及生产
MAF_ACTION_SECRET_KEY已按 Phase 5 前置条件完成。
在这之前,任何“会话/run 原型页面通过构建或轮询测试”的结果,都只能算技术验证,不算产品升级验收。
阶段 3 实施记录(当前代码基线)
本轮已补齐阶段 3 的服务端安全路由与真实 MAF Workflow 入口,范围仅针对新 MAF 会商;旧 DeerFlow、旧 roundtable 和 AI 写作行为不变。
配置与入口闸门
- 仓库默认
maf_roundtable.enabled: false。部署环境必须注入真实的default_manager_agent_id、席位 ID 和业务路由后再开启,避免出现“入口显示正常但首条消息必然 503”的空配置。 - 健康接口返回非敏感的
conversation_dispatch_ready与conversation_dispatch_status;新会商入口只有在配置路由可用且服务已启用时才开放。 - 首条消息使用服务端可信能力快照校验 manager/seat 的可访问性;浏览器、会话请求和模型输出都不能提供或扩大 agent、thread、tool、capability 范围。
- 配置模型会清理并校验 manager/seat ID,拒绝 manager 出现在 seat 列表、重复席位、超过
max_seats_per_run的路由和非法业务 code。
受约束的总控派活
服务端先由业务链与可信 capability snapshot 生成候选席位集合。总控模型只能返回严格 JSON:intent_type、selected_seat_agent_ids、每席 task_goal/delivery_requirements、execution_mode、convergence_path 和 reason。Pydantic schema、服务端 allowlist 和顺序校验全部通过后,最终计划才会写入 checkpoint,并产生 manager.dispatch 审计/SSE 投影。
非法席位、重复席位、空任务、错误 schema、席位超限、缺少收敛路径或链式顺序错误,统一回退到服务端安全计划,不会扩大权限或启动越权席位。
四种结构化拓扑已固定为:
direct_answer:manager-only Workflow,不创建专家席位任务;single_seat/tool_write:一个可信席位;parallel_consultation:至少两个可信席位并行;chain_consultation:按服务端业务链顺序串行。
阶段 3 验证状态
已覆盖配置校验、候选路由、非法总控计划回退、manager-only 真实 WorkflowBuilder 拓扑、线程/执行阶段回归、旧 DeerFlow 回归和会话 API 回归。当前仍不能据此标记整个 MAF 项目或阶段 5 为“验收完成”;真实 UAT 写入系统、最小权限凭据、外部核验 API、补偿协议和生产 MAF_ACTION_SECRET_KEY 仍按阶段 5/8 前置条件保持阻塞。
Stage 3 P0 dispatch correction
- New MAF conversations no longer classify user text with server keyword rules. The server first freezes only the business-route candidate set and trusted, redacted capability summary;
ManagerDispatchExecutorthen returns the strict intent-and-dispatch JSON contract. - The final plan is Pydantic-validated and allowlisted before it is checkpointed. Invalid JSON, illegal intent or seat, missing convergence, manager failure, and timeout all finish on the clarification branch; they do not create expert threads or start expert/tool work.
- A conversation initially persists and binds the manager only. After a valid decision, only
selected_seat_agent_idsare added to the participant store and receive internal threads. - Every non-clarification route, including
group_chat, starts at the same manager dispatch node. Group speakers are limited to the verified selected seats; static candidate configuration cannot bypass the plan.
阶段 4 实施记录(当前代码基线)
本轮完成阶段 4(R3-Q:席位任务合同、总控验收、打回/改派/受控缺口、阶段质量闸门)的服务端实现。范围仅限 V2 structured 派活(dispatch_contract_enabled 且 quality_gate_enabled);旧 DeerFlow、旧 roundtable、AI 写作、group_chat 与 quality 关闭的 V2 路径行为不变。
纯策略层(app/maf_roundtable/quality_contracts.py,无 I/O、无 SDK)
MafTaskContract:objective / expected_deliverable / acceptance_criteria / required / max_rework_attempts(默认 2)/ fallback_policy(reassign_then_gap/controlled_gap/ask_user),由校验后的派发 assignment 服务端冻结。- 确定性检查
check_delivery_deterministic:empty_content、schema_invalid、missing_conclusion、below_min_length、missing_evidence、duplicate_content;任一失败即不可 accept(总控模型自评不是验收证据)。 - 总控验收 schema
MafManagerReviewOutput(decision ∈ accept / return_for_rework / reassign / ask_user / controlled_gap + reason + revision_requirements),finalize_review_decision服务端终审:确定性失败永不 accept;返工受合同上限约束;改派受max_reassignments约束;耗尽后只能controlled_gap(带风险标记)或ask_user暂停,绝不伪装成功;总控输出缺失/非法时确定性降级。
持久化
- 新表
maf_roundtable_seat_tasks(model.py+seat_tasks.py+ store facade 注册):task_key 稳定(NN:agent_id),改派只变agent_id不新建任务;(run_id, task_key)唯一;状态机 CHECK(assigned/delivering/submitted/manager_review/accepted/rework/reassigned/exhausted/controlled_gap)。 maf_roundtable_seat_runs.execution_stage闭合枚举新增rework、manager_review(seat_runs 常量 + ORM CHECK + 迁移脚本同步)。- 迁移脚本
scripts/migrate_maf_roundtable_stage4.py(建表 + SQLite 重建 seat_runs 以放宽 CHECK,PG/MySQL drop+add,幂等,validate_schema)。
执行器与接线
QualitySeatTasksExecutor(id=quality_seat_tasks)替换 V2 structured 的席位 fan-out:有界质量轮(初稿 + 最多 2 次返工 + 每次改派 1 轮),每轮「交付(复用 SeatExecutor,静默 ctx 防消息重入图)→ 确定性检查 → 批处理总控验收 → 服务端终审落库」,ask_user置waiting_input;改派席位须为服务端候选且未占用其他任务(一个席位同时只承担一个任务,避免四元组冲突)。QualityGateExecutor(id=quality_gate):所有 required 任务达到 accepted / controlled_gap 终态才放行(passed/passed_with_gaps);非终态 required 任务确定性阻塞(硬失败安全网);waiting_input路由到WaitingInputTerminalExecutor(不跑 cross_review/finalizer)。- 最终报告:受控缺口注入综合 prompt 的「风险/待补信息」章节并逐条要求不得写成已验证事实;
final_result.quality_decision有缺口即为controlled_gap,final_result.controlled_gaps可追溯。 - 配置:
quality_gate_enabled(默认 True,V2 会话可用maf_v2.quality_gate_enabled显式关闭)、max_rework_attempts、max_reassignments、min_delivery_chars、min_delivery_evidence、default_fallback_policy。 - 事件:
seat.delivery.submitted、manager.review.decision(带 task_key/attempt/source)、seat.rework.assigned、seat.reassigned、stage.quality_gate;conversation 投影白名单与安全键已扩展。
测试
tests/test_maf_quality_contracts.py(34 例纯策略:合同冻结、确定性检查、验收解析、终审规则矩阵)。tests/test_maf_phase4_quality_gate.py(6 例 Runner 级端到端:好交付接受、短答→2 返工→1 改派→受控缺口(含 DB/事件/最终报告断言)、ask_user→waiting_input、质量闸门阻塞、缺失验收的确定性降级、事件落库)。tests/test_maf_migration_stage4.py(3 例迁移:建表+CHECK 放宽、幂等、旧数据保留、新阶段可写入)。- 回归:全量 MAF 测试 459 通过;
ruff check全绿。
仍按阶段 5/8 前置条件保持阻塞:真实 UAT 写入系统、最小权限凭据、外部核验 API、补偿协议和生产 MAF_ACTION_SECRET_KEY。前端对话页的质量反馈(派活卡显示尝试次数、「总控审核中」、打回/改派/缺口卡片、席位条状态区分)属阶段 7 的前端工作,尚未实施。