AI 에이전트 개발 실전 #5 서브에이전트로 일 나누기

5 분 소요

4편에서 컨텍스트를 줄이고 비우고 요약했습니다. 그런데 더 근본적인 해법이 하나 있습니다. 애초에 한 컨텍스트에 다 담지 않는 것입니다. 일의 일부를 별도의 에이전트에게 떼어 주고 결과만 돌려받으면, 그 일의 중간 과정은 본 에이전트의 컨텍스트에 아예 들어오지 않습니다. 이번 글에서는 서브에이전트를 다룹니다.

왜 나누는가 #

서브에이전트의 이점은 세 가지로 정리됩니다.

  • 컨텍스트 격리 — 조사 작업은 검색 결과 수십 건을 뒤지는 과정이 따라옵니다. 서브에이전트가 그 과정을 자기 컨텍스트에서 치르고 결론만 보고하면, 메인 에이전트는 결론만 받습니다. 4편의 기법들이 “쌓인 것을 줄이는” 방법이라면 이것은 “쌓이지 않게 하는” 방법입니다.
  • 역할 분리 — 서브에이전트마다 다른 시스템 프롬프트와 다른 도구 목록을 줄 수 있습니다. 조사 담당에게는 검색 도구만, 작성 담당에게는 파일 도구만 주는 식입니다. 2편에서 본 “도구 목록은 좁을수록 좋다"는 원칙을 역할 단위로 실현하는 셈입니다.
  • 병렬 실행 — 서로 독립적인 작업이라면 서브에이전트 여러 개를 동시에 돌릴 수 있습니다.

delegate 도구 만들기 #

구현의 핵심은 의외로 단순합니다. 서브에이전트는 결국 별도의 messages 배열로 도는 또 하나의 루프입니다. 1편의 run_agent를 거의 그대로 쓰되, 역할과 도구를 파라미터로 받게 만듭니다.

run_subagent.py
def run_subagent(system: str, tools: list, task: str, max_steps: int = 15) -> str:
    """독립 컨텍스트에서 작업을 수행하고 최종 보고만 반환한다."""
    messages = [{"role": "user", "content": task}]
    for _ in range(max_steps):
        response = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=16000,
            system=system,
            tools=tools,
            messages=messages,
        )
        if response.stop_reason == "end_turn":
            return next(b.text for b in response.content if b.type == "text")
        messages.append({"role": "assistant", "content": response.content})
        messages.append({"role": "user", "content": run_tools(response)})
    return "(서브에이전트가 단계 한도 안에 작업을 끝내지 못했습니다)"

그리고 이것을 메인 에이전트의 도구로 노출합니다.

delegate_tool.py
{
    "name": "delegate_research",
    "description": (
        "조사 전문 서브에이전트에게 조사 작업을 맡긴다. "
        "여러 문서를 검색하고 읽어야 답이 나오는 질문이면 직접 검색하지 말고 이 도구를 쓴다. "
        "task에는 무엇을 알아낼지와 보고 형식을 구체적으로 적는다."
    ),
    "input_schema": {
        "type": "object",
        "properties": {
            "task": {"type": "string", "description": "조사할 내용과 기대하는 보고 형식"},
        },
        "required": ["task"],
    },
}

def delegate_research(task: str) -> str:
    return run_subagent(
        system="너는 조사 전문 에이전트다. 요청받은 내용을 조사해 근거와 함께 간결히 보고한다.",
        tools=research_tools,   # 검색·읽기 도구만
        task=task,
    )

메인 에이전트 입장에서 서브에이전트는 그냥 도구 하나입니다. 루프 구조는 아무것도 바뀌지 않습니다.

보고 형식을 계약으로 만들기 #

서브에이전트에서 흔한 실패는 위임이 아니라 보고에서 납니다. 메인 에이전트는 서브에이전트의 최종 텍스트만 받으므로, 그 텍스트에 필요한 정보가 빠져 있으면 위임 전체가 헛수고가 됩니다. 그래서 task에 보고 형식을 명시하는 것이 중요합니다.

