Deep Agents 动态 Subagents 介绍

@sydneyrunkle
英语2天前 · 2026年6月29日
138K
300
52
12
555

TL;DR

Sydney Runkle 详细介绍了 Deep Agents 从工具调用向程序化编排的转变,使模型能够编写脚本来管理复杂的多阶段 Subagent 工作流。

随着 Agent 承担的任务越来越复杂,它们往往会面临两个难题:

  1. 大规模下可靠完成任务
  2. 管理自身的上下文

我们一直在尝试以所谓的 动态子 Agent 形式来应对这些挑战:Agent 不再通过通用工具调用来分发子任务,而是编写一个简短脚本来驱动子 Agent 的执行。这意味着模型可以利用其擅长的代码模式(如循环、分支或并发)来编写适合任务的编排逻辑。

为什么需要动态子 Agent?

Deep Agents 已经支持 子 Agent。它们可以隔离上下文,让主 Agent 委派离散的工作单元,并将中间结果排除在主上下文窗口之外。那么,为什么我们还需要动态子 Agent 呢?

使用普通的子 Agent 时,它们由主模型逐一直接调用。这在规模较小时可行。但当需要生成数百个子 Agent,或者编排逻辑是条件性或多阶段时,这种方式就会失效。

动态子 Agent 通过 程序化编排 解决了这个问题。Agent 不再逐轮进行工具调用,而是编写一个简短脚本来编排和调用子 Agent,并在一个轻量级解释器中运行它。

典型的例子:一个 Agent 处理一份 300 页文档的每一页。Agent 不会调用子 Agent 工具 300 次,而是编写一个循环:

javascript
1const results = await Promise.all(pages.map(page =>
2 task({ description: `总结第 ${page.number}`, subagentType: "summarizer" })
3));

这解锁了基于工具调用的编排无法可靠交付的两项能力:

大规模的确定性覆盖。 没有结构,Agent 会对范围做出判断,筛选 75 项中的 500 项就声称完成。而分发循环不会这样。覆盖范围成为一种结构性保证,而不是提示工程问题。

可靠的复杂编排。 将编排逻辑写成代码,比让模型将其重现为一系列工具调用更可靠,尤其是在扇出 + 综合、多阶段管道或条件分支的场景下。

这与 Claude Code 中的工作流递归语言模型 (RLMs) 的思路相同:模型编写代码,然后该代码分发更多的 Agent。

快速开始

动态子 Agent 需要两个东西:子 Agent 用于分发工作,以及一个 代码解释器:一个安全、轻量级的运行时,模型在此编写和执行编排代码。Deep Agents 包含一个基于 QuickJS 的可选代码解释器。要使用它,请安装 QuickJS 中间件包,然后通过 create_deep_agentmiddleware 参数传入 CodeInterpreterMiddleware

bash
1pip install -U "deepagents[quickjs]"
python
1from deepagents import create_deep_agent
2from langchain_quickjs import CodeInterpreterMiddleware
3
4agent = create_deep_agent(
5 model="openai:gpt-5.5",
6 middleware=[CodeInterpreterMiddleware()],
7)

Deep Agents 内置了一个通用的 子 Agent,因此已经有一个通用的子 Agent 模板可用于工作流。对于专门的工作流,请配置具有各自名称、描述和系统提示词的 自定义子 Agent:名称和描述是 Agent 知道该调用哪个角色的方式。

要触发动态子 Agent,请使用 "workflow" 这个词来提示你的 Agent,如下所示:

python
1result = await agent.ainvoke({
2 "messages": [{"role": "user", "content": "运行一个工作流,审查 src/routes/ 下的每个文件,并总结最严重的风险。"}]
3})

与编程 Agent 一起使用

体验动态子 Agent 最快的方式是使用 dcode,这是我们基于 Deep Agent 构建的终端编程 Agent。它默认启用代码解释器,所以无需任何配置——动态子 Agent 开箱即用。

安装

bash
1curl -LsSf https://langch.in/dcode | bash

运行

bash
1dcode

要触发动态子 Agent,只需要求进行一个 "工作流"。Agent 不会自己费力执行工作,也不会尝试使用其原生工具来管理子 Agent 扇出,而是编写一个编排脚本,调用内置的 task() 全局函数,并在代码解释器中执行它。例如:"运行一个 工作流,审查 src/ 中每个文件是否存在 SQL 注入漏洞。"

当子 Agent 生成时,dcode 会在动态子 Agent 面板中实时显示它们,并按分发阶段进行分组。

Sydney Runkle - inline image

你可以通过 dcode 最快地体验此功能,也可以通过 ACP(例如 Zed)在你选择的工具中使用它。

工作原理

Agent 被赋予一个 eval 工具。它编写在解释器内安全执行的 JavaScript 代码。当配置了 子 Agent 时,解释器会暴露一个内置的 task() 全局函数,用于从代码中分发它们。根据手头的任务,模型会编写不同的代码——一个循环、一个分支、一个 Promise.all——然后解释器确定性地执行它们。

Sydney Runkle - inline image

task() 接受一个描述 (description)、一个子 Agent 类型 (subagentType) 和一个可选的响应模式 (responseSchema)——当提供时,结果已经是一个类型化的对象,可以立即过滤或传递给下一步。

javascript
1const result = await task({
2 description: "审查 src/auth/login.ts 是否存在安全问题。",
3 subagentType: "reviewer",
4 responseSchema: {
5 type: "object",
6 properties: {
7 severity: { type: "string", enum: ["high", "medium", "low"] },
8 issues: { type: "array", items: { type: "string" } },
9 },
10 },
11});
12
13const critical = result.severity === "high" ? result.issues : [];
14critical; // 模型看到最后一行

