跳转到内容

团队 - 委派模式

Supervisor(主智能体)委派子智能体,适合“一次性找个专家帮忙”。用户仍然只和主智能体对话;主智能体在需要时调用一个临时子智能体,让它完成一个明确任务,再把子智能体的最终答案以 tool_result 形式取回。

这个模式适合:

  • explore 子智能体:读取代码库并报告相关发现。
  • plan 子智能体:给出实现方案。
  • review 子智能体:检查一次 patch。
  • implement 子智能体:真正动手写代码,产出一个明确的 artifact,并汇报改了什么、如何验证。

这个模式中,子智能体只为一次请求运行,返回一个结果,然后由 supervisor 决定下一步。

import {
agentTool,
createAgent,
} from "agent-lattice";
const explorer = createAgent({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/anthropic",
model: "deepseek-v4-flash",
name: "explorer",
systemPrompt: [
"你是 explore 子智能体。",
"检查仓库,找出相关文件,并输出简洁发现。",
"不要修改代码。",
].join("\n"),
workspace: ".agent-workspaces/explorer",
});
const supervisor = createAgent({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/anthropic",
model: "deepseek-v4-flash",
name: "supervisor",
systemPrompt: "你负责监督任务,并在需要时调用专门的子智能体。",
tools: [
agentTool("explore", explorer, {
description: "让一个临时 explore 子智能体检查代码库并报告发现。",
}),
],
});
const result = await supervisor.prompt("找出 SDK team delegation 涉及的模块。");
console.log(result.result);

当 supervisor 智能体用 mode: "ask" 调用 explore 工具时,SDK 会调用 explorer.prompt(...)explorer 的最终结果会成为 supervisor 这一轮的 tool_result,然后 supervisor 继续自己的 agent loop。

agentTool() 把子智能体包装成一个普通工具——返回的就是一个 ToolDefinition,用法和任何自定义 tool 一样,丢进 createAgenttools 即可。对 supervisor 模型来说,它和别的工具毫无区别;唯一的不同在内部:模型调用它时,SDK 不执行代码,而是转去运行被包装的子智能体,再把结果作为工具结果返回。

这个工具暴露给模型的是一套标准输入:

{
mode: "ask",
task: "检查 SDK team runtime,并总结相关文件。",
expectedOutput: "简洁的文件地图和实现笔记",
acceptanceCriteria: [
"提到 runner 入口",
"提到 mailbox 状态转换"
]
}

对于一次性 supervisor 委派,优先使用 mode: "ask"

模式 在 supervisor 委派中的含义
ask 立即运行子 AgentLike,并把它的最终答案作为当前工具结果返回。
handoff 需要 team runtime。没有 runtime 时会返回明确错误。异步 handoff 应该使用 mailbox team。
observe 预留给可观察长任务。当前除非宿主 runtime 提供支持,否则会报告 unsupported。

这里的 team runtime 指驱动 mailbox 持久团队的运行时——它维护消息队列、保存任务状态,并负责 handoff 之后成员的生命周期。本模式是一次性委派,默认没有 runtime,所以 handoff / observe 基本用不上;需要它们时请改用 Mailbox Team 持久团队

AgentToolOptions 还接收 metadata:一个宿主持有的 Record<string, unknown>,原样透传到生成的 ToolDefinition.metadata(例如契约版本)。SDK 不读也不解释它,也不会展示给模型。需要 0.22.0 及以上版本。

需要 0.15.0 及以上版本。

agentTool() 的 target 既可以传存活的 AgentLike 会话(如上例),也可以传 defineAgent() 创建的 AgentSpec 模板:

import { agentTool, defineAgent } from "agent-lattice";
const explorerSpec = defineAgent({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/anthropic",
model: "deepseek-v4-flash",
name: "explorer",
systemPrompt: "You are an explore subagent. Inspect and report; do not make code changes.",
});
const supervisor = createAgent({
// ...
tools: [
agentTool("explore", explorerSpec, {
description: "Ask a temporary explore subagent to inspect the codebase and report findings.",
}),
],
});

模板目标会在每次工具调用时 spawn 一个全新会话——不相关的任务之间不会泄漏历史,并发调用也不会争抢同一段对话。会话目标则跨调用保留历史,先前的任务可能影响后续回答。Supervisor 委派场景优先传模板;只有当专家需要记住之前的任务时,才注册 spec.spawn() 产生的会话。生成的工具描述会声明目标是哪种语义,supervisor 模型据此知道任务是否必须自包含。

需要 0.20.0 及以上版本。

当子智能体的交付物应该是带类型的数据而不是一段散文时,在子级声明一份 OutputSchema(zod schema 直接可用):子 agent 必须通过注入的 submit_output 工具提交答案,父级一侧负责校验返回的内容。自 0.21.0 起 agentTool() 会从 target 的声明继承 schema——AgentSpecspec.options.outputSchema,活 Agent 走 outputSchema getter——父级这份可以省略:

import { agentTool, createAgent } from "agent-lattice";
import { z } from "zod/v4";
const findingsSchema = z.object({
files: z.array(z.string()),
notes: z.string(),
});
const explorer = createAgent({
model: "deepseek-v4-flash",
name: "explorer",
systemPrompt: "你是 explore 子智能体。检查并报告;不要修改代码。",
outputSchema: findingsSchema,
});
const supervisor = createAgent({
model: "deepseek-v4-flash",
name: "supervisor",
tools: [
agentTool("explore", explorer, {
description: "让一个临时 explore 子智能体检查代码库并报告发现。",
// outputSchema 自 target 继承(0.21.0+)。
}),
],
});

