2026年3月27日,来腾讯会议(限50人)了解掌握如何用Openclaw构建企业AI生产力
免费POC, 零成本试错
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


我要投稿

LangChain的DeepAgents子代理实战:复杂任务为什么一定要交给 SubAgent

发布日期:2026-03-28 05:15:25 浏览次数: 1513
作者:与AI同行之路

微信搜一搜,关注“与AI同行之路”

推荐语

LangChain的DeepAgents子代理系统解决了复杂任务中Agent"精神分裂"的痛点,让每个子代理专注一项任务,大幅提升执行效率。

核心内容:
1. 传统单一Agent处理复杂任务时的问题分析
2. 子代理系统的三大优势:上下文隔离、专业化和并行化
3. DeepAgents提供的三种子代理类型及应用场景

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

 

你有没有想过,为什么很多 Agent 一碰到复杂任务就开始"精神分裂"?

前一阵我让某个 Agent 帮我做一个项目调研:先搜资料、再分析数据、最后写报告。结果它搜着搜着就开始分析,分析到一半又回头去搜,最后写出来的报告东一榔头西一棒槌,像个注意力涣散的实习生。

问题就在这里:一个 Agent 同时干太多事,上下文里堆满了各种信息,搜索关键词、网页内容、分析思路、报告草稿,全混在一起。模型很容易"串台",把搜索时的一个无关信息当成分析结论,或者把草稿里的猜测当成事实。

DeepAgents 的解决方案很直观:既然一个人干会乱,那就多找几个人,每人专职干一件事。

这就是子代理系统的核心思想。

为什么需要分身

子代理不是炫技,它解决的是很现实的工程问题。

上下文隔离是最直接的原因。主代理的上下文窗口是有限的,如果所有子任务都在主线程里做,很快就会爆炸。子代理有独立的上下文,干完活只把结果返回,不会污染主代理的上下文。

专业化是另一个好处。你可以为特定任务配置专门的子代理。比如一个专门做代码审查的,一个专门写文档的,一个专门做测试的。每个子代理有自己的系统提示、工具集和工作方式。

并行化是隐藏的收益。多个独立的子任务可以同时派给不同的子代理执行,总体时间大大缩短。

但子代理也有代价:创建和调度有开销,通信有成本,状态管理更复杂。所以 DeepAgents 的思路一直很克制,是"按需 spawn",不是"先摆一排角色再说"。

三种分身术

DeepAgents 支持三种子代理类型,对应不同的使用场景。

SubAgent:声明式子代理

这是最常用的类型。你声明一个配置,DeepAgents 负责创建和管理。

from deepagents import create_deep_agent

research_agent = {
    "name"
: "researcher",
    "description"
: "Deep research on any topic using web search",
    "system_prompt"
: """You are a research specialist.

Use web search to gather comprehensive information.
Always cite your sources.
Return a structured summary of findings."""
,
    "tools"
: [web_search],
    "model"
: "openai:gpt-4o"
}

agent = create_deep_agent(
    subagents=[research_agent]
)

这几个字段里,真正影响效果的其实就这么几项:

  • • name —— 主代理调用时用的标识
  • • description —— 告诉主代理这个子代理是干什么的
  • • system_prompt —— 子代理的系统提示
  • • tools —— 子代理能用的工具(如果不指定,继承主代理的)
  • • model —— 子代理用的模型(可以跟主代理不同)

description 特别重要。主代理就是靠它来判断这个子代理值不值得调用。如果描述不清楚,主代理可能该用的时候不用,不该用的时候反而乱派活。

CompiledSubAgent:预编译子代理

有时候你已经有一个现成的 Agent,想把它挂到主代理下面当子代理用。

from langgraph import StateGraph
from
 deepagents import CompiledSubAgent

# 你已经有一个用 LangGraph 写的复杂 Agent

my_existing_agent = StateGraph(...).compile()

subagent = CompiledSubAgent(
    name="custom-analyzer",
    description="Specialized code analyzer",
    runnable=my_existing_agent
)

agent = create_deep_agent(
    subagents=[subagent]
)

CompiledSubAgent 的唯一要求是:返回的 state 里必须有 messages 键,因为结果要从 messages 里提取。

这种类型适合复用已有的 Agent 实现,或者做一些 DeepAgents 默认不支持的高级定制。

