Subagents
新增于: @mastra/core@1.8.0
Subagent 是可由另一个 Agent 委托任务的专用 Agent。将它们添加到父 Agent 的 agents 属性,然后调用 Agent.stream() 或 Agent.generate()。父 Agent 会根据自身 instructions 和每个 Subagent 的 description,决定何时以及如何委托任务。
何时使用 Subagent何时使用 Subagent的直接链接
当一项任务需要不同专业方向的 Agent 协同工作时,请使用 Subagent。父 Agent 决定何时委托,并将上下文传递给每个 Subagent,然后综合它们的结果。
常见用例:
- 由一个 Agent 收集数据、另一个 Agent 生成内容的研究与写作工作流
- 每个阶段都需要不同专业知识的多步骤任务
- 需要对委托行为进行细粒度控制的任务
协调 Subagent 的父 Agent 通常称为 supervisor。Supervisor 模式是在 Mastra 中构建多 Agent 系统的一种方法。有关其他模式,请阅读概念概览。
快速入门快速入门的直接链接
使用清晰的 description 定义 Subagent,然后将它们添加到父 Agent:
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { LibSQLStore } from '@mastra/libsql'
const researchAgent = new Agent({
id: 'research-agent',
description: 'Gathers factual information and returns bullet-point summaries.',
model: 'openai/gpt-5-mini',
})
const writingAgent = new Agent({
id: 'writing-agent',
description: 'Transforms research into well-structured articles.',
model: 'openai/gpt-5-mini',
})
const parentAgent = new Agent({
id: 'parent-agent',
instructions: `You coordinate research and writing using specialized agents.
Delegate to research-agent for facts, then writing-agent for content.`,
model: 'openai/gpt-5.6-sol',
agents: { researchAgent, writingAgent },
memory: new Memory({
storage: new LibSQLStore({ id: 'storage', url: 'file:mastra.db' }),
}),
})
const stream = await parentAgent.stream('Research AI in education and write an article', {
maxSteps: 10,
})
for await (const chunk of stream.textStream) {
process.stdout.write(chunk)
}
委托 hook委托 hook的直接链接
委托 hook 允许你在委托发生时拦截、修改或拒绝委托。可以在 Agent 的 defaultOptions 或每次调用的 delegation 选项下配置。
onDelegationStartondelegationstart的直接链接
在父 Agent 委托给 Subagent 前调用。返回一个对象以控制委托:
proceed: true:允许委托(默认行为)proceed: false:使用rejectionReason拒绝委托modifiedPrompt:重写发送给 Subagent 的 promptmodifiedMaxSteps:限制 Subagent 的迭代次数
const stream = await parentAgent.stream('Research AI trends', {
maxSteps: 10,
delegation: {
onDelegationStart: async context => {
console.log(`Delegating to: ${context.primitiveId}`)
// Modify the prompt for a specific agent
if (context.primitiveId === 'research-agent') {
return {
proceed: true,
modifiedPrompt: `${context.prompt}\n\nFocus on 2024-2025 data.`,
modifiedMaxSteps: 5,
}
}
// Reject delegation after too many iterations
if (context.iteration > 8) {
return {
proceed: false,
rejectionReason: 'Max iterations reached. Synthesize current findings.',
}
}
return { proceed: true }
},
},
})
context 对象包括:
| 属性 | 说明 |
|---|---|
primitiveId | 被委托任务的 Subagent ID |
prompt | 父 Agent 正在发送的 prompt |
iteration | 当前迭代编号 |
requestContext | Subagent 运行将收到的 request context |
委托边界处的 request context委托边界处的 request context的直接链接
每次委托都会收到一个 request context,其中的条目从父级运行进行浅拷贝,但不包括运行范围内的身份键。在 Subagent 运行期间设置或删除条目不会影响父级 context。可在 onDelegationStart 中对 context.requestContext 设置条目,将值传递给受委托的运行:
const stream = await parentAgent.stream('Research AI trends', {
maxSteps: 10,
delegation: {
onDelegationStart: async context => {
context.requestContext.set('audience', 'technical')
},
},
})
Subagent 会在其 Tool 和动态配置中读取这些条目,例如 instructions: ({ requestContext }) => ...。详情请参阅 Request Context。要与持久化 Agent 配合使用,值必须可进行 JSON 序列化。
onDelegationCompleteondelegationcomplete的直接链接
在委托完成后调用。可用它检查结果或提供反馈,也可以停止执行:
context.bail():立即停止父 Agent 的循环- 返回
{ feedback: '...' }:添加反馈;该反馈会保存到父 Agent 的 Memory 中,并对后续迭代可见
const stream = await parentAgent.stream('Research AI trends', {
maxSteps: 10,
delegation: {
onDelegationComplete: async context => {
console.log(`Completed: ${context.primitiveId}`)
// Bail on errors
if (context.error) {
context.bail()
return {
feedback: `Delegation to ${context.primitiveId} failed: ${context.error}. Try a different approach.`,
}
}
},
},
})
context 对象包括:
| 属性 | 说明 |
|---|---|
primitiveId | 已运行的 Subagent ID |
result | Subagent 的响应 |
error | 委托失败时的错误 |
bail() | 用于停止父 Agent 循环的函数 |
消息过滤消息过滤的直接链接
默认情况下,Subagent 会从父 Agent 接收完整的对话上下文。使用 messageFilter 可控制共享哪些消息,例如移除敏感数据或限制上下文大小。
const stream = await parentAgent.stream('Research AI trends', {
maxSteps: 10,
delegation: {
messageFilter: ({ messages, primitiveId, prompt }) => {
// Remove messages containing sensitive data
return messages
.filter(msg => {
const content =
typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)
return !content.includes('confidential')
})
.slice(-10) // Only pass the last 10 messages
},
},
})
回调会收到 messages(完整对话历史记录)、primitiveId(Subagent ID)和 prompt(委托 prompt)。请返回过滤后的消息数组。
Subagent 结果上下文Subagent 结果上下文的直接链接
Subagent 完成后,父 Agent 的模型会在后续迭代中收到 Subagent 的文本响应。嵌套 Tool 调用和 Subagent 元数据(例如线程 ID 和资源 ID)不会添加到父 Agent 的模型上下文中。
应用代码和 UI 集成仍可在 Tool 结果 payload 中检查 subAgentToolResults 和委托原始结果的其余内容。
这使调试和显示数据保持可用,同时避免将嵌套 Tool 的参数或输出发回父 Agent 的下一次模型调用。
设置 includeSubAgentToolResultsInModelContext,可将完整的 Subagent 结果(包括嵌套 Tool 结果和 Subagent 元数据)包含在父 Agent 的模型上下文中。
await parentAgent.generate('Research AI trends', {
delegation: {
includeSubAgentToolResultsInModelContext: true,
},
})
迭代监控迭代监控的直接链接
每次父 Agent 循环迭代后都会调用 onIterationComplete。可用它监控执行或指导下一次迭代,也可以提前停止执行。
const stream = await parentAgent.stream('Research AI trends', {
maxSteps: 10,
onIterationComplete: async context => {
console.log(`Iteration ${context.iteration}/${context.maxIterations}`)
console.log(`Finish reason: ${context.finishReason}`)
// Inject feedback to guide the agent
if (!context.text.includes('recommendations')) {
return {
continue: true,
feedback: 'Please include specific recommendations in your analysis.',
}
}
// Stop early when the response is sufficient
if (context.text.length > 1000 && context.finishReason === 'stop') {
return { continue: false }
}
return { continue: true }
},
})
返回 { continue: true } 可继续迭代,返回 { continue: false } 可停止。包含可选的 feedback 可向对话注入指导。当 feedback 与 continue: false 结合使用时,模型可能获得最后一次机会来生成包含该反馈的文本响应,但前提是当前迭代仍处于活动状态(例如在 Tool 调用之后);否则不会获得额外轮次。
Memory 隔离Memory 隔离的直接链接
Mastra 会在委托期间隔离 Subagent Memory。Subagent 会收到完整对话上下文以便更好地作出决策,但其 Memory 中只会保存特定的委托 prompt 和响应。
工作方式:
- 转发完整上下文:父 Agent 委托时,Subagent 会收到父 Agent 对话中的所有消息
- 按范围保存 Memory:只有委托 prompt 和 Subagent 响应会保存到 Subagent 的 Memory
- 每次调用使用新线程:每次委托都使用唯一的线程 ID,确保完全隔离
因此,Subagent 能够获得所需上下文,而不会用父 Agent 的完整对话弄乱自身 Memory。有关更多详细信息,请访问多 Agent 系统中的 Memory。
Tool 审批传播Tool 审批传播的直接链接
Tool 审批会沿委托链传播。当 Subagent 使用设置了 requireApproval: true 的 Tool 或调用 suspend() 时,审批请求会出现在父 Agent 的流中。
const sensitiveDataTool = createTool({
id: 'get-user-data',
requireApproval: true,
execute: async input => {
return await database.getUserData(input.userId)
},
})
const dataAgent = new Agent({
id: 'data-agent',
tools: { sensitiveDataTool },
})
const parentAgent = new Agent({
id: 'parent-agent',
agents: { dataAgent },
memory: new Memory(),
})
const stream = await parentAgent.stream('Get data for user 123')
for await (const chunk of stream.fullStream) {
if (chunk.type === 'tool-call-approval') {
console.log('Tool requires approval:', chunk.payload.toolName)
}
}
取消取消的直接链接
向父 Agent 的 stream() 或 generate() 调用传入 abortSignal 时,Mastra 会将同一 signal 转发给受委托的 Subagent。调用 AbortController.abort() 会在进行中的 Subagent 运行进入下一步时将其取消,而不会让它们一直运行至完成。
const controller = new AbortController()
const stream = await parentAgent.stream('Research AI trends', {
abortSignal: controller.signal,
})
// Cancel the parent agent and any in-flight subagents
controller.abort()
任务完成度评分任务完成度评分的直接链接
Agent 不一定能在第一次尝试时就生成完整、正确的输出。任务完成度 Scorer 可以在每次迭代后验证任务是否完成。如果验证失败,父 Agent 会继续迭代。失败 Scorer 的反馈会包含在对话上下文中,让 Subagent 能够了解缺少了什么。
import { createScorer } from '@mastra/core/evals'
const taskCompleteScorer = createScorer({
id: 'task-complete',
name: 'Task Completeness',
}).generateScore(async context => {
const text = (context.run.output || '').toString()
const hasAnalysis = text.includes('analysis')
const hasRecommendations = text.includes('recommendation')
return hasAnalysis && hasRecommendations ? 1 : 0
})
const stream = await parentAgent.stream('Research AI in education', {
maxSteps: 10,
isTaskComplete: {
scorers: [taskCompleteScorer],
strategy: 'all',
onComplete: async result => {
console.log('Task complete:', result.complete)
},
},
})
Rubric ScorerRubric Scorer的直接链接
内置 Rubric Scorer 让你能够以检查清单的形式定义“正确”的标准,并让 Agent 进行自我评估和迭代,直到满足每项标准或达到 maxSteps。
它作为 LLM-as-judge Scorer 工作。每次迭代后,独立的评分模型会根据 rubric 审查 Agent 的输出。当所有必需标准都通过时,循环结束。失败标准会将其反馈添加到对话中,让 Agent 可以再次尝试。
这种方法最适合具有明确、可验证成功标准的任务。用法如下:
import { Agent } from '@mastra/core/agent'
import { createRubricScorer } from '@mastra/evals/scorers/prebuilt'
const parentAgent = new Agent({
id: 'parent-agent',
instructions: 'You coordinate research and writing using specialized agents.',
model: 'openai/gpt-5.6-sol',
agents: { researchAgent, writingAgent },
})
const rubricScorer = createRubricScorer({
model: 'openai/gpt-5-mini',
criteria: [
{ description: 'The response includes an analysis section' },
{ description: 'The response includes concrete recommendations' },
],
})
const stream = await parentAgent.stream('Research AI in education', {
maxSteps: 10,
isTaskComplete: {
scorers: [rubricScorer],
strategy: 'all',
},
})
如需完整 API 详情,请参阅 Rubric Scorer Reference。
编写有效的 instructions编写有效的 instructions的直接链接
清晰的 instructions 对有效委托至关重要。
父 Agent 的 instructions 应指定可用资源以及每项资源的使用时机,还应定义协调行为和成功标准。
每个 Subagent 都应具有明确的 description,说明其用途和返回格式,包括父 Agent 应在何时使用它。
父 Agent 使用这些 description 作出委托决策。
const parentAgent = new Agent({
id: 'parent-agent',
instructions: `You coordinate research and writing tasks.
Available resources:
- researchAgent: Gathers factual data and sources (returns bullet points)
- writingAgent: Transforms research into narrative content (returns full paragraphs)
Delegation strategy:
1. For research requests: Delegate to researchAgent first
2. For writing requests: Delegate to writingAgent
3. For complex requests: Delegate to researchAgent first, then writingAgent
Success criteria:
- All user questions are fully answered
- Response is well-formatted and complete`,
agents: { researchAgent, writingAgent },
})
在后台运行 Subagent在后台运行 Subagent的直接链接
Subagent 调用以 Tool 调用的形式分派,因此可以作为后台任务运行。当一个或多个委托需要长时间运行,而你不希望它们阻塞父 Agent 的响应时,这种方式很有用。
在 Mastra 实例上启用 backgroundTasks manager,然后在父 Agent 上选择启用 Subagent:
const parentAgent = new Agent({
id: 'parent-agent',
instructions: 'Coordinate research and writing using the available agents.',
model: 'openai/gpt-5.6-sol',
agents: { researchAgent, writingAgent },
backgroundTasks: {
tools: {
researchAgent: { enabled: true, timeoutMs: 900_000 },
writingAgent: { enabled: true, timeoutMs: 900_000 },
},
},
})
const stream = await parentAgent.streamUntilIdle('Research AI in education and write an article', {
memory: { thread: 't1', resource: 'u1' },
})
请使用 streamUntilIdle() 而不是 stream(),这样数据流会保持开放,直到 Subagent 完成且父 Agent 有机会响应其结果。
如果某个 Subagent 未列在父 Agent 的 backgroundTasks.tools 下,但拥有自己的后台可用 Tool,父 Agent 仍会将该 Subagent 作为后台任务分派,并继承其配置。详情请参阅从 Subagent 继承。
Subagent 版本控制Subagent 版本控制的直接链接
使用 editor 时,可以控制父 Agent 在运行时使用每个 Subagent 的哪个存储版本。可在 Mastra 实例上或每次调用时设置版本覆盖:
const result = await parentAgent.generate('Research and write about AI safety', {
versions: {
agents: {
'research-agent': { status: 'published' },
'writing-agent': { versionId: 'draft-456' },
},
},
})
版本覆盖会通过委托自动传播。有关解析顺序和 Server API 用法的详细信息,请参阅 Subagent 版本控制。