# 主智能体工具调用与阶段说明

本文面向 **lead_agent（主智能体）**：按协作流程阶段说明**应调用哪些工具**、**参数如何传**、**工具返回什么**（以当前 `evoflow` 实现为准）。  
说明：以下工具均在 **LangGraph 运行**内由模型发起；`tool_call_id` 等由框架注入，模型无需填写。


## 一、工具一览（主智能体侧）

| 工具名 | 典型用途 | 是否常开 |
|--------|----------|----------|
| `ask_clarification` | 信息不足、多义、风险确认时向用户追问 | 是 |
| `supervisor` | 复杂多步任务：主任务、子任务、`worker_profile`、进度、授权、查询 | 按需 |
| `task` | 把具体工作交给子智能体模板执行（需运行时开启 subagent） | 按需（协作执行时） |
| `present_file` / `view_image` 等 | 交付物展示、读图等 | 按需 |
| 配置中的其它工具（检索、读文件等） | 直接由主智能体调用 | 按需 |

`task` 是否出现在工具列表取决于 **`subagent_enabled`**；未开启时主智能体只能走 `supervisor` 规划或其它直连工具。


## 二、按流程阶段：做什么、调什么

### 阶段 A — 需求澄清（可选但推荐）

**何时**：缺关键信息、需求多义、有风险操作需确认、需用户选方案。

**工具**：`ask_clarification`

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `question` | string | 是 | 向用户提出的具体问题 |
| `clarification_type` | 枚举 | 是 | `missing_info` \| `ambiguous_requirement` \| `approach_choice` \| `risk_confirmation` \| `suggestion` |
| `context` | string | 否 | 为何需要澄清 |
| `options` | string[] | 否 | 备选答案（适合 approach_choice / suggestion） |

**返回**：中间件会拦截并中断运行，占位字符串为 `Clarification request processed by middleware`；用户答复后对话继续。主智能体应以**用户新消息**为准继续推理。


### 阶段 B — 简单任务 vs 复杂协作任务

**简单任务**：无需结构化主/子任务时，主智能体直接用**普通工具**（读文件、搜索等）完成，**不必**调用 `supervisor`。

**复杂协作任务**（多步、多角色、要持久化计划与进度）：进入 **阶段 C～F**，以 `supervisor` 为主；执行子工作可配合 **阶段 G** 的 `task`。


### 阶段 C — 建立主任务（拿到 `task_id`）

**工具**：`supervisor`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | 固定为 `"create_task"` |
| `task_name` | 是 | 主任务名称 |
| `task_description` | 否 | 主任务描述 |

**返回（成功，纯文本）**：  
`Task created successfully. ID: <task_id>, Name: <task_name>\nDescription: ...`  
主智能体需从文本中取得 **`<task_id>`**，后续 `task_id` 均指该值。

**其它返回**：

- 同名未关闭任务：`Task '<name>' already exists with ID: <task_id>`（可复用该 ID）
- 失败：`Error: task_name is required...` / `Error: Failed to create task`

**说明**：创建主任务时会绑定当前运行时的 **thread_id**（若存在），便于协作与线程一致。


### 阶段 D — 查看已有子任务（避免重复创建）

**工具**：`supervisor`

**推荐在 `create_subtask` 之前调用其一。**

#### D1 `list_subtasks`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"list_subtasks"` |
| `task_id` | 是 | 主任务 ID |

**返回**：  
- 有子任务：多行文本，每行含状态图标、名称、Status、**Agent（assigned_to）**、Progress、可选 **`profile:`**（`worker_profile` 摘要）、**子任务 ID**。  
- 无子任务：`No subtasks found for task '<task_id>'`  
- 找不到主任务：`Error: Task '<task_id>' not found`

#### D2 `get_status`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"get_status"` |
| `task_id` | 是 | 主任务 ID |

**返回**：结构化文本块，包含主任务 ID、名称、状态、进度、**Execution authorized**、**Thread ID**、子任务列表（含 Agent 与 profile 摘要）。


### 阶段 D3 — 匹配「已有子任务」还是「新建 + 分配」（对智能体的操作）

**两层含义**：

| 层 | 含义 | 如何知道 |
|----|------|----------|
| **模板层** | 当前环境允许哪些 **assigned_agent**（子智能体类型名） | `assign_subtask` 报错时会列出 `Available: ...`；提示词里也有常用列表 |
| **计划层** | 当前主任务下**已经有哪些子任务行**，是否已带 **`worker_profile`**、是否已 **`assigned_to`** | **`list_subtasks` / `get_status`** 的每一行（含 `Agent:` 与 `profile:`） |