mode: "ask" 时,工具结果是子级校验后的结构化输出序列化成的 JSON 字符串,生成的工具描述也会告诉 supervisor 模型这一点。如果子级没有提交就结束了,或提交的内容没通过 schema 校验,工具会返回一条以 child_output_invalid: 开头的 is_error tool_result——这在 supervisor 的 loop 里就是一条普通的工具错误,supervisor 可以重试或换个说法再派。runtime delegate 路径同理:子级失败会抛 child_output_invalid,并带上原始的 failure code 和 message。

结构由 harness 把守,而不是靠 prompt 纪律;与 outputFormat 不同,它不依赖各 provider 的 response_format/json_schema 特性——任何支持工具调用的 provider 都能用(见 Provider 兼容性)。

需要 0.21.0 及以上版本。

仍然可以显式传 AgentToolOptions.outputSchema,但它必须与 target 的声明一致——先按引用相等比较,再按派生 JSON Schema 的结构比较。不一致时 agentTool() 在装配期直接抛错,错误信息会建议在 createAgent/defineAgentagentTool() 之间共享一个 schema 实例,或省略 agentTool() 这份直接继承。宿主自定义的 AgentLike 适配器没有可读的声明,因此对它们既不继承也不核对——显式传的 outputSchema 仍然生效。

自 0.23.0 起还固定了一种组合:target 未声明 schema、agentTool() 显式声明时,装配期放行(没有可核对的对象),ask 会把子级的 structuredResult 按父级这份 schema 校验后以 JSON 返回。这适合子级用自造的 endTurn + structuredResult 工具做 schema 之外的领域校验(如引用真实性)、契约由父级单方面声明的场景。

*0.21.0 行为变化:*子级声明了 outputSchema 而父级没声明的现存代码,ask 的工具结果从固定文本 "Structured output submitted." 变为校验后的 JSON。这是修复意图,0.x 阶段随 minor 发布。

需要 0.23.0 及以上版本。

父子都没声明 outputSchema 时,如果子级带着 structuredResult 结束(经自定义 endTurn 工具),ask 的工具结果会原样返回它的 JSON——不做校验——而不是回退成文本 content 把它丢掉。信任等级与回文本相同;schema 的职责收敛为「校验」,不再是结构化通道的开关。直连路径和 team runtime delegate 路径都生效。

*0.23.0 行为变化:*现存「子级 endTurnstructuredResult、父级无 schema」的代码,ask 的结果从文本变为结构化 JSON。

需要 0.21.0 及以上版本。

AgentToolOptions.inputSchema 把默认的 {mode, task, expectedOutput, acceptanceCriteria, workspaceGrants} 输入形状换成你自己的 schema,mapInput 负责把校验后的 typed 入参投影成子级 prompt:

const judge = createAgent({
model: "deepseek-v4-flash",
name: "judge",
systemPrompt: "你负责判案并提交结构化裁决。",
outputSchema: verdictSchema,
});
const judgeTool = agentTool("judge", judge, {
description: "根据案情摘要和文档判案。",
inputSchema: z.object({
caseSummary: z.string(),
documents: z.array(z.object({ title: z.string(), content: z.string() })),
}),
mapInput: input => renderJudgeTask(input.caseSummary, input.documents),
});

父模型的入参先按 inputSchema parse,不合格当场作为 error tool_result 打回 supervisor 的 loop——与普通 tool() 的打回语义一致——子级不会被调用。inputSchemamapInput 必须成对出现,缺一个在 agentTool() 装配期抛错。Typed 委派是 ask-only:没有 mode 字段,也没有 workspaceGrantsmapInput 可以返回 string 或 ContentBlock[],但 ContentBlock[] 只支持直连 ask 调用;在 team runtime 里投影出的 prompt 必须是 string,否则运行时报错。

每个子智能体都有自己的 workspace。对于报告、日志、生成文件或代码等持久交付物,让子智能体写在自己的 workspace 下,并在最终文本里说明关键路径。

workspace 是可选的。不传时 SDK 会按智能体的 name 自动分配一个默认工作区 ~/.agent/workspaces/<name>/(没有 name 则用 agent-<sessionId>),并在首次运行时自动创建。大多数情况下直接用默认即可——它已经按智能体隔离,而且落在仓库目录之外,不会污染项目。只有当你想把产物放到指定位置(例如仓库内某个目录)时,才需要显式传 workspace,就像下面这样:

const reviewer = createAgent({
model: "deepseek-v4-flash",
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/anthropic",
systemPrompt: "检查 patch,并把 review notes 写入你的 workspace。",
workspace: ".agent-workspaces/reviewer",
});

本模式里子智能体的交付物就是一段自然语言 tool_result(说明做了什么、产物在 workspace 的哪个路径、怎么验证)——没有持久状态、消息队列或结构化事件协议。

当工作需要留在团队里——持久状态、具名成员 mailbox、可回复/可跟进、可持久化,或需要嵌套团队——请改用 Mailbox Team 持久团队。一句话区分:Supervisor 委派是“现在调用这个 helper 拿一个结果”;mailbox team 是“把任务放进 mailbox,由成员按消息流完成并回报”,过程中还产出 team_message / team_agent 等结构化事件,供 tracing 和 UI 使用。