📚 什么是子代理?

子代理(Subagents)是 DeepAgents 中用于解决上下文膨胀问题的机制。 当主代理使用返回大量数据的工具时(如网页搜索、文件读取、数据库查询), 中间结果会迅速填满上下文窗口。子代理将详细工作隔离在独立的代理中, 主代理只接收最终的简洁结果

💡 子代理的核心价值
问题 传统方案 子代理方案
上下文污染 大量中间结果填充主 Agent 隔离到子 Agent,主 Agent 仅获取摘要
专门化任务 主 Agent 必须处理所有类型任务 不同子 Agent 专注不同领域
模型选择 主 Agent 必须使用一个模型 不同子 Agent 可使用最适合的模型
协调复杂度 主 Agent 处理所有细节 主 Agent 专注高层协调
graph TB User["用户请求
复杂研究任务"] --> Main["主 Agent
高层协调"] Main -->|委派| Sub1["子 Agent 1
数据收集"] Main -->|委派| Sub2["子 Agent 2
数据分析"] Main -->|委派| Sub3["子 Agent 3
报告生成"] Sub1 -->|"简洁摘要
(< 500字)"| Main Sub2 -->|"分析结果
(< 500字)"| Main Sub3 -->|"最终报告
(< 500字)"| Main Main --> Result["整合结果
返回用户"] Sub1 -.->|大量中间数据
不传递给主 Agent| Data1[("隔离上下文 1")] Sub2 -.->|大量中间数据
不传递给主 Agent| Data2[("隔离上下文 2")] Sub3 -.->|大量中间数据
不传递给主 Agent| Data3[("隔离上下文 3")] style Main fill:#3b82f6,color:#fff style Sub1 fill:#10b981,color:#fff style Sub2 fill:#f59e0b,color:#fff style Sub3 fill:#8b5cf6,color:#fff style Result fill:#10b981,color:#fff

何时使用子代理?

✅ 适合使用子代理
  • 多步骤任务:任务会让主 Agent 的上下文变得混乱
  • 专门化领域:需要专门的指令或工具
  • 不同模型能力:某些子任务需要不同模型的能力
  • 高层协调:需要保持主 Agent 专注于协调工作
❌ 不适合使用子代理
  • 简单单步任务:创建子 Agent 的开销超过收益
  • 需要维护中间上下文:所有步骤必须共享详细上下文
  • 开销大于收益:任务足够简单,不需要上下文隔离

🔧 子代理的两种形式

DeepAgents 支持两种方式定义子代理:

方式 1: 字典形式(推荐)

字典形式是最常用且简单的方式,适用于大多数场景:

Python 🟢 基础
"""
字典形式定义子代理
"""
from deepagents import create_deep_agent

# 定义子代理
research_subagent = {
    # 必需字段
    "name": "research-agent",  # 唯一标识符,主 Agent 通过此名调用
    "description": "用于深入研究问题,收集和综合信息",  # 清晰的行动导向说明
    "system_prompt": """你是一名优秀的研究者。你的任务是:

1. 将研究问题分解为可搜索的查询
2. 使用 internet_search 查找相关信息
3. 综合发现成简明总结
4. 引用来源

输出格式:
- 摘要(2-3 段)
- 关键发现(要点)
- 来源(带 URL)

⚠️ 重要:保持回复在 500 字以内以维持清洁上下文。""",
    "tools": [internet_search],  # 子代理可用的工具列表

    # 可选字段
    "model": "openai:gpt-4o",  # 覆盖主 Agent 的模型
}

# 创建主 Agent,传入子代理
agent = create_deep_agent(
    model="claude-sonnet-4-5-20250929",
    subagents=[research_subagent]
)

# 主 Agent 可以调用子代理
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "研究量子计算的最新进展"
    }]
})

# 主 Agent 会自动决定何时调用子代理
# 子代理完成任务后,主 Agent 只接收简洁的摘要

字典形式的字段说明

字段 必需/可选 说明
name ✅ 必需 唯一标识符,主 Agent 通过此名调用子代理
description ✅ 必需 清晰、专一且以行动为导向的说明,帮助主 Agent 决策
system_prompt ✅ 必需 子代理的详细指令、工作流程、输出格式要求
tools ✅ 必需 子代理可用的工具列表(保持最小化)
model ⬜ 可选 覆盖主 Agent 模型,使用特定模型处理子任务
middleware ⬜ 可选 自定义行为、日志记录、速率限制等
interrupt_on ⬜ 可选 为特定工具配置人工介入(HITL)