更多信息,请参阅文档中的 程序化子 Agent解释器

常见编排模式

Anthropic 的 动态工作流 推广了一组用于并行 Agent 工作的编排模式。它们不是需要开启的功能。它们是工作中自然产生的形态,Agent 会根据任务的变化而切换到不同的模式。下表将每种形态映射到其适合的工作类型。

Sydney Runkle - inline image

下面我们将深入探讨每种模式在 Deep Agents 中的工作原理,并附上实时追踪。我们还制作了一个视频来解释这六种模式,你可以点击 这里 观看。

分类并执行

先对项目进行分类,然后每个项目根据其分类由专门的子 Agent 处理。这允许你处理混合输入,其中不同的项目需要不同的专业知识。

Sydney Runkle - inline image

使用场景: 对支持工单、错误日志、用户反馈或任何需要根据类型进行不同处理的批量项目进行分类。

示例:对支持工单积压进行分类。Agent 读取工单并将每个工单分类为 bug、功能请求或问题。bug 交给 bug 调查员,功能请求交给功能分析师,问题交给支持回复员。结果是一个按类别分组的摘要。

点击 这里 查看追踪。

扇出与综合

Agent 并行地将同一类工作分发给多个项目,然后合并结果。

Sydney Runkle - inline image

使用场景: 跨目录的代码审查,分析一批文档,处理日志文件,跨多个服务运行相同的检查。

示例:在源代码树中对每个文件进行安全审查。Agent 发现 src/ 下的所有 TypeScript 文件,并为每个文件并行分派一个安全审查官。然后将结果合并成一个单一的优先级报告,包含严重性评级和需要修改的代码行。

点击 这里 查看追踪。

对抗性验证

一种两阶段模式。第一阶段产生发现结果。第二阶段将每个发现结果发送给独立的验证器,只有通过一致性验证的发现结果才被保留。当置信度比速度更重要时,这可以减少误报。

Sydney Runkle - inline image

使用场景: 误报代价高昂的安全审计、合规性检查、任何需要对发现结果有高度信心的审查。

示例:一次不可接受误报的安全审计。审计员广泛撒网寻找潜在漏洞,然后将每个发现结果交给一个独立的验证器,该验证器重新阅读代码并返回 CONFIRMED(确认)或 REFUTED(反驳)的判断。只有被确认的发现结果才会进入最终报告。

点击 这里 查看追踪。

生成与过滤

多个子 Agent 为同一问题生成独立的解决方案。Agent 在代码中比较、评分和过滤结果,只保留最好的。

Sydney Runkle - inline image

使用场景: 架构提案、重构策略、内容变体、任何在承诺之前探索多个选项能产生更好结果的任务。

示例:对 rate-limiter.ts 的竞争性改写方案进行排序。Agent 让一个架构师生成多个独立的 rate-limiter.ts 改写方案,每个方案写入自己的文件以避免相互覆盖。然后根据突发流量下的正确性、多实例支持和复杂性进行评分。最强的方案胜出,并附带其胜出的理由。

点击 这里 查看追踪。

锦标赛

变体由一个裁判子 Agent 进行两两比较,优胜者通过淘汰赛晋级。

Sydney Runkle - inline image

使用场景: 在主观标准下的优化、风格选择、在竞争性实现之间做出选择。

示例:对一个混乱的 createOrder 处理程序的改写进行成对淘汰赛。几个编写者各自生成一个具有不同侧重点的候选改写方案,然后一个裁判对它们进行两两比较,逐轮晋级优胜者,直到一个冠军脱颖而出。它会返回裁判的推理过程。

点击 这里 查看追踪。

循环直到完成

Agent 运行一个发现循环,对已发现的结果进行去重,直到没有新结果出现。当工作的范围未知时,这非常有用。

Sydney Runkle - inline image

使用场景: 彻底搜索、死代码检测、依赖审计、任何追求完整性而非固定结果数量的扫描。

示例:基于多轮扫描的安全检查。Agent 运行一轮扫描,在代码中检查发现的内容,只有当上一轮发现了新问题时才开始新一轮扫描。当一轮扫描没有发现任何新问题时停止。它报告合并后的发现结果以及进行了多少轮扫描。

点击 这里 查看追踪。

结论

动态子 Agent 是你给 Agent 更多自主权和更高可靠性的方式。代码处理覆盖范围和中间上下文,而模型仍负责判断密集型工作。上述模式是一个起点。在实践中,Agent 会根据任务需求组合和混合使用它们。

这就是递归语言模型思想的最简单形式。一个编写代码的 Agent,并且该代码分发更多的 Agent。它是一个递归调用自身的 Agent,不受上下文窗口的限制,也不会被限制在固定的工作流中。Agent 可以根据需要将问题分解到任意深度,并以任何合适的形式重新组合这些片段。上面强调的编排模式只是对未来可能性的一瞥,但随着模型编写代码的能力越来越强,天花板只会越来越高。

动态子 Agent 就是 Deep Agents 今天将这种能力交到你手中的方式。现在就开始,为你的 Agent 添加一个代码解释器,或者直接使用 dcode,动态子 Agent 在那里开箱即用。

致谢

@colifran_@huntlovell 共同撰写。感谢 @hwchase17@masondrxy@chester_curme 的审阅。

存到 YouMind

使用 YouMind 深度阅读爆款文章

保存原文、追问细节、总结观点,并在一个 AI 工作空间里把爆款文章沉淀成可复用笔记。

了解 YouMind

更多可拆解样本

近期爆款文章

探索更多爆款文章