AsyncSubAgent:异步子代理

前两种都是同步的:主代理调用子代理,然后等它返回。但有时候子任务执行时间很长,你不想在那干等着。

AsyncSubAgent 支持后台执行、非阻塞调用。

from deepagents import AsyncSubAgent

async_subagent = AsyncSubAgent(
    name="long-running-task",
    description="Tasks that take a long time",
    graph_id="my-deployment-id",  # LangSmith 部署 ID
    url="https://my-agent-server.com",
    headers={"Authorization": "Bearer token"}
)

agent = create_deep_agent(
    subagents=[async_subagent]
)

异步子代理会暴露额外的工具:

  • • launch_async_task —— 启动任务
  • • check_async_task —— 查询状态
  • • update_async_task —— 更新参数
  • • cancel_async_task —— 取消任务
  • • list_async_tasks —— 列出所有任务

主代理可以启动任务后继续做其他事,过一会儿再查结果。

目前 AsyncSubAgent 主要支持通过 LangSmith 部署的远程 Agent。这种模式很适合把重负载任务卸载到专门的服务器上执行。

task 工具的设计艺术

子代理系统的核心是那个 task 工具。它看起来只是一个委派入口,但 DeepAgents 在这个工具的提示词上下了很大功夫。

subagents.py 里的 TASK_TOOL_DESCRIPTION 有整整两百多行,是我见过的最详细的工具描述之一。让我带你看看里面都写了什么。

使用场景指导

提示词首先告诉主代理什么时候该用子代理:

Launch an ephemeral subagent to handle complex, multi-step independent tasks with isolated context windows.

When to use the task tool:
- When a task is complex and multi-step, and can be fully delegated in isolation
- When a task is independent of other tasks and can run in parallel
- When a task requires focused reasoning or heavy token/context usage that would bloat the orchestrator thread
- When sandboxing improves reliability
- When you only care about the output of the subagent, and not the intermediate steps

然后又告诉什么时候不该用:

When NOT to use the task tool:
- If you need to see the intermediate reasoning or steps after the subagent has completed
- If the task is trivial (a few tool calls or simple lookup)
- If delegating does not reduce token usage, complexity, or context switching
- If splitting would add latency without benefit

这种明确的边界指导特别重要。我见过很多 Agent 框架,要么过度使用子代理,简单任务也层层委派;要么完全不用,所有事都自己硬扛。DeepAgents 的提示词,本质上是在教模型判断什么情况下委派才划算。

并行化鼓励

提示词里有句加粗的话:

Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses

它在主动鼓励主代理并行思考。如果用户问"比较 A、B、C 三个产品",主代理应该同时 spawn 三个子代理分别研究,而不是一个一个来。

这其实是个很高级的提示工程技巧。不是告诉模型"你可以并行",而是明确告诉它"你应该并行,因为这样性能更好"。

生命周期说明

提示词详细描述了子代理的生命周期:

Subagent lifecycle:
1. Spawn → Provide clear role, instructions, and expected output
2. Run → The subagent completes the task autonomously
3. Return → The subagent provides a single structured result
4. Reconcile → Incorporate or synthesize the result into the main thread

这不仅是在给模型做指导,某种程度上也是给开发者看的文档。它把子代理的边界说得很清楚:一次性的、轻状态的、只返回最终结果。

实战例子

最让我印象深刻的是提示词里嵌了五个详细的例子:

例子一:研究三个篮球明星,分别派三个子代理并行处理,最后主代理汇总对比。

例子二:分析大型代码库,派一个子代理深入分析,主代理只收最终报告。

例子三:准备两个会议议程,两个子代理并行准备。

例子四:点外卖(披萨、汉堡、沙拉),主代理直接调用工具,不走子代理,因为太简单。

例子五:写代码后让 reviewer 子代理审查。

这些例子覆盖了常见的使用模式,等于是在用具体场景教模型:什么时候该用,什么时候别用,怎么用才划算。

状态隔离的实现

子代理能安全运行的关键是状态隔离。子代理不能访问主代理的内存,也不能污染主代理的上下文。

看 subagents.py 里的关键代码:

_EXCLUDED_STATE_KEYS = {
    "messages"
,
    "todos"
,
    "structured_response"
,
    "skills_metadata"
,
    "memory_contents"

}

