하네스 엔지니어링 적용편 — Anthropic은 AI 에이전트를 어떻게 설계했나

하네스 엔지니어링 적용편 — Anthropic은 AI 에이전트를 어떻게 설계했나

이전 글에서 하네스 엔지니어링의 개념과 구성 요소를 다뤘다. 이번에는 실전이다. Anthropic이 공식 엔지니어링 블로그에서 공개한 구체적인 아키텍처 패턴들과, OpenAI Codex 팀의 실험 결과를 바탕으로 하네스가 실제로 어떻게 적용되는지 살펴본다.


에이전트 루프의 기본 구조: Inner Loop

모든 AI 에이전트의 심장에는 에이전트 루프(Agent Loop)가 있다. Claude Code에서는 이것을 queryLoop라고 부른다. 본질적으로 while(true) 루프다.

while (true) {
    1. 컨텍스트 준비 (계획 모드 첨부파일, 작업 리마인더)
    2. 모델 호출 (스트리밍 API 호출)
    3. 도구 실행 (도구 호출 감지 → 스키마 검증 → 권한 확인 → 실행)
    4. 계속 결정 (모델이 더 할 일이 있는가?)
}

각 반복이 하나의 "사고 → 행동 → 관찰" 사이클이다. 모델이 생각하고, 도구를 호출하고, 결과를 관찰하고, 다시 생각한다.

도구 실행 흐름은 이렇다:

  1. 모델이 출력에서 도구 호출을 생성
  2. 하네스가 도구 호출을 감지하고 텍스트 생성을 중지
  3. 입력을 스키마(Zod 검증 JSON Schema)에 대해 검증
  4. 권한 파이프라인 실행 (일반 규칙 → 도구별 체크 → 자동 분류기 → 사용자 승인 폴백)
  5. 도구 핸들러가 작업 실행
  6. 결과가 모델의 컨텍스트에 다시 주입
  7. 루프 계속

이것이 Inner Loop다. 대부분의 간단한 작업은 이 루프 안에서 완료된다.

하지만 복잡한 작업, 특히 여러 시간이 걸리는 장기 실행 작업에서는 이것만으로 부족하다. 컨텍스트 윈도우가 가득 차고, 모델의 추론 능력이 저하된다.


Outer Loop: Ralph Loop 패턴

Anthropic이 장기 실행 작업을 위해 개발한 것이 Ralph Loop 패턴이다.

아이디어는 단순하다. 모델이 작업을 끝내려고 할 때, 훅이 이를 가로채서 깨끗한 컨텍스트 윈도우에서 원래 프롬프트를 다시 주입한다. 에이전트가 강제로 작업을 계속하게 만드는 것이다.

왜 이것이 작동하느냐? 파일시스템이 있기 때문이다. 각 반복은 깨끗한 컨텍스트로 시작하지만, 이전 반복의 상태를 파일시스템에서 읽어온다.

[세션 1: 초기화]
  ↓ 환경 설정, 구조화된 아티팩트 생성
  ↓ claude-progress.txt 작성
  ↓ feature_list.json 생성
  ↓ Git 커밋

[세션 2~N: 코딩]
  ↓ claude-progress.txt + git log 읽기
  ↓ feature_list.json에서 최우선 미완성 기능 선택
  ↓ 하나의 기능 구현
  ↓ 테스트로 검증
  ↓ Git 커밋 + 진행 파일 업데이트
  ↓ 컨텍스트 리셋 → 다음 세션 시작

여기서 Anthropic이 택한 것은 컴팩션 대신 전체 리셋이다. Anthropic은 컴팩션(기존 컨텍스트를 요약해서 줄이는 방식)이 "컨텍스트 불안"을 유발한다는 것을 발견했다. 모델이 컨텍스트 한계에 가까워지고 있다는 것을 인식하면 서둘러 작업을 마무리하려 한다. 깨끗한 슬레이트에서 시작하되, 구조화된 인수인계 아티팩트로 세션 간 연결을 유지하는 것이 더 효과적이었다.


상태 관리: 파일시스템이 다리가 된다

장기 실행 에이전트의 핵심 도전은 이것이다. 이산적 세션들로 작업해야 하는데, 각 세션은 이전에 무슨 일이 있었는지 기억하지 못한다.

