背景任務
新增於: @mastra/core@1.29.0
背景任務讓 Agent 分派長時間運行的 Tool 調用,而不會阻塞 Agent 迴圈。Tool 會立即傳回確認,LLM 繼續回應,而任務則在背景運行直至完成。完成後,結果會寫入記憶體;如果你使用 stream() 並啟用 untilIdle 選項,系統會自動再次調用 Agent,讓結果在同一次調用中得到處理。
何時使用背景任務何時使用背景任務 的直接連結
如果 Tool 調用可能需時較長,而你不希望用戶等待完成後才看到回應,便應使用背景任務。常見情況包括:
- 委派 subagent 進行多步驟研究或寫作。
- Tool 調用需要存取緩慢的外部服務、佇列或大型資料工作。
- 從 Tool 調用觸發、可能需時數分鐘才能完成的 Workflow。
對於能快速傳回結果的 Tool 調用,使用 agent.stream() 和 agent.generate() 在前景執行會較簡單。
背景任務要求在 Mastra 實例上設定好儲存空間後端。任務會持久儲存,因此即使程序重新啟動仍可繼續運行。
快速開始快速開始 的直接連結
背景任務預設為停用。請在 Mastra 實例上設定 backgroundTasks.enabled 來啟用:
import { Mastra } from '@mastra/core'
import { LibSQLStore } from '@mastra/libsql'
export const mastra = new Mastra({
storage: new LibSQLStore({ id: 'storage', url: 'file:mastra.db' }),
backgroundTasks: {
enabled: true,
globalConcurrency: 10,
perAgentConcurrency: 5,
backpressure: 'queue',
defaultTimeoutMs: 300_000,
},
})
完整選項載於 backgroundTasks 設定參考。
在背景運行 Tool在背景運行 Tool 的直接連結
啟用管理器本身不會令任何項目在背景運行,因為所有 Tool 預設都在前景執行。Tool 可在以下兩個層級之一選擇加入:
- Tool 層級設定:Tool 本身宣告可以在背景運行。
- Agent 層級設定:Agent 宣告其哪些 Tool 可以在背景運行。
Tool 選擇加入後,LLM 可選擇在 Tool 引數中加入 _background 欄位,為特定調用覆寫已解析的設定(逾時、重試次數,或將該次調用改回前景運行)。
Tool 層級Tool 層級 的直接連結
在 Tool 定義中設定 background.enabled: true。在此層級選擇加入的 Tool,只要由已啟用管理器的 Agent 調用,便會在背景運行。
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'
export const researchTool = createTool({
id: 'research',
description: 'Run a long research job',
inputSchema: z.object({ topic: z.string() }),
background: {
enabled: true,
timeoutMs: 600_000,
maxRetries: 1,
},
execute: async ({ topic }) => {
// Run the research job for topic
},
})
Agent 層級Agent 層級 的直接連結
使用 Agent 上的 backgroundTasks.tools,讓指定 Tool 選擇加入、覆寫個別 Tool 的逾時設定,或讓所有可在背景運行的 Tool 都在背景運行。使用 disabled: true 可完全中止該 Agent 的背景分派。
import { Agent } from '@mastra/core/agent'
export const researcher = new Agent({
id: 'researcher',
instructions: 'You research topics and answer questions.',
model: 'openai/gpt-5.6-sol',
tools: { researchTool, summarizeTool },
backgroundTasks: {
tools: {
researchTool: { enabled: true, timeoutMs: 600_000 },
summarizeTool: false,
},
},
})
設定 tools: 'all',即可讓 Agent 的所有 Tool 選擇加入。
LLM 的單次調用覆寫LLM 的單次調用覆寫 的直接連結
如果 Tool 已註冊至啟用背景任務的 Agent,模型可在 Tool 引數中加入 _background 欄位,覆寫該次調用的已解析設定。模型只需加入想覆寫的項目;_background 中所有欄位均為選填。Tool 運行前,系統會從引數移除這項覆寫。
{
"topic": "solana",
"_background": { "enabled": true, "timeoutMs": 900_000 }
}
_background 覆寫是對開發者已在 Tool 或 Agent 層級選擇加入之 Tool 的_修飾項_,不能單獨用來選擇加入。如果 Tool 尚未選擇加入,模型提供的 _background.enabled: true 會被忽略,Tool 仍會在前景運行。這可防止具確定性而只應在前景運行的 Tool(計算器、查詢、結構描述驗證器)在沒有提示的情況下被分派為任務。
解析次序解析次序 的直接連結
分派 Tool 調用時,系統按以下優先次序計算最終背景設定:
- 該 Tool 的 Agent 層級
backgroundTasks.tools項目。 - Tool 層級
background設定。 - LLM 的
_background.enabled覆寫(只會在 Tool 已於上述其中一個層級選擇加入時,用來啟用背景分派)。 - 管理器預設值(
defaultTimeoutMs、defaultRetries)。
如果 Agent 設有 backgroundTasks.disabled: true,無論上述層級如何設定,每次 Tool 調用都會同步運行。
與背景任務相關的串流區塊與背景任務相關的串流區塊 的直接連結
Tool 調用分派為背景任務時,兩個串流可能會顯示其生命週期事件:Agent 本身的串流,以及 backgroundTaskManager.stream() SSE 串流。每個串流涵蓋不同的區塊類型:
| 區塊類型 | 觸發時機 | 發出者 |
|---|---|---|
background-task-started | 任務已加入佇列,並獲指派 taskId。 | Agent 串流 |
background-task-running | 任務已由工作執行緒接手並開始執行。 | 管理器串流 |
background-task-progress | 顯示正在運行的背景任務數目。 | Agent 串流 |
background-task-output | 任務的 execute 所串流輸出的區塊。 | 管理器串流 |
background-task-completed | 任務已成功完成。payload.result 與最終 Tool 結果相符。 | 管理器串流 |
background-task-failed | 任務拋出錯誤或逾時。 | 管理器串流 |
background-task-cancelled | 任務在完成前已取消。 | 管理器串流 |
background-task-suspended | Tool 從其 execute 內調用了 suspend()。 | 管理器串流 |
background-task-resumed | 已透過 manager.resume(taskId, resumeData) 恢復暫停的任務。 | 管理器串流 |
agent.stream().fullStream 本身只會發出 Agent 迴圈區塊(background-task-started、background-task-progress)。使用 untilIdle: true 的 agent.stream() 會發出相同的兩種區塊,亦會為該次運行的記憶體範圍訂閱管理器的發佈/訂閱機制,並將七種管理器區塊(background-task-running、background-task-output、background-task-completed、background-task-failed、background-task-cancelled、background-task-suspended、background-task-resumed)傳送至同一個 fullStream。
backgroundTaskManager.stream() 只會發出七種管理器區塊。
完整的承載資料結構載於背景任務區塊參考。
使用 untilIdle 保持 Agent 串流開啟keep-the-agent-stream-open-with-untilidle 的直接連結
即使背景任務仍在運行,agent.stream() 亦會在 LLM 發出最終回應後傳回。如果你想串流保持開啟,直至所有已分派的背景任務完成,且 LLM 有機會回應結果,請傳入 untilIdle: true:
const stream = await agent.stream('Research solana for me', {
memory: { thread: 't1', resource: 'u1' },
untilIdle: true,
})
for await (const chunk of stream.fullStream) {
// chunks from the initial turn AND any continuation turns triggered by
// background task completions flow through here
}
背景任務完成後,結果會注入 Agent 記憶體,stream() 會重新進入 Agent 迴圈,讓 LLM 可以作出回應。當沒有任務正在運行,亦沒有完成事件等候處理時,串流便會關閉。
如要自訂閒置逾時,請傳入物件而非 true。計時器只會在包裝器等待兩個回合之間運行,因此首個 token 回應緩慢不會令串流關閉。預設值為 5 分鐘:
const stream = await agent.stream('Research solana for me', {
memory: { thread: 't1', resource: 'u1' },
untilIdle: { maxIdleMs: 30_000 },
})
完整 API 請參閱 Agent.stream()。
彙總屬性彙總屬性 的直接連結
使用 untilIdle 的 stream() 會傳回與一般 stream() 調用相似的 MastraModelOutput,但只有 fullStream 會橫跨初始回合及所有自動延續回合。彙總屬性(text、toolCalls、toolResults、finishReason、messageList、getFullOutput())仍會根據首個回合的內部緩衝區解析。如需涵蓋所有延續回合的彙總檢視,請自行使用並累積 fullStream。
在背景運行 subagent在背景運行 subagent 的直接連結
subagent 調用在底層會以 Tool 調用方式分派,因此適用相同的背景設定。建議做法是在 supervisor 上讓每個 subagent 選擇加入;這樣較清晰,亦可在同一處為每個 subagent 調整 timeoutMs:
import { Agent } from '@mastra/core/agent'
const supervisor = new Agent({
id: 'supervisor',
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 supervisor.stream('Research AI in education and write an article', {
memory: { thread: 't1', resource: 'u1' },
untilIdle: true,
})
從 subagent 繼承從 subagent 繼承 的直接連結
如果 subagent 未列於 supervisor 的 backgroundTasks.tools 之下,但它本身有可在背景運行的 Tool(透過 Tool 層級的 background.enabled: true 或其本身的 backgroundTasks.tools 項目),框架仍會將整個 subagent 調用分派為背景任務。supervisor 會繼承 subagent 的意圖:subagent 本身成為背景任務,而其內部 Tool 則在 subagent 迴圈內以前景方式運行。
繼承分派所使用的背景設定(例如 waitTimeoutMs)源自 subagent 本身的 backgroundTasks 設定。
const researchAgent = new Agent({
id: 'research-agent',
description: 'Gathers factual information.',
model: 'openai/gpt-5-mini',
tools: { deepResearchTool },
backgroundTasks: {
tools: {
deepResearchTool: { enabled: true, timeoutMs: 600_000 },
},
waitTimeoutMs: 900_000,
},
})
從沒有為 researchAgent 設定背景任務的 supervisor 委派至此 researchAgent 時,supervisor 仍會將整個 researchAgent 調用分派為背景任務,而 deepResearchTool 會在該次調用內以前景方式運行,不會分派其本身的巢狀背景任務。
如果你希望 subagent 無論由哪個 supervisor 調用,都能在背景保持一致的行為,請使用此模式。如果你希望在每個 supervisor 集中調整背景行為,請使用上述 supervisor 端選擇加入方式。
暫停與恢復暫停與恢復 的直接連結
背景任務可以在執行途中自行暫停,等待外部訊號後才繼續。這適用於人工核准、webhook,或下一步需要等待稍後到達之資料的任何流程。
Tool 從其 execute 內調用 suspend(data),其作用如下:
- 在任務記錄上持久儲存
status: 'suspended'及data承載資料。 - 儲存 Workflow 快照,讓該次運行可在程序重新啟動後繼續。
- 在管理器串流上發出
background-task-suspended區塊。 - 釋放並行運行名額,讓其他任務可以運行。
使用 mastra.backgroundTaskManager.resume(taskId, resumeData) 恢復任務。恢復運行時,resumeData 會傳入 Tool 的 execute 選項,而任務會轉回 running 狀態。
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'
export const reviewTool = createTool({
id: 'review',
description: 'Submit a draft for human review.',
inputSchema: z.object({ draft: z.string() }),
outputSchema: z.object({ approvedBy: z.string(), edits: z.string().optional() }),
background: { enabled: true },
execute: async ({ draft }, context) => {
const { suspend, resumeData } = context.agent
if (!resumeData) {
await suspend?.({ awaiting: 'approval', draft })
return { approvedBy: '', edits: undefined }
}
const { reviewer, edits } = resumeData as { reviewer: string; edits?: string }
return { approvedBy: reviewer, edits }
},
})
首次調用 execute 時會看到 resumeData === undefined,並調用 suspend。任務恢復後,執行環境會以已填入的 resumeData 重新啟動 Tool。此時 if 條件為 false,因此 Tool 會傳回實際結果。
核准到達後,可按以下方式恢復任務:
await mastra.backgroundTaskManager?.resume(taskId, {
reviewer: 'alice@example.com',
edits: 'Reworded paragraph 3.',
})
Agent 迴圈會如何運作Agent 迴圈會如何運作 的直接連結
如果任務在使用 untilIdle 的 stream() 運行途中暫停,包裝器會將其視為當前反覆運算的終止狀態並關閉。如要在收到恢復承載資料後立即繼續 Agent,請調用 agent.resumeStream(resumeData, { runId, toolCallId, memory, untilIdle: true }):恢復的背景任務會運行至完成,結果會加入訊息清單,而 Agent 會運行後續回合;整個過程均使用同一個 SSE 連線。如果你想在頻帶外控制恢復,請直接調用 mastra.backgroundTaskManager.resume(taskId, resumeData),結果仍會寫入對話串,供下一個用戶回合讀取。
恢復時重新註冊執行器恢復時重新註冊執行器 的直接連結
管理器會在程序記憶體中保留 Tool 執行器。如果程序在任務暫停期間重新啟動,執行器閉包便會消失,resume() 的調用者必須先透過 manager.registerTaskContext(taskId, ...) 重新註冊。在同一程序內分派及恢復的任務無需執行此步驟。
取消已暫停的任務取消已暫停的任務 的直接連結
manager.cancel(taskId) 對已暫停任務的運作方式與運行中任務相同。資料列會變為 cancelled,而 Workflow 快照則會清除。隨後會觸發 task.cancelled 事件。
生命週期回呼生命週期回呼 的直接連結
每個層級都可註冊終止狀態回呼。它們不會互相取代,而成功/失敗掛鈎會在相應結果出現時觸發:
- Tool 層級
background.onComplete/onFailed:適用範圍為單一 Tool。 - Agent 層級
backgroundTasks.onTaskComplete/onTaskFailed:適用範圍為此 Agent 分派的所有任務。 - 管理器層級
onTaskComplete/onTaskFailed:全域適用。
export const mastra = new Mastra({
storage,
backgroundTasks: {
enabled: true,
onTaskComplete: task => {
logger.info('Background task complete', { taskId: task.id, toolName: task.toolName })
},
onTaskFailed: task => {
logger.error('Background task failed', { taskId: task.id, error: task.error })
},
},
})
串流串流 的直接連結
訂閱所有任務事件訂閱所有任務事件 的直接連結
不帶篩選條件調用 stream(),會傳回系統中每個任務事件的串流。連線時,串流會發出所有當時正在運行之任務的快照,之後再即時轉送事件。
const bgManager = mastra.backgroundTaskManager
if (!bgManager) throw new Error('Background tasks are not enabled')
const controller = new AbortController()
const stream = bgManager.stream({ abortSignal: controller.signal })
for await (const chunk of stream) {
switch (chunk.type) {
case 'background-task-running':
console.log('started', chunk.payload.taskId, chunk.payload.toolName)
break
case 'background-task-completed':
console.log('done', chunk.payload.taskId, chunk.payload.result)
break
case 'background-task-failed':
console.error('failed', chunk.payload.taskId, chunk.payload.error)
break
}
}
串流會保持開啟,直至調用者的 AbortSignal 觸發。請務必傳入 abortSignal,以便妥善中斷連線。
篩選串流篩選串流 的直接連結
傳入任何篩選選項組合,即可縮窄接收事件的範圍。篩選條件同時適用於初始快照及即時事件訂閱。
const stream = bgManager.stream({
agentId: 'researcher',
threadId: 't1',
resourceId: 'u1',
abortSignal: controller.signal,
})
| 篩選條件 | 說明 |
|---|---|
agentId | 只接收由此 Agent 分派的任務事件 |
runId | 只接收此特定 Agent 運行的事件 |
threadId | 只接收限定於此記憶體對話串的任務事件 |
resourceId | 只接收限定於此資源的任務事件 |
taskId | 只接收單一任務的事件 |
abortSignal | 訊號中止時關閉串流 |
直接查閱任務狀態直接查閱任務狀態 的直接連結
如要單次查閱而非使用即時串流,請使用 getTask 和 listTasks:
const task = await mastra.backgroundTaskManager?.getTask(taskId)
const { tasks, total } = await mastra.backgroundTaskManager?.listTasks({
status: 'running',
agentId: 'researcher',
})
這些方法會從儲存空間而非發佈/訂閱串流讀取資料,因此適合分頁清單及詳細資料檢視。