def
 _validate_and_prepare_state(subagent_type, description, runtime):
    # 创建新 state,过滤掉敏感 key

    subagent_state = {
        k: v for k, v in runtime.state.items()
        if
 k not in _EXCLUDED_STATE_KEYS
    }
    # 子代理只收到一个初始消息

    subagent_state["messages"] = [HumanMessage(content=description)]
    return
 subagent, subagent_state

_EXCLUDED_STATE_KEYS 定义了哪些状态不能传给子代理:

  • • messages —— 主代理的对话历史,子代理不应该看到
  • • todos —— 主代理的任务清单
  • • structured_response —— 结构化输出配置
  • • skills_metadata —— 已加载的 Skill 元数据(子代理自己会加载)
  • • memory_contents —— 记忆内容(子代理自己会加载)

子代理启动时,拿到的是一个干净的 state,只有一个 messages 包含任务描述。这有点像新同事接任务,给你的不是一堆历史聊天记录,而是一张写清楚目标的任务单。

结果回传

子代理完成后,结果怎么回到主代理?

def _return_command_with_state_update(result, tool_call_id):
    # 验证结果里有 messages

    if
 "messages" not in result:
        raise
 ValueError("Subagent must return state with 'messages' key")

    # 提取最后一条消息作为结果

    message_text = result["messages"][-1].text

    # 包装成 ToolMessage 返回

    return
 Command(update={
        "messages"
: [ToolMessage(message_text, tool_call_id=tool_call_id)]
    })

子代理的返回被简化成一条 ToolMessage,就像普通工具调用的返回值一样。主代理看不到子代理的中间步骤,只能看到最终结果。

这种设计有个直接后果:如果子代理执行过程中犯了错,但自己没发现,主代理通常也看不出来。所以子代理的提示词里一般都会强调"仔细检查你的工作"、"验证结果准确性"。

实战:政策研究 Agent

来做一个完整的例子。假设我们要做一个政策研究系统,任务是研究某个AI法规,分析其影响,生成报告。

这个任务天然适合拆分:

  • • 研究子代理 —— 搜集资料、查法规、找案例
  • • 分析子代理 —— 对比不同国家的做法、分析利弊
  • • 写作子代理 —— 把研究结果整理成专业报告
  • • 审核子代理 —— 检查报告质量、准确性、中立性

代码实现:

from deepagents import create_deep_agent, SubAgent
from
 langchain.tools import tool

@tool

def
 web_search(query: str) -> str:
    """Search the web for information"""

    # 实现省略

    return
 results

# 研究子代理

research_subagent = SubAgent(
    name="policy-researcher",
    description="Research AI policies and regulations using web search",
    system_prompt="""You are a policy research specialist.

Research the given topic thoroughly:
1. Search for official documents and sources
2. Find recent news and analysis
3. Compare different perspectives
4. Cite all sources with URLs

Return a comprehensive research summary."""
,
    tools=[web_search],
    model="openai:gpt-4o"
)

# 分析子代理

analysis_subagent = SubAgent(
    name="policy-analyst",
    description="Analyze policy implications and compare approaches",
    system_prompt="""You are a policy analyst.

Analyze the provided research:
1. Identify key stakeholders and their positions
2. Compare different regulatory approaches
3. Assess potential impacts (economic, social, technical)
4. Highlight areas of consensus and controversy

Provide structured analysis."""
,
    tools=[]  # 这个子代理不需要工具,只做分析
)

# 写作子代理

writer_subagent = SubAgent(
    name="report-writer",
    description="Write professional policy reports",
    system_prompt="""You are a professional policy report writer.

Write a clear, structured report:
- Executive summary
- Background and context
- Key findings
- Analysis and implications
- Recommendations
- References

Use formal but accessible language."""
,
    tools=[]
)

# 审核子代理

critique_subagent = SubAgent(
    name="quality-reviewer",
    description="Review reports for accuracy, clarity, and balance",
    system_prompt="""You are a quality assurance reviewer.

Review the report critically:
1. Check factual accuracy against research
2. Assess clarity and readability
3. Verify balanced perspective (no bias)
4. Confirm proper citations
5. Suggest specific improvements

Be thorough but constructive."""
,
    tools=[]
)