**决策（主智能体应按此顺序）**：

1. **先查**：对当前 `task_id` 调用 **`list_subtasks`**（或 **`get_status`**），拿到全部子任务 ID、状态、已分配模板、`worker_profile` 摘要。  
2. **能匹配则复用**：若存在一条子任务，其名称/职责与当前工作项一致，且 **`worker_profile.base_subagent`（若有）与拟用模板一致**，状态仍适合继续（例如未作废）—— **不要再 `create_subtask`**；若尚未分配模板，再 **`assign_subtask`**；执行时用 **`task`** + `collab_task_id` + `collab_subtask_id`。  
3. **不能匹配则新建**：**`create_subtask`**（建议带 `worker_profile_json`），再 **`assign_subtask`** 把模板名写上，再 **`start_execution`**（若门禁需要）后 **`task`**。

**小结**：「直接使用相关智能体」= 直接使用**已有子任务行** + 其上**已分配或可分配的模板**；「创建子智能体」在计划层 = **`create_subtask`** 一行新记录，不是新建一个全局进程。


### 阶段 D4 — 判断与创建能否并发、怎样更快

- **同一主任务内**：至少先完成 **一次** `list_subtasks`（或 `get_status`），再批量决定「复用 / 新建」；避免未看列表就并发 `create_subtask` 导致重复建行。  
- **可提速的做法**：在已掌握列表后，对 **彼此无依赖** 的多个新子任务，可在**同一轮模型响应**里发起 **多个** `supervisor` 调用（例如多个 `create_subtask`、接着多个 `assign_subtask`）。框架是否**并行执行**多工具取决于 LangGraph/调度；存储层通常有锁，写入可能实际串行，但能减少 **对话轮数**。  
- **有 `depends_on` 时**：必须先创建被依赖子任务并拿到其 **子任务 ID**，再在后续子任务的 `worker_profile_json` 里写 `depends_on: ["<前置ID>"]`；这类链式步骤**不能**颠倒顺序。  
- **与并行 `task` 调用**：若协作门禁与资源允许，多个无依赖子任务的 **`task`** 也可在同一轮并行发起（仍受主智能体并发上限等策略约束）。


### 阶段 E — 创建子任务与工人配置（`worker_profile`）

**工具**：`supervisor`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"create_subtask"` |
| `task_id` | 是 | 主任务 ID |
| `subtask_name` | 是 | 子任务名称 |
| `subtask_description` | 否 | 子任务描述 |
| `worker_profile_json` | 否 | **字符串**：JSON 对象，对应 `WorkerProfile`（见下表） |

**`worker_profile_json` 对象字段（均为可选组合）**：

| 字段 | 类型 | 含义 |
|------|------|------|
| `base_subagent` | string | 子智能体模板名，如 `general-purpose`、`bash` |
| `tools` | string[] | 允许的工具名白名单（会与全局工具表求交） |
| `skills` | string[] | 注入提示的技能关键词 |
| `instruction` | string | 该子任务额外系统说明 |
| `depends_on` | string[] | **依赖的子任务 ID 列表**（不要用自然语言名） |

**返回（成功）**：  
`Subtask created successfully. ID: <subtask_id>, Name: <subtask_name>\nParent Task: <task_id>`  
需记下 **`<subtask_id>`** 供分配与执行。

**错误示例**：`task_id`/`subtask_name` 缺失、`worker_profile_json` 非合法 JSON、不符合 Pydantic、`Task '<task_id>' not found`。


### 阶段 F — 分配、进度、完成、授权、读记忆

#### F1 `assign_subtask`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"assign_subtask"` |
| `task_id` | 是 | 主任务 ID |
| `subtask_id` | 是 | 子任务 ID |
| `assigned_agent` | 否 | 配置的子智能体模板名；缺省则存为 `general-purpose` |

**返回（成功）**：`Subtask <subtask_id> assigned to agent: <agent_name>`  
**错误**：未知 agent、找不到任务/子任务；失败时可能带 `DIAG` 扫描信息（纯文本）。

#### F2 `update_progress`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"update_progress"` |
| `task_id` | 是 | 主任务 ID |
| `progress` | 是 | 0～100 |
| `subtask_id` | 否 | 有则更新子任务；无则更新主任务 |

**返回**：`Updated progress of subtask <id> to N%` 或 `Updated progress of main task <id> to N%`；失败为 `Error: ...`。

#### F3 `complete_subtask`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"complete_subtask"` |
| `task_id` | 是 | 主任务 ID |
| `subtask_id` | 是 | 子任务 ID |

