ForcePilot/docs/agents/subagents-management.md
2026-06-02 18:47:28 +08:00

116 lines
5.8 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.

# 子智能体
Yuxi 的子智能体是 Agent-backed 形态:它仍然是 `agents` 表中的一级 Agent只是额外带有 `is_subagent=true` 标记,并使用专用后端 `SubAgentBackend`。子智能体不再有独立的创建入口、独立表或独立管理接口。
## 用户视角
### 子智能体能解决什么问题
当任务复杂、需要分工处理时,主 Agent 可以通过 `task` 工具把一个子任务交给子智能体。例如:
- 研究型子任务:聚焦检索和资料整理。
- 评审型子任务:对草稿进行结构和质量审查。
- 领域型子任务:使用指定模型、工具、知识库或 Skills 处理特定领域问题。
### 在哪里创建和编辑
子智能体与普通 Agent 使用同一个管理入口:进入模型配置中的“智能体”管理页,点击新增智能体,并在后端类型中选择 `SubAgentBackend`
创建和编辑流程与普通 Agent 保持一致:
- 展示信息、共享权限、系统提示词和运行配置都保存在同一份 Agent 配置中。
- 模型、工具、知识库、MCP 和 Skills 仍通过 Agent runtime config 表单配置。
- 子智能体不会出现在聊天页的 Agent 快速切换列表中。
- 子智能体不能再配置或调用其他子智能体。
### 如何让主 Agent 调用子智能体
仅创建子智能体不会让它自动参与运行。需要编辑主 Agent在 runtime config 的“子智能体”字段中选择允许调用的子智能体。
`subagents` 字段表示当前主 Agent 的允许列表:
- 未选择时表示不启用子智能体。
- 只会调用当前用户可访问且 `is_subagent=true` 的 Agent。
- 每个子智能体使用自己的 `config_json.context`包括模型、工具、知识库、MCP、Skills 和系统提示词。
这和工具、知识库、MCP、Skills 的默认全量语义不同:这些资源未显式配置时会默认启用当前用户可访问的全部资源,但子智能体必须显式选择。
## 开发者视角
### 数据模型
子智能体复用 `agents` 表,核心字段包括:
| 字段 | 说明 |
|------|------|
| `backend_id` | 子智能体固定使用 `SubAgentBackend` |
| `is_subagent` | 子智能体标记,`SubAgentBackend` 必须对应 `true` |
| `config_json.context` | 子智能体自己的运行配置 |
| `share_config` | 可见性与管理权限,沿用 Agent 共享模型 |
后端会校验 `backend_id``is_subagent` 一致:普通 Agent 不能伪装成子智能体,`SubAgentBackend` 也不能以普通 Agent 形态保存。子智能体不能被设置为默认 Agent。
### API 与列表语义
子智能体沿用 `/api/agent` CRUD
- `GET /api/agent` 默认只返回聊天可用的普通 Agent。
- `GET /api/agent?include_subagents=true` 返回管理页需要的完整 Agent 列表。
- 创建或更新 `SubAgentBackend`payload 会携带或推导 `is_subagent=true`
- 详情、更新和删除仍走同一套 Agent 管理接口,并复用现有权限过滤。
旧的独立 SubAgent 管理链路已经移除,不再维护单独的启停状态、内置初始化或 spec 缓存。
### 运行时调用链
主 Agent 构图时,如果 `context.subagents` 非空,会挂载 Yuxi 的 task middleware。middleware 会把允许的子智能体列表注入模型提示,并暴露一个 `task` 工具。
工具参数为:
```python
class TaskToolSchema(BaseModel):
description: str
subagent_type: str
thread_id: str | None = None
```
`thread_id` 是可选的子智能体线程 ID。新任务不需要填写如果要继续之前同一个子智能体任务应使用上一次 `task` 工具结果中的 `子智能体线程 ID`
执行时的关键流程:
1. 从父 Agent 的 `context.subagents` 读取允许的子智能体 slug。
2. 使用 `AgentRepository` 加载当前用户可见且 `is_subagent=true` 的 Agent。
3. 新任务会为本次调用生成 child checkpoint thread id例如 `<parent_thread_id>_sub_<slug>_<uuid8>`;续跑任务会校验并复用传入的 `thread_id`
4. 使用子智能体自己的 `SubAgentContext``config_json.context` 构建真实 Agent graph。
5. 调用结束后,把子智能体线程 ID 和最终 assistant 文本作为 `task` 工具结果返回给主 Agent。
`SubAgentBackend` 复用普通 Agent 的运行时资源归一化流程,但不会挂载 task middleware它的 `subagents` 字段隐藏且默认为空,因此不会形成嵌套子智能体调用。
### 文件系统与沙盒作用域
子智能体与主 Agent 共享文件系统时使用拆分作用域:
| 路径/作用域 | 普通 Agent | 子智能体 |
|------|------|------|
| LangGraph checkpoint | 当前 `thread_id` | child `thread_id` |
| `/home/gem/user-data/workspace` | 当前 `uid` 的共享工作区 | 同一 `uid` 的共享工作区 |
| `/home/gem/user-data/uploads` | 当前会话文件作用域 | 父会话 `file_thread_id` |
| `/home/gem/user-data/outputs` | 当前会话文件作用域 | 父会话 `file_thread_id` |
| `/home/gem/skills` | 当前 Agent 的 Skills 作用域 | 子智能体自己的 `skills_thread_id` |
这保证子智能体可以读取父会话上传、产物也会回到父会话 artifacts 中,同时子智能体的 Skills 不会污染主 Agent。
## 常见问题
### 为什么创建了子智能体,主 Agent 仍不会调用?
需要在主 Agent 的 runtime config 中显式选择该子智能体。`subagents` 为空时不会启用 task 工具。
### 为什么聊天 Agent 列表里看不到子智能体?
这是预期行为。子智能体是被主 Agent 调用的后端配置,不是直接进入聊天的 Agent管理页会使用包含子智能体的列表。
### 子智能体能否继承主 Agent 的模型或工具?
子智能体运行时使用自己的 Agent 配置。确实需要一致时,应在子智能体配置中显式选择相同模型、工具或 Skills运行时只继承必要的父会话作用域例如 uploads/outputs。