主题
07. 子代理系统:任务委托的艺术
专业化分工,保持上下文干净
引言:为什么需要子代理?
想象一个场景:你让 AI 代理研究一个技术主题,它执行了 10 次网络搜索,每次返回大量结果。很快,对话上下文就被这些中间结果"淹没"了,主代理可能会迷失方向或遗漏重要信息。
子代理就是解决这个问题的方案——通过上下文隔离,让专门的"助理"处理细节工作,主代理只接收精炼的结果。
核心概念
上下文隔离模式
┌────────────────────────────────────────────────────────────────┐
│ 主代理 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 上下文(保持干净) │ │
│ │ - 用户请求 │ │
│ │ - 高层规划 │ │
│ │ - 子代理返回的摘要 ←──────────────────────┐ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ task() │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 子代理 │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ 隔离的上下文 │ │ │
│ │ │ - 搜索结果 1 (5000 tokens) │ │ │
│ │ │ - 搜索结果 2 (8000 tokens) │ │ │
│ │ │ - 搜索结果 3 (6000 tokens) │ │ │
│ │ │ - 分析过程... │ │ │
│ │ │ → 最终输出:300 词摘要 ─────────────────────────┘ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
生活类比
子代理系统就像一个公司的组织架构:
主代理 = 项目总监
- 负责理解客户需求
- 制定整体计划
- 协调各部门工作
- 做最终决策
子代理 = 专业顾问/部门
- 研究员:负责信息搜索和整理
- 分析师:负责数据分析
- 写手:负责报告撰写
- 各自有独立的"办公室"(上下文)
- 完成后只汇报结论
何时使用/不使用子代理
✅ 适合使用子代理
- 多步骤任务会"污染"主代理上下文
- 需要专门化指令或工具的领域
- 不同任务需要不同的模型能力
- 希望主代理专注于高层协调
❌ 不需要子代理
- 简单的单步任务
- 需要保留中间上下文的场景
- 开销大于收益时

子代理类型
DeepAgents 支持两种子代理类型:
1. SubAgent(基于字典)
最常用的方式,通过字典配置:
typescript
import { createDeepAgent, SubAgent } from "deepagents";
const researchAgent: SubAgent = {
name: "researcher",
description: "使用网络搜索开展深入研究并综合结论",
systemPrompt: `你是一位严谨的研究员。你的工作是:
1. 将研究问题拆解为可搜索的查询
2. 使用 internet_search 查找相关信息
3. 将发现综合为全面但简洁的摘要
4. 在提出主张时引用来源
输出格式:
- 摘要(2-3 段)
- 关键发现(要点列表)
- 来源(包含 URL)
请将响应控制在 500 词以内。`,
tools: [internetSearchTool],
model: "gpt-4o", // 可选:覆盖主代理的模型
};
const agent = createDeepAgent({
model: "claude-sonnet-4-5-20250929",
subagents: [researchAgent],
systemPrompt: "你是一个项目经理。对于需要深入研究的任务,委托给 researcher。"
});SubAgent 配置项详解
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | ✅ | 唯一标识符,主代理通过此名称委托任务 |
description | string | ✅ | 功能描述,主代理据此决定何时委托 |
systemPrompt | string | ✅ | 子代理的角色定义和工作指令 |
tools | Tool[] | ✅ | 子代理可用的工具(不继承主代理) |
model | string | ❌ | 覆盖主代理的模型(默认继承) |
middleware | Middleware[] | ❌ | 子代理的中间件(不继承) |
interruptOn | object | ❌ | 人机协作配置(默认继承,可覆盖) |
skills | string[] | ❌ | 子代理的技能路径(不继承) |
2. CompiledSubAgent(预构建图)
用于复杂工作流,可以传入预构建的 LangGraph 图:
typescript
import { createDeepAgent, CompiledSubAgent } from "deepagents";
import { createAgent } from "langchain";
const customGraph = createAgent({
model: new ChatOpenAI({ model: "gpt-4o" }),
tools: [dataAnalysisTool, visualizationTool],
prompt: "你是一个专门用于数据分析的代理...",
});
const dataAnalyzer: CompiledSubAgent = {
name: "data-analyzer",
description: "用于复杂数据分析任务的专门化代理",
runnable: customGraph, // 已编译的 LangGraph 图
};
const agent = createDeepAgent({
subagents: [dataAnalyzer],
});
task 工具
主代理通过内置的 task 工具将任务委托给子代理:
typescript
// 主代理内部调用
task({
name: "researcher", // 子代理名称
task: "研究量子计算的最新进展" // 任务描述
})执行流程:
- 主代理调用
task()工具 - 系统创建子代理实例,传入任务
- 子代理在隔离的上下文中执行任务
- 子代理返回摘要结果
- 主代理接收结果,继续处理