方式 2: CompiledSubAgent(高级)

CompiledSubAgent 用于复杂工作流程, 基于预构建的 LangGraph 图:

Python 🔴 高级
"""
CompiledSubAgent - 基于 LangGraph 的复杂子代理
"""
from deepagents import create_deep_agent, CompiledSubAgent
from langgraph.graph import StateGraph

# 定义复杂的工作流图
class AnalysisState(TypedDict):
    raw_data: str
    processed_data: dict
    insights: list

def load_data(state: AnalysisState) -> AnalysisState:
    # 加载数据的逻辑
    state["raw_data"] = "..."
    return state

def process_data(state: AnalysisState) -> AnalysisState:
    # 处理数据的逻辑
    state["processed_data"] = {...}
    return state

def generate_insights(state: AnalysisState) -> AnalysisState:
    # 生成洞察的逻辑
    state["insights"] = [...]
    return state

# 构建 LangGraph 工作流
workflow = StateGraph(AnalysisState)
workflow.add_node("load", load_data)
workflow.add_node("process", process_data)
workflow.add_node("insights", generate_insights)

workflow.set_entry_point("load")
workflow.add_edge("load", "process")
workflow.add_edge("process", "insights")
workflow.add_edge("insights", END)

custom_graph = workflow.compile()

# 创建 CompiledSubAgent
custom_subagent = CompiledSubAgent(
    name="data-analyzer",
    description="复杂数据分析任务的专属代理,包含多步骤工作流",
    runnable=custom_graph
)

# 使用 CompiledSubAgent
agent = create_deep_agent(
    model="claude-sonnet-4-5-20250929",
    subagents=[custom_subagent]
)

# 主 Agent 可以调用此复杂子代理
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "分析用户行为数据并生成洞察报告"
    }]
})

🌐 通用目的子代理

每个 DeepAgent 都自动拥有一个名为 "general-purpose" 的内置子代理, 它具有以下特点:

  • 共享主 Agent 的系统提示:行为与主 Agent 一致
  • 访问相同工具:无需额外配置
  • 使用相同模型:除非显式覆盖
✨ 通用目的子代理的用途

用途:在无需专门行为的情况下进行上下文隔离。 主 Agent 将复杂的多步骤任务委托给它,保持自己的上下文清洁。

Python 🟢 基础
"""
使用通用目的子代理
"""
from deepagents import create_deep_agent

# 创建 Agent(无需显式定义 general-purpose 子代理)
agent = create_deep_agent(
    model="gpt-4o",
    tools=[internet_search],
    system_prompt="你是研究助手,可以搜索和分析信息。"
)

# 主 Agent 会自动使用 general-purpose 子代理
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "研究 AI 安全的最新进展,并生成详细报告"
    }]
})

# 执行过程:
# 1. 主 Agent 识别到这是复杂的多步骤任务
# 2. 自动调用 general-purpose 子代理
# 3. 子代理执行搜索、分析、报告生成
# 4. 子代理返回简洁的最终报告给主 Agent
# 5. 主 Agent 将结果返回给用户

# 优势:
# - 无需定义专门的子代理
# - 主 Agent 上下文保持清洁
# - 子代理的中间步骤被隔离

🎯 多个专业化子代理

在复杂场景中,你可以定义多个专业化子代理, 每个子代理专注于特定的任务类型:

graph TB User["用户请求
复杂项目分析"] --> Main["主 Agent
项目经理"] Main -->|"需要收集数据"| Collector["数据收集器
子代理"] Main -->|"需要分析数据"| Analyzer["数据分析器
子代理"] Main -->|"需要生成报告"| Reporter["报告生成器
子代理"] Collector -->|工具| Web["网络搜索"] Collector -->|工具| API["API 调用"] Collector -->|工具| DB["数据库查询"] Analyzer -->|工具| Stats["统计分析"] Analyzer -->|工具| ML["机器学习"] Reporter -->|工具| Format["格式化文档"] Reporter -->|工具| Charts["图表生成"] Collector -->|"原始数据摘要"| Main Analyzer -->|"分析结果"| Main Reporter -->|"最终报告"| Main Main --> Result["整合输出
返回用户"] style Main fill:#3b82f6,color:#fff style Collector fill:#10b981,color:#fff style Analyzer fill:#f59e0b,color:#fff style Reporter fill:#8b5cf6,color:#fff style Result fill:#10b981,color:#fff
Python 🔴 高级 - 完整示例
"""
多个专业化子代理 - 完整协作示例
"""
import os
from typing import Literal
from tavily import TavilyClient
from deepagents import create_deep_agent

# 初始化工具
tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])