Anthropic의 해결책은 다층적이다.

claude-progress.txt

사람이 읽을 수 있는 세션 간 인수인계 로그다. 완료된 작업, 깨진 항목, 다음 단계를 기록한다.

## Session 3 (2026-04-14)
- Completed: User authentication flow (login, signup, password reset)
- Fixed: Session token not persisting across page reloads
- Known issue: OAuth redirect URL not configured for production
- Next: Implement chat message history with infinite scroll

feature_list.json

구조화된 기능 백로그다. Anthropic이 의도적으로 Markdown 대신 JSON을 선택한 이유가 있다. 모델이 JSON 항목을 부적절하게 수정하거나 삭제할 가능성이 Markdown보다 낮기 때문이다.

{
    "category": "functional",
    "description": "New chat button creates a fresh conversation",
    "steps": [
      "Navigate to main interface",
      "Click the 'New Chat' button",
      "Verify a new conversation is created",
      "Check that chat area shows welcome state",
      "Verify conversation appears in sidebar"
    ],
    "passes": false
}

초기화 에이전트가 200개 이상의 이런 기능을 생성한다. 코딩 에이전트에게는 강한 지시가 주어진다: "테스트를 삭제하거나 수정하는 것은 허용되지 않는다. 이는 기능 누락이나 버그로 이어질 수 있다."

세션 초기화 루틴

각 코딩 세션은 이 순서를 따른다:

  1. pwd 실행 — 올바른 작업 디렉토리인지 확인 (단순하지만 비용이 큰 혼란을 방지)
  2. claude-progress.txtgit log 읽기 — 인수인계 노트
  3. feature_list.json 읽기 — 최우선 미완성 기능 식별
  4. init.sh 실행 — 개발 서버 시작
  5. 기본 E2E 테스트 실행 — 문서화되지 않은 버그 확인
  6. 앱 안정성 확인 후에만 작업 시작

이 루틴 자체가 하네스의 구체적인 구현이다. 사람 엔지니어가 매일 아침 하는 일을 코드화한 것이다.


Anthropic의 3-에이전트 아키텍처

Anthropic의 두 번째 하네스 논문(2026년 3월)에서는 GAN(Generative Adversarial Networks)에서 영감을 받은 3-에이전트 아키텍처를 소개한다.

Planner Agent (기획자)

1~4문장의 짧은 프롬프트를 받아 포괄적인 제품 명세서로 확장한다. 16개 기능, 10개 스프린트의 상세한 백로그를 생성한다. 구현 디테일보다 범위(scope)에 집중하되, AI 기능을 통합할 기회를 식별한다.

Generator Agent (구현자)

기능을 하나씩 점진적으로 구현한다. React + Vite + FastAPI + SQLite/PostgreSQL 스택을 사용하고, 각 스프린트 끝에 자기 작업을 평가한 후 QA에 넘긴다. Git 버전 관리를 직접 수행한다.

Evaluator Agent (평가자)

GAN의 Discriminator에 해당한다. 각 스프린트마다 Generator와 "계약(Contract)"을 협상한다. 구현 디테일과 테스트 가능한 행동을 정의하는 계약이다.

차별점은 Playwright MCP를 사용해 실제 페이지를 탐색하고 상호작용한다는 것이다. 코드를 읽는 게 아니라, 사용자처럼 애플리케이션을 사용하면서 평가한다.

스프린트 계약 패턴

고수준 명세와 테스트 가능한 구현 사이의 간극을 메우는 것이 "계약"이다.

Sprint 3 Contract:
- Generator delivers: Chat history with infinite scroll, message timestamps
- Evaluator verifies:
  ✓ Scroll up loads older messages (batch of 20)
  ✓ Timestamps display in relative format
  ✓ New messages appear at bottom without scroll jump
  ✓ Empty state shows welcome message

이 계약 덕분에 평가가 주관적이지 않다. "잘 작동하는가?"가 아니라, "합의된 기준을 충족하는가?"로 평가한다.

진화: 모델이 좋아지면 하네스도 단순해진다

초기 작업은 Claude Opus 4.5로 진행됐다. 이 모델은 "컨텍스트 불안"이 있어 스프린트 분할 구조가 필수였다.