通用子代理
除了自定义子代理,DeepAgents 始终提供一个名为 general-purpose 的通用子代理:
特点
- 与主代理具有相同的系统提示词
- 可访问完全相同的工具
- 使用相同的模型(除非被覆盖)
- 继承主代理的技能
何时使用
当你只需要上下文隔离,而不需要专门化行为时:
typescript
// 主代理不必进行 10 次 Web 搜索填满上下文,
// 而是委托给通用子代理:
task({
name: "general-purpose",
task: "研究量子计算趋势,返回摘要报告"
})
// 子代理在内部执行所有搜索,仅返回摘要多代理协作模式
模式一:流水线协作
typescript
const subagents = [
{
name: "data-collector",
description: "从各种来源收集原始数据",
systemPrompt: "收集关于该主题的全面数据",
tools: [webSearch, apiCall, databaseQuery],
},
{
name: "data-analyzer",
description: "分析收集到的数据以提取洞察",
systemPrompt: "分析数据并提取关键洞察",
tools: [statisticalAnalysis],
},
{
name: "report-writer",
description: "基于分析结果撰写报告",
systemPrompt: "将洞察整理为专业报告",
tools: [formatDocument],
},
];
const agent = createDeepAgent({
systemPrompt: `你是项目经理,负责协调数据分析与报告撰写。
工作流程:
1. 将数据收集委派给 data-collector
2. 将结果交给 data-analyzer
3. 将洞察交给 report-writer
4. 汇总最终输出`,
subagents: subagents,
});模式二:专家会诊
typescript
const subagents = [
{
name: "contract-reviewer",
description: "审阅法律文件与合同",
systemPrompt: "你是一位资深法律审阅专家...",
tools: [readDocument, analyzeContract],
model: "claude-sonnet-4-5-20250929", // 长上下文
},
{
name: "financial-analyst",
description: "分析财务数据与市场趋势",
systemPrompt: "你是一位资深金融分析师...",
tools: [getStockPrice, analyzeFundamentals],
model: "gpt-4o", // 数值分析更强
},
{
name: "tech-expert",
description: "评估技术可行性与架构方案",
systemPrompt: "你是一位资深技术架构师...",
tools: [codeAnalysis, architectureReview],
model: "claude-sonnet-4-5-20250929",
},
];
const agent = createDeepAgent({
systemPrompt: `你是一位综合顾问,可以召集不同领域的专家。
根据问题类型,选择合适的专家进行咨询。`,
subagents: subagents,
});模式三:软件开发团队
typescript
const subagents = [
{
name: "pm",
description: "需求分析和任务拆解",
systemPrompt: "你是产品经理,负责理解需求并拆解任务...",
tools: [],
},
{
name: "architect",
description: "技术方案设计",
systemPrompt: "你是技术架构师,负责设计系统架构...",
tools: [readCodeTool],
},
{
name: "developer",
description: "代码实现",
systemPrompt: "你是高级开发者,负责编写高质量代码...",
tools: [readFileTool, writeFileTool, editFileTool],
},
{
name: "reviewer",
description: "代码审查",
systemPrompt: "你是代码审查专家,负责发现潜在问题...",
tools: [readFileTool, grepTool],
},
{
name: "tester",
description: "测试执行",
systemPrompt: "你是 QA 工程师,负责编写和执行测试...",
tools: [readFileTool, executeTool],
},
];
技能与子代理
技能继承规则
| 子代理类型 | 技能继承 |
|---|---|
| 通用子代理 (general-purpose) | ✅ 自动继承主代理技能 |
| 自定义子代理 | ❌ 不继承,需显式配置 |
配置子代理技能
typescript
const researchSubagent: SubAgent = {
name: "researcher",
description: "具备专门化技能的研究助手",
systemPrompt: "你是一名研究员。",
tools: [webSearch],
skills: ["/skills/research/", "/skills/web-search/"], // 子代理专属技能
};
const agent = createDeepAgent({
skills: ["/skills/main/"], // 主代理 + 通用子代理的技能
subagents: [researchSubagent], // 只获得自己配置的技能
});技能隔离
技能状态完全隔离:
- 主代理的技能对子代理不可见
- 子代理的技能对主代理不可见
- 每个子代理有独立的 SkillsMiddleware 实例