def internet_search(query: str, max_results: int = 5):
    """网络搜索工具"""
    return tavily_client.search(query, max_results=max_results)

def database_query(sql: str):
    """数据库查询工具(模拟)"""
    # 实际会连接真实数据库
    return {"status": "success", "data": [...]}

def statistical_analysis(data: dict):
    """统计分析工具(模拟)"""
    # 实际会执行统计分析
    return {"mean": 42.5, "median": 40.0, "insights": [...]}

def format_document(content: str, format: Literal["pdf", "markdown", "html"]):
    """文档格式化工具(模拟)"""
    # 实际会生成格式化文档
    return f"formatted_{format}_document.pdf"

# 定义多个专业化子代理
subagents = [
    {
        "name": "data-collector",
        "description": "从各种来源收集原始数据:网络搜索、API 调用、数据库查询",
        "system_prompt": """你是数据收集专家。你的任务是:

1. 使用 internet_search 搜索网络信息
2. 使用 database_query 查询数据库
3. 整理和清理收集到的数据

输出格式:
- 数据来源列表
- 数据质量评估
- 关键数据点摘要(< 300 字)

保持输出简洁,主 Agent 不需要看到所有原始数据。""",
        "tools": [internet_search, database_query],
        "model": "openai:gpt-4o",  # 使用快速模型
    },
    {
        "name": "data-analyzer",
        "description": "分析数据并生成统计洞察和业务建议",
        "system_prompt": """你是数据分析专家。你的任务是:

1. 使用 statistical_analysis 执行统计分析
2. 识别趋势和异常值
3. 生成可操作的业务洞察

输出格式:
- 关键发现(3-5 个要点)
- 业务建议(具体可行)
- 数据质量说明

保持输出在 400 字以内。""",
        "tools": [statistical_analysis],
        "model": "claude-sonnet-4-5-20250929",  # 使用推理能力强的模型
    },
    {
        "name": "report-writer",
        "description": "从分析结果生成精美的专业报告",
        "system_prompt": """你是报告撰写专家。你的任务是:

1. 整合分析结果
2. 使用 format_document 生成格式化报告
3. 确保报告清晰、专业、易读

输出格式:
- 执行摘要
- 详细分析章节
- 结论和建议

使用清晰的标题和要点列表。""",
        "tools": [format_document],
        "model": "claude-sonnet-4-5-20250929",
    },
]

# 创建主 Agent
agent = create_deep_agent(
    model="claude-sonnet-4-5-20250929",
    subagents=subagents,
    system_prompt="""你是项目经理 Agent。你负责协调专业化的子代理团队。

可用的子代理:
1. data-collector: 收集数据
2. data-analyzer: 分析数据
3. report-writer: 生成报告

工作流程:
1. 接收用户请求
2. 分解任务
3. 按顺序委派给相应的子代理
4. 整合子代理的结果
5. 返回最终输出给用户

你只需要协调,不需要直接执行数据收集、分析或报告生成。"""
)

# 使用主 Agent
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": """请分析我们公司 2024 年的销售数据:
        1. 从数据库和网络收集相关数据
        2. 执行统计分析
        3. 生成专业的 PDF 报告
        """
    }]
})

print(result["messages"][-1].content)

# 执行流程:
# 1. 主 Agent 分解任务为 3 个子任务
# 2. 调用 data-collector 子代理收集数据
#    → 返回简洁的数据摘要(< 300 字)
# 3. 调用 data-analyzer 子代理分析数据
#    → 返回关键发现和建议(< 400 字)
# 4. 调用 report-writer 子代理生成报告
#    → 返回报告文件路径和摘要
# 5. 主 Agent 整合所有结果,返回给用户

# 优势:
# - 每个子代理专注于特定任务
# - 主 Agent 的上下文始终清洁
# - 可以使用最适合每个任务的模型
# - 易于维护和扩展

✨ 子代理最佳实践

1. 编写清晰的 Description

description 字段是主 Agent 决定何时调用子代理的关键:

✅ 好的 Description
  • 具体:"分析财务数据并生成投资见解与置信度评分"
  • 行动导向:"从多个来源收集数据、验证准确性并摘要"
  • 明确范围:"执行 SQL 查询,处理结果,返回结构化数据"
❌ 差的 Description
  • 模糊:"处理财务事项"
  • 过于宽泛:"做任何与数据相关的事情"
  • 非行动性:"财务分析助手"

2. 编写详细的 System Prompt

Python 🟡 中级
"""
详细的子代理系统提示词示例
"""
research_subagent = {
    "name": "research-agent",
    "description": "深入研究技术主题,综合多个来源的信息",
    "system_prompt": """你是一名彻底的研究者。你的工作是:

