Back to Blog
Research

AI 에이전트 아키텍처 기본기 — 서브에이전트·멀티에이전트 패턴·하네스

에이전트란 무엇인가부터 서브에이전트 상호작용, 멀티에이전트 패턴 카탈로그, 그리고 이 모든 것을 감싸는 하네스 엔지니어링까지. AI 에이전트 시스템 설계의 기본기를 한 편으로 정리한다.

··11 min read
AI-AgentsMulti-Agent-SystemsArchitectureSub-AgentsHarness

두괄식 요약

AI 에이전트 아키텍처의 기본기는 네 층으로 이해하면 된다. 에이전트가 무엇인지(자율 실행 루프), 왜 서브에이전트로 쪼개는지(단일 에이전트의 3한계), 어떤 패턴으로 조합하는지(멀티에이전트 카탈로그), 이 모든 걸 무엇이 감싸는지(하네스)다.

핵심 명제 세 가지를 먼저 던진다.

  • 도구 호출 능력만으로는 에이전트가 아니다. 에이전트의 본질은 중간 결과에 따라 다음 행동을 스스로 결정하는 루프다.
  • 서브에이전트는 일회용 전문가다. 독립 컨텍스트에서 작업하고, 요약만 반환하고, 소멸한다. 부모 컨텍스트를 오염시키지 않는 것이 핵심이다.
  • 프롬프트 엔지니어링과 하네스 엔지니어링은 다른 층위다. 전자는 "좋은 명령 쓰기", 후자는 "에이전트가 작동하는 환경 전체 설계"다.

이 글은 입문에서 중급까지를 다룬다. 프레임워크 실전 분석은 오픈소스 보안 AI 에이전트 해부를 참고하라.


1. 에이전트란 무엇인가

LLM과 에이전트의 구조적 차이

가장 흔한 오해부터 정리하자. "LLM이 API를 호출할 수 있으면 에이전트다"는 틀렸다.

LLM은 **반응형(reactive)**이다. 입력을 받아 출력을 생성하고 멈춘다. 외부 세계를 바꾸지 못하고, 세션이 끝나면 기억도 사라진다. 반면 에이전트는 **목표 지향형(goal-oriented)**이다. 목표를 설정하고, 계획을 세우고, 행동하고, 결과를 관찰하고, 반성하며, 목표에 도달할 때까지 이 루프를 돈다.

LLM:                    Agent:
입력 → [처리] → 출력      목표 → 계획 → 행동 → 관찰 → 반성 → (반복)
       (끝)                          목표 달성? No → 계획으로 복귀

구체적인 예로 차이를 보자.

# LLM: 반응형
사용자: "이 코드의 버그를 찾아줘"
LLM:   "3번째 줄에 off-by-one 에러가 있습니다"   # 끝. 고치지는 않음
 
# Agent: 목표 지향형
사용자: "이 코드의 버그를 고쳐줘"
Agent:
  1. 코드를 읽는다 (Read)
  2. 버그를 분석한다 (추론)
  3. 수정안을 만든다 (계획)
  4. 코드를 수정한다 (Edit)
  5. 테스트를 실행한다 (Bash)
  6. 실패? → 3번으로 복귀
  7. 통과 → 완료 보고

차이의 본질은 하나다. 에이전트는 중간 결과에 따라 다음 행동을 스스로 결정한다. "내일 서울 야외 미팅을 잡아줘"라는 요청에 날씨를 확인하고("비 예보"), 스스로 판단해("실내로 변경하는 게 좋겠다") 캘린더를 확인하고 회의실을 예약하는 것 — 이 자체 판단의 연쇄가 에이전트다.

MIT의 4가지 필수 특성과 자율성 레벨

MIT AI Agent Index(2025)는 진정한 에이전트가 갖춰야 할 4가지 특성을 정의한다. 넷을 모두 만족해야 한다.

특성결여 시
자율성 (최소 감독으로 독립 작동)매번 지시가 필요한 챗봇
목표 복잡성 (계획으로 고수준 목표 추구)단순 반응형 FAQ 봇
환경 상호작용 (도구·API·파일시스템 직접 조작)말만 하는 LLM
일반성 (명시되지 않은 새 상황 처리)하드코딩된 RPA 스크립트

