diff --git a/docs/multi_agent_mode/01_overview.md b/docs/multi_agent_mode/01_overview.md new file mode 100644 index 0000000..f02193b --- /dev/null +++ b/docs/multi_agent_mode/01_overview.md @@ -0,0 +1,227 @@ +# 多智能体模式总体架构 + +> 文档状态:设计草案 +> 适用范围:宿主机模式(host mode),不覆盖 docker/web 模式 +> 隔离原则:与现有对话系统完全隔离,复用底层能力但上层独立 + +--- + +## 1. 设计目标 + +在 Astrion 中引入一个实验性的「多智能体模式」: + +- 主智能体固定扮演 **Team Leader**,负责任务拆解、调度、协调、回答子智能体提问。 +- 支持预置角色与自定义角色,每个角色可以有多个实例(`RoleName_1`、`RoleName_2`)。 +- 子智能体之间、子智能体与主智能体之间可以双向通信。 +- 所有通信遵循统一的消息格式与路由规则。 +- 与现有单智能体模式完全隔离,不影响现有代码与用户体验。 + +--- + +## 2. 核心设计原则 + +### 2.1 完全隔离 + +- 数据目录隔离:`~/.astrion/astrion/host/mutiagents/` +- 页面隔离:新页面 `/multiagent/new` +- 入口隔离:登录页单独按钮「多智能体模式 beta」 +- 代码隔离:所有新增代码放在 `modules/multi_agent/`、`docs/multi_agent_mode/`、`static/src/views/MultiAgentView.vue` 等独立位置 +- 现有文件如需改造,优先复制一份再改,不直接修改 + +### 2.2 能复用则复用 + +- 模型调用:复用 `DeepSeekClient` +- 工具执行链路:复用 `WebTerminal.handle_tool_call` 的底层执行能力 +- 文件/终端/搜索等工具:复用现有工具实现 +- 对话持久化格式:复用 `ConversationManager` 的存储格式 +- 沙箱/权限机制:复用现有 `evaluate_tool_permission` 与宿主机沙箱 + +### 2.3 子智能体即完整对话 + +每个子智能体是一个独立的、完整的对话上下文: + +- 有自己的 `messages` 列表 +- 有自己的系统提示词 +- 有自己的工具列表 +- 自然输出 assistant 消息 +- 支持被主智能体/其他子智能体在运行中插入消息引导 +- 任务结束 = 本轮自然停止输出,但上下文保留 + +--- + +## 3. 角色与实例 + +### 3.1 角色(Role) + +角色由 Markdown + YAML Frontmatter 定义,存储在: + +``` +~/.astrion/astrion/host/mutiagents/agents/.md +``` + +示例 `ui-operator.md`: + +```markdown +--- +id: ui-operator +name: UI Operator +description: 负责前端设计、UI 还原、配色方案 +model: qwen3-max +thinking_mode: fast +--- + +你是团队的前端设计专家。你擅长: +- 根据需求设计 UI 界面 +- 制定配色方案 +- 输出设计文档和前端代码 + +工作风格: +- 先分析需求,再给出设计方案 +- 输出简洁明确的设计说明 +``` + +### 3.2 实例(Agent) + +- `role_id`:角色类型,如 `ui-operator` +- `agent_id`:这个角色的第几个实例,从 1 开始 +- 显示名:`{Role Name}_{agent_id}`,如 `UI Operator_1`、`Full-Stack Engineer_1` +- 同一个 `role_id` 可以有多个实例:UI Operator_1、UI Operator_2 +- 不同 `role_id` 的实例序号独立:Full-Stack Engineer_1 与 UI Operator_1 可以同时存在 +- 主智能体固定显示名为 `Team Leader`,没有 agent_id + +--- + +## 4. 总体架构图 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 用户(Web 前端) │ +│ /multiagent/new 页面 │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ MultiAgentTerminal │ +│ (基于 MainTerminal 复制改造) │ +│ - 工具列表:主工具 + 多智能体专用工具 │ +│ - 子智能体管理器:MultiAgentSubAgentManager │ +│ - 对话存储:指向 mutiagents/conversations/ │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌─────────────────┼─────────────────┐ + ▼ ▼ ▼ + ┌──────────┐ ┌──────────┐ ┌──────────┐ + │ Agent 1 │ │ Agent 2 │ │ Agent 3 │ + │UIOperator│ │ Full- │ │ Code │ + │ 1 │ │ Stack │ │ Reviewer │ + │ │ │Engineer1│ │ 1 │ + └──────────┘ └──────────┘ └──────────┘ + │ │ │ + └─────────────────┴─────────────────┘ + │ + ▼ + ┌───────────────────────────────┐ + │ MessageRouter │ + │ 根据接收方状态决定: │ + │ - inline 插入工具结果后 │ + │ - 空闲时作为 user 消息触发新任务│ + └───────────────────────────────┘ +``` + +--- + +## 5. 主智能体职责 + +主智能体 = Team Leader,其系统提示词中明确: + +- 除非任务极其简单或明确不需要,否则主动拆解任务并调用子智能体。 +- 为每个子任务选择最合适的角色(role_id)。 +- 子智能体可以向你提问,你必须及时通过 `answer_sub_agent_question` 回答。 +- 子智能体之间可以互相沟通,你负责监督整体进度。 +- 如果子智能体的中间输出需要干预,使用 `send_message_to_sub_agent` 引导。 + +--- + +## 6. 子智能体职责 + +子智能体系统提示词由两部分组成: + +1. **基础 prompt**:通用团队规则 +2. **自定义 prompt**:角色专属设定 + +基础 prompt 中明确: + +- 你是智能体集群团队的一员。 +- 不要频繁输出内容,不重要内容会污染主智能体上下文。 +- 只汇报关键步骤。 +- 任务完成后给出详细结论。 +- 需要主智能体决策时,使用 `ask_master`。 +- 需要与其他子智能体沟通时,使用 `ask_other_agent` / `answer_other_agent`。 +- 如果向其他子智能体提问,必须同时直接向主智能体输出汇报。 + +--- + +## 7. 与现有系统的边界 + +| 现有系统 | 多智能体模式处理方式 | +|---------|---------------------| +| 现有对话页面 | 不改动,新增 `/multiagent/new` | +| 现有 `MainTerminal` | 不改动,复制为 `MultiAgentTerminal` | +| 现有 `SubAgentManager` | 不改动,继承创建 `MultiAgentSubAgentManager` | +| 现有 `SubAgentTask` | 不改动,继承创建 `MultiAgentSubAgentTask` | +| 现有 `ConversationManager` | 不改动,多智能体模式用自己的存储目录 | +| 现有后台通知池机制 | 参考其设计,多智能体模式实现自己的消息路由 | +| 现有工具执行链路 | 复用 `execute_tool_for_sub_agent` | +| 现有沙箱/权限 | 复用,不额外限制子智能体工具参数 | + +--- + +## 8. 入口与数据目录 + +### 8.1 入口 + +登录页面增加按钮:「多智能体模式 beta」。 + +点击后进入 `/multiagent/new` 页面,加载 `MultiAgentTerminal`。 + +### 8.2 数据目录 + +``` +~/.astrion/astrion/host/mutiagents/ +├── agents/ # 角色定义 +├── conversations/ # 多智能体会话 +│ └── / +│ ├── metadata.json +│ ├── messages.json # Team Leader 对话 +│ └── agents/ +│ └── / +│ ├── metadata.json +│ └── messages.json # 子智能体完整对话记录 +└── state.json # 全局状态 +``` + +子智能体对话记录的保存精度、时机、格式与主智能体对话记录一致。 + +--- + +## 9. 实现顺序(非严格 phase) + +1. 创建独立目录与数据存储结构 +2. 实现角色配置加载与预置角色 +3. 实现 `MultiAgentSubAgentTask` / `MultiAgentSubAgentManager` +4. 实现 `MultiAgentTerminal` 与多智能体工具定义 +5. 实现消息路由(inline / idle / 通知池) +6. 实现前端 `/multiagent/new` 页面 +7. 登录页加入口按钮 +8. 联调测试 + +--- + +## 10. 相关文档 + +- `02_message_protocol.md`:统一消息格式 +- `03_tool_definitions.md`:工具定义 +- `04_message_routing.md`:消息路由机制 +- `05_data_model.md`:数据模型 +- `06_implementation_plan.md`:实现细节 +- `07_existing_code_analysis.md`:现有代码分析 diff --git a/docs/multi_agent_mode/02_message_protocol.md b/docs/multi_agent_mode/02_message_protocol.md new file mode 100644 index 0000000..44c5863 --- /dev/null +++ b/docs/multi_agent_mode/02_message_protocol.md @@ -0,0 +1,249 @@ +# 多智能体模式消息协议 + +> 所有插入对话的 user 消息必须遵循统一格式。 +> 不使用 `[系统通知|xxx]` 前缀,改用自然语言前缀。 + +--- + +## 1. 消息格式模板 + +所有通信 user 消息都使用以下结构: + +``` +来自 {显示名} 的{消息类型} +id: {消息id} + +<{显示名}> +<{标签}> +{内容} + + +``` + +### 字段说明 + +| 字段 | 说明 | 示例 | +|------|------|------| +| 显示名 | `{Role Name}_{agent_id}` 或 `Team Leader` | `UI Operator_1`、`Full-Stack Engineer_1` | +| 消息类型 | 任务发布 / 任务进度输出 / 任务完成汇报 / 提问 / 消息 / 回答 | 见下表 | +| 消息id | 本次消息的全局唯一标识,用于 answer 时引用 | `ask_fse_001`、`msg_uio_003` | +| 标签 | Task / Output / Ask / Message / Answer | 与消息类型对应 | +| 内容 | 消息正文 | 任意文本 | + +### 消息类型与标签对应表 + +| 消息类型 | 标签 | 发送方 | 接收方 | +|---------|------|--------|--------| +| 任务发布 | `` | Team Leader | 子智能体 | +| 任务进度输出 | `` | 子智能体 | Team Leader | +| 任务完成汇报 | `` | 子智能体 | Team Leader | +| 提问 | `` | 子智能体 | Team Leader / 其他子智能体 | +| 消息 | `` | Team Leader / 子智能体 | 子智能体 | +| 回答 | `` | 子智能体 | 子智能体(返回到 ask 工具结果) | + +--- + +## 2. 主智能体 → 子智能体 + +### 2.1 任务发布 + +当主智能体通过 `create_sub_agent` 或 `send_message_to_sub_agent` 向子智能体发布任务时使用。 + +``` +来自 Team Leader 的任务发布 +id: task_001 + + + +请为项目设计前端配色方案,输出 design.md 到 sub_agent_results/design/。 + + +``` + +### 2.2 后续消息 / 运行中引导 + +当主智能体在子智能体运行期间通过 `send_message_to_sub_agent` 插入引导消息时使用。 + +``` +来自 Team Leader 的消息 +id: msg_tl_002 + + + +先不要创建 API,先确认一下现有的 auth 模块是否可复用。 + + +``` + +### 2.3 主智能体问子智能体(ask_sub_agent) + +当主智能体通过 `ask_sub_agent` 向子智能体提问时使用。 + +``` +来自 Team Leader 的提问 +id: ask_tl_001 + + + +你预计还需要多久完成? + + +``` + +子智能体的回答返回到 `ask_sub_agent` 工具结果中,不插入主智能体对话。 + +--- + +## 3. 子智能体 → 主智能体 + +### 3.1 任务进度输出 + +子智能体在自然输出中汇报进度时,由后端捕获并插入主智能体对话。 + +``` +来自 UI Operator_1 的任务进度输出 +id: out_uio_001 + + + +我现在开始分析现有设计风格和用户需求... + + +``` + +### 3.2 任务完成汇报 + +子智能体本轮自然结束输出时,最后一条输出作为完成汇报插入主智能体对话。 + +``` +来自 UI Operator_1 的任务完成汇报 +id: out_uio_002 + + + +我完成了前端配色的设计,生成了 design.md,主色调为蓝色系。 + + +``` + +**注意**:子智能体不调用 `report_progress` 或 `finish_task` 工具。自然的 assistant 输出即表示进度或完成。 + +### 3.3 子智能体向主智能体提问 + +子智能体通过 `ask_master` 工具向主智能体提问。 + +``` +来自 Full-Stack Engineer_1 的提问 +id: ask_fse_001 + + + +我该怎么处理版本冲突问题?项目里当前用的是什么分支策略? + + +``` + +主智能体通过 `answer_sub_agent_question` 工具回答,回答内容返回到 `ask_master` 工具结果中。 + +--- + +## 4. 子智能体 → 子智能体 + +### 4.1 A 向 B 提问 + +子智能体 A 通过 `ask_other_agent` 向子智能体 B 提问。 + +``` +来自 UI Operator_1 的提问 +id: ask_uio_001 + + + +API 接口已经确定了吗?我需要接口字段来设计表单。 + + +``` + +这条消息插入到 B 的 user 消息中。 + +### 4.2 B 回答 A + +子智能体 B 通过 `answer_other_agent` 回答 A。 + +``` +来自 Full-Stack Engineer_1 的回答 +id: ans_fse_001 + + + +已经确定,见 api.md。用户注册接口为 POST /api/users,字段为... + + +``` + +回答返回到 A 的 `ask_other_agent` 工具结果中。 + +### 4.3 A 向 B 发送普通消息 + +子智能体 A 通过 `ask_other_agent` 问 B,但内容不是需要回答的问题,而是通知。 + +``` +来自 UI Operator_1 的消息 +id: msg_uio_003 + + + +前端页面已经 ready,可以开始对接了。 + + +``` + +B 可以直接通过自然输出回复,回复会返回到 A 的 `ask_other_agent` 工具结果中。 + +--- + +## 5. ID 生成规则 + +| 消息类型 | ID 前缀 | 示例 | +|---------|---------|------| +| 任务发布 | `task_` | `task_001` | +| 任务进度输出 | `out_` | `out_uio_001` | +| 任务完成汇报 | `out_` | `out_uio_002` | +| 子智能体问主智能体 | `ask_` | `ask_fse_001` | +| 主智能体问子智能体 | `ask_` | `ask_tl_001` | +| 子智能体间提问 | `ask_` | `ask_uio_001` | +| 子智能体间回答 | `ans_` | `ans_fse_001` | +| 普通消息 | `msg_` | `msg_tl_002` | + +ID 需要保证在多智能体会话内全局唯一。 + +--- + +## 6. 前端渲染 + +前端消息气泡只显示三部分: + +1. 角色:如 `UI Operator_1` +2. 目的/动作:如 `任务进度输出`、`提问`、`消息` +3. 内容:XML 标签内的文本 + +不显示 XML 标签本身。 + +示例渲染: + +``` +┌────────────────────────────────────┐ +│ UI Operator_1 任务进度输出 │ +│ │ +│ 我现在开始分析现有设计风格... │ +└────────────────────────────────────┘ +``` + +--- + +## 7. 关键约束 + +1. 所有插入对话的 user 消息都必须包含完整的 XML 包裹,便于后端解析和前端渲染。 +2. `id` 放在 XML 外面,不放在 `<>` 属性中。 +3. 子智能体之间的通信不强制同步到主智能体,但子智能体必须在提示词中被要求:向其他子智能体提问时,必须同时直接向主智能体输出汇报。 +4. 回答类消息(`answer_sub_agent_question`、`answer_other_agent`)不插入 user 消息,只返回到对应 ask 工具的结果中。 diff --git a/docs/multi_agent_mode/03_tool_definitions.md b/docs/multi_agent_mode/03_tool_definitions.md new file mode 100644 index 0000000..e2c7f4f --- /dev/null +++ b/docs/multi_agent_mode/03_tool_definitions.md @@ -0,0 +1,470 @@ +# 多智能体模式工具定义 + +> 主智能体工具基于现有主智能体工具,移除旧版子智能体工具,新增多智能体专用工具。 +> 子智能体工具保留现有 8 个基础工具,新增多智能体通信工具。 +> 所有工具定义集中在 `modules/multi_agent/tools/` 目录下,不修改现有 `core/main_terminal_parts/tools_definition/`。 + +--- + +## 1. 主智能体(Team Leader)工具 + +主智能体 = Team Leader,其工具列表 = 现有主智能体工具(去掉旧版子智能体工具) + 多智能体专用工具。 + +### 1.1 从现有工具中移除 + +以下旧版子智能体工具不在多智能体模式中使用: + +- `create_sub_agent`(旧版) +- `close_sub_agent` +- `terminate_sub_agent`(旧版) +- `get_sub_agent_status`(旧版) + +### 1.2 新增/替换的多智能体工具 + +#### `create_sub_agent` + +创建并启动一个子智能体实例。 + +```json +{ + "type": "function", + "function": { + "name": "create_sub_agent", + "description": "创建一个子智能体实例并启动它。一个角色可以有多个实例,如 UI Operator_1、UI Operator_2。", + "parameters": { + "type": "object", + "properties": { + "agent_id": { + "type": "integer", + "description": "这个角色的第几个实例,从 1 开始。同一 role_id 下每个编号只能用一次。" + }, + "role_id": { + "type": "string", + "description": "角色 ID,如 ui-operator、full-stack-engineer。" + }, + "task": { + "type": "string", + "description": "任务描述,会作为给子智能体的首条任务发布消息。" + }, + "run_in_background": { + "type": "boolean", + "description": "是否后台运行。多智能体模式下通常直接运行(false),因为需要观察输出。" + }, + "timeout_seconds": { + "type": "integer", + "description": "超时时间,默认 600 秒。" + }, + "thinking_mode": { + "type": "string", + "enum": ["fast", "thinking"], + "description": "思考模式,不指定则使用角色配置。" + }, + "model_key": { + "type": "string", + "description": "模型 key,不指定则使用角色配置。" + } + }, + "required": ["agent_id", "role_id", "task"] + } + } +} +``` + +#### `terminate_sub_agent` + +强制终止指定子智能体实例。 + +```json +{ + "type": "function", + "function": { + "name": "terminate_sub_agent", + "description": "强制终止指定子智能体实例。终止后无法恢复,但已生成的文件保留。", + "parameters": { + "type": "object", + "properties": { + "agent_id": { + "type": "integer", + "description": "要终止的子智能体实例编号。" + } + }, + "required": ["agent_id"] + } + } +} +``` + +#### `send_message_to_sub_agent` + +向子智能体发送消息或运行中引导。不等待回答。 + +```json +{ + "type": "function", + "function": { + "name": "send_message_to_sub_agent", + "description": "向指定子智能体发送消息。如果子智能体正在运行,消息会插入到当前输出流中作为引导;如果子智能体空闲,消息会触发新一轮运行。用于运行中纠正、补充上下文、追加指令。", + "parameters": { + "type": "object", + "properties": { + "agent_id": { + "type": "integer", + "description": "目标子智能体实例编号。" + }, + "message": { + "type": "string", + "description": "要发送的消息内容。" + } + }, + "required": ["agent_id", "message"] + } + } +} +``` + +#### `ask_sub_agent` + +向子智能体提问并等待回答。 + +```json +{ + "type": "function", + "function": { + "name": "ask_sub_agent", + "description": "向指定子智能体提问并等待其回答。适用于需要子智能体给出明确答复的场景。", + "parameters": { + "type": "object", + "properties": { + "agent_id": { + "type": "integer", + "description": "目标子智能体实例编号。" + }, + "question": { + "type": "string", + "description": "问题内容。" + }, + "question_id": { + "type": "string", + "description": "问题唯一 ID,子智能体回答时会引用。" + } + }, + "required": ["agent_id", "question", "question_id"] + } + } +} +``` + +#### `answer_sub_agent_question` + +回答子智能体向主智能体提出的问题。 + +```json +{ + "type": "function", + "function": { + "name": "answer_sub_agent_question", + "description": "回答子智能体提出的问题。回答会返回到子智能体 ask_master 工具的结果中。", + "parameters": { + "type": "object", + "properties": { + "agent_id": { + "type": "integer", + "description": "提问的子智能体实例编号。" + }, + "question_id": { + "type": "string", + "description": "问题 ID,与 ask_master 时一致。" + }, + "answer": { + "type": "string", + "description": "回答内容。" + } + }, + "required": ["agent_id", "question_id", "answer"] + } + } +} +``` + +#### `list_active_sub_agents` + +查询当前多智能体会话中所有活跃/可通信的子智能体。 + +```json +{ + "type": "function", + "function": { + "name": "list_active_sub_agents", + "description": "查询当前多智能体会话中所有活跃或可通信的子智能体列表,包括运行中和空闲的实例。", + "parameters": { + "type": "object", + "properties": {} + } + } +} +``` + +返回示例: + +```json +{ + "success": true, + "agents": [ + { + "agent_id": 1, + "role_id": "ui-operator", + "display_name": "UI Operator_1", + "status": "running", + "summary": "设计前端配色方案" + }, + { + "agent_id": 2, + "role_id": "full-stack-engineer", + "display_name": "Full-Stack Engineer_1", + "status": "idle", + "summary": "等待 API 接口确认" + } + ] +} +``` + +#### `get_sub_agent_status` + +查询指定子智能体的详细状态。 + +```json +{ + "type": "function", + "function": { + "name": "get_sub_agent_status", + "description": "查询指定子智能体实例的详细状态、统计和最近输出。", + "parameters": { + "type": "object", + "properties": { + "agent_id": { + "type": "integer", + "description": "子智能体实例编号。" + } + }, + "required": ["agent_id"] + } + } +} +``` + +#### `create_custom_agent` + +创建并保存自定义角色。 + +```json +{ + "type": "function", + "function": { + "name": "create_custom_agent", + "description": "创建一个自定义角色并保存到本地,后续可通过 role_id 调用。", + "parameters": { + "type": "object", + "properties": { + "role_id": { + "type": "string", + "description": "角色 ID,唯一标识。" + }, + "name": { + "type": "string", + "description": "角色显示名。" + }, + "description": { + "type": "string", + "description": "角色简短描述。" + }, + "model": { + "type": "string", + "description": "默认使用的模型。" + }, + "thinking_mode": { + "type": "string", + "enum": ["fast", "thinking"], + "description": "默认思考模式。" + }, + "prompt": { + "type": "string", + "description": "角色专属 prompt。" + } + }, + "required": ["role_id", "name", "description", "prompt"] + } + } +} +``` + +#### `list_agents` + +列出所有可用角色。 + +```json +{ + "type": "function", + "function": { + "name": "list_agents", + "description": "列出所有可用的预置和自定义角色。", + "parameters": { + "type": "object", + "properties": {} + } + } +} +``` + +--- + +## 2. 子智能体工具 + +子智能体保留现有 8 个基础工具: + +- `read_file` +- `write_file` +- `edit_file` +- `run_command` +- `web_search` +- `extract_webpage` +- `search_workspace` +- `read_mediafile` + +新增以下多智能体通信工具: + +### 2.1 `ask_master` + +向主智能体(Team Leader)提问,阻塞等待回答。 + +```json +{ + "type": "function", + "function": { + "name": "ask_master", + "description": "向主智能体(Team Leader)提问。主智能体回答后会将结果返回到此工具调用中。", + "parameters": { + "type": "object", + "properties": { + "question": { + "type": "string", + "description": "问题内容。" + }, + "question_id": { + "type": "string", + "description": "问题唯一 ID。" + } + }, + "required": ["question", "question_id"] + } + } +} +``` + +### 2.2 `ask_other_agent` + +向其他子智能体提问或发送消息,阻塞等待回复。 + +```json +{ + "type": "function", + "function": { + "name": "ask_other_agent", + "description": "向其他子智能体提问或发送消息。对方回复后会将结果返回到此工具调用中。注意:向其他子智能体提问时,必须同时直接向主智能体输出汇报。", + "parameters": { + "type": "object", + "properties": { + "target_agent_id": { + "type": "integer", + "description": "目标子智能体实例编号。" + }, + "content": { + "type": "string", + "description": "提问或消息内容。" + }, + "message_id": { + "type": "string", + "description": "消息唯一 ID。" + } + }, + "required": ["target_agent_id", "content", "message_id"] + } + } +} +``` + +### 2.3 `answer_other_agent` + +回答其他子智能体的问题。 + +```json +{ + "type": "function", + "function": { + "name": "answer_other_agent", + "description": "回答其他子智能体的问题。回答会返回到对方 ask_other_agent 工具的结果中。", + "parameters": { + "type": "object", + "properties": { + "source_agent_id": { + "type": "integer", + "description": "提问方的子智能体实例编号。" + }, + "message_id": { + "type": "string", + "description": "对方提问时的 message_id。" + }, + "answer": { + "type": "string", + "description": "回答内容。" + } + }, + "required": ["source_agent_id", "message_id", "answer"] + } + } +} +``` + +### 2.4 `list_active_sub_agents` + +查询当前活跃子智能体。 + +```json +{ + "type": "function", + "function": { + "name": "list_active_sub_agents", + "description": "查询当前多智能体会话中所有活跃或可通信的子智能体。", + "parameters": { + "type": "object", + "properties": {} + } + } +} +``` + +--- + +## 3. 工具与消息映射 + +| 动作 | 工具 | 发送方 | 接收方形式 | +|------|------|--------|-----------| +| 创建子智能体 | `create_sub_agent` | Team Leader | 启动实例,首条消息以任务发布形式插入 | +| 终止子智能体 | `terminate_sub_agent` | Team Leader | 强制停止实例 | +| 向子智能体发消息/引导 | `send_message_to_sub_agent` | Team Leader | 插入子智能体 user 消息(inline 或触发新任务) | +| Team Leader 问子智能体 | `ask_sub_agent` | Team Leader | 插入子智能体 user 消息,等待回复 | +| 子智能体问 Team Leader | `ask_master` | 子智能体 | 插入 Team Leader user 消息,等待回答 | +| Team Leader 回答子智能体 | `answer_sub_agent_question` | Team Leader | 返回到 `ask_master` 工具结果 | +| 子智能体 A 问 B | `ask_other_agent` | A | 插入 B 的 user 消息(inline 或触发新任务) | +| 子智能体 B 回答 A | `answer_other_agent` | B | 返回到 A 的 `ask_other_agent` 工具结果 | +| 查询活跃子智能体 | `list_active_sub_agents` | 任意 | 返回列表 | +| 子智能体输出/汇报 | 自然 assistant 输出 | 子智能体 | 捕获后插入 Team Leader user 消息 | + +--- + +## 4. 工具定义文件位置 + +- 主智能体工具:`modules/multi_agent/tools/master_tools.py` +- 子智能体工具:`modules/multi_agent/tools/agent_tools.py` +- 工具处理:`modules/multi_agent/tools/tool_handlers.py` + +不修改现有 `core/main_terminal_parts/tools_definition.py` 或 `modules/sub_agent/toolkit.py`。 diff --git a/docs/multi_agent_mode/04_message_routing.md b/docs/multi_agent_mode/04_message_routing.md new file mode 100644 index 0000000..c52a5c9 --- /dev/null +++ b/docs/multi_agent_mode/04_message_routing.md @@ -0,0 +1,222 @@ +# 多智能体模式消息路由机制 + +> 消息路由由**接收方**决定:根据接收方当前状态,选择 inline 插入工具结果后,或作为 user 消息触发新一轮任务。 +> 参考现有后台任务通知池机制实现,保证消息不丢失、不错乱、可批量处理。 + +--- + +## 1. 核心思想 + +### 1.1 接收方决定插入方式 + +当一条消息需要发送给某个子智能体(或主智能体)时,路由层只关心接收方当前处于什么状态: + +| 接收方状态 | 插入方式 | 效果 | +|-----------|---------|------| +| 正在运行中,且当前在某次工具调用中阻塞等待 | 把消息作为该工具调用的结果返回 | 子智能体在当前轮次继续执行,立即看到消息 | +| 正在运行中,但不在阻塞等待状态 | 把消息 inline 插入到当前对话上下文末尾 | 子智能体下一轮输出时自然看到 | +| 空闲状态(本轮已自然结束) | 把消息作为普通 user 消息插入 | 触发子智能体新一轮运行 | + +### 1.2 参考现有后台通知池 + +现有后台任务通知机制: + +- **运行期间(inline)**:`server/chat_flow_tool_loop.py` 中 `execute_tool_calls` 末尾调用 `process_sub_agent_updates(..., inline=True)`,把已完成的子智能体任务一次性插入当前 `messages`,不触发新任务。 +- **停止输出后(polling)**:`server/chat_flow_task_main.py` 中 `handle_task_with_sender` 结尾启动 `run_completion_poll`,统一轮询子智能体 + 后台命令完成通知,批量插入 user 消息,只触发一个后续任务。 + +多智能体模式的消息路由借鉴此机制: + +- 每个子智能体有自己的「待处理消息队列」。 +- 子智能体每次进入可接收消息的状态时,从队列中取出所有消息,按顺序处理。 +- 避免逐条消息触发多次「工作 → 停止 → 再工作」循环。 + +--- + +## 2. 消息路由状态机 + +### 2.1 子智能体状态 + +``` + ┌─────────────┐ + │ idle │ 空闲 + └──────┬──────┘ + │ create_sub_agent / send_message_to_sub_agent + ▼ + ┌─────────────┐ + │ running │ 运行中 + │ (normal) │ 正常输出 + └──────┬──────┘ + │ 调用 ask_master / ask_other_agent + ▼ + ┌─────────────┐ + │ waiting │ 阻塞等待回答 + │ (asking) │ + └──────┬──────┘ + │ 收到 answer / 自然结束 + ▼ + ┌─────────────┐ + │ completed │ 本轮结束(上下文保留) + └─────────────┘ +``` + +### 2.2 路由决策 + +```python +def route_message(target_agent_id, message): + agent = get_agent(target_agent_id) + + if agent.state == "waiting" and agent.pending_tool_call: + # 目标正在阻塞等待回答:直接返回到工具结果 + agent.resolve_pending_tool_call(message) + return "resolved" + + if agent.state == "running": + # 目标正在运行:inline 插入到当前对话上下文末尾 + agent.inject_inline_message(message) + return "injected_inline" + + if agent.state in ("idle", "completed"): + # 目标空闲:作为 user 消息插入,触发新一轮运行 + agent.inject_user_message(message) + return "triggered_new_turn" +``` + +--- + +## 3. 关键场景分析 + +### 3.1 子智能体正在输出,主智能体要引导 + +场景: +- UI Operator_1 正在运行,输出了「接下来我会创建新 API...」 +- Team Leader 要立即干预:「先不要创建 API,先确认现有 auth 模块是否可复用。」 + +处理: +- UI Operator_1 状态为 `running`(正常输出,不在阻塞等待) +- `send_message_to_sub_agent` 的消息 inline 插入到 UI Operator_1 的 `messages` 末尾 +- UI Operator_1 下一轮模型调用时会看到这条 user 消息 + +### 3.2 子智能体正在等待回答 + +场景: +- Full-Stack Engineer_1 调用了 `ask_master`,等待 Team Leader 回答 +- Team Leader 调用 `answer_sub_agent_question` + +处理: +- Full-Stack Engineer_1 状态为 `waiting` +- 回答直接返回到 `ask_master` 工具结果中 +- Full-Stack Engineer_1 继续执行 + +### 3.3 子智能体已经完成,主智能体追加任务 + +场景: +- Full-Stack Engineer_1 已经自然结束输出,状态为 `completed` +- Team Leader 要追加新任务 + +处理: +- `send_message_to_sub_agent` 的消息作为普通 user 消息插入 +- 触发 Full-Stack Engineer_1 新一轮运行 + +### 3.4 边界情况:子智能体正在进行最后一轮输出 + +场景: +- UI Operator_1 正在输出最后一段话,后面没有工具调用了 +- Team Leader 此时调用 `send_message_to_sub_agent` + +处理: +- 如果消息到达时 UI Operator_1 还在运行:尝试 inline 插入 +- 但由于这是最后一轮,后面没有工具调用了,inline 的消息不会被模型看到 +- 因此需要在 UI Operator_1 本轮任务结束后,把这条消息作为触发新一轮任务的 user 消息发送 + +实现要点: +- 路由层维护每个子智能体的「待处理消息队列」 +- 子智能体任务自然结束时,检查队列 +- 如果有待处理消息,立即作为 user 消息触发新一轮运行 + +### 3.5 子智能体 A 问 B,B 正在运行 + +场景: +- UI Operator_1 调用 `ask_other_agent(target=2)` 问 Full-Stack Engineer_1 +- Full-Stack Engineer_1 正在运行中 + +处理: +- 如果 Full-Stack Engineer_1 处于 `running` 状态:inline 插入 user 消息 +- Full-Stack Engineer_1 下一轮输出时看到问题 +- 如果 Full-Stack Engineer_1 调用 `answer_other_agent`:回答返回到 UI Operator_1 的 `ask_other_agent` 工具结果 + +--- + +## 4. 待处理消息队列 + +每个子智能体维护一个待处理消息队列 `pending_messages`。 + +```python +@dataclass +class PendingMessage: + id: str + source_display_name: str + source_agent_id: Optional[int] + target_agent_id: int + message_type: str # task / output / ask / message / answer + content: str + question_id: Optional[str] # 用于 answer 匹配 + created_at: float +``` + +### 4.1 队列消费时机 + +1. 子智能体每次模型调用前,先检查队列,把待处理消息合并到 `messages` 中 +2. 子智能体从 `waiting` 状态恢复时,优先消费回答类消息 +3. 子智能体自然结束时,如果有剩余待处理消息,立即触发新一轮运行 + +### 4.2 批量消费 + +参考现有通知池,每次消费时尽可能一次性取出所有可消费消息: + +```python +def consume_pending_messages(agent): + messages = agent.pending_messages.drain_all() + for msg in messages: + formatted = format_message(msg) + agent.messages.append({"role": "user", "content": formatted}) + return len(messages) +``` + +--- + +## 5. 与现有通知池的对比 + +| 维度 | 现有后台通知池 | 多智能体消息路由 | +|------|--------------|----------------| +| 触发源 | 子智能体/后台命令完成 | 子智能体间/主智能体向子智能体发消息 | +| 接收方 | 主智能体对话 | 子智能体对话或主智能体对话 | +| 插入方式 | inline / 触发新任务 | inline / 返回到工具结果 / 触发新任务 | +| 批量处理 | `_collect_pending_completion_notices` 一次性取多条 | 每个子智能体维护自己的待处理队列 | +| 持久化 | 直接插入对话历史 | 先进入队列,再按状态消费并持久化 | + +--- + +## 6. 消息路由实现位置 + +- 核心路由逻辑:`modules/multi_agent/message_router.py` +- 待处理队列:`MultiAgentSubAgentTask.pending_messages` +- 状态管理:`MultiAgentSubAgentTask.state` +- 工具调用等待:`MultiAgentSubAgentTask.pending_tool_calls` + +--- + +## 7. 防丢失机制 + +1. 每条消息都有唯一 `id` +2. 消息进入队列时立即持久化到子智能体 metadata +3. 消费完成后从队列移除并持久化 +4. 子智能体恢复时从 metadata 加载未消费消息 +5. 回答类消息通过 `question_id` / `message_id` 精确匹配 + +--- + +## 8. 关键代码参考 + +- `server/chat_flow_task_support.py`:`inject_runtime_user_message`、`process_sub_agent_updates` +- `server/chat_flow_task_main.py`:`_collect_pending_completion_notices`、`poll_completion_notifications`、`_dispatch_completion_user_notice` +- `server/chat_flow_tool_loop.py`:`execute_tool_calls` 末尾的 `process_sub_agent_updates(..., inline=True)` diff --git a/docs/multi_agent_mode/05_data_model.md b/docs/multi_agent_mode/05_data_model.md new file mode 100644 index 0000000..2d427f9 --- /dev/null +++ b/docs/multi_agent_mode/05_data_model.md @@ -0,0 +1,304 @@ +# 多智能体模式数据模型 + +> 所有数据存储在 `~/.astrion/astrion/host/mutiagents/` 下,与现有系统完全隔离。 +> 子智能体对话记录的保存精度、时机、格式与主智能体对话记录一致。 + +--- + +## 1. 目录结构 + +``` +~/.astrion/astrion/host/mutiagents/ +├── agents/ # 角色定义 +│ ├── ui-operator.md +│ ├── full-stack-engineer.md +│ ├── code-reviewer.md +│ └── researcher.md +├── conversations/ # 多智能体会话 +│ └── / +│ ├── metadata.json # 会话级元数据 +│ ├── messages.json # Team Leader 对话 +│ └── agents/ +│ └── / +│ ├── metadata.json # 子智能体元数据 +│ └── messages.json # 子智能体完整对话 +└── state.json # 全局状态 +``` + +--- + +## 2. 角色定义(Agent Role) + +文件路径:`agents/.md` + +格式:YAML Frontmatter + Markdown 正文 + +```markdown +--- +id: ui-operator +name: UI Operator +description: 负责前端设计、UI 还原、配色方案 +model: qwen3-max +thinking_mode: fast +--- + +你是团队的前端设计专家... +``` + +### Frontmatter 字段 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `id` | string | 是 | 角色唯一标识,文件名也使用此 id | +| `name` | string | 是 | 角色显示名 | +| `description` | string | 是 | 角色简短描述 | +| `model` | string | 否 | 默认模型 key | +| `thinking_mode` | string | 否 | fast / thinking | + +### 正文 + +正文部分为角色专属 prompt,会拼接在基础 prompt 之后。 + +--- + +## 3. 全局状态(state.json) + +```json +{ + "version": "1.0", + "last_conversation_id": "conv_xxx", + "agent_id_counter": 5, + "created_at": "2026-07-11T21:00:00", + "updated_at": "2026-07-11T21:30:00" +} +``` + +| 字段 | 说明 | +|------|------| +| `version` | 数据格式版本 | +| `last_conversation_id` | 最近一次会话 id | +| `agent_id_counter` | 全局实例编号计数器(可选) | + +--- + +## 4. 会话元数据(metadata.json) + +```json +{ + "id": "conv_20260711_210000_001", + "title": "多智能体任务:设计前端", + "created_at": "2026-07-11T21:00:00", + "updated_at": "2026-07-11T21:30:00", + "project_path": "/Users/jojo/project", + "model_key": "qwen3-max", + "thinking_mode": true, + "run_mode": "thinking", + "status": "active", + "agent_count": 3, + "agent_ids": [1, 2, 3] +} +``` + +| 字段 | 说明 | +|------|------| +| `id` | 会话 id | +| `title` | 会话标题 | +| `created_at` | 创建时间 | +| `updated_at` | 更新时间 | +| `project_path` | 关联项目路径 | +| `model_key` | Team Leader 使用的模型 | +| `thinking_mode` | 是否思考模式 | +| `run_mode` | fast / thinking / deep | +| `status` | active / archived | +| `agent_count` | 当前子智能体数量 | +| `agent_ids` | 当前子智能体 agent_id 列表 | + +--- + +## 5. 主智能体对话(messages.json) + +与现有 `ConversationManager` 保存格式一致。 + +```json +{ + "id": "conv_20260711_210000_001", + "title": "多智能体任务:设计前端", + "created_at": "2026-07-11T21:00:00", + "updated_at": "2026-07-11T21:30:00", + "messages": [ + { + "role": "user", + "content": "帮我设计一个前端页面", + "message_id": "msg_user_001", + "metadata": { + "message_source": "user", + "visibility": "chat", + "starts_work": true + } + }, + { + "role": "assistant", + "content": "我来安排 UI Operator 处理这个任务...", + "message_id": "msg_assistant_001", + "tool_calls": [...] + }, + { + "role": "user", + "content": "来自 UI Operator_1 的任务完成汇报\nid: out_uio_001\n\n\n\n我完成了前端配色的设计...\n\n", + "message_id": "msg_auto_001", + "metadata": { + "message_source": "sub_agent", + "visibility": "compact", + "starts_work": false, + "agent_id": 1 + } + } + ], + "metadata": { ... }, + "token_statistics": { ... } +} +``` + +--- + +## 6. 子智能体元数据(agents//metadata.json) + +```json +{ + "agent_id": 1, + "role_id": "ui-operator", + "display_name": "UI Operator_1", + "status": "running", + "created_at": "2026-07-11T21:05:00", + "updated_at": "2026-07-11T21:15:00", + "task_summary": "设计前端配色方案", + "model_key": "qwen3-max", + "thinking_mode": "fast", + "pending_messages": [ + { + "id": "msg_tl_001", + "source_display_name": "Team Leader", + "source_agent_id": null, + "message_type": "message", + "content": "先不要创建 API...", + "created_at": 1752251700.0 + } + ], + "pending_tool_calls": [ + { + "tool_call_id": "tc_ask_001", + "tool_name": "ask_master", + "question_id": "ask_uio_001", + "created_at": 1752251800.0 + } + ] +} +``` + +| 字段 | 说明 | +|------|------| +| `agent_id` | 实例编号 | +| `role_id` | 角色 id | +| `display_name` | 显示名 | +| `status` | running / waiting / idle / completed / terminated | +| `task_summary` | 当前任务摘要 | +| `pending_messages` | 待处理消息队列 | +| `pending_tool_calls` | 正在等待回答的工具调用 | + +--- + +## 7. 子智能体对话(agents//messages.json) + +保存精度、时机、格式与主智能体对话完全一致。 + +```json +{ + "agent_id": 1, + "role_id": "ui-operator", + "display_name": "UI Operator_1", + "created_at": "2026-07-11T21:05:00", + "updated_at": "2026-07-11T21:15:00", + "messages": [ + { + "role": "system", + "content": "你是智能体集群团队的一员..." + }, + { + "role": "user", + "content": "来自 Team Leader 的任务发布\nid: task_001\n\n\n\n请为项目设计前端配色方案...\n\n", + "message_id": "msg_user_001" + }, + { + "role": "assistant", + "content": "我先分析一下现有设计风格...", + "message_id": "msg_assistant_001" + }, + { + "role": "user", + "content": "来自 Team Leader 的消息\nid: msg_tl_001\n\n\n\n先不要创建 API...\n\n", + "message_id": "msg_user_002" + }, + { + "role": "assistant", + "content": "好的,我先确认现有 auth 模块...", + "message_id": "msg_assistant_002" + } + ] +} +``` + +--- + +## 8. 持久化策略 + +### 8.1 保存时机 + +- 每次模型调用前保存子智能体 metadata 和 messages +- 每次工具调用后保存 +- 每次状态变更时保存 +- 每次收到外部消息并处理后保存 + +### 8.2 原子写入 + +参考 `ConversationManager._atomic_write_json`,使用临时文件 + replace: + +```python +def _atomic_write_json(path: Path, data: dict): + tmp = path.with_suffix(path.suffix + ".tmp") + tmp.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8") + tmp.replace(path) +``` + +### 8.3 索引 + +参考 `ConversationManager` 的索引机制,在 `conversations/index.json` 中维护会话列表: + +```json +{ + "conv_20260711_210000_001": { + "title": "多智能体任务:设计前端", + "created_at": "2026-07-11T21:00:00", + "updated_at": "2026-07-11T21:30:00", + "agent_count": 3 + } +} +``` + +--- + +## 9. 与现有 ConversationManager 的关系 + +多智能体模式实现自己的 `MultiAgentConversationStore`,但: + +- 数据格式与 `ConversationManager` 保持一致 +- 文件结构与 `ConversationManager` 类似 +- 不修改 `utils/conversation_manager/` 任何文件 +- 可以复制 `ConversationManager` 的 CRUD 代码到 `MultiAgentConversationStore` + +--- + +## 10. 实现位置 + +- 角色存储:`modules/multi_agent/agent_store.py` +- 会话存储:`modules/multi_agent/conversation_store.py` +- 全局状态:`modules/multi_agent/manager.py` diff --git a/docs/multi_agent_mode/06_implementation_plan.md b/docs/multi_agent_mode/06_implementation_plan.md new file mode 100644 index 0000000..d20f036 --- /dev/null +++ b/docs/multi_agent_mode/06_implementation_plan.md @@ -0,0 +1,235 @@ +# 多智能体模式实现计划 + +> 实现顺序不作为严格 phase,而是按依赖关系自然推进。 +> 核心原则:完全隔离、复制改造、底层复用。 + +--- + +## 1. 目录与文件规划 + +### 1.1 后端代码 + +``` +modules/multi_agent/ +├── __init__.py +├── terminal.py # MultiAgentTerminal +├── manager.py # 多智能体会话与全局状态管理 +├── agent_store.py # 角色配置加载与保存 +├── conversation_store.py # 多智能体会话存储 +├── message_router.py # 消息路由与待处理队列 +├── sub_agent_task.py # MultiAgentSubAgentTask +├── sub_agent_manager.py # MultiAgentSubAgentManager +├── prompts.py # prompt 模板 +└── tools/ + ├── __init__.py + ├── master_tools.py # Team Leader 工具定义 + ├── agent_tools.py # 子智能体工具定义 + └── tool_handlers.py # 工具处理函数 +``` + +### 1.2 前端代码 + +``` +static/src/views/MultiAgentView.vue +static/src/components/multi-agent/ +├── ChatPanel.vue +├── AgentList.vue +├── MessageBubble.vue +└── CreateAgentDialog.vue +``` + +### 1.3 设计文档 + +``` +docs/multi_agent_mode/ +├── 01_overview.md +├── 02_message_protocol.md +├── 03_tool_definitions.md +├── 04_message_routing.md +├── 05_data_model.md +├── 06_implementation_plan.md +└── 07_existing_code_analysis.md +``` + +### 1.4 数据目录 + +``` +~/.astrion/astrion/host/mutiagents/ +├── agents/ +├── conversations/ +└── state.json +``` + +--- + +## 2. 实现步骤 + +### Step 1:基础设施 + +1. 创建 `modules/multi_agent/` 包 +2. 创建 `docs/multi_agent_mode/` 目录(已完成) +3. 创建 `~/.astrion/astrion/host/mutiagents/` 数据目录 +4. 预置 4 个角色文件到 `agents/` + +### Step 2:角色配置 + +1. 实现 `agent_store.py` + - 加载角色 Frontmatter + - 保存自定义角色 + - 列出所有角色 + - 构建完整 prompt(基础 prompt + 自定义 prompt) + +2. 预置角色: + - `ui-operator` + - `full-stack-engineer` + - `code-reviewer` + - `researcher` + +### Step 3:子智能体改造 + +1. 实现 `MultiAgentSubAgentTask`(继承 `SubAgentTask`) + - 覆盖 `_run_loop`,使用多智能体工具列表 + - 覆盖系统提示词生成 + - 捕获 assistant 输出并转发到主智能体 + - 维护 `pending_messages` 队列 + - 维护 `pending_tool_calls` 等待列表 + - 支持 inline 消息注入 + - 支持自然结束(不依赖 finish_task) + +2. 实现 `MultiAgentSubAgentManager`(继承 `SubAgentManager`) + - 创建 `MultiAgentSubAgentTask` 实例 + - 管理所有子智能体状态 + - 提供查询活跃子智能体接口 + - 提供终止实例接口 + +### Step 4:消息路由 + +1. 实现 `message_router.py` + - `route_message(target_agent_id, message)` + - 根据目标状态选择 inline / 工具结果返回 / 触发新任务 + - 处理边界情况(最后一轮输出时收到消息) + - 批量消费待处理消息 + +2. 实现消息格式化函数 + - `format_task_message(display_name, content)` + - `format_output_message(display_name, content)` + - `format_ask_message(display_name, content, message_id)` + - `format_message_message(display_name, content, message_id)` + - `format_answer_message(display_name, content, message_id)` + +### Step 5:主智能体 Terminal + +1. 实现 `MultiAgentTerminal`(基于 `MainTerminal` 复制) + - 移除旧版子智能体工具 + - 添加多智能体专用工具 + - 使用 `MultiAgentSubAgentManager` + - 使用 `MultiAgentConversationStore` + - 实现 `answer_sub_agent_question` 等工具处理 + +2. 实现工具处理函数 + - `create_sub_agent` + - `terminate_sub_agent` + - `send_message_to_sub_agent` + - `ask_sub_agent` + - `answer_sub_agent_question` + - `list_active_sub_agents` + - `get_sub_agent_status` + - `create_custom_agent` + - `list_agents` + +### Step 6:会话存储 + +1. 实现 `MultiAgentConversationStore` + - 复制 `ConversationManager` 的 CRUD 逻辑 + - 数据目录指向 `~/.astrion/astrion/host/mutiagents/conversations/` + - 保存主智能体对话 + - 保存每个子智能体对话 + +### Step 7:前端页面 + +1. 创建 `MultiAgentView.vue` + - 类似现有 ChatView,但专门用于多智能体模式 + - 支持消息气泡按角色/类型渲染 + - 支持显示活跃子智能体列表 + - 支持创建子智能体 + +2. 创建组件 + - `MessageBubble.vue`:渲染统一消息格式 + - `AgentList.vue`:显示子智能体状态 + - `CreateAgentDialog.vue`:创建自定义角色 + +3. 添加路由 `/multiagent/new` + +### Step 8:入口 + +1. 登录页添加「多智能体模式 beta」按钮 +2. 点击后跳转到 `/multiagent/new` +3. 初始化 `MultiAgentTerminal` + +### Step 9:联调测试 + +1. 测试创建子智能体 +2. 测试子智能体自然输出转发 +3. 测试 `send_message_to_sub_agent` 运行中引导 +4. 测试 `ask_master` / `answer_sub_agent_question` +5. 测试 `ask_other_agent` / `answer_other_agent` +6. 测试子智能体对话持久化 +7. 测试角色创建与保存 + +--- + +## 3. 代码隔离清单 + +| 现有文件 | 处理方式 | +|---------|---------| +| `core/main_terminal.py` | 复制为 `modules/multi_agent/terminal.py` | +| `core/main_terminal_parts/tools_definition/agent_tools.py` | 复制改造为 `modules/multi_agent/tools/master_tools.py` | +| `core/main_terminal_parts/tools_execution.py` | 复制需要的部分到 `modules/multi_agent/terminal.py` | +| `modules/sub_agent/manager.py` | 继承创建 `modules/multi_agent/sub_agent_manager.py` | +| `modules/sub_agent/task.py` | 继承创建 `modules/multi_agent/sub_agent_task.py` | +| `modules/sub_agent/toolkit.py` | 复制改造为 `modules/multi_agent/tools/agent_tools.py` | +| `modules/sub_agent/prompts.py` | 复制改造为 `modules/multi_agent/prompts.py` | +| `utils/conversation_manager/*.py` | 复制改造为 `modules/multi_agent/conversation_store.py` | +| `server/chat_flow.py` | 参考实现,为 `/multiagent` 创建新的 API 入口 | +| `server/chat_flow_task_support.py` | 参考 `inject_runtime_user_message` 实现多智能体消息注入 | +| `static/src/views/ChatView.vue` | 复制改造为 `static/src/views/MultiAgentView.vue` | + +--- + +## 4. 复用点清单 + +| 能力 | 复用方式 | +|------|---------| +| 模型调用 | `DeepSeekClient` | +| 工具执行底层 | `WebTerminal.handle_tool_call` 的执行链路 | +| 文件/终端/搜索等工具 | 现有工具函数 | +| 沙箱/权限 | `evaluate_tool_permission` | +| 对话存储格式 | `ConversationManager` 的 JSON 结构 | +| 原子写入 | `_atomic_write_json` 模式 | +| 前端组件 | 复制 ChatView 改造 | + +--- + +## 5. 风险与应对 + +| 风险 | 应对 | +|------|------| +| 子智能体消息丢失 | 待处理队列持久化 + 唯一 id + 消费确认 | +| 子智能体状态错乱 | 状态机清晰 + reconcile 机制 | +| 主智能体上下文爆炸 | 子智能体只汇报关键步骤,详细内容放文件 | +| 多实例并发冲突 | 每个实例独立上下文,独立存储 | +| 与现有代码耦合 | 严格隔离,复制改造 | + +--- + +## 6. 验收标准 + +1. 登录页有「多智能体模式 beta」按钮 +2. 点击后进入 `/multiagent/new` +3. 可以创建至少 2 个不同角色的子智能体 +4. 子智能体输出自动显示在主对话中 +5. Team Leader 可以运行中引导子智能体 +6. 子智能体可以向 Team Leader 提问并收到回答 +7. 子智能体可以向其他子智能体提问并收到回答 +8. 子智能体对话完整保存,刷新后可恢复 +9. 现有单智能体模式不受影响 diff --git a/docs/multi_agent_mode/07_existing_code_analysis.md b/docs/multi_agent_mode/07_existing_code_analysis.md new file mode 100644 index 0000000..73b8bf3 --- /dev/null +++ b/docs/multi_agent_mode/07_existing_code_analysis.md @@ -0,0 +1,277 @@ +# 多智能体模式:现有代码分析 + +> 本文档梳理实现多智能体模式需要理解的现有代码,为复制改造提供依据。 + +--- + +## 1. 子智能体实现 + +### 1.1 核心文件 + +``` +modules/sub_agent/ +├── __init__.py +├── manager.py # SubAgentManager +├── task.py # SubAgentTask +├── toolkit.py # 工具定义 +├── prompts.py # 提示词 +├── state.py # 状态管理 +├── stats.py # 统计 +├── creation.py # 创建参数 +└── tools.py # 本地工具实现 +``` + +### 1.2 SubAgentManager(manager.py) + +- 在主进程内以独立事件循环运行子智能体协程 +- `create_sub_agent()` 创建并启动任务 +- `wait_for_completion()` 阻塞等待完成 +- `terminate_sub_agent()` 强制终止 +- `poll_updates()` 检查已完成任务 +- `execute_tool_for_sub_agent()` 代理工具执行,复用主进程链路 +- `tasks` 字典保存所有任务状态 + +多智能体模式可继承点: +- 创建 `MultiAgentSubAgentManager`,重写 `create_sub_agent` 以创建 `MultiAgentSubAgentTask` +- 扩展任务记录字段:`role_id`、`display_name`、`pending_messages`、`pending_tool_calls` +- 扩展查询接口:`list_active_sub_agents()`、`get_sub_agent_status()` + +### 1.3 SubAgentTask(task.py) + +- `_run_loop()`:LLM 主循环,最多 50 轮 +- `_call_model()`:流式调用模型 +- `_execute_tool()`:通过 manager 执行工具 +- `_finalize_task()`:任务结束时保存 output.json、stats.json、conversation.json +- `FINISH_TOOL`:必须调用 finish_task 才结束 + +多智能体模式改造点: +- 移除 `FINISH_TOOL` 依赖,自然结束输出即任务完成 +- 在 `_run_loop` 中每轮模型调用前消费 `pending_messages` +- 捕获 assistant 输出并转发到主智能体对话 +- 新增 `ask_master`、`ask_other_agent`、`answer_other_agent` 工具处理 +- 维护 `pending_tool_calls`,支持阻塞等待回答 + +### 1.4 工具定义(toolkit.py) + +现有 8 个工具: +- `read_file` +- `write_file` +- `edit_file` +- `run_command` +- `web_search` +- `extract_webpage` +- `search_workspace` +- `read_mediafile` + +多智能体模式可复用这些工具定义,新增通信工具。 + +### 1.5 提示词(prompts.py) + +- `build_user_message()`:给子智能体的任务消息 +- `build_system_prompt()`:子智能体系统提示词 + +多智能体模式需要: +- 新的 `build_system_prompt()`,包含团队规则 +- 新的 `build_user_message()`,使用统一消息格式 +- 角色 prompt 拼接函数 + +--- + +## 2. 后台任务通知池机制 + +### 2.1 核心文件 + +- `server/chat_flow_task_support.py` +- `server/chat_flow_task_main.py` +- `server/chat_flow_tool_loop.py` + +### 2.2 inject_runtime_user_message + +位置:`server/chat_flow_task_support.py` + +功能:运行期/空闲期统一向对话插入一条 user 消息。 + +关键参数: +- `web_terminal`:终端实例 +- `messages`:当前运行中的消息列表(inline 时用) +- `text`:消息文本 +- `source`:消息来源,如 `sub_agent` +- `inline`:True 表示运行期插入,不触发新任务 +- `persist`:是否持久化到对话历史 + +多智能体模式参考点: +- 子智能体输出转发到主智能体时,使用类似机制 +- 但消息格式改为统一 XML 格式,不使用 `[系统通知|sub_agent]` 前缀 + +### 2.3 process_sub_agent_updates + +位置:`server/chat_flow_task_support.py` + +功能:轮询子智能体完成状态,把结果插入当前对话上下文。 + +两种模式: +- `inline=True`:运行期间,插入 `messages` 不触发新任务 +- `inline=False`:空闲期间,触发后续任务 + +多智能体模式参考点: +- 子智能体自然输出捕获后,可以 inline 插入主智能体 `messages` +- 子智能体空闲时收到的消息,作为 user 消息触发新任务 + +### 2.4 _collect_pending_completion_notices + +位置:`server/chat_flow_task_main.py` + +功能:从子智能体和后台命令两路统一取出所有待通知项,按时间排序,一次性处理。 + +关键设计: +- 取出时即就地标记 `notified`,防止重复消费 +- 返回多条通知时,前 N-1 条作为前置通知,最后一条触发新任务 + +多智能体模式参考点: +- 每个子智能体维护自己的待处理消息队列 +- 消费时批量取出,避免多次触发新任务 +- 使用唯一 id 标记已消费 + +### 2.5 poll_completion_notifications + +位置:`server/chat_flow_task_main.py` + +功能:统一轮询器,单工作区只 spawn 一个,避免并发冲突。 + +多智能体模式参考点: +- 多智能体模式也需要一个类似的通知/消息处理循环 +- 但消息源更多(Team Leader → Agent、Agent → Agent、Agent → Team Leader) + +--- + +## 3. 主智能体工具调用链路 + +### 3.1 工具定义 + +位置:`core/main_terminal_parts/tools_definition/agent_tools.py` + +现有主智能体子智能体工具: +- `create_sub_agent` +- `close_sub_agent` +- `terminate_sub_agent` +- `get_sub_agent_status` + +多智能体模式需要移除这些,新增自己的工具定义。 + +### 3.2 工具执行 + +位置:`core/main_terminal_parts/tools_execution.py` 中 `handle_tool_call` + +- 参数预检查 +- 权限检查 +- 根据 tool_name 分发到具体处理函数 +- 返回 JSON 字符串 + +多智能体模式参考点: +- `MultiAgentTerminal.handle_tool_call` 中增加多智能体工具的分支 +- 子智能体工具处理函数放在 `modules/multi_agent/tools/tool_handlers.py` + +### 3.3 WebTerminal 广播 + +位置:`core/web_terminal.py` + +- `handle_tool_call()` 覆盖父类,广播 `tool_execution_start` / `tool_status` / `tool_execution_complete` +- `broadcast()` 发送 WebSocket 事件 + +多智能体模式参考点: +- `MultiAgentTerminal` 可继承 `WebTerminal` 或 `MainTerminal` +- 保留广播能力 + +--- + +## 4. 对话上下文管理 + +### 4.1 ContextManager + +位置:`utils/context_manager/` + +- `ConversationMixin.start_new_conversation()`:创建新对话 +- `ConversationMixin.load_conversation_by_id()`:加载对话 +- `ConversationMixin.save_current_conversation()`:保存当前对话 + +多智能体模式参考点: +- 创建 `MultiAgentContextManager` 或直接用 `MultiAgentConversationStore` +- 保存格式与现有 `messages.json` 一致 + +### 4.2 ConversationManager + +位置:`utils/conversation_manager/` + +- `crud_mixin.py`:`create_conversation`、`save_conversation`、`load_conversation` +- `path_mixin.py`:文件路径管理 +- `index_mixin.py`:索引管理 + +多智能体模式参考点: +- 复制 `ConversationManager` 的实现到 `MultiAgentConversationStore` +- 修改数据目录为 `~/.astrion/astrion/host/mutiagents/conversations/` + +--- + +## 5. Skill 归档机制 + +### 5.1 核心文件 + +`modules/skills_manager.py` + +### 5.2 关键函数 + +- `validate_skill_directory()`:验证 skill 目录 +- `archive_skill_directory()`:移动 skill 到归档目录 +- `_parse_frontmatter()`:解析 YAML Frontmatter +- `_scan_skills_catalog()`:扫描 skill 目录 + +多智能体模式参考点: +- 角色配置使用类似的 Frontmatter 格式 +- 角色归档目录:`~/.astrion/astrion/host/mutiagents/agents/` +- 可以复制 `_parse_frontmatter`、`_scan_skills_catalog` 的实现到 `agent_store.py` + +--- + +## 6. 前端消息渲染 + +### 6.1 现有机制 + +- `server/chat_flow_task_support.py` 中 `inject_runtime_user_message` 发送 `user_message` 事件 +- 前端 `messaging.ts` 处理 `user_message` 事件 +- 根据 `message_source`、`visibility`、`starts_work` 等 metadata 渲染 + +### 6.2 多智能体模式改造点 + +- 多智能体消息也发送 `user_message` 事件 +- 前端根据消息内容中的 XML 解析出角色、类型、内容 +- 渲染为特殊气泡,不显示 XML 标签 + +--- + +## 7. 关键接口总结 + +| 能力 | 现有实现位置 | 多智能体模式实现位置 | +|------|------------|-------------------| +| 子智能体创建/管理 | `modules/sub_agent/manager.py` | `modules/multi_agent/sub_agent_manager.py` | +| 子智能体运行循环 | `modules/sub_agent/task.py` | `modules/multi_agent/sub_agent_task.py` | +| 子智能体工具 | `modules/sub_agent/toolkit.py` | `modules/multi_agent/tools/agent_tools.py` | +| 子智能体提示词 | `modules/sub_agent/prompts.py` | `modules/multi_agent/prompts.py` | +| 主智能体工具定义 | `core/main_terminal_parts/tools_definition/agent_tools.py` | `modules/multi_agent/tools/master_tools.py` | +| 主智能体工具执行 | `core/main_terminal_parts/tools_execution.py` | `modules/multi_agent/terminal.py` | +| 运行时消息注入 | `server/chat_flow_task_support.py` | `modules/multi_agent/message_router.py` | +| 通知池轮询 | `server/chat_flow_task_main.py` | `modules/multi_agent/message_router.py` | +| 对话存储 | `utils/conversation_manager/` | `modules/multi_agent/conversation_store.py` | +| 角色归档 | `modules/skills_manager.py` | `modules/multi_agent/agent_store.py` | +| 前端页面 | `static/src/views/ChatView.vue` | `static/src/views/MultiAgentView.vue` | + +--- + +## 8. 实现注意事项 + +1. **不要修改现有文件**:所有改造在 `modules/multi_agent/` 中完成,通过继承或复制实现。 +2. **状态同步**:子智能体状态变更时需要同步更新 `metadata.json`。 +3. **消息不丢失**:待处理消息队列需要持久化。 +4. **上下文隔离**:每个子智能体独立 messages,不要互相污染。 +5. **模型工具列表**:每轮模型调用前需要重新构造工具列表,确保多智能体通信工具可用。 +6. **自然结束检测**:子智能体某轮没有工具调用且 assistant 输出为空时,认为本轮结束。 +7. **阻塞问答超时**:`ask_master` / `ask_other_agent` 需要设置合理超时,避免永久阻塞。