# 主代理

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    subagents=[
        research_subagent,
        analysis_subagent,
        writer_subagent,
        critique_subagent
    ],
    system_prompt="""You are a policy research coordinator.

When given a research topic:
1. First, delegate to policy-researcher to gather information
2. Then, pass research to policy-analyst for analysis
3. Then, pass analysis to report-writer for drafting
4. Finally, have quality-reviewer check the draft
5. Incorporate review feedback and deliver final report

Each step should build on the previous work."""

)

# 使用

result = agent.invoke({
    "messages"
: [{
        "role"
: "user",
        "content"
: "Research the EU AI Act's requirements for high-risk AI systems and its global impact"
    }]
})

这个流程是串行的,每个子代理完成一个阶段。如果想优化,研究阶段可以并行:一个子代理研究欧盟法规、一个研究美国做法、一个研究中国做法,然后汇总给分析子代理。

通用子代理

如果你不给 create_deep_agent 传任何子代理,它会自动给你补一个默认的 general-purpose 子代理。

这个默认子代理有什么特别?从源码看:

GENERAL_PURPOSE_SUBAGENT: SubAgent = {
    "name"
: "general-purpose",
    "description"
: "General-purpose agent for researching complex questions...",
    "system_prompt"
: "In order to complete the objective...",
}

它继承主代理的所有工具,有完整的文件操作、任务规划、上下文管理能力。你可以把它理解成主代理的一个"通用分身",专门用来隔离某类任务的上下文。

什么时候用通用子代理?

  • • 需要深入执行复杂任务,但不想污染主上下文
  • • 研究性工作,只需要最终结果
  • • 试错性质的探索,可能走弯路

通用子代理其实就是子代理系统的"保底选项"。如果你还不确定需不需要专门定制子代理,先上通用子代理,效果不够再细分。

调试子代理系统

子代理一多,调试复杂度马上就上来了。这里分享几个我觉得最实用的排查点。

看调用链

LangSmith 会完整记录主代理和子代理的调用关系。你可以看到:

  • • 主代理什么时候决定调用子代理
  • • 子代理收到的具体指令
  • • 子代理的执行过程
  • • 返回给主代理的结果

如果子代理返回的结果不符合预期,首先检查主代理给的指令是否清晰。

检查状态隔离

如果子代理似乎"知道"不该知道的信息,检查 _EXCLUDED_STATE_KEYS 是否被正确过滤。自定义 Backend 时要特别注意这点。

子代理超时

子代理如果陷入死循环或执行太久,可以通过 interrupt_on 配置超时控制:

agent = create_deep_agent(
    subagents=[...],
    interrupt_on={
        "task"
: {"timeout": 300}  # 5分钟超时
    }
)

结果太短

如果子代理返回的结果太简略,通常是因为子代理的提示词里没有明确要求"详细返回"。在 system_prompt 里加一句:"Provide detailed findings with specific examples and citations"。

小结

这一篇其实想说的也不复杂:子代理的价值,不在于"多几个 Agent 看起来更高级",而在于它把复杂任务拆成了更稳的执行单元。

SubAgentCompiledSubAgentAsyncSubAgent 这几种形态,对应的是不同的工程场景;task 工具的提示词,负责教主代理什么时候该委派;状态隔离,则保证这些分出去的活不会反过来把主线程搞乱。把这些东西拼起来,DeepAgents 做的就不只是"多 Agent 协作",而是一套比较完整的委派机制。

所以我更愿意把子代理理解成一种上下文治理手段,而不只是调度技巧。用好了,它能让 Agent 从"一个人硬扛所有事"变成"有人统筹、有人专做、结果再汇总"。

最后一篇,我们聊落地之技——CLI、HITL、Memory、LangSmith、生产部署。从原型到生产,还差哪些步骤?


延伸阅读

  • • SubAgent Best Practices: https://docs.langchain.com/oss/python/deepagents/subagents
  • • LangSmith Distributed Tracing: https://docs.smith.langchain.com/tracing
  • • Prompt Engineering for Tool Use: https://docs.anthropic.com/claude/docs/tool-use

练习建议

  1. 1. 创建一个包含两个子代理的系统,让它们并行处理独立任务
  2. 2. 观察 LangSmith 里的调用链,理解主代理和子代理的关系
  3. 3. 尝试定制子代理的 system_prompt,看看对输出质量的影响
  4. 4. 故意在子代理里制造错误,观察主代理如何处理失败结果

 

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询