자율성은 스위치가 아니라 스펙트럼이다. L1(제안만, GitHub Copilot)부터 L2(매 단계 승인), L3(계획+실행, 사람은 감독만), L4(예외 시만 개입), L5(완전 자율, 아직 미실용)까지 다섯 단계로 나뉜다.

에이전트의 3요소와 기억 체계

에이전트는 역할(Role: 무엇을 하는 존재인가), 도구(Tools: 어떤 행동이 가능한가), 지침(Instructions: 어떤 규칙을 따르는가)의 세 요소로 정의된다.

LLM과 에이전트를 가르는 또 하나의 축은 기억이다. LLM의 컨텍스트는 휘발성이고 단일 계층이지만, 에이전트는 시간 척도가 다른 3계층 기억을 활용한다.

기억 유형LLMAgent실제 구현 예
단기컨텍스트 윈도우작업 기억태스크 상태 추적
중기없음에피소드 기억과거 실패 기록([DEAD END])
장기없음의미 기억학습된 규칙(Lessons Learned)

왜 에이전트를 쓰는가 — 그리고 언제 쓰지 말아야 하는가

에이전트가 필요한 기술적 근거는 여섯 가지다. 컨텍스트 한계 극복, 전문화에 의한 품질 향상, 병렬 속도, 권한 제어 안전성, 실패 격리, 비용 최적화다. 이 중 몇 가지는 다음 절 서브에이전트에서 자세히 다룬다.

중요한 것은 쓰지 말아야 할 때를 아는 것이다.

상황이유대안
단순 Q&A오버헤드 불필요일반 LLM 호출
결정론적 작업매번 같은 결과 필요전통 프로그래밍
지연 시간 중요에이전트 루프는 느림사전 정의 파이프라인
극도 저비용다중 LLM 호출 비용단일 호출 + 규칙
완전한 감사 필요판단의 비결정성규칙 기반 시스템

에이전트는 강력하지만 무조건 유리하지 않다. 다단계 의사결정, 외부 시스템 통합, 지속적 모니터링, 복잡하고 동적인 작업일 때 에이전트를 쓰고, 그 외에는 LLM이나 전통 프로그래밍이 낫다.


2. 왜 서브에이전트인가

진화: LLM → Agent → Sub-Agent

에이전트의 진화는 두 단계다. LLM은 "말만 할 수 있어서" 도구가 필요했고, 그래서 Agent가 등장했다. 단일 Agent는 "혼자서는 한계여서" 분업이 필요했고, 그래서 Sub-Agent가 등장했다. 서브에이전트는 단일 에이전트의 구조적 한계를 극복하기 위해 나온 것이다.

단일 에이전트의 3한계

1. 컨텍스트 오염. 복잡한 작업을 하면 컨텍스트가 관련 없는 정보로 가득 찬다. "버그 수정"을 하는데 시스템 프롬프트 2K, 파일 A~D 13K, 테스트+에러 로그 13K가 쌓이면 — 그중 사실 관련 없던 파일 C도 컨텍스트를 차지하며 핵심을 놓치기 시작한다.

서브로 분리하면 해결된다.

Main: "파일 A~D 중 버그 원인 찾아줘"
  └→ Sub (탐색 전용, 독립 컨텍스트)
       A, B, C(무관), D 모두 읽고
       → "B의 42번째 줄이 원인" (요약만 반환)
Main: 요약 한 줄만 받음 (컨텍스트 깨끗)

2. 역할 충돌. 하나의 에이전트에게 상반된 역할을 시키면 확증 편향이 생긴다. 자기가 쓴 코드를 자기가 리뷰하면 "내가 쓴 거니까 괜찮을 거야"가 된다. implementer(생성 마인드셋)와 reviewer(문제 찾기 마인드셋)를 별도 컨텍스트로 분리하는 것은, 실제 소프트웨어 팀에서 작성자와 리뷰어를 나누는 원칙과 같다.

3. 단일 실패점. 단일 에이전트가 10단계 중 7단계에서 실패하면 이후가 전부 오염되어 처음부터 다시 해야 한다. 서브로 나누면 Sub-C만 실패했을 때 A·B 결과를 보존하고 C만 재시도한다.