流式输出
子代理支持流式输出,可以在元数据中区分来源:
typescript
const agent = createDeepAgent({
name: "main-agent",
subagents: [{
name: "research-agent",
...
}],
});
// 流式输出时,元数据中包含代理名称
for await (const chunk of stream) {
const agentName = chunk.metadata?.lc_agent_name;
if (agentName === "research-agent") {
console.log("[研究员]", chunk.content);
} else {
console.log("[主代理]", chunk.content);
}
}最佳实践
1. 编写清晰的描述
主代理根据描述决定调用哪个子代理:
typescript
// ✅ 好:具体、以行动为导向
{
name: "financial-analyst",
description: "分析财务数据,并生成带置信度分数的投资洞察"
}
// ❌ 差:模糊、不具体
{
name: "helper",
description: "做点财务相关的事"
}2. 详细的系统提示词
包含工具使用指导和输出格式要求:
typescript
const researchSubagent = {
systemPrompt: `你是一位严谨的研究员。
工作流程:
1. 将问题拆解为可搜索的查询
2. 使用 internet_search 查找信息
3. 综合发现为简洁摘要
4. 引用来源
输出格式:
- 摘要(2-3 段)
- 关键发现(要点列表)
- 来源(包含 URL)
重要:响应控制在 500 词以内。`,
};3. 最小化工具集合
只给子代理必要的工具:
typescript
// ✅ 好:聚焦的工具集合
const emailAgent = {
tools: [sendEmail, validateEmail], // 仅与邮件相关
};
// ❌ 差:工具过多
const emailAgentBad = {
tools: [sendEmail, webSearch, databaseQuery, fileUpload],
};4. 返回简洁结果
指示子代理返回摘要,而非原始数据:
typescript
const dataAnalyst = {
systemPrompt: `分析数据并返回:
1. 关键洞察(3-5 条要点)
2. 总体置信度分数
3. 推荐的下一步行动
不要包含:
- 原始数据
- 中间计算过程
- 详细的工具输出
响应控制在 300 词以内。`,
};5. 按任务选择模型
typescript
const subagents = [
{
name: "contract-reviewer",
model: "claude-sonnet-4-5-20250929", // 长上下文,适合文档
},
{
name: "code-generator",
model: "gpt-4o", // 代码生成更强
},
{
name: "quick-lookup",
model: "gpt-4o-mini", // 简单任务用小模型
},
];
故障排查
子代理未被调用
原因:主代理倾向于自己完成工作。
解决方案:
- 让描述更具体
- 在主代理提示词中明确指示委托
typescript
const agent = createDeepAgent({
systemPrompt: `...你的指令...
IMPORTANT: 对于复杂任务,请使用 task() 工具委派给子代理。
这能保持上下文干净并提升结果质量。`,
subagents: [...],
});上下文仍然膨胀
原因:子代理返回了太多原始数据。
解决方案:
- 指示子代理返回简洁结果
- 对大数据使用文件系统
typescript
systemPrompt: `当你收集了大量数据时:
1. 将原始数据保存到 /data/raw_results.txt
2. 处理并分析数据
3. 仅返回分析摘要
响应控制在 500 词以内。`选择了错误的子代理
原因:描述不够区分度。
解决方案:清晰区分子代理的职责
typescript
const subagents = [
{
name: "quick-researcher",
description: "用于简单、快速的研究,仅需 1-2 次搜索。适合基本事实或定义。",
},
{
name: "deep-researcher",
description: "用于复杂、深入的研究,需多次搜索和综合分析。适合生成全面报告。",
},
];小结
本文介绍了 DeepAgents 子代理系统的核心概念和使用方法:
| 概念 | 说明 |
|---|---|
| 上下文隔离 | 子代理在独立空间工作,只返回摘要 |
| SubAgent | 基于字典的简单配置方式 |
| CompiledSubAgent | 预构建 LangGraph 图 |
| task 工具 | 主代理委托任务的接口 |
| 通用子代理 | 继承主代理配置,用于简单隔离 |
最佳实践:
- ✅ 清晰具体的描述
- ✅ 详细的系统提示词
- ✅ 最小化工具集合
- ✅ 返回简洁结果
- ✅ 按任务选择模型
下一步
在下一篇文章中,我们将学习人机协作——如何配置敏感操作的审批流程。
实践任务
- 创建一个研究型子代理,让它能搜索并整理信息
- 尝试多子代理协作,构建"研究员 + 写手"组合
- 比较使用子代理和不使用子代理时的上下文消耗