**返回（成功）**：`Subtask <subtask_id> marked as completed`  
若所有子任务均完成，会同步将主任务标为完成并触发记忆聚合等（侧效应见实现，对模型仍是一段成功文本）。

#### F4 `start_execution`（协作门禁：允许执行）

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"start_execution"` |
| `task_id` | 是 | 主任务 ID |
| `authorized_by` | 否 | 记录授权者，默认 `"lead"` |

**返回**：`Execution authorized for task <task_id>. (...)` 或 `Error: <原因>`。

#### F5 `get_task_memory`

| 参数 | 必填 | 说明 |
|------|------|------|
| `action` | 是 | `"get_task_memory"` |
| `task_id` | 是 | 主任务或子任务 ID（实现按存储解析） |

**返回**：多行文本，含 `project_id`、`memory_key_agent_id`、status、progress、current_step、output_summary、facts 列表等；找不到则 `Error: Task '...' not found`。


### 阶段 G — 把子任务交给子智能体执行（`task` 工具）

**前提**：运行时 **`subagent_enabled=true`**；若走协作门禁，通常需主任务已 **`start_execution`** 且线程与绑定任务一致（由 `collab_execution_gate_error` 校验）。

**工具**：`task`

| 参数 | 必填 | 说明 |
|------|------|------|
| `description` | 是 | 短描述（日志/展示，约 3～5 个词） |
| `prompt` | 是 | 交给子智能体的完整任务说明 |
| `subagent_type` | 是 | 模板名；若下面提供协作子任务且 profile 含 `base_subagent`，实际以 profile 为准 |
| `max_turns` | 否 | 子智能体最大轮次 |
| `collab_task_id` | 否 | 主任务 ID；可与 runtime context 的 `collab_task_id` 二选一 |
| `collab_subtask_id` | 否 | 子任务 ID；**若填则必须同时有主任务 ID**；用于加载存储中的 `worker_profile`（工具白名单、技能、instruction） |

**返回（终端状态，纯文本）**：

| 情况 | 返回内容形态 |
|------|----------------|
| 成功 | `Task Succeeded. Result: <子智能体最终输出>` |
| 失败 | `Task failed. Error: <错误信息>` |
| 超时 | `Task timed out. Error: ...` 或轮询超时提示 |
| 门禁/配置错误 | `Error: ...`（如未授权、找不到子任务、`worker_profile.tools` 与全局工具交集为空、未知 subagent 类型等） |

**流式侧效应（给前端/观测，非工具返回值字符串）**：运行中会 `get_stream_writer()` 推送 `task_started` / `task_running` / `task_completed` 等事件；协作模式下还可能向 Gateway 广播 `task:started` 等（与部署环境有关）。


## 三、参数传递约定（易错点）

1. **`worker_profile_json`**：必须是 **字符串**；内容为 **一个 JSON 对象**；`depends_on` 必须是 **子任务 ID 数组**，不要写子任务显示名称。  
2. **`task_id` / `subtask_id`**：避免首尾空格与换行（实现会 `strip`）。  
3. **`assigned_agent`**：必须是当前环境 **`get_available_subagent_names()`** 中的名字，否则 `assign_subtask` 报错并列出可用名。  
4. **`task` 与 `collab_*`**：仅 `collab_subtask_id` 而无 `collab_task_id` 会报错。  
5. **主智能体不会收到结构化 JSON 工具返回**：均为 **字符串**；`create_task` / `create_subtask` 的 ID 需从返回正文解析。


## 四、与 HTTP/API 的关系（主智能体不直接调）

用户在 **EvoPanel** 侧通过 **`POST /api/langgraph/threads/{thread_id}/runs/stream`** 发起对话；任务、记忆的 **REST 查询**由 Gateway 提供，与上表工具**并行存在**：主智能体只通过 **工具** 读写协作计划；页面刷新列表走的是 **HTTP**，不是工具返回。


## 五、实现位置（便于对照源码）

| 工具 | 代码文件 |
|------|----------|
| `supervisor` | `backend/packages/harness/evoflow/tools/builtins/supervisor_tool.py` |
| `task` | `backend/packages/harness/evoflow/tools/builtins/task_tool.py` |
| `ask_clarification` | `backend/packages/harness/evoflow/tools/builtins/clarification_tool.py` |
| `WorkerProfile` 模型 | `backend/packages/harness/evoflow/collab/models.py` |


## 六、相关文档

- 端到端流程见：`docs/实时对话任务协作流程说明.md`