작동 원리: 일회용 전문가

서브에이전트의 작동 원리는 세 단계로 요약된다.

단계설명
독립 컨텍스트 생성부모와 별개의 컨텍스트를 가짐
요약 반환전체 로그가 아닌 결과 요약만 전달
컨텍스트 소멸작업 완료 후 메모리 해제

수치로 보면 효과가 분명하다. 서브에이전트가 Glob + 7개 파일 Read로 약 15K 토큰을 소비해도, 부모에게는 "7 에이전트, 역할..." 같은 200토큰 요약만 반환된다. 부모가 직접 했다면 컨텍스트 절반이 탐색 결과로 채워져 이후 성능이 저하됐을 것이다.

여기에 두 이점이 더해진다. 비용 최적화 — 부모는 opus를, 문서 검색 서브는 haiku를, 코드 생성 서브는 sonnet을 쓰면 전부 opus 대비 약 40% 절감된다. 병렬 속도 — 독립 작업을 동시 실행하면 총 시간이 max(A, B, C)로 줄어든다.

상호작용: 생명주기·통신·실행 모드

서브에이전트의 생명주기는 6단계다. 요청 수신 → 작업 분해 → 서브 생성·위임 → 결과 수신(요약) → 다음 판단 → 최종 보고.

생성 시 전달되는 것과 전달되지 않는 것이 명확히 구분된다.

전달미전달
prompt (작업 지시)부모의 대화 히스토리
subagent_type (역할+도구)다른 서브의 결과
model (비용/성능)사용자와의 이전 대화
mode (권한)부모의 추론 과정

통신은 부모-자식만 허용된다. 형제 간 직접 통신은 금지된다.

        Main
       /  |  \
    Sub-A Sub-B Sub-C
 
✅ Main ↔ Sub-X (양방향)
❌ Sub-A ↔ Sub-B (직접 불가)

이유는 셋이다. 순환 참조 위험(Sub-A → Sub-B → Sub-C → Sub-A), 결정권자 불명확, 디버깅 난제다. 모든 통신이 부모를 경유하므로 Main이 항상 전체 상황을 파악하고 추적할 수 있다.

상태 공유 범위는 "외부 자원은 공유, 내부 인지는 격리"로 요약된다. 파일시스템·Git·환경 변수·MCP 서버는 공유되고, 컨텍스트 윈도우·추론 상태·도구 호출 히스토리는 격리된다. 두 서브가 같은 파일을 동시 수정하는 충돌은 worktree 격리(독립 Git 복사본)로 막는다.

실행 모드는 셋이다. 순차(앞 결과가 뒤에 필요할 때, 총 시간 = A+B+C), 병렬(독립적일 때, 한 메시지에 여러 에이전트 호출, 총 시간 = max(A,B,C)), 백그라운드(오래 걸리는 작업, 부모는 다른 일을 계속)다. 실행 중인 서브에게는 SendMessage로 추가 지시를 보낼 수 있어, 장시간 실행 서브가 외부 정보 변화에 적응한다.

부모-자식 vs A2A

부모-자식 모델은 A2A(Agent-to-Agent) 프로토콜과 대비된다. 전자는 한 프로세스 내 계층적 분업이고, 후자는 독립 서비스 간 수평적 협업이다.

차원부모-자식A2A
관계계층적 (부모 통제)수평적 (동등 피어)
생명주기부모가 생성/제거각자 독립
통신부모 경유직접 가능
적합한 프로세스 내 분업독립 서비스 간 협업
비유팀장이 지시하는 팀부서 간 협업

A2A를 포함한 상호운용 표준은 에이전트 상호운용 표준에서 별도로 정리한다.


3. 멀티에이전트 패턴 카탈로그

서브에이전트를 어떻게 조합하느냐가 멀티에이전트 패턴이다. 대부분의 실제 시스템은 단일 패턴이 아니라 **복합(Composite)**이라는 점을 미리 기억하자.

Anthropic 6 프로덕션 패턴