## 职责
1. 将研究问题分解为可搜索的查询
2. 使用 internet_search 查找相关信息
3. 综合发现成简明总结
4. 引用来源

## 工作流程
1. 分析研究问题的核心要点
2. 设计 3-5 个有针对性的搜索查询
3. 执行搜索并评估结果质量
4. 交叉验证重要信息
5. 综合成结构化摘要

## 输出格式
### 摘要
[2-3 段总结核心发现]

### 关键发现
- 发现 1
- 发现 2
- 发现 3

### 来源
- [标题](URL)
- [标题](URL)

## 注意事项
- 优先使用权威来源(.edu, .gov, 知名媒体)
- 标注信息的时效性
- 如有矛盾,说明不同观点
- ⚠️ **重要**:保持回复在 500 字以内以维持清洁上下文
""",
    "tools": [internet_search],
}

3. 最小化工具集

只给予子代理完成任务所必需的工具

  • 专一性更强:子代理不会被无关工具分散注意力
  • 安全性更高:减少潜在的滥用风险
  • 性能更好:模型选择工具的效率更高
Python
# ❌ 不好:给子代理过多工具
subagent = {
    "name": "data-collector",
    "tools": [search, database, api_call, file_read, email_send, slack_notify, ...]  # 太多了!
}

# ✅ 好:只给必需工具
subagent = {
    "name": "data-collector",
    "tools": [search, database]  # 仅收集数据所需
}

4. 按任务选择模型

不同模型在不同任务中表现优异,利用 model 字段覆盖:

任务类型 推荐模型 原因
数据收集 openai:gpt-4o 速度快,成本低
复杂分析 claude-opus-4-5 推理能力强
代码生成 openai:gpt-4o 代码能力优秀
法律审查 claude-sonnet-4-5 理解力和准确性

5. 保持返回结果简洁

关键原则:子代理应返回摘要而非原始数据

⚠️ 简洁输出的重要性

在系统提示中明确指示子代理:

  • 保持输出在 500 字以内
  • 返回摘要和关键发现,而非完整数据
  • 使用要点列表而非长段落
  • 如有大量数据,使用文件系统工具保存,返回文件路径

❓ 常见问题

Q1: 如何调用子代理?

自动调用。你无需手动调用,主 Agent 会根据任务需求和子代理的 description 自动决定何时调用哪个子代理。

Q2: 子代理未被调用,如何解决?

常见原因和解决方案:

  • description 不够清晰:使其更具体、行动导向
  • 主 Agent 系统提示缺乏指导:在主 Agent 的 system_prompt 中明确说明可以委派任务给子代理
  • 任务过于简单:主 Agent 判断无需委派
Python
# 在主 Agent 的系统提示中指导委派
agent = create_deep_agent(
    model="gpt-4o",
    subagents=[research_subagent],
    system_prompt="""你是协调助手。你可以将任务委派给专门的子代理:

- research-agent: 用于深入研究问题

当遇到需要深入研究的任务时,应该委派给 research-agent。"""
)

Q3: 子代理的上下文仍然膨胀,怎么办?

解决方案

  • 在子代理的 system_prompt 中明确要求简洁输出(< 500 字)
  • 指示子代理使用文件系统工具保存大量数据,只返回摘要
  • 确保子代理返回结构化要点而非长段落

Q4: 如何选择多个子代理中的正确一个?

主 Agent 根据description字段决策。确保:

  • 每个子代理的 description 清晰区分用例
  • 避免描述重叠或模糊
  • 使用行动导向的语言

Q5: 子代理可以调用其他子代理吗?

不能直接调用。子代理只能执行自己的任务并返回结果给主 Agent。 如需多层委派,应该:

  • 主 Agent 协调多个子代理的顺序调用
  • 或使用 CompiledSubAgent 构建包含多步骤的复杂工作流

Q6: 子代理会消耗更多成本吗?

是的,每个子代理调用都是独立的模型调用。但从整体看:

  • 成本效益可能更高:通过上下文隔离,主 Agent 可以保持小型高效的上下文
  • 可以使用不同成本的模型:简单任务用便宜模型,复杂任务用贵模型
  • 总 Token 数可能更少:避免重复传递大量中间数据

📖 参考资源