한 줄 요약: 서브에이전트(Sub-agent)란, 상위 오케스트레이터 에이전트가 복잡한 작업을 분해해 위임하면 독립적인 컨텍스트에서 세부 작업을 수행하고 결과를 반환하는 하위 AI 에이전트이다.


1. 서브에이전트란 무엇인가?

대형 프로젝트를 진행하는 팀을 상상해 보세요. 프로젝트 매니저(PM)가 전체 계획을 세우고, 각 팀원에게 세부 작업을 분배합니다. 팀원들은 자신의 전문 영역에서 독립적으로 작업하고 결과를 PM에게 보고합니다.

멀티에이전트 시스템에서 PM 역할은 오케스트레이터(Orchestrator)가, 팀원 역할은 서브에이전트(Sub-agent)가 맡습니다. 서브에이전트의 핵심 특성은 독립적인 컨텍스트입니다. 각 서브에이전트는 자신에게 주어진 작업의 컨텍스트만 가지므로, 오케스트레이터의 전체 컨텍스트가 오염되지 않습니다.

2. 핵심 개념 이해하기

오케스트레이터-서브에이전트 구조

사용자 요청: "경쟁사 분석 보고서 작성해줘"
                    ↓
         [오케스트레이터 에이전트]
          작업 분해 + 결과 통합
         /         |          \
        ↓          ↓           ↓
[서브에이전트1] [서브에이전트2] [서브에이전트3]
 A사 조사        B사 조사         C사 조사
 (독립 컨텍스트) (독립 컨텍스트)  (독립 컨텍스트)
        \          |          /
         ↓         ↓         ↓
         [오케스트레이터 에이전트]
              결과 통합 → 보고서 생성

서브에이전트의 핵심 특성

특성 설명
컨텍스트 격리 각 서브에이전트는 독립적인 컨텍스트 윈도우 보유
전문화 특정 도메인/작업에 최적화된 역할 및 도구
병렬 실행 여러 서브에이전트가 동시에 작업 수행 가능
결과 반환 완료 후 오케스트레이터에게 구조화된 결과 전달

서브에이전트 vs 도구(Tool)

도구(Tool): 오케스트레이터가 직접 호출, 결과를 같은 컨텍스트에서 처리
서브에이전트: 별도 LLM 호출, 독립 컨텍스트, 복잡한 멀티스텝 수행 가능

3. 실무 적용 예시

Claude의 agent 도구를 활용한 서브에이전트 패턴입니다.

import anthropic
from concurrent.futures import ThreadPoolExecutor

client = anthropic.Anthropic()

def sub_agent(task: str, role: str) -> str:
    """독립적인 컨텍스트에서 세부 작업을 수행하는 서브에이전트."""
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=2048,
        system=f"당신은 {role} 전문가입니다. 주어진 작업만 수행하고 결과를 반환하세요.",
        messages=[{"role": "user", "content": task}]
    )
    return response.content[0].text

def orchestrator(user_request: str) -> str:
    """작업을 분해하고 서브에이전트에 위임한 후 결과를 통합하는 오케스트레이터."""

    # 작업 분해
    subtasks = [
        ("삼성전자의 AI 제품 라인업과 최근 발표를 조사하세요.", "시장 조사"),
        ("LG전자의 AI 전략과 주요 파트너십을 정리하세요.", "경쟁사 분석"),
        ("국내 AI 가전 시장 규모와 성장률 트렌드를 분석하세요.", "데이터 분석"),
    ]

    # 병렬 서브에이전트 실행
    with ThreadPoolExecutor(max_workers=3) as executor:
        futures = [
            executor.submit(sub_agent, task, role)
            for task, role in subtasks
        ]
        results = [f.result() for f in futures]

    # 결과 통합
    combined = "\n\n".join([
        f"## {subtasks[i][1]} 결과\n{results[i]}"
        for i in range(len(results))
    ])

    final = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=4096,
        system="당신은 경영 컨설턴트입니다. 제공된 조사 결과를 통합해 경쟁사 분석 보고서를 작성하세요.",
        messages=[{
            "role": "user",
            "content": f"원래 요청: {user_request}\n\n서브에이전트 결과:\n{combined}"
        }]
    )

    return final.content[0].text

# 실행
report = orchestrator("AI 가전 시장 경쟁사 분석 보고서 작성")
print(report)

4. 서브에이전트 vs 유사 개념 비교

구분 서브에이전트 도구(Tool) 에이전트 체인
실행 방식 병렬 가능 순차적 순차적
컨텍스트 독립 공유 공유
복잡도 높음 (LLM 다중 호출) 낮음 (함수 호출) 중간
전문화 ✅ 역할별 분리 ❌ 단순 기능 부분적
비용 높음 낮음 중간
적합한 작업 복잡한 멀티스텝 단순 외부 연동 순서가 중요한 작업

5. 마치며

서브에이전트는 복잡한 작업을 병렬로 처리하고 전문화된 에이전트로 분리할 수 있는 강력한 패턴입니다. 단, 각 서브에이전트 호출마다 LLM 비용이 발생하므로, 작업의 복잡도와 비용을 함께 고려해야 합니다. 단순한 작업은 도구(Tool)로, 복잡하고 독립적인 작업은 서브에이전트로 처리하는 것이 이상적입니다.

참고 자료

함께 읽으면 좋은 용어

이 개념과 함께 알아두면 이해가 깊어지는 관련 용어들입니다.

댓글 남기기