Anthropic은 워크플로우(사전 정의 코드 경로로 오케스트레이션)와 에이전트(LLM이 자율 결정)를 구분하고, 6개 프로덕션 패턴을 제시한다. 핵심 질문은 하나다 — 누가 다음 단계를 결정하는가(프로그래머 vs LLM).

  1. Augmented LLM — 가장 기본. LLM에 검색·도구·메모리를 붙인다. 나머지 5개는 이것의 조합이다.
  2. Prompt Chaining — 순차 단계. 한 번에 10K자를 처리하면 중간 실수를 모르지만, 1K씩 쪼개면 조기 발견한다.
  3. Routing — 분류 후 전문가. 입력을 분류기가 판단해 전문화 프로세스로 보낸다.
  4. Parallelization — 동시 실행. 작업을 분할(Sectioning)하거나 다수결(Voting)로 처리한다.
  5. Orchestrator-Workers — 동적 분배. Parallelization과 비슷하나 작업 개수·종류를 미리 모른다.
  6. Evaluator-Optimizer — 생성과 검토 반복. Generator가 초안을 만들고 Evaluator가 피드백하며 기준 충족까지 반복한다.

Chaining·Routing·Parallel의 구분이 자주 헷갈린다. 기준은 실행 수와 의존성이다.

Chaining:  A → B → C         (직선, 전부 순차, 의존성 있음)
Routing:   A or B or C       (갈림길, 하나만, 의존성 없음)
Parallel:  A + B + C → 합류  (동시, 전부, 의존성 없음)

같은 "코드 리뷰"라도 Chaining은 "읽기 → 문제 목록 → 수정 제안"(의존적), Routing은 "Python? → Python 리뷰어"(하나만), Parallel은 "보안+성능+스타일 동시 → 통합"(독립)이다.

선택 순서는 "가장 단순한 패턴부터"다. Augmented LLM으로 충분한가 → 순차로 나눌 수 있나 → 유형별 분기인가 → 독립 병렬인가 → 개수가 동적인가 → 반복 개선인가 → 그래도 부족하면 자율 에이전트. Anthropic의 원칙 그대로다: "복잡한 것이 항상 좋은 건 아니다."

Google ADK 8 패턴

Google ADK는 더 세분화된 8개 패턴을 제시한다.

패턴용도단점
Sequential Pipeline선형 워크플로한 단계 실패 시 전체 중단
Coordinator/Dispatcher유형별 라우팅Coordinator가 병목·단일 장애점
Parallel Fan-Out/Gather독립 작업 동시 실행Aggregator 로직 복잡
Hierarchical Decomposition트리 구조 분해깊은 계층 = 지연 누적
Generator + Critic생성 후 비평·재생성루프 탈출 조건 필수
Iterative Refinement자기평가 반복무한 루프 위험
Human-in-the-Loop인간 검토 체크포인트속도 제약
Composite실제 프로덕션 시스템(조합)

여기에 Azure는 Magentic-One Orchestrator, Group Chat(합의 도출), Supervisor(재시도·스킵 권한을 가진 강한 제어), Swarm(중앙 조율자 없이 handoff로 서로 호출) 등을 추가한다. Swarm은 추적이 어려워 프로덕션 사용에 신중해야 한다.

패턴 선택 가이드는 결정 트리로 정리된다.

순서 의존적?     → YES: Sequential / Hierarchical
독립적?          → YES: Parallel Fan-Out
품질 반복 향상?   → YES: Generator+Critic / Iterative
인간 승인 필요?   → YES: Human-in-the-Loop
유형이 다양?      → YES: Coordinator/Dispatcher
                  → NO:  Sequential Pipeline

실제 시스템은 조합이다

프로덕션 시스템은 이 패턴들을 조합한다. 예를 들어 자율 펜테스트 플랫폼은 Prompt Chaining(generator → primary → reporter)에 Routing(pentester/coder/searcher 선택)과 Augmented LLM(nmap 실행)을 겹쳐 쓰고, 완전 자율 CRS는 Chaining(분석 → PoV → 패치)에 Parallel(여러 PoV 동시)과 Routing(언어별 도구 선택)을 조합한다. 이런 실제 조합은 오픈소스 보안 AI 에이전트 해부에서 코드 수준으로 다룬다.


