핵심 요약
- 에이전트가 더 큰 목표를 수행하게 되면서, 여러 개의 긴 작업을 동시에 진행하면서도 사용자에게 즉각적으로 응답할 수 있어야 합니다.
- 비동기 서브에이전트는 에이전트를 사용자에게 지속적으로 접근 가능한 오케스트레이터와, 백그라운드에서 작업을 실행하고 완료 시 오케스트레이터에 보고하는 서브에이전트로 분리합니다.
- Claude Code 같은 코딩 에이전트부터 OpenAI의 dots 같은 개인 에이전트에 이르기까지, 백그라운드 작업이 에이전트 인프라의 표준이 되고 있습니다.
큰 프로젝트를 맡길 때마다 사라지고 다 끝난 뒤에야 돌아오는 비서실장을 상상해 보세요. 아마 즉시 해고했을 것입니다. 좋은 비서실장은 프로젝트를 백그라운드에서 진행시키면서도 연락이 닿고, 진행 상황을 계속 알려줍니다. 에이전트에게 더 큰 목표를 요구할수록, 에이전트도 같은 두 가지 성질이 필요합니다. 에이전트는 이전의 모든 맥락을 갖고 새로운 지시에 즉시 대응하는 응답성과, 동시에 여러 큰 작업을 진행하는 생산성을 갖추어야 합니다.
지금까지 에이전트를 만들어 온 아키텍처로는 두 요구 사항을 모두 충족할 수 없습니다. 표준 ReAct 루프에서는 긴 도구 호출 하나가 루프를 막고, 다른 모든 작업은 그 뒤에 줄지어 기다립니다. 대신 사용자 곁에 남는 하나의 에이전트와 긴 작업을 수행하는 백그라운드 워커로 분리하는 방향으로 생태계가 수렴하고 있습니다. Claude Code 는 기본적으로 서브에이전트를 백그라운드에서 실행하고, OpenAI의 dots 는 여러 작업을 동시에 진행하기 위해 작업을 백그라운드 워커에 넘기며, DeepSeek Harness 는 사람과 대화하는 라우터와 병렬로 작업을 실행하는 백그라운드 워커를 중심으로 슈퍼 에이전트를 만들었습니다.
우리는 이 패턴을 Deep Agents 에 비동기 서브에이전트형태로 도입하고 있습니다. 오케스트레이터는 사용자에게 접근 가능한 상태를 유지하며 대화 맥락을 정리하고, 비동기 서브에이전트는 백그라운드 워커로 실행되어 완료 시 보고합니다. 이렇게 하면 에이전트가 감당할 수 있는 작업량이 하나의 루프 길이 대신 백그라운드 워커 수에 따라 늘어납니다.
비동기 서브에이전트의 작동 방식
에이전트는 루프 안에서 실행됩니다. 모델이 도구를 호출하고, 결과를 기다리고, 다음에 무엇을 할지 결정합니다. 전통적으로 도구와 서브에이전트는 반환될 때까지 그 루프를 막았습니다. 느린 호출마다 순서대로 await하는 코드처럼 말입니다. 비동기 서브에이전트는 아직 await하지 않은 asyncio.create_task 로 시작하거나 Promise 작업처럼 동작합니다. 호출은 즉시 반환되고, 작업은 백그라운드에서 독립적으로 실행되며, 결과는 나중에 돌아옵니다.
비동기 작업은 시스템의 두 가지 성질에 의존합니다:
- 사용자가 오케스트레이터에 도달할 수 있다. 오케스트레이터는 사용자가 직접 상호작용하는 에이전트입니다. 서브에이전트가 더 이상 오케스트레이터의 루프를 붙잡고 있지 않으므로, 오케스트레이터 자신의 루프가 바쁘지 않다면 사용자는 언제든 오케스트레이터에 접근할 수 있고, 모든 서브에이전트가 끝나기를 기다릴 필요가 없습니다.
- 작업이 블로킹 없이 병렬로 실행된다. 오케스트레이터는 전체 배치가 반환되기를 기다리는 대신, 작업이 들어올 때마다 서브에이전트를 시작합니다.
오케스트레이터는 다섯 가지 도구로 비동기 서브에이전트를 관리합니다:
start_async_task자체 스레드에서 서브에이전트를 시작하고 즉시 반환합니다.check_async_task작업의 상태를 가져오고, 완료되면 그 결과를 가져옵니다.update_async_task실행 중인 작업에 새 지시를 보냅니다.cancel_async_task실행 중인 작업을 중지합니다.list_async_tasks모든 작업과 그 상태를 나열합니다.
실행 중인 서브에이전트를 조작(steering)하는 것은 오케스트레이터에 도달하는 것과 별개입니다. 오케스트레이터가 후속 지시를 보낼 때 update_async_task를 사용하면, 해당 서브에이전트 정의의 update_strategy 필드가 어떤 일이 일어날지 결정합니다:
"interrupt"(기본값)은 현재 실행을 중지하고 새 지시로 서브에이전트를 재시작합니다. "대신 Postgres를 사용해." 같은 수정 사항에 사용하세요."enqueue"은(는) 후속 지시를 현재 실행이 끝날 때까지 보류합니다. "끝나면 테스트를 실행해." 같은 추가 사항에 사용하세요.
알림이 작동하는 방식
완료되지 않은 모든 작업은 오케스트레이터의 시스템 프롬프트에 나열되므로, 오케스트레이터는 항상 진행 중인 작업이 무엇인지 알고 있습니다. 오케스트레이터는 check_async_task 으(로) 폴링할 수 있고, 작업은 스스로 결과를 보고할 수도 있습니다:
- 오케스트레이터가 busy상태라면, 각 모델 호출 전에 완료되지 않은 작업을 확인하고 실행 도중에 결과를 가져옵니다.
- 오케스트레이터가 idle상태라면, 서브에이전트가 새 실행으로 이를 깨웁니다.
- 오케스트레이터가 승인 대기 중으로 paused 상태라면, 승인은 그대로 유지되고 사용자가 답한 후에 결과가 도착합니다.
승인이 필요한 서브에이전트는 waiting으(로) 표시되며, 사용자는 오케스트레이터를 중단하지 않고 서브에이전트 자체의 스레드에서 답변합니다. Slack의 Managed Deep Agents에서는 요청이 원래 스레드로 다시 게시됩니다.
우리는 이러한 패턴이 서브에이전트를 넘어 모든 도구 전반으로 일반화될 것으로 기대합니다. OpenAI는 최근 다음에 대한 지원을 추가했습니다 비동기 도구 호출, 모델이 도구를 호출한 후에도 계속 작동하고 애플리케이션이 결과를 이후 요청에서 되돌려 보내는 방식입니다.
비동기 하위 에이전트 사용
비동기 서브에이전트는 Deep Agents에서 사용할 수 있으며 파이썬(Python) 그리고 자바스크립트, 그리고 관리형 딥 에이전트(Managed Deep Agents), 하위 에이전트를 비동기로 만드는 데 필드 하나만 필요한 곳입니다:
from managed_deepagents import define_deep_agent
agent = define_deep_agent(
name="research-assistant",
model="openai:gpt-5.5",
subagents=[
{
"name": "researcher",
"description": "Researches a topic in the background.",
"system_prompt": "Research the topic and report your findings.",
"async": True,
},
],
)Managed Deep Agents에서는 제공되는 모든 에이전트가 비동기 사본도 함께 받습니다. general-purpose 서브에이전트를 통해, 위임된 작업을 포그라운드에서 실행할지 백그라운드에서 실행할지 런타임에 결정할 수 있습니다.
작업 알림은 베타 버전이므로 API가 아직 변경될 수 있습니다. 이 async-deep-agents repo에는 Python과 TypeScript로 된 researcher 및 coder 하위 에이전트를 갖춘 작동하는 supervisor가 포함되어 있습니다.
비동기 서브에이전트를 사용해 보시고, 에서 여러분의 의견을 알려주세요. GitHub 이슈 혹은 그 위에 포럼.