이후 Opus 4.6이 출시되면서 장기 컨텍스트 계획과 코드 리뷰 능력이 개선됐다. 그 결과:

  • 스프린트 분해 구조를 제거할 수 있었다
  • 평가자가 단일 패스 검증으로 전환됐다
  • 복잡도가 줄어들면서도 성능은 유지됐다

하네스가 인코딩하는 가정은 모델이 발전하면 낡아진다. Anthropic 스스로 이것을 명시적으로 인정한다. 정기적으로 각 하네스 컴포넌트가 여전히 필요한지 재검토해야 한다.

DAW(디지털 오디오 워크스테이션) 예시에서 업데이트된 하네스는:
- 3시간 50분, $124.70
- Generator가 스프린트 구조 없이 2시간 이상 일관성 있게 작업
- QA가 여전히 여러 라운드에 걸쳐 의미 있는 기능 갭을 발견


Brain / Hands / Session: 최신 아키텍처

2026년 4월, Anthropic은 "Managed Agents" 아키텍처를 공개했다. 기존 모놀리식 접근의 근본적 문제를 해결하기 위한 분리 설계다.

기존 방식의 문제: LLM 컨트롤러 + 도구 + 실행 환경 + 세션 상태가 모두 하나의 컨테이너에 있으면 — 스케일링이 어렵고, 단일 장애점이 되며, 보안 위험이 크다.

Brain (뇌)

LLM과 그것을 감싸는 하네스/컨트롤러 로직. 인지적 핵심이다. 사고하고, 계획하고, 도구 호출을 결정한다.

Hands (손)

샌드박스된, 일시적(ephemeral) 실행 환경이다. Bash, Python REPL 등. 상태가 없고(stateless), 장기 자격 증명에 접근할 수 없으며, Brain이 도구 호출로 필요할 때만 생성한다.

Session (기억)

영속적(persistent), 추가 전용(append-only) 이벤트 로그다. 모든 사고, 도구 호출, 관찰이 기록된다. Claude의 컨텍스트 윈도우 바깥에 존재한다.

Session API:
  emitEvent(id, event)  → 세션에 이벤트 기록
  getSession(id)        → 이벤트 로그 조회
  getEvents()           → 이벤트 스트림
  rewind / slice        → 위치 기반 접근

핵심 원칙: 무상태성. 어떤 Harness 인스턴스든 어떤 Session이든 집어 들고 마지막 이벤트부터 계속할 수 있다.

성능과 보안 효과

  • p50 TTFT(Time To First Token)가 약 60% 감소
  • p95 TTFT가 90% 이상 감소
  • 컨테이너가 Brain의 도구 호출로만 생성되므로, 세션이 컨테이너 부팅을 기다리지 않음

보안 측면: 기존에는 프롬프트 인젝션 하나로 같은 컨테이너의 환경 변수(자격 증명)를 읽을 수 있었다. 분리하면 이 공격 표면이 완전히 제거된다.

장애 복구

Session이 하네스 바깥에 있으므로, 하네스에서 살아남아야 할 것이 없다.

장애 복구 과정:
1. 새 하네스 인스턴스가 부팅
2. wake(sessionId) 호출
3. getSession(id)로 이벤트 로그 조회
4. 마지막 이벤트부터 재개

OpenAI Codex 팀의 실전: 5개월의 실험

개념이 아닌 실전의 이야기다. OpenAI Codex 팀은 5개월간 극단적인 실험을 수행했다.

제약: 코드를 직접 타이핑하지 않는다. 한 줄도.

결과:
- 3명의 엔지니어로 약 100만 줄의 프로덕션 애플리케이션 개발
- 1,500개 PR 머지
- 엔지니어 1인당 하루 평균 3.5개 PR 처리
- 수작업 대비 약 10배 속도

초기에는 환경 설정 부족, 도구 연결 미비, 에러 복구 로직 부재로 생산성이 낮았다. 하네스를 개선하면서 성과가 폭발적으로 올라갔다.

"1,000페이지 매뉴얼이 아니라 지도를 줘라"

OpenAI 팀이 발견한 핵심 원칙이다. 세세한 지시 대신 코드베이스 자체에 지식을 녹여 넣었다.