4. 하네스 엔지니어링 — 모든 것을 감싸는 층

프롬프트 엔지니어링과의 차이

지금까지의 개념을 모두 담는 상위 개념이 **하네스(Harness)**다. 프롬프트 엔지니어링과 하네스 엔지니어링은 층위가 다르다.

프롬프트 엔지니어링하네스 엔지니어링
초점단일 모델 호출전체 에이전트 생명주기
시간축일회성장기(다중 세션)
범위명령 개선도구·메모리·상태·안전성
비유"좋은 명령 쓰기""말의 안장·고삐·울타리·도로 설계"

왜 하네스가 필요한가. LLM 단독으로는 컨텍스트가 넘치면 잊고, 도구를 잘못 호출하고, 위험 행동을 할 수 있으며, 세션 간 작업을 관리하지 못한다. 하네스가 컨텍스트를 압축·관리하고, 도구 호출을 검증·제한하고, 권한과 승인으로 안전성을 강제하고, 메모리로 세션 연속성을 준다. OpenAI의 실제 경험(3명 × 5개월 = 100만 줄 자동 생성)에서도 상당 시간이 결정론적 도구 구축에 투입됐다 — 하네스 없이는 장기 운영이 불가능하다.

두 계층: Scaffolding과 Runtime

하네스는 시간축으로 두 계층으로 나뉜다.

──── 시간 ────────────────────→
[Scaffolding]          [Harness Runtime]
  실행 전                실행 중
  ├─ System Prompt       ├─ 도구 호출 검증
  ├─ Agent Registry      ├─ 컨텍스트 압축
  ├─ Skill Registry      ├─ 안전성 강제
  ├─ MCP 서버(도구 스키마) ├─ 메모리 업데이트
  ├─ Configuration       ├─ 에러 복구
  └─ Memory Schema       └─ 상태 추적

Scaffolding은 에이전트가 작동하기 전에 미리 준비하는 것이다. 시스템 프롬프트 템플릿(역할·목표·제약), 도구 스키마, 서브에이전트 레지스트리, 메모리 스키마, 설정(모드·모델·파라미터)이다.

Runtime은 실행 중 관리하는 것이다. 사용자 커스텀 훅(PreToolUse로 호출 전 검증, PostToolUse로 후 처리), 내부 엔진(컨텍스트 자동 압축, 권한 승인, 서브에이전트 생명주기, 도구 디스패치, 토큰 카운팅), 그리고 LLM이 준수하는 규칙(Anti-Loop 3-Strike, THINK-THEN-ACT 등)이다.

6단계 ReAct 루프와 5단계 안전성

하네스 안에서 매 턴은 6단계 ReAct 루프를 돈다. Pre-Check(상태 검증, 토큰 예산) → Thinking(내부 추론) → Self-Critique(자체 계획 검토) → Action(도구 호출 결정) → Tool Execution(실행) → Post-Processing(정리, 메모리 업데이트)다.

안전성은 5단계 방어(Defense-in-Depth)로 쌓는다. ① 프롬프트 가드레일(규칙 문서) → ② 스키마 제약(도구 입력 JSON Schema) → ③ 런타임 승인(사용자 승인 요청) → ④ 도구 레벨 검증(도구 내부) → ⑤ 생명주기 훅(PreToolUse·PostToolUse)이다.

지금까지 배운 모든 것이 하네스의 일부다

이 글에서 다룬 개념들은 전부 하네스의 구성 요소로 수렴한다.

개념하네스 역할
Agent실행 주체
Sub-Agent분업
Skills방법론 주입 (Scaffolding)
Tools행동 능력
MCP도구 표준 접근
A2A외부 통신
Workflow순서 관리 (Runtime)
RAG지식 검색 (Runtime)
Memory경험 기억 (Runtime)

에이전트가 무엇인지 이해하고, 왜 쪼개는지 알고, 어떤 패턴으로 조합하는지 익혔다면, 마지막으로 그것들을 견고하게 감싸는 하네스를 설계하는 것이 에이전트 아키텍처의 기본기다. 화려한 자율성보다 견고한 환경 설계가 먼저다.


참고 자료