백그라운드 작업
추가된 항목: @mastra/core@1.29.0
백그라운드 작업을 사용하면 Agent가 Agent 루프를 차단하지 않고 장기 실행 Tool 호출을 위임할 수 있습니다. Tool은 즉시 확인 응답을 반환하고 LLM은 응답을 계속 생성하며, 작업은 백그라운드에서 완료될 때까지 실행됩니다. 완료되면 결과가 Memory에 기록되며, untilIdle 옵션과 함께 stream()을 사용하면 Agent가 자동으로 다시 호출되어 동일한 호출 내에서 결과를 처리합니다.
백그라운드 작업을 사용해야 하는 경우백그라운드 작업을 사용해야 하는 경우에 대한 직접 링크
Tool 호출이 사용자가 응답을 보기 전에 기다릴 수 없을 만큼 오래 걸릴 수 있는 경우 백그라운드 작업을 사용하십시오. 일반적인 경우:
- 자체적으로 다단계 조사 또는 작성을 실행하는 하위 Agent 위임입니다.
- 느린 외부 서비스, 대기열 또는 대규모 데이터 작업에 대한 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 configuration reference.
백그라운드에서 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을 백그라운드에서 실행할 수 있습니다. Agent의 백그라운드 위임을 완전히 차단하려면 disabled: true를 사용하세요.
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,
},
},
})
Agent가 보유한 모든 Tool을 옵트인하려면 tools: 'all'을 설정하세요.
LLM 호출별 재정의LLM 호출별 재정의에 대한 직접 링크
백그라운드 작업이 활성화된 Agent에 Tool이 등록되면 Model은 Tool 인수에 _background 필드를 포함하여 해당 호출에 대해 결정된 구성을 재정의할 수 있습니다. Model은 재정의하려는 항목만 포함하며 _background의 모든 필드는 선택 사항입니다. Tool이 실행되기 전에 이 재정의 항목은 인수에서 제거됩니다.
{
"topic": "solana",
"_background": { "enabled": true, "timeoutMs": 900_000 }
}
_background 재정의는 개발자가 Tool 또는 Agent 계층에서 이미 옵트인한 Tool에 적용되는 수정자이며, 독립적인 옵트인 수단이 아닙니다. Tool이 옵트인되지 않았다면 Model의 _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 | The task has been enqueued and assigned a taskId. | Agent stream |
background-task-running | 작업이 worker에 할당되어 실행을 시작했습니다. | Manager stream |
background-task-progress | 실행 중인 background tasks 수를 표시합니다. | Agent stream |
background-task-output | A streamed output chunk from the task's execute. | Manager stream |
background-task-completed | The task finished successfully. The payload.result matches the eventual tool result. | Manager stream |
background-task-failed | The task threw or timed out. | Manager stream |
background-task-cancelled | 작업이 완료되기 전에 취소되었습니다. | Manager stream |
background-task-suspended | The tool called suspend() from inside its execute. | Manager stream |
background-task-resumed | A suspended task was resumed via manager.resume(taskId, resumeData). | Manager stream |
agent.stream().fullStream은 Agent 루프 청크(background-task-started, background-task-progress)만 자체적으로 내보냅니다. untilIdle: true와 함께 사용하는 agent.stream()은 동일한 두 청크를 내보내며, 추가로 실행의 Memory 범위에 대한 관리자 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()7개의 관리자 청크만 내보냅니다.
전체 페이로드 형태는background task chunks reference.
다음을 사용하여 Agent 스트림을 열어두세요.untilIdlekeep-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 Memory에 주입되고, stream()이 Agent 루프에 다시 진입하여 LLM이 결과에 반응할 수 있게 합니다. 실행 중인 작업이 없고 대기 중인 완료 항목도 없으면 스트림이 닫힙니다.
true 대신 객체를 전달하여 유휴 시간 제한을 맞춤 설정하세요. 타이머는 래퍼가 턴 사이에서 대기할 때만 실행되므로 첫 토큰이 늦어도 스트림이 닫히지 않습니다. 기본값은 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을 직접 소비하고 누적하세요.
백그라운드의 하위 Agent백그라운드의 하위 Agent에 대한 직접 링크
하위 Agent 호출은 내부적으로 Tool 호출로 위임되므로 동일한 백그라운드 구성이 적용됩니다. 권장 패턴은 감독자에서 각 하위 Agent를 옵트인하는 것입니다. 이 방식이 더 명확하며 한곳에서 하위 Agent별 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,
})
하위 Agent에서 상속하위 Agent에서 상속에 대한 직접 링크
하위 Agent가 감독자의 backgroundTasks.tools에 나열되어 있지 않지만 자체적으로 백그라운드 실행이 가능한 Tool을 보유한 경우(Tool 수준의 background.enabled: true 또는 자체 backgroundTasks.tools 항목을 통해), 프레임워크는 여전히 전체 하위 Agent 호출을 백그라운드 작업으로 위임합니다. 감독자는 하위 Agent의 의도를 상속합니다. 즉, 하위 Agent 자체가 백그라운드 작업이 되고 내부 Tool은 하위 Agent 루프 안에서 포그라운드로 실행됩니다.
상속된 위임에 사용되는 백그라운드 구성(예: waitTimeoutMs)은 하위 Agent 자체의 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에 대한 backgroundTask 구성이 없는 감독자가 researchAgent에 작업을 위임하더라도, 감독자는 전체 researchAgent 호출을 백그라운드 작업으로 위임합니다. 이때 deepResearchTool은 자체적으로 중첩된 백그라운드 작업을 위임하는 대신 해당 호출 내부의 포그라운드에서 실행됩니다.
어떤 감독자가 호출하는지에 관계없이 하위 Agent가 백그라운드에서 일관되게 작동하도록 하려면 이 패턴을 사용하십시오. 감독자별로 중앙에서 백그라운드 동작을 조정하려면 감독자 측 옵트인(위)을 사용하십시오.
일시중단 및 재개일시중단 및 재개에 대한 직접 링크
백그라운드 작업은 실행 중에 자체를 일시 중지하고 계속하기 전에 외부 신호를 기다릴 수 있습니다. 이는 사람의 승인, 웹후크 또는 다음 단계가 나중에 도착하는 데이터에 따라 달라지는 모든 흐름에 유용합니다.
Tool은 execute 내부에서 suspend(data)를 호출하며, 이 호출은 다음을 수행합니다.
- 작업 레코드에
status: 'suspended'와data페이로드를 영속화합니다. - 프로세스가 다시 시작되어도 실행을 유지할 수 있도록 Workflow 스냅샷을 저장합니다.
- Manager 스트림에
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 조건이 거짓이 되므로 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)를 직접 호출하세요. 이 경우에도 결과는 스레드에 기록되어 다음 사용자 턴에서 사용할 수 있습니다.
이력서에 실행자를 다시 등록이력서에 실행자를 다시 등록에 대한 직접 링크
Manager는 Tool 실행기를 프로세스 Memory에 유지합니다. 작업이 일시 중지된 동안 프로세스가 다시 시작되면 실행기 클로저가 사라지므로, 호출자는 먼저 manager.registerTaskContext(taskId, ...)를 통해 실행기를 다시 등록한 후 resume()을 호출해야 합니다. 동일한 프로세스 안에서 위임되고 재개된 작업에는 이 과정이 필요하지 않습니다.
일시 중지된 작업 취소일시 중지된 작업 취소에 대한 직접 링크
manager.cancel(taskId)는 실행 중인 작업과 동일하게 일시 중지된 작업에도 작동합니다. 레코드 상태가 cancelled로 변경되고 Workflow 스냅샷이 정리됩니다. 그런 다음 task.cancelled 이벤트가 발생합니다.
수명주기 콜백수명주기 콜백에 대한 직접 링크
각 계층은 터미널 상태 콜백을 등록할 수 있습니다. 그들은 서로를 대체하지 않으며 성공/실패는 결과에 따라 실행됩니다.
- Tool 수준의
background.onComplete/onFailed: 하나의 Tool에 적용됩니다. - Agent 수준의
backgroundTasks.onTaskComplete/onTaskFailed: 이 Agent가 위임한 모든 작업에 적용됩니다. - Manager 수준의
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 | 이 Memory 스레드로 범위가 지정된 작업의 이벤트만 포함합니다. |
resourceId | 이 리소스로 범위가 지정된 작업의 이벤트만 포함합니다. |
taskId | 단일 작업의 이벤트만 포함합니다. |
abortSignal | 신호가 중단되면 스트림을 닫습니다. |
작업 상태를 직접 조회작업 상태를 직접 조회에 대한 직접 링크
라이브 스트림 대신 일회성 조회가 필요하면 getTask와 listTasks를 사용하세요.
const task = await mastra.backgroundTaskManager?.getTask(taskId)
const { tasks, total } = await mastra.backgroundTaskManager?.listTasks({
status: 'running',
agentId: 'researcher',
})
이는 pubsub 스트림이 아닌 저장소에서 읽혀지므로 페이지가 매겨진 목록 및 세부정보 보기에 적합합니다.