--- title: "feat: 私董会讨论模式(Board Meeting Mode)" type: feat status: completed created: 2026-06-17 origin: docs/brainstorms/2026-06-17-board-meeting-mode-requirements.md --- # Plan: 私董会讨论模式(Board Meeting Mode) **Origin**: `docs/brainstorms/2026-06-17-board-meeting-mode-requirements.md` **Depth**: Deep **Created**: 2026-06-17 --- ## Summary 为 Fischer AgentKit 新增私董会讨论模式,与现有 hub-and-spoke 任务分解模式并列。用户通过 `@board` 前缀触发,指定预设名人专家(如马斯克、贝佐斯、张小龙),针对决策类问题进行多轮自主循环讨论。每轮全员并行发言 + 主持人小结,达到最大轮次后主持人给出最终决策建议。整个过程以群聊形式呈现,用户可随时干预。 --- ## Problem Frame 当前专家团功能(`src/agentkit/experts/`)采用 hub-and-spoke 模式,仅支持任务分解执行,无群聊式讨论能力。且该功能未集成到主聊天流程(`chat.py:584-590` 中 `TEAM_COLLAB` 回退到 REACT)。用户希望就决策类问题召集名人专家团进行多视角讨论,获得综合建议。 **核心问题**: 1. 无预设名人专家库(`configs/experts/` 不存在) 2. 无自主循环讨论机制(现有模式是任务分解,非群聊讨论) 3. 专家团功能未集成到主聊天 WebSocket 流程 --- ## Requirements 本计划实现需求文档中的以下功能需求(FR-1 到 FR-15): - **FR-1/FR-2**: `@board` 前缀路由,与 `@team` 共存 - **FR-3**: 预设 5-8 位名人专家 YAML - **FR-4**: `ExpertConfig` 扩展(`speaking_style`、`decision_framework`) - **FR-5**: 默认私董会模板 `private_board` - **FR-6**: `BoardTeam` 容器(`BoardStatus` 生命周期) - **FR-7**: `BoardOrchestrator` 讨论引擎(开场→循环讨论→总结) - **FR-8**: 讨论历史管理(含压缩) - **FR-9**: 终止条件(最大轮次 + 用户干预 + 异常) - **FR-10/FR-11**: WebSocket 事件(5 个新事件)+ 广播 - **FR-12/FR-13/FR-14**: 前端群聊式 UI + 状态展示 + 干预输入 - **FR-15**: `agentkit.yaml` 配置项 **成功标准**(见需求文档 §7): - `@board:elon_musk,jeff_bezos 讨论主题` 能触发讨论 - 每轮专家并行发言,主持人小结 - 达到最大轮次后主持人给出最终决策建议 - 用户可随时插入消息影响讨论 - 前端以群聊形式展示 - 单元测试覆盖率 ≥ 80% --- ## Key Technical Decisions ### KTD-1: 独立模块而非扩展现有 ExpertTeam **决策**: 新建 `board.py`、`board_orchestrator.py`、`board_router.py`,不修改现有 `team.py`、`orchestrator.py`、`router.py`。 **理由**: 私董会讨论模式(多轮群聊)与 hub-and-spoke(任务分解执行)的执行流程完全不同。独立模块职责清晰,避免语义混淆,符合需求文档"新增并列模式"决策。 **复用**: `ExpertConfig`(扩展)、`Expert`(运行时包装器)、`AgentPool`、`HandoffTransport`、`SharedWorkspace`、`ExpertTemplateRegistry`。 ### KTD-2: 讨论历史结构 **决策**: 使用 `list[dict]` 结构存储讨论历史,每条记录包含 `round`、`expert_name`、`content`、`timestamp`、`role`(expert/moderator/user)。 **理由**: 简单的列表结构易于序列化和注入到 LLM prompt。主持人小结也作为历史记录,角色为 `moderator`。用户干预消息角色为 `user`。 **压缩策略**: 当历史 token 数超过阈值(默认 4000)时,主持人先压缩历史(保留每轮关键观点),再继续下一轮。压缩 prompt 在实现时细化。 ### KTD-3: 并行发言生成 **决策**: 使用 `asyncio.gather` 并行生成所有非主持人专家的发言,然后按专家列表顺序追加到历史和广播事件。 **理由**: 并行生成提高效率(5 专家并行 vs 串行)。前端展示顺序按配置顺序,即使并行生成也按顺序追加到 UI。 ### KTD-4: 主持人角色 **决策**: 主持人默认为首位专家,通过 `ExpertConfig.is_lead=True` 标识。主持人负责开场介绍、每轮小结、最终总结。 **理由**: 复用现有 `is_lead` 字段,无需引入新角色。主持人也是名人专家之一,其发言风格由其 persona 决定。 ### KTD-5: WebSocket 事件复用与扩展 **决策**: 新增 5 个事件类型(`board_started`、`expert_speech`、`round_summary`、`user_intervention`、`board_concluded`),加入现有 `_VALID_TEAM_EVENT_TYPES` 集合。复用 `emit_team_event()` 辅助函数推送。 **理由**: 现有 `emit_team_event()` 已定义但未被调用,本期同时完成其调用集成。事件类型加入现有集合,复用验证逻辑。 ### KTD-6: 配置加载 **决策**: 在 `app.py` 启动时,类似 skills 加载,从 `configs/experts/` 目录加载所有专家 YAML 到 `ExpertTemplateRegistry`,挂载到 `app.state.expert_template_registry`。 **理由**: 复用 `ExpertTemplateRegistry.load_from_directory()` 方法。与 skills 加载模式一致,保持架构一致性。 --- ## High-Level Technical Design ### 组件关系图 ```mermaid graph TB User[用户输入 @board:experts 主题] Router[BoardRouter] Registry[ExpertTemplateRegistry] Team[BoardTeam] Orchestrator[BoardOrchestrator] Expert1[Expert: 马斯克] Expert2[Expert: 贝佐斯] Expert3[Expert: 张小龙] Transport[HandoffTransport] ChatWS[chat.py WebSocket] Frontend[前端群聊 UI] User --> Router Router --> Registry Registry --> Team Team --> Orchestrator Orchestrator --> Expert1 Orchestrator --> Expert2 Orchestrator --> Expert3 Expert1 --> Transport Expert2 --> Transport Expert3 --> Transport Transport --> ChatWS ChatWS --> Frontend ``` ### 讨论流程状态机 ```mermaid stateDiagram-v2 [*] --> FORMING: @board 触发 FORMING --> DISCUSSING: 专家创建完成 DISCUSSING --> DISCUSSING: 每轮发言+小结 DISCUSSING --> CONCLUDING: 达到最大轮次/用户停止 DISCUSSING --> DISSOLVED: 异常终止 CONCLUDING --> COMPLETED: 主持人最终总结 COMPLETED --> DISSOLVED: 资源回收 DISSOLVED --> [*] ``` ### 单轮讨论时序图 ```mermaid sequenceDiagram participant O as BoardOrchestrator participant E1 as Expert 1 participant E2 as Expert 2 participant M as Moderator participant T as Transport participant WS as WebSocket O->>WS: board_started 事件 O->>M: 开场介绍请求 M->>T: 发言内容 T->>WS: expert_speech (moderator) loop 每轮讨论 par 并行生成发言 O->>E1: 发言请求(历史+角色prompt) E1-->>O: 发言内容 and O->>E2: 发言请求(历史+角色prompt) E2-->>O: 发言内容 end O->>T: 广播 E1 发言 T->>WS: expert_speech (E1) O->>T: 广播 E2 发言 T->>WS: expert_speech (E2) O->>M: 小结请求(本轮发言) M-->>O: 小结内容 O->>T: 广播小结 T->>WS: round_summary end O->>M: 最终总结请求 M-->>O: 决策建议 O->>WS: board_concluded 事件 ``` --- ## Scope Boundaries ### In Scope - `BoardTeam`、`BoardOrchestrator`、`BoardRouter` 新模块 - `configs/experts/` 预设名人 YAML(8 位) - `ExpertConfig` 扩展(`speaking_style`、`decision_framework`) - WebSocket 事件(5 个新事件)+ `emit_team_event()` 调用集成 - 前端群聊式展示增强 + 事件处理 - 主聊天流程集成(`chat.py` 接入 `BoardRouter`) - `app.py` 启动加载专家配置 - `agentkit.yaml` 配置项 - 单元测试覆盖 ### Deferred to Follow-Up Work - 集成外部蒸馏工具(colleague.skill/nuwa-skill) - LLM 自动蒸馏生成名人 SOUL - 共识检测自动终止(置信度/投票) - 技术评审/创意脑暴场景 - Expert Team Canvas 式可视化 - 专家间直接通信(辩论模式) - 语音/视频输出 - 历史讨论回顾与检索 - 修复 `@team` 在 `chat.py` 的集成缺口(独立任务) ### Outside This Product's Identity - 实时名人数据更新 - 名人本人授权或验证 - 娱乐向角色扮演 --- ## Implementation Units ### U1. 扩展 ExpertConfig 新增讨论模式字段 **Goal**: 为 `ExpertConfig` 新增 `speaking_style` 和 `decision_framework` 字段,支持名人专家的个性化表达和决策框架。 **Requirements**: FR-4 **Dependencies**: 无 **Files**: - `src/agentkit/experts/config.py` — 修改 `ExpertConfig.__init__`、`from_dict`、`to_dict` - `tests/unit/experts/test_config.py` — 新增字段测试 **Approach**: - 在 `ExpertConfig.__init__` 新增 `speaking_style: str = ""` 和 `decision_framework: str = ""` 参数 - 在 `from_dict` 中读取 `data.get("speaking_style", "")` 和 `data.get("decision_framework", "")` - 在 `to_dict` 中序列化这两个字段 - 字段有默认值,向后兼容现有 `@team` 模式和动态生成的 ExpertConfig **Patterns to follow**: 现有 `persona`、`thinking_style` 字段的实现模式(`src/agentkit/experts/config.py:35-65`) **Test scenarios**: - **Happy path**: 创建 ExpertConfig 时传入 speaking_style 和 decision_framework,验证字段值正确 - **Happy path**: 从 dict 创建 ExpertConfig,包含 speaking_style 和 decision_framework,验证字段值正确 - **Edge case**: 不传 speaking_style 和 decision_framework,验证默认值为空字符串 - **Edge case**: to_dict 输出包含 speaking_style 和 decision_framework 字段 - **Integration**: 现有 ExpertConfig 用法(不传新字段)仍正常工作 **Verification**: `pytest tests/unit/experts/test_config.py` 通过,现有测试不受影响 --- ### U2. 创建预设名人专家 YAML 库 **Goal**: 在 `configs/experts/` 目录下创建 8 位名人专家 YAML 文件,每位名人包含 persona、thinking_style、speaking_style、decision_framework 等字段。 **Requirements**: FR-3, FR-5 **Dependencies**: U1 **Files**: - `configs/experts/elon_musk.yaml` - `configs/experts/jeff_bezos.yaml` - `configs/experts/allenzhang.yaml` - `configs/experts/charlie_munger.yaml` - `configs/experts/paul_graham.yaml` - `configs/experts/steve_jobs.yaml` - `configs/experts/warren_buffett.yaml` - `configs/experts/ray_dalio.yaml` - `configs/experts/private_board.yaml` — 默认私董会模板(引用上述专家) **Approach**: - 每个 YAML 遵循 `ExpertTemplateRegistry.load_from_yaml` 的格式(见 `src/agentkit/experts/registry.py:71-87`) - 字段:`name`、`description`、`is_builtin: true`、`config`(含 `name`、`agent_type: expert`、`persona`、`thinking_style`、`speaking_style`、`decision_framework`、`avatar`、`color`、`is_lead: false`、`task_mode: llm_generate`、`prompt.identity`) - `private_board.yaml` 是一个特殊的"团队模板",定义默认专家组合(3-5 位),格式为 `name: private_board`、`members: [elon_musk, jeff_bezos, allenzhang, charlie_munger, paul_graham]` - 名人 persona 内容需体现其标志性思维模式: - 马斯克:第一性原理、物理思维、激进创新 - 贝佐斯:Day 1 思维、客户至上、长期主义 - 张小龙:用户体验、极简主义、社交产品直觉 - 芒格:心智模型、跨学科思维、逆向思考 - Paul Graham:创业、做用户想要的东西、反从众 - 乔布斯:产品设计、现实扭曲力场、专注 - 巴菲特:价值投资、能力圈、复利思维 - Ray Dalio:原则驱动决策、极度透明 **Patterns to follow**: `src/agentkit/experts/registry.py:71-87` 的 YAML 格式示例 **Test scenarios**: - **Test expectation**: none — YAML 配置文件,由 U9 的集成测试覆盖加载逻辑 **Verification**: `ExpertTemplateRegistry.load_from_directory("configs/experts/")` 能成功加载所有 8 位专家 + 1 个团队模板 --- ### U3. 实现 BoardRouter @board 前缀路由 **Goal**: 实现 `BoardRouter` 类,解析 `@board` 前缀,支持指定专家或使用默认私董会模板。 **Requirements**: FR-1, FR-2 **Dependencies**: U1, U2 **Files**: - `src/agentkit/experts/board_router.py` — 新建 - `tests/unit/experts/test_board_router.py` — 新建 **Approach**: - 参考 `ExpertTeamRouter`(`src/agentkit/experts/router.py`)的实现模式 - 正则匹配 `@board` 前缀:`^@board(?::(\S+))?\s*(.*)` - 支持两种格式: - `@board:elon_musk,jeff_bezos 讨论主题` — 指定专家 - `@board 讨论主题` — 使用默认 `private_board` 模板 - 专家名验证:复用 `_EXPERT_NAME_RE = re.compile(r"^[a-zA-Z0-9_-]{1,64}$")` - 最多 10 位专家(`MAX_EXPERTS = 10`) - 返回 `BoardRoutingResult` dataclass:`matched`、`board_mode`、`specified_experts`、`topic`、`use_default_template` - `resolve_expert_configs()` 方法:从 `ExpertTemplateRegistry` 解析专家名到 `ExpertConfig` 列表,首位设为 `is_lead=True`(主持人) - 如果指定 `private_board`,从 `private_board.yaml` 加载成员列表 - 未识别的专家名:记录警告,动态创建基本 ExpertConfig **Patterns to follow**: `src/agentkit/experts/router.py` 的 `ExpertTeamRouter` 实现 **Test scenarios**: - **Happy path**: `@board:elon_musk,jeff_bezos 讨论主题` → matched=True, specified_experts=["elon_musk", "jeff_bezos"], topic="讨论主题" - **Happy path**: `@board 讨论主题` → matched=True, use_default_template=True, topic="讨论主题" - **Happy path**: `@board:private_board 讨论主题` → matched=True, 加载 private_board 成员列表 - **Edge case**: `@board` 无主题 → matched=True, topic 为空 - **Edge case**: 专家名超过 10 个 → 截断到 10 个 - **Error path**: 无效专家名(含特殊字符)→ 过滤掉无效名,记录警告 - **Error path**: 指定不存在的专家 → 动态创建基本 ExpertConfig - **Integration**: `resolve_expert_configs()` 返回的列表首位 is_lead=True **Verification**: `pytest tests/unit/experts/test_board_router.py` 通过 --- ### U4. 实现 BoardTeam 容器 **Goal**: 实现 `BoardTeam` 容器,管理私董会的专家生命周期、讨论状态和事件广播。 **Requirements**: FR-6, FR-8 **Dependencies**: U1 **Files**: - `src/agentkit/experts/board.py` — 新建(`BoardTeam`、`BoardStatus`、`DiscussionHistory`) - `tests/unit/experts/test_board.py` — 新建 **Approach**: - 参考 `ExpertTeam`(`src/agentkit/experts/team.py`)的容器模式 - `BoardStatus` 枚举:`FORMING` → `DISCUSSING` → `CONCLUDING` → `COMPLETED` → `DISSOLVED` - `BoardTeam` 持有: - `team_id`、`topic`、`experts: dict[str, Expert]`、`moderator_name: str` - `history: list[dict]` — 讨论历史(每条含 round、expert_name、content、timestamp、role) - `current_round: int`、`max_rounds: int` - `_handoff_transport`、`_workspace`、`_pool`、`_team_channel` - `create_board()` 方法:创建主持人和成员专家,注入 board_context 到 system prompt - `_build_board_context()` 方法:构建私董会上下文(强调群聊讨论模式、角色差异、讨论规则) - `add_to_history()` 方法:追加发言到历史 - `get_history_text()` 方法:返回格式化的历史文本用于 LLM prompt - `compress_history()` 方法:主持人压缩历史(超过阈值时) - `broadcast_user_message()` 方法:广播用户干预消息 - `dissolve()` 方法:解散团队,回收资源 - 复用 `Expert.create()`、`HandoffTransport`、`SharedWorkspace` **Patterns to follow**: `src/agentkit/experts/team.py` 的 `ExpertTeam` 容器模式 **Technical design** (directional): ```python class BoardStatus(str, enum.Enum): FORMING = "forming" DISCUSSING = "discussing" CONCLUDING = "concluding" COMPLETED = "completed" DISSOLVED = "dissolved" class BoardTeam: async def create_board(self, topic: str, expert_configs: list[ExpertConfig], max_rounds: int) -> None async def add_to_history(self, round: int, expert_name: str, content: str, role: str) -> None def get_history_text(self, up_to_round: int | None = None) -> str async def compress_history(self, moderator: Expert) -> None async def broadcast_user_message(self, content: str) -> None async def dissolve(self) -> None ``` **Test scenarios**: - **Happy path**: `create_board()` 创建主持人和成员,状态变为 DISCUSSING - **Happy path**: `add_to_history()` 追加发言,`get_history_text()` 返回格式化文本 - **Edge case**: 空历史时 `get_history_text()` 返回空字符串 - **Edge case**: `compress_history()` 超过阈值时压缩,未超过时不操作 - **Integration**: `broadcast_user_message()` 通过 handoff_transport 发送事件 - **Integration**: `dissolve()` 清理所有专家,状态变为 DISSOLVED - **Error path**: 未配置 AgentPool 时 `create_board()` 抛出 RuntimeError **Verification**: `pytest tests/unit/experts/test_board.py` 通过 --- ### U5. 实现 BoardOrchestrator 讨论引擎 **Goal**: 实现 `BoardOrchestrator`,驱动私董会讨论流程:开场 → 多轮并行发言 + 主持人小结 → 最终决策建议。 **Requirements**: FR-7, FR-9 **Dependencies**: U4 **Files**: - `src/agentkit/experts/board_orchestrator.py` — 新建 - `tests/unit/experts/test_board_orchestrator.py` — 新建 **Approach**: - 参考 `TeamOrchestrator`(`src/agentkit/experts/orchestrator.py`)的执行引擎模式 - `execute(topic)` 主入口流程: 1. 广播 `board_started` 事件 2. 主持人开场介绍(介绍议题、讨论规则) 3. 循环 `max_rounds` 轮: - 并行生成所有非主持人专家发言(`asyncio.gather`) - 每个专家发言基于:角色 persona + thinking_style + speaking_style + decision_framework + 完整讨论历史 + 当前轮次/最大轮次 - 按专家列表顺序广播 `expert_speech` 事件 - 主持人小结本轮要点,广播 `round_summary` 事件 - 检查用户干预消息(通过 handoff_transport 或共享状态) - 检查历史 token 长度,超过阈值时压缩 4. 主持人最终总结(决策建议、共识点、分歧点),广播 `board_concluded` 事件 - `_generate_expert_speech()` 方法:构建专家发言 prompt,调用 LLM - `_generate_moderator_summary()` 方法:构建主持人小结 prompt,调用 LLM - `_generate_final_conclusion()` 方法:构建最终总结 prompt,调用 LLM - `_check_user_intervention()` 方法:检查是否有用户干预消息 - `_handle_stop_command()` 方法:处理用户 `/stop` 命令 - 复用 `_get_llm_gateway()` 和 `_broadcast_event()` 模式(来自 TeamOrchestrator) - 异常处理:LLM 不可用时,主持人用已有历史总结;所有专家发言失败时,提前进入总结阶段 **Patterns to follow**: `src/agentkit/experts/orchestrator.py` 的 `TeamOrchestrator` 执行模式 **Technical design** (directional): ```python class BoardOrchestrator: def __init__(self, team: BoardTeam) -> None async def execute(self, topic: str) -> dict[str, Any] # Returns: {status, summary, decision_advice, total_rounds, consensus_points, dissent_points} async def _generate_expert_speech(self, expert: Expert, round: int) -> str async def _generate_moderator_summary(self, round: int) -> str async def _generate_final_conclusion(self) -> dict[str, Any] async def _check_user_intervention(self) -> str | None ``` **Test scenarios**: - **Happy path**: `execute()` 完成完整讨论流程,返回 status="completed" - **Happy path**: 每轮生成 N-1 个专家发言 + 1 个主持人小结 - **Happy path**: 最终总结包含 decision_advice、consensus_points、dissent_points - **Edge case**: max_rounds=1 时,只进行一轮讨论后直接总结 - **Edge case**: 用户发送 `/stop` → 提前终止,用已有历史总结 - **Error path**: LLM 不可用 → 主持人用已有历史拼接总结 - **Error path**: 某专家发言失败 → 跳过该专家,其他专家继续 - **Error path**: 所有专家发言失败 → 提前进入总结阶段 - **Integration**: `board_started`、`expert_speech`、`round_summary`、`board_concluded` 事件正确广播 **Verification**: `pytest tests/unit/experts/test_board_orchestrator.py` 通过 --- ### U6. 后端集成 BoardRouter 到主聊天流程 **Goal**: 在 `chat.py` 的 WebSocket 处理中接入 `BoardRouter`,实现 `@board` 前缀触发私董会讨论,并通过 `emit_team_event()` 推送事件到前端。 **Requirements**: FR-1, FR-10, FR-11, FR-15 **Dependencies**: U3, U5 **Files**: - `src/agentkit/server/routes/chat.py` — 修改 `_handle_chat_message`,接入 `BoardRouter` - `src/agentkit/server/app.py` — 启动时加载 `configs/experts/`,挂载 `expert_template_registry` 和 `board_config` 到 `app.state` - `src/agentkit/server/config.py` — 新增 `board` 配置项(max_rounds、default_template、parallel_speech、history_compression_threshold) - `tests/unit/server/test_chat_board_integration.py` — 新建 **Approach**: - 在 `app.py` 启动时(参考 skills 加载逻辑 `app.py:261-282`): - 创建 `ExpertTemplateRegistry` 实例 - 调用 `load_from_directory("configs/experts/")` 加载所有专家 YAML - 挂载到 `app.state.expert_template_registry` - 从 `agentkit.yaml` 读取 `board` 配置,挂载到 `app.state.board_config` - 在 `chat.py` 的 `_handle_chat_message` 中: - 在 `RequestPreprocessor` 之前,检查 `@board` 前缀 - 如果匹配 `@board`,创建 `BoardRouter`,解析路由 - 创建 `BoardTeam` 和 `BoardOrchestrator` - 注册 `handoff_transport` 的 handler,将事件转发到 WebSocket(调用 `emit_team_event()`) - 调用 `orchestrator.execute(topic)` - 将最终结果作为 `final_answer` 发送 - 扩展 `_VALID_TEAM_EVENT_TYPES`:新增 `board_started`、`expert_speech`、`round_summary`、`user_intervention`、`board_concluded` - 用户干预处理:讨论进行中,如果用户发送新消息(非 `/stop`),通过 `board_team.broadcast_user_message()` 广播 **Patterns to follow**: - skills 加载模式:`src/agentkit/server/app.py:261-282` - `emit_team_event()` 辅助函数:`src/agentkit/server/routes/chat.py:117-142` **Test scenarios**: - **Happy path**: `@board:elon_musk,jeff_bezos 讨论主题` → 触发 BoardRouter,创建 BoardTeam,执行讨论 - **Happy path**: 讨论事件通过 `emit_team_event()` 推送到 WebSocket - **Happy path**: `@board 讨论主题` → 使用默认 private_board 模板 - **Edge case**: 讨论中用户发送消息 → 广播为 user_intervention - **Edge case**: 讨论中用户发送 `/stop` → 终止讨论 - **Integration**: `app.state.expert_template_registry` 在启动时正确加载 - **Integration**: `@board` 与 `@team` 和普通聊天互不干扰 **Verification**: `pytest tests/unit/server/test_chat_board_integration.py` 通过;手动测试 `@board` 触发讨论 --- ### U7. 前端事件类型和处理扩展 **Goal**: 在前端 TypeScript 类型和 Pinia store 中新增私董会事件类型和处理逻辑。 **Requirements**: FR-10, FR-12, FR-13 **Dependencies**: U6 **Files**: - `src/agentkit/server/frontend/src/api/types.ts` — 新增 board 事件类型和接口 - `src/agentkit/server/frontend/src/stores/chat.ts` — 新增 board 事件处理 - `src/agentkit/server/frontend/src/stores/team.ts` — 新增 board 状态管理(可选,或新建 `stores/board.ts`) **Approach**: - 在 `types.ts` 中: - 新增 `WsServerMessage` 联合类型成员:`board_started`、`expert_speech`、`round_summary`、`user_intervention`、`board_concluded` - 新增 `IBoardState` 接口:`team_id`、`topic`、`experts`、`moderator_name`、`current_round`、`max_rounds`、`status` - 新增 `IBoardSpeech` 接口:`expert_name`、`expert_avatar`、`expert_color`、`content`、`round`、`role` - 在 `chat.ts` 的 `handleWsMessage` 中新增 case: - `board_started`: 创建 board 状态,推送步骤提示 - `expert_speech`: 创建专家消息(带头像、颜色、轮次标识),追加到消息列表 - `round_summary`: 创建主持人小结消息(特殊样式,message_type='milestone') - `user_intervention`: 标记用户消息已广播 - `board_concluded`: 创建总结消息(含决策建议、共识点、分歧点) - 参考 `chat.ts:554-646` 的现有 team 事件处理模式 **Patterns to follow**: `src/agentkit/server/frontend/src/stores/chat.ts:554-646` 的 team 事件处理 **Test scenarios**: - **Test expectation**: none — 前端 TypeScript 类型,由 U8 的组件测试和手动测试覆盖 **Verification**: `npm run typecheck` 通过 --- ### U8. 前端群聊式 UI 增强 **Goal**: 增强 `ExpertMessage.vue` 组件,新增讨论状态展示,实现群聊式体验。 **Requirements**: FR-12, FR-13, FR-14 **Dependencies**: U7 **Files**: - `src/agentkit/server/frontend/src/components/chat/ExpertMessage.vue` — 增强(新增轮次标识、角色标签) - `src/agentkit/server/frontend/src/components/chat/BoardStatusView.vue` — 新建(讨论状态展示) - `src/agentkit/server/frontend/src/views/ChatView.vue` — 集成 BoardStatusView **Approach**: - 增强 `ExpertMessage.vue`: - 新增 props:`round?: number`、`role?: 'expert' | 'moderator' | 'user'` - 显示轮次标识(如"第 2 轮") - 主持人消息特殊样式(背景色、边框) - 用户干预消息右侧气泡展示 - 新建 `BoardStatusView.vue`: - 顶部显示:讨论主题、当前轮次/最大轮次、参与专家列表(头像、名称、角色标签) - 专家列表可点击查看其所有发言 - 讨论结束后展示总结卡片(决策建议、共识点、分歧点) - 在 `ChatView.vue` 中: - 当 board 状态激活时,渲染 ``(类似现有 ``) **Patterns to follow**: - `src/agentkit/server/frontend/src/components/chat/ExpertMessage.vue` 现有组件 - `src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue` 团队视图 - `src/agentkit/server/frontend/src/views/ChatView.vue:19` 的 ExpertTeamView 集成 **Test scenarios**: - **Test expectation**: none — Vue 组件,由手动测试覆盖 **Verification**: `npm run typecheck` 通过;手动测试 `@board` 触发讨论,前端正确展示群聊 --- ### U9. 单元测试覆盖 **Goal**: 为所有新增模块编写单元测试,确保覆盖率 ≥ 80%。 **Requirements**: 成功标准 §7.1 **Dependencies**: U1-U8 **Files**: - `tests/unit/experts/test_config.py` — 扩展(U1 新字段测试) - `tests/unit/experts/test_board_router.py` — 新建(U3) - `tests/unit/experts/test_board.py` — 新建(U4) - `tests/unit/experts/test_board_orchestrator.py` — 新建(U5) - `tests/unit/server/test_chat_board_integration.py` — 新建(U6) **Approach**: - 使用 `pytest` + `pytest-asyncio`(asyncio_mode=auto) - Mock `LLMGateway`、`AgentPool`、`HandoffTransport` 进行隔离测试 - 测试覆盖: - 配置字段序列化/反序列化 - 路由解析各种格式 - BoardTeam 生命周期和状态转换 - BoardOrchestrator 讨论流程(正常、异常、用户干预) - chat.py 集成(@board 触发、事件广播) - 测试标记:单元测试无特殊标记,集成测试标记 `@pytest.mark.integration` **Patterns to follow**: - `tests/unit/experts/test_team_orchestrator.py` 的测试模式 - `tests/unit/experts/test_router.py` 的路由测试模式 **Test scenarios**: - 见各实现单元的测试场景 **Verification**: `pytest tests/unit/experts/ tests/unit/server/test_chat_board_integration.py -v` 全部通过;`pytest --cov=src/agentkit/experts --cov-report=term-missing` 覆盖率 ≥ 80% --- ## Risks & Dependencies ### Risks | 风险 | 影响 | 缓解 | |------|------|------| | 专家发言同质化 | 讨论质量低 | 强化角色 prompt 差异化,`decision_framework` 字段强制不同视角 | | token 消耗过高(5轮×5专家=25次调用) | 成本问题 | 提供轮次配置,历史压缩机制 | | 讨论发散无结论 | 用户体验差 | 主持人每轮小结,最终强制总结 | | 名人 persona 不准确 | 发言不像本人 | YAML 可迭代优化,未来支持蒸馏 | | `chat.py` 集成复杂度高 | 可能破坏现有聊天 | `@board` 路由在 `RequestPreprocessor` 之前检查,不影响普通聊天 | | 前端事件处理与现有 team 事件冲突 | UI 错乱 | 事件类型独立(board_* vs team_*),store 独立 | ### Dependencies - **现有基础设施**: `Expert`、`AgentPool`、`HandoffTransport`、`SharedWorkspace`、`ExpertTemplateRegistry` - **LLM Gateway**: `src/agentkit/llm/gateway.py` 提供多 provider 支持 - **WebSocket**: `src/agentkit/server/routes/chat.py` 现有 WebSocket 通道 - **前端组件**: `ExpertMessage.vue`、`ChatView.vue`、`stores/chat.ts` --- ## System-Wide Impact ### 影响方 - **终端用户**: 获得私董会讨论能力,可就决策类问题获得多视角建议 - **开发者**: 新增 `@board` 路由模式,需了解与 `@team` 的区别 - **配置管理**: 新增 `configs/experts/` 目录和 `agentkit.yaml` 的 `board` 配置项 - **前端**: 新增 board 事件处理和 UI 组件 ### 兼容性 - `ExpertConfig` 新增字段有默认值,向后兼容 - `@board` 路由独立,不影响 `@team` 和普通聊天 - `_VALID_TEAM_EVENT_TYPES` 扩展是增量式,不影响现有事件 - 前端事件处理新增 case,不影响现有 case --- ## Open Questions 1. **历史压缩 prompt 具体设计** — 超过 token 阈值时,主持人如何压缩历史? - **决策**: 实现时细化,初步思路是让主持人总结每轮关键观点,替换原始发言。 2. **用户干预消息的实时性** — 用户发送干预后,当前轮次是否立即中断? - **决策**: 不中断当前轮次,干预消息在下一轮生效。避免复杂的中断逻辑。 3. **private_board 模板格式** — 如何在 YAML 中定义"团队模板"(引用多个专家)? - **决策**: `private_board.yaml` 使用 `members: [expert1, expert2, ...]` 字段,`BoardRouter` 解析时加载成员配置。 4. **讨论历史持久化** — 讨论结束后是否保存到数据库? - **决策**: 本期不持久化,仅保存到 SharedWorkspace。未来可扩展。 --- ## Sources & Research - **需求文档**: `docs/brainstorms/2026-06-17-board-meeting-mode-requirements.md` - **现有实现**: `src/agentkit/experts/` 目录所有文件 - **对标产品**: Qoder Experts Mode、WorkBuddy、Legends MCP、colleague.skill(详见需求文档 §1.2) - **架构参考**: AgentVerse 通信框架、ARMOR-MAD 协议阈值终止 --- **Next Step**: 交由 `/ce-work` 执行实现,或由开发者按 U1-U9 顺序逐步实现。