Subagent
新增於: @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 製作內容的研究及寫作 Workflow
- 每個階段需要不同專業知識的多步驟任務
- 需要精細控制委派行為的任務
協調 Subagent 的父 Agent 通常稱為 supervisor。Supervisor 模式是在 Mastra 建立多 Agent 系統的其中一種方式。如要了解其他模式,請閱讀概念概覽。
快速開始快速開始 的直接連結
為 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 的提示modifiedMaxSteps:限制 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 正在傳送的提示 |
iteration | 目前的迭代次數 |
requestContext | Subagent 執行時將會收到的請求上下文 |
委派邊界的請求上下文委派邊界的請求上下文 的直接連結
每次委派都會收到一個請求上下文,其項目是從父 Agent 執行的上下文淺層複製而來,但不包括執行範圍內的身份識別 key。在 Subagent 執行期間設定或刪除項目,不會影響父 Agent 的上下文。可在 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 }) => ...。詳情請參閱請求上下文。如要配合 durable Agent 使用,值必須可序列化為 JSON。
onDelegationCompleteondelegationcomplete 的直接連結
在委派完成後呼叫。可用它檢查結果、提供回饋,或停止執行:
context.bail():立即停止父 Agent 的循環- 傳回
{ feedback: '...' }:加入回饋;回饋會儲存至父 Agent 的記憶,並可供之後的迭代查看
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(委派提示)。請傳回篩選後的訊息陣列。
Subagent 結果上下文Subagent 結果上下文 的直接連結
Subagent 完成後,父 Agent 的模型會在之後的迭代中收到 Subagent 的文字回應。巢狀 Tool 呼叫及 Subagent metadata(例如 thread 和 resource ID)不會加入父 Agent 的模型上下文。
應用程式程式碼及 UI 整合仍可檢查 Tool 結果 payload 中的 subAgentToolResults,以及原始委派結果的其餘部分。
這樣既可保留除錯及顯示資料,又不會將巢狀 Tool 的引數或輸出傳回父 Agent 的下一次模型呼叫。
設定 includeSubAgentToolResultsInModelContext,即可在父 Agent 的模型上下文中加入完整的 Subagent 結果,包括巢狀 Tool 結果及 Subagent metadata。
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 一併使用時,模型可能會獲得最後一次 turn,以產生包含該回饋的文字回應;但只有目前的迭代仍在進行時(例如 Tool 呼叫後)才會如此,否則不會提供額外 turn。
記憶隔離記憶隔離 的直接連結
Mastra 會在委派期間隔離 Subagent 的記憶。Subagent 會收到完整的對話上下文,以便作出更佳決策,但只有其特定的委派提示及回應會儲存至其記憶。
運作方式:
- 轉發完整上下文:父 Agent 委派時,Subagent 會收到父 Agent 對話中的所有訊息
- 限定範圍的記憶儲存:只有委派提示及 Subagent 的回應會儲存至 Subagent 的記憶
- 每次呼叫使用全新 thread:每次委派都使用獨有的 thread ID,確保互相清楚分隔
因此,Subagent 可取得所需的上下文,而不會將父 Agent 的整段對話塞滿其記憶。詳情請參閱多 Agent 系統中的記憶。
Tool 核准傳遞Tool 核准傳遞 的直接連結
Tool 核准會沿委派鏈傳遞。當 Subagent 使用設有 requireApproval: true 的 Tool 或呼叫 suspend() 時,核准請求會顯示於父 Agent 的 stream 中。
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)
}
}
取消取消 的直接連結
將 abortSignal 傳給父 Agent 的 stream() 或 generate() 呼叫時,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 讓你以 checklist 定義「正確」的標準,並讓 Agent 自行評估及迭代,直至符合所有準則或達到 maxSteps。
它以 LLM-as-judge scorer 的方式運作。每次迭代後,另一個 grader 模型會按照 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 參考資料。
撰寫有效的 instructions撰寫有效的 instructions 的直接連結
清晰的 instructions 是有效委派的關鍵。
父 Agent 的 instructions 應指明可用資源及何時使用各項資源,亦應定義協調行為及成功準則。
每個 Subagent 都應有清晰的 description,說明其用途及傳回格式,包括父 Agent 應在何時使用它。
父 Agent 會使用這些描述作出委派決定。
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 instance 啟用 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(),令 stream 維持開啟,直至 Subagent 完成,而父 Agent 亦有機會回應其結果。
如果某個 Subagent 未列於父 Agent 的 backgroundTasks.tools 下,但擁有本身符合背景執行資格的 Tool,父 Agent 仍會將該 Subagent 分派為背景任務,並繼承其設定。詳情請參閱從 Subagent 繼承。
Subagent 版本控制Subagent 版本控制 的直接連結
使用 editor 時,你可控制父 Agent 在執行期間使用每個 Subagent 的哪一個已儲存版本。在 Mastra instance 或每次呼叫時設定版本覆寫:
const result = await parentAgent.generate('Research and write about AI safety', {
versions: {
agents: {
'research-agent': { status: 'published' },
'writing-agent': { versionId: 'draft-456' },
},
},
})
版本覆寫會自動透過委派傳遞。關於解析次序及伺服器 API 使用方式的詳情,請參閱 Subagent 版本控制。