> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # 背景任務 **新增於:** `@mastra/core@1.29.0` 背景任務讓 Agent 能分派長時間執行的 Tool 呼叫,而不會阻塞 Agent 迴圈。Tool 會立即傳回確認,LLM 可繼續回應,而任務則在背景執行至完成。完成後,結果會寫入記憶體;若你搭配 [`untilIdle`](https://mastra.zisheng.pro/zh-TW/reference/streaming/agents/stream) 選項使用 `stream()`,系統會自動再次叫用 Agent,讓同一次呼叫能處理該結果。 ## 何時使用背景任務 當 Tool 呼叫可能耗時較久,而使用者不應等到它完成才看到回應時,請使用背景任務。常見情況包括: - 子 Agent 委派的工作本身包含多步驟研究或寫作。 - Tool 呼叫需要存取速度較慢的外部服務、佇列或大型資料工作。 - 從 Tool 呼叫觸發的 Workflow 可能需要數分鐘才能完成。 對於很快就會傳回的 Tool 呼叫,使用 `agent.stream()` 和 `agent.generate()` 在前景執行會更簡單。 > **備註:** 背景任務要求 Mastra 執行個體已設定[儲存空間](https://mastra.zisheng.pro/zh-TW/docs/storage/overview)後端。任務會持久化,因此即使處理程序重新啟動也能繼續存在。 ## 快速開始 背景任務預設為停用。請在 Mastra 執行個體上設定 `backgroundTasks.enabled` 來啟用: ```typescript 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 設定參考](https://mastra.zisheng.pro/zh-TW/reference/configuration)。 ## 在背景執行 Tool 啟用管理器本身不會讓任何工作在背景執行,因為所有 Tool 預設都在前景執行。Tool 可在以下兩個層級之一選擇加入: 1. **Tool 層級設定**:Tool 本身宣告可在背景執行。 2. **Agent 層級設定**:Agent 宣告其哪些 Tool 可在背景執行。 Tool 選擇加入後,LLM 可視需要在 Tool 引數中加入 `_background` 欄位,針對特定呼叫覆寫解析後的設定(逾時、重試,或將呼叫改回前景執行)。 ### Tool 層級 在 Tool 定義上設定 `background.enabled: true`。透過此層級選擇加入的 Tool,只要由已啟用管理器的 Agent 呼叫,就會在背景執行。 ```typescript 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 的 `backgroundTasks.tools` 讓特定 Tool 選擇加入,或覆寫個別 Tool 的逾時時間;你也可以讓所有符合背景執行資格的 Tool 都在背景執行。使用 `disabled: true` 可完全略過該 Agent 的背景分派。 ```typescript 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 的單次呼叫覆寫 當 Tool 註冊於已啟用背景任務的 Agent 時,模型可在 Tool 引數中加入 `_background` 欄位,以覆寫該次呼叫解析後的設定。模型只需包含想覆寫的項目;`_background` 中的所有欄位皆為選填。Tool 執行前,系統會從引數中移除這項覆寫。 ```json { "topic": "solana", "_background": { "enabled": true, "timeoutMs": 900_000 } } ``` `_background` 覆寫只是套用於開發者已在 Tool 或 Agent 層級選擇加入之 Tool 的\_修飾設定\_,並不能單獨用來選擇加入。若 Tool 尚未選擇加入,模型提供的 `_background.enabled: true` 會被忽略,Tool 仍會在前景執行。如此可避免原本應確定在前景執行的 Tool(計算器、查詢、結構描述驗證器)在未察覺的情況下被分派為任務。 ### 解析順序 分派 Tool 呼叫時,系統會依下列優先順序計算解析後的背景設定: 1. 該 Tool 在 Agent 層級的 `backgroundTasks.tools` 項目。 2. Tool 層級的 `background` 設定。 3. LLM 的 `_background.enabled` 覆寫(只有 Tool 已在上述任一層級選擇加入時,才會用於啟用背景分派)。 4. 管理器預設值(`defaultTimeoutMs`、`defaultRetries`)。 若 Agent 設有 `backgroundTasks.disabled: true`,無論上述各層如何設定,每個 Tool 呼叫都會同步執行。 ## 背景任務相關的串流區塊 Tool 呼叫分派為背景任務後,兩種串流都可能提供其生命週期事件:Agent 本身的串流,以及 [`backgroundTaskManager.stream()`](https://mastra.zisheng.pro/zh-TW/docs/long-running-agents/background-tasks) SSE 串流。各串流涵蓋不同的區塊類型: | 區塊類型 | 觸發時機 | 發出來源 | | --------------------------- | ------------------------------------------------- | -------- | | `background-task-started` | 任務已排入佇列並取得 `taskId`。 | Agent 串流 | | `background-task-running` | 任務已由 Worker 取出並開始執行。 | 管理器串流 | | `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()` 會發出相同的兩種區塊,並額外訂閱該次執行記憶體範圍的管理器 pubsub,將七種管理器區塊(`background-task-running`、`background-task-output`、`background-task-completed`、`background-task-failed`、`background-task-cancelled`、`background-task-suspended`、`background-task-resumed`)導入同一個 `fullStream`。 `backgroundTaskManager.stream()` 只會發出這七種管理器區塊。 完整 payload 結構請參閱[背景任務區塊參考](https://mastra.zisheng.pro/zh-TW/reference/streaming/ChunkType)。 ## 使用 `untilIdle` 讓 Agent 串流保持開啟 即使背景任務仍在執行,`agent.stream()` 也會在 LLM 發出最終回應後傳回。若要讓串流保持開啟,直到所有已分派的背景任務都完成,且 LLM 有機會回應結果,請傳入 `untilIdle: true`: ```typescript 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 分鐘: ```typescript const stream = await agent.stream('Research solana for me', { memory: { thread: 't1', resource: 'u1' }, untilIdle: { maxIdleMs: 30_000 }, }) ``` 完整 API 請參閱 [`Agent.stream()`](https://mastra.zisheng.pro/zh-TW/reference/streaming/agents/stream)。 ### 彙總屬性 搭配 `untilIdle` 的 `stream()` 會傳回 `MastraModelOutput`,外觀與一般 `stream()` 呼叫的結果相同,但只有 `fullStream` 會橫跨初始輪次與所有自動接續輪次。彙總屬性(`text`、`toolCalls`、`toolResults`、`finishReason`、`messageList`、`getFullOutput()`)仍會針對**第一輪**的內部緩衝區解析。若需要跨接續輪次的彙總檢視,請自行取用 `fullStream` 並累積內容。 ## 在背景執行子 Agent 子 Agent 呼叫實際上會以 Tool 呼叫的形式分派,因此適用相同的背景設定。建議做法是在監督 Agent 上逐一讓子 Agent 選擇加入;這種方式更清楚,也能集中調整每個子 Agent 的 `timeoutMs`: ```typescript 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, }) ``` ### 繼承子 Agent 的設定 如果子 Agent 未列於監督 Agent 的 `backgroundTasks.tools`,但自身擁有符合背景執行資格的 Tool(透過 Tool 層級的 `background.enabled: true` 或自己的 `backgroundTasks.tools` 項目),框架仍會將整個子 Agent 呼叫分派為背景任務。監督 Agent 會繼承子 Agent 的意圖:子 Agent 本身會成為背景任務,而它的內部 Tool 則在子 Agent 迴圈中以前景方式執行。 繼承分派所使用的背景設定(例如 `waitTimeoutMs`)來自子 Agent 自己的 `backgroundTasks` 設定。 ```typescript 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` 由未替它設定 backgroundTask 的監督 Agent 委派,監督 Agent 仍會將整個 `researchAgent` 呼叫分派為背景任務;`deepResearchTool` 會在該呼叫內以前景方式執行,而不會再分派自己的巢狀背景任務。 若希望子 Agent 無論由哪個監督 Agent 呼叫,都能一致地在背景執行,請使用此模式。若希望集中針對每個監督 Agent 調整背景行為,請使用前述在監督 Agent 端選擇加入的方式。 ## 暫停與恢復 背景任務可在執行途中自行暫停,等待外部訊號後再繼續。這適合用於人工核准、Webhook,或下一個步驟取決於稍後抵達之資料的任何流程。 Tool 會從其 `execute` 內部呼叫 `suspend(data)`,其作用如下: - 在任務記錄上持久化 `status: 'suspended'` 與 `data` payload。 - 儲存 Workflow 快照,讓該次執行能在處理程序重新啟動後繼續存在。 - 在管理器串流上發出 `background-task-suspended` 區塊。 - 釋放並行執行配額,讓其他任務得以執行。 使用 `mastra.backgroundTaskManager.resume(taskId, resumeData)` 恢復任務。`resumeData` 會在恢復後的執行中,傳入 Tool 的 `execute` 選項,而任務會轉回 `running`。 ```typescript 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 會傳回實際結果。 核准資料送達後,請使用以下方式恢復任務: ```typescript await mastra.backgroundTaskManager?.resume(taskId, { reviewer: 'alice@example.com', edits: 'Reworded paragraph 3.', }) ``` ### Agent 迴圈會如何運作 搭配 `untilIdle` 的 `stream()` 執行期間,若任務中途暫停,包裝器會將它視為目前反覆運算的終止狀態並關閉。若取得恢復 payload 後要立即繼續 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`:全域範圍。 ```typescript 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()`,會傳回系統中每個任務事件的串流。連線時,串流會先發出所有目前執行中任務的快照,再轉送即時發生的事件。 ```typescript 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`,以便正常中斷連線。 ### 篩選串流 傳入任意篩選選項組合,即可縮小接收事件的範圍。篩選條件同時套用於初始快照及即時事件訂閱。 ```typescript const stream = bgManager.stream({ agentId: 'researcher', threadId: 't1', resourceId: 'u1', abortSignal: controller.signal, }) ``` | 篩選條件 | 說明 | | ------------- | ------------------- | | `agentId` | 僅限由此 Agent 分派之任務的事件 | | `runId` | 僅限這次特定 Agent 執行的事件 | | `threadId` | 僅限此記憶體對話串範圍內任務的事件 | | `resourceId` | 僅限此資源範圍內任務的事件 | | `taskId` | 僅限單一任務的事件 | | `abortSignal` | 訊號中止時關閉串流 | ### 直接查詢任務狀態 若只需單次查詢而非即時串流,請使用 `getTask` 和 `listTasks`: ```typescript const task = await mastra.backgroundTaskManager?.getTask(taskId) const { tasks, total } = await mastra.backgroundTaskManager?.listTasks({ status: 'running', agentId: 'researcher', }) ``` 這些方法會從儲存空間而非 pubsub 串流讀取資料,因此適合用於分頁清單及詳細資料檢視。 ## 相關內容 - [`Agent.stream()` 參考](https://mastra.zisheng.pro/zh-TW/reference/streaming/agents/stream) - [backgroundTasks 設定參考](https://mastra.zisheng.pro/zh-TW/reference/configuration) - [持久型 Agent](https://mastra.zisheng.pro/zh-TW/docs/long-running-agents/durable-agents) - [監督 Agent](https://mastra.zisheng.pro/zh-TW/docs/capabilities/subagents) - [串流區塊類型](https://mastra.zisheng.pro/zh-TW/reference/streaming/ChunkType) - [儲存空間](https://mastra.zisheng.pro/zh-TW/docs/storage/overview)