task_with_contract.txt
2026년 5월의 환불 정책 변경 내용을 조사해라.
보고 형식:
- 변경 요점 (3줄 이내)
- 근거 문서의 제목과 위치
- 확인하지 못한 것이 있으면 명시

“확인하지 못한 것을 명시하라"는 줄이 특히 유용합니다. 이게 없으면 서브에이전트는 빈손일 때 그럴듯한 추정으로 보고서를 채우는 경향이 있습니다.

오케스트레이터-워커와 병렬 실행 #

서브에이전트가 여럿이 되면 메인 에이전트의 역할이 바뀝니다. 직접 일하는 대신 일을 나누고 결과를 합치는 오케스트레이터(orchestrator, 오케스트라의 지휘처럼 전체 진행을 조율하는 역할)가 됩니다. 서로 독립적인 위임이라면 동시에 실행할 수 있습니다. Claude가 한 응답에서 delegate_research를 세 번 부르면, 그 세 호출을 스레드로 병렬 처리하는 식입니다.

parallel_delegation.py
from concurrent.futures import ThreadPoolExecutor

def run_tools(response) -> list:
    blocks = [b for b in response.content if b.type == "tool_use"]
    with ThreadPoolExecutor(max_workers=4) as pool:
        results = list(pool.map(execute_tool, blocks))
    return results

1편에서 “병렬 호출의 결과를 전부 돌려줘야 한다"고 했던 것이 여기서 그대로 적용됩니다. 서브에이전트 세 개가 각자 몇 분씩 걸리는 조사를 동시에 하면, 전체 시간은 가장 느린 하나로 줄어듭니다.

위임이 과해지지 않게 #

서브에이전트는 공짜가 아닙니다. 호출마다 별도의 루프가 통째로 돌기 때문에 비용과 시간이 듭니다. 두 가지 기준을 권합니다.

  • 한 번에 끝날 일은 직접 한다. 조회 한 번이면 답이 나오는 일에 서브에이전트를 띄우는 것은 낭비입니다. delegate 도구의 description에 “여러 문서를 검색하고 읽어야 하는 경우에만"처럼 조건을 적으면 과한 위임이 줄어듭니다.
  • 위임의 깊이는 한 단계로 제한한다. 서브에이전트가 또 서브에이전트를 부르기 시작하면 비용과 동작을 추적하기 어려워집니다. 서브에이전트에게는 delegate 도구를 주지 않는 것으로 구조적으로 막을 수 있습니다.

흔히 걸려 넘어지는 곳 #

  • 서브에이전트가 맥락을 공유한다고 가정한다 — 서브에이전트는 메인 대화를 전혀 모릅니다. task에 적힌 것이 아는 것의 전부입니다. 필요한 배경은 task에 다 담아야 합니다.
  • 보고 형식 없이 위임한다 — 형식 없는 보고는 핵심이 빠지거나 장황해집니다. 기대하는 출력을 task에 명시합니다.
  • 모든 것을 위임한다 — 위임 자체가 목적이 되면 단순 작업에도 루프 하나씩을 태웁니다. 직접 하는 게 빠른 일의 기준을 description에 적어 둡니다.

마무리 #

이번 글에서는 일을 나눠 맡기는 서브에이전트를 다뤘습니다.

  • 서브에이전트는 별도 messages로 도는 또 하나의 루프이고, 메인 에이전트에게는 도구 하나로 보입니다.
  • 가치의 핵심은 컨텍스트 격리입니다. 중간 과정은 서브에이전트가 치르고 결론만 돌아옵니다.
  • task에 보고 형식을 계약처럼 명시하고, 위임 조건과 깊이를 제한해 비용을 관리합니다.

지금까지 도구는 모두 우리 코드 안의 파이썬 함수였습니다. 다음 글인 “AI 에이전트 개발 실전 #6 MCP 서버 직접 만들기"에서는 도구를 표준 프로토콜의 서버로 분리해서, 어떤 에이전트에서든 재사용하는 방법을 다룹니다.

X