---
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 顺序逐步实现。