fischer-agentkit/docs/plans/2026-06-17-001-feat-board-m...

690 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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/` 预设名人 YAML8 位)
- `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 状态激活时,渲染 `<BoardStatusView />`(类似现有 `<ExpertTeamView />`
**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 顺序逐步实现。