초기에 하나의 거대한 AGENTS.md 파일을 사용했을 때의 실패:
- 컨텍스트 윈도우라는 희소 자원에서 핵심 제약을 놓침
- 모든 것이 "중요"로 표시되면 에이전트가 지침을 무시하고 패턴 매칭만 수행
- 낡은 규칙들의 무덤이 되어 빠르게 망가짐

해결: AGENTS.md를 목차(Map)로 취급하고, 디렉토리 구조로 지시를 분산시킴.

docs/
├── design-docs/
│   ├── index.md
│   └── core-beliefs.md
├── exec-plans/
│   └── tech-debt-tracker.md
├── product-specs/
└── references/
    └── design-system-reference-llms.txt

기계적 강제

OpenAI 팀이 컨텍스트 엔지니어링과 하네스를 가장 뚜렷하게 구분한 요소는 기계적 강제(Mechanical Enforcement)다.

아키텍처 제약을 커스텀 린터와 구조 테스트로 강제한다. 에이전트에게 "이렇게 하라"고 프롬프트로 지시하는 대신, 코드 수준에서 위반을 차단한다.

도메인 의존성 방향:
Types → Config → Repo → Service → Runtime → UI

이 방향을 위반하는 코드 → 린터가 차단 → 에이전트가 즉시 수정

린터 실패 시 에러 메시지에 "수정 방법" 지시를 직접 주입한다. 에이전트의 컨텍스트에 피드백이 자동으로 반영된다.

코드 가비지 컬렉션

에이전트가 대량으로 코드를 생성하면 안 좋은 패턴이 복제되고 기술 부채가 쌓인다. OpenAI 팀은 이것을 사람이 수동으로 청소하지 않고, 백그라운드 에이전트를 배치해서 해결했다.

  • 지속적으로 코드와 문서 편차 스캔
  • 리팩토링 PR 자동 생성
  • 낡은 패턴과 부채 치우기 자동화

Human on the Loop: 개발자의 새로운 위치

bcho.tistory.com의 분석이 이 변화를 잘 정리한다. 개발자와 AI의 관계는 네 단계로 진화한다.

단계 설명 개발자 역할
Human Outside the Loop 사람은 기획만, AI가 전체 개발 아이디어 제공자
Human in the Loop AI와 실시간 상호작용 결과물을 직접 수정
Human on the Loop 하네스를 설계하고 개선 시스템 설계자
Agent Flywheel AI가 스스로 하네스를 개선 초기 조건 설계자

지금은 3단계, "Human on the Loop"가 주류다. 결과물을 직접 고치는 것이 아니라, 왜 이런 결과가 나왔는지 분석하고, 다음에는 에이전트가 스스로 더 나은 결과를 내도록 하네스를 개선하는 것.

이것이 "in the loop"과 "on the loop"의 핵심 차이다.


주의할 점: 하네스가 만능은 아니다

실전 적용 시 반드시 기억해야 할 점들이 있다.

가트너의 현실 체크

가트너 리포트에 따르면 AI 에이전트가 실제 프로덕션 코딩에 적용되는 비율은 아직 11%에 불과하다.

Amazon의 사례

Amazon에서 실제로 발생한 사고들:

  • AI 에이전트 'Kiro'가 운영 환경 무단 삭제 (13시간 중단)
  • Amazon Q 생성 코드로 160만 건 에러, 12만 건 주문 손실
  • 북미 주문 99% 감소 사태 (630만 건 주문 손실)

결과적으로 Amazon은 "사람이 모든 코드에 대한 교차 검증"을 하도록 프로세스를 변경했다.

하네스 자체의 과잉 설계

Everything Claude Code(ECC) 프로젝트는 36개 에이전트, 151개 스킬, 68개 명령어, 25개 훅, 34개 규칙을 포함한다. 이 정도 규모의 설정이 대부분 팀에게는 과도하다는 비판이 있다. 151개 스킬과 36개 에이전트의 방대한 표면적이 오히려 컨텍스트를 빠르게 소모할 수 있다.

Anthropic의 원칙: "설정은 거대한 아키텍처 설계가 아니라, 미세 조정의 관점으로 접근하라."


그렇다면 이것을 당신의 프로젝트에는 어떻게 활용할 수 있을까.

댓글

이 블로그의 인기 게시물

The Complete Scenario Architecture — Weaving It All Together

사랑을 직접 올리지 않는 설계

Read This Before You Pay for a Vibe Coding Course