본문으로 건너뛰기
H
Harness 101
학습 경로/Act 2 — 성장/06. Agents
Context·중급·75분

산만한 리뷰

“큰 작업을 나누면, 각 조각은 깨끗한 컨텍스트를 얻는다”

Agents — 격리된 전문 에이전트

이전 이야기에서: 지민은 Task System으로 10단계 작업을 계획대로 진행할 수 있게 됐다. Verification Loop로 자동 검증까지. 하지만 결제 시스템 구현 중 코드 리뷰를 요청했더니 이상한 일이 벌어졌다...

Harness = Tools + Knowledge + Context + Permissions

Agents는 Context 격리로 노이즈 없는 집중을 가능하게 한다. "Break big tasks down; each subtask gets a clean context"


산만한 리뷰

코드 리뷰를 요청했을 뿐이었다.

그런데 Claude는 "잠깐만요, 먼저 전체 코드를 파악할게요"라며 파일 20개를 읽기 시작했다. 10분 후, Claude의 리뷰는 이상하게 산만했다.

DB 스키마 이야기를 하다가 갑자기 패키지 설치 방법을 언급했다. 방금 물어본 결제 로직의 보안 취약점에 대해서는 한 줄도 없었다.

현우가 리뷰 결과를 보더니 말했다. "AI한테 코드 리뷰를? 사람이 보는 게 낫지 않아?"

지민은 깨달았다. 현우의 말이 틀린 건 아니었다. 하지만 문제는 AI가 아니라 환경이었다. Claude가 멍청해진 게 아니다. 50,000 토큰의 잡음 속에서 리뷰를 하고 있었다.

messages = [
    "user: 결제 시스템 구현해줘",
    "[tool_result] src/api/routes.ts (500줄)",       # ← 2000 토큰
    "[tool_result] src/models/user.ts (300줄)",      # ← 1200 토큰
    "[tool_result] src/db/schema.sql (200줄)",       # ← 800 토큰
    ... (파일 탐색 20개 더)
    "assistant: 계획을 세울게요...",
    ... (구현 과정 전체)
    "user: 이제 코드 리뷰해줘"    # ← 여기서 리뷰 요청
]
# 총 컨텍스트: 50,000 토큰. 리뷰에 필요한 것: 5,000 토큰. 노이즈: 90%.

"리뷰어에게 리뷰 대상만 보여줄 수 없을까? 지금까지의 탐색 과정, 계획, 잡담 없이?"


용어 정리: Subagent vs Teammate

이 파일에서 다루는 "에이전트"는 정확히는 Subagent다.

Subagent (이 파일):
  부모가 생성 → 작업 수행 → 요약 반환 → 소멸
  수직적 관계. 부모가 기다린다.
  예: code-reviewer, planner, security-reviewer

Teammate (10-agent-teams.md):
  독립적으로 생존 → 작업 보드로 협력 → 여러 작업 순회
  수평적 관계. 아무도 기다리지 않는다.
  예: backend-agent, frontend-agent, qa-agent

둘 다 "Agent"이지만 생명주기가 다르다. Subagent는 일회용 전문가, Teammate는 상주 팀원이다.


탄생 배경: 컨텍스트가 오염된다

Agent Loop와 Skills가 완성되면서 Claude Code는 복잡한 작업을 처리하기 시작했다.

그런데 치명적인 문제가 드러났다.

# Agent Loop의 메시지 배열이 점점 커진다
messages = [
    "user: 결제 시스템 구현해줘",
    "assistant: 먼저 코드베이스를 파악해볼게요...",
    "user: [tool_result] src/api/routes.ts (500줄)",       ← 2000 토큰
    "user: [tool_result] src/models/user.ts (300줄)",      ← 1200 토큰
    "user: [tool_result] src/db/schema.sql (200줄)",       ← 800 토큰
    "user: [tool_result] package.json",                    ← 300 토큰
    "user: [tool_result] README.md",                       ← 500 토큰
    ... (파일 탐색 20개 더)
    "assistant: 좋아요, 이제 계획을 세울게요...",
    "assistant: 1단계: stripe 패키지 설치...",
    ... (계획과 구현이 섞이기 시작)
]
# 총 컨텍스트: 50,000 토큰
# 그 중 실제 코드 리뷰에 필요한 것: 5,000 토큰
# 노이즈 비율: 90%

코드 리뷰 에이전트가 50,000 토큰의 컨텍스트를 전부 들고 리뷰해야 한다. 탐색 과정, 계획, 잡담, 파일 내용들... 정작 리뷰에는 필요 없는 것들이 대부분이다.

핵심 통찰:

"As the agent works, its messages array grows. Every file read, every bash output stays in context permanently."


핵심 통찰: 프로세스 격리 = 컨텍스트 격리

해결책은 우아했다.

새로운 에이전트에게는 항상 빈 메시지 배열을 준다.

# 서브에이전트 실행
def run_subagent(prompt: str) -> str:
    sub_messages = [{"role": "user", "content": prompt}]
    # ↑ messages=[] 로 시작! 부모 대화 내용 없음

    # 서브에이전트만의 루프
    while True:
        response = client.messages.create(messages=sub_messages, ...)
        if response.stop_reason != "tool_use":
            break
        # 툴 실행, 결과 추가...

    # 부모에게는 요약만 반환
    return last_text_from(response)
    # 서브에이전트의 30개 툴 콜은 부모 컨텍스트에 들어오지 않음
부모 에이전트                    서브에이전트
┌──────────────────┐             ┌──────────────────┐
│ messages=[       │             │ messages=[]      │ ← 깨끗!
│   긴 대화...     │             │                  │
│   30개 파일...   │  요청       │  독립적으로 작업  │
│                  │ ──────────> │  (파일 읽기, 분석)│
│   result = "..." │ <────────── │  return 요약     │
│                  │  요약만     │                  │
└──────────────────┘             └──────────────────┘
                                 서브에이전트의 30개 툴 콜 = 버려짐

"탐색해서 답을 찾아주는 일"을 서브에이전트에게 맡기면:

  1. 서브에이전트가 깨끗한 컨텍스트로 탐색
  2. 찾은 내용을 요약해서 부모에게 전달
  3. 부모 컨텍스트에는 요약만 남음 (탐색 노이즈 없음)