3.3.2 하네스 아키텍처
평가 하네스는 4대 컴포넌트(Task·Dataset·Runner·Metric)로 모델 품질을 측정하고, 운영 하네스는 6개 레이어(샌드박스→컨텍스트→도구→게이트→라이프사이클→관찰)로 에이전트를 안전하게 실행한다. 업데이트: 2026-03-16
핵심 요약
| 구분 | 내용 |
|---|---|
| 📖 정의 | 하네스를 구성하는 구조적 요소와 각 레이어가 맡는 역할의 설계 |
| 💡 핵심 | 평가 하네스는 “측정 인프라”, 운영 하네스는 “실행 환경”이며, 두 가지는 피드백 루프로 연결된다 |
| 🎯 대상 | 에이전트 시스템의 내부 동작 원리와 설계 패턴을 이해하려는 엔지니어 |
| ⚠️ 주의 | 6레이어 중 하나라도 빠지면 시스템 안정성이 크게 저하된다. 특히 결정론적 게이트(레이어 4)는 에이전트가 우회할 수 없도록 설계해야 한다 |
문서 탐색
목차
- 평가 하네스의 4대 컴포넌트
- 평가 파이프라인 흐름
- 운영 하네스의 6레이어 — Stripe Minions 패턴
- 각 레이어 상세 설명
- Claude 멀티에이전트 하네스
- 평가 하네스와 운영 하네스의 피드백 루프
- lm-evaluation-harness 내부 구조 (심화)
1. 평가 하네스의 4대 컴포넌트
평가 하네스는 LLM 또는 에이전트의 출력을 자동으로 측정하기 위한 인프라다. 공통적으로 4개의 핵심 컴포넌트로 구성된다.
graph TD Task["Task<br/>(무엇을 평가하는가)"] --> Dataset["Dataset<br/>(어떤 데이터로)"] Dataset --> Runner["Runner<br/>(어떻게 실행하는가)"] Runner --> LLM["LLM / Agent<br/>(평가 대상)"] LLM --> Runner Runner --> Metric["Metric<br/>(어떻게 채점하는가)"] Metric --> Aggregator["Aggregator<br/>(최종 집계)"] Aggregator --> Report["리포트 / 대시보드"]
| 컴포넌트 | 역할 | 예시 |
|---|---|---|
| Task | 무엇을 평가하는가 정의. 입력 형식, 출력 형식, 채점 방식을 명세 | MMLU, HellaSwag, 커스텀 QA |
| Dataset | 평가에 사용할 입력 데이터. Task와 연결되어 인스턴스를 생성 | HuggingFace 데이터셋, CSV, JSON |
| Runner | 모델에 입력을 보내고 출력을 수집. 배치 처리, 병렬화, 재시도 담당 | lm-eval Runner, DeepEval Runner |
| Metric | 출력 품질을 수치화. 정확도 기반, LLM-Judge 기반, 확률 기반 등 다양 | Accuracy, F1, G-Eval, Pass@k |
| Filter | 출력 후처리 (선택). CoT 추론 제거, 답변 정규화 등 | think_end_token 제거, 소문자 변환 |
| Aggregator | 태스크별 점수를 최종 집계. 가중 평균, 부트스트랩 신뢰 구간 | 평균, 매크로 평균 |
메트릭 유형 비교
| 메트릭 유형 | 특징 | 대표 메트릭 | 사용 시점 |
|---|---|---|---|
| 규칙 기반 | 빠르고 결정론적. 정답이 명확한 태스크에 적합 | Exact Match, ROUGE, BLEU | 분류, 번역, 요약 |
| LLM-Judge | GPT/Claude를 심사위원으로 사용. 주관적 품질 평가 가능 | G-Eval, LLM Rubric | 응답 품질, 어조, 창의성 |
| 확률 기반 | 토큰 로그 확률을 이용. 속도 빠름 | Perplexity, Log-Likelihood | 언어 모델 자체 평가 |
| 에이전트 전용 | 도구 호출 시퀀스와 목표 달성 여부를 평가 | Pass@k, Tool Correctness, Goal Completion | 에이전트 평가 |
2. 평가 파이프라인 흐름
graph TD YML["YAML 태스크 정의<br/>(doc_to_text, metric 등)"] DS["데이터셋 로드<br/>(HuggingFace / CSV / JSON)"] INS["문서 → 인스턴스 변환<br/>(Few-shot 포함)"] LM["LLM 입력 전달<br/>(loglikelihood 또는 generation)"] OUT["모델 출력 수집"] FLT["Filter 적용<br/>(후처리, CoT 제거 등)"] MTR["Metric 함수 채점"] AGG["태스크별 집계<br/>(평균, 부트스트랩)"] RPT["최종 리포트 출력<br/>(JSON / 터미널)"] YML --> DS DS --> INS INS --> LM LM --> OUT OUT --> FLT FLT --> MTR MTR --> AGG AGG --> RPT
3. 운영 하네스의 6레이어 — Stripe Minions 패턴
Stripe의 Minions 시스템에서 도출된 운영 하네스의 계층 구조다. 아래에서 위로 쌓이는 레이어 구조이며, 각 레이어는 독립적으로 설계된다.
graph TD LM["AI 모델<br/>(추론 엔진)"] L1["레이어 1: 샌드박스 격리<br/>컨테이너·VM·독립 체크아웃"] L2["레이어 2: 컨텍스트 엔지니어링<br/>아키텍처 문서·코드 맵·의존성 경계"] L3["레이어 3: 도구 접근<br/>MCP 서버·API·내부 시스템 (최소 권한)"] L4["레이어 4: 결정론적 게이트<br/>린터·테스트·정적 분석 (우회 불가)"] L5["레이어 5: 라이프사이클 관리<br/>PR 생성·CI·리뷰·머지"] L6["레이어 6: 관찰 가능성<br/>로그·메트릭·알림·실행 추적"] LM --> L1 L1 --> L2 L2 --> L3 L3 --> L4 L4 --> L5 L5 --> L6
4. 각 레이어 상세 설명
레이어 1 — 샌드박스 격리
에이전트가 실수를 해도 다른 시스템에 영향을 주지 않도록 격리된 환경에서 실행한다.
| 항목 | 내용 |
|---|---|
| 핵심 원칙 | 격리가 구조적 안전을 보장한다. 에이전트는 격리된 컨테이너 안에서만 동작한다 |
| Stripe 구현 | 독립 컨테이너, 저장소 신선한 체크아웃, 작업마다 새로운 환경 |
| 도구 | Docker, Podman, VM, GitHub Codespaces |
| 장점 | 부작용 차단, 병렬 실행 가능, 재현 가능한 환경 |
레이어 2 — 컨텍스트 엔지니어링
에이전트가 올바른 결정을 내리려면 올바른 정보가 필요하다. 1,000페이지 문서 대신 지도(map)를 제공한다.
| 항목 | 내용 |
|---|---|
| 핵심 원칙 | 모델에게 전체 정보를 쏟아붓지 않는다. 태스크에 필요한 컨텍스트를 동적으로 구성한다 |
| Stripe 구현 | 아키텍처 경계 문서, 의존성 레이어 다이어그램, 동적 관찰 가능성 데이터 주입 |
| Claude Code 적용 | CLAUDE.md 파일, 프로젝트 구조 설명, 코딩 컨벤션 문서 |
| 장점 | 컨텍스트 창 효율화, 관련성 높은 결정, 환각 감소 |
레이어 3 — 도구 접근 (최소 권한 원칙)
에이전트에게 모든 도구를 주지 않는다. 태스크에 필요한 도구만 선택적으로 제공한다.
| 항목 | 내용 |
|---|---|
| 핵심 원칙 | 전체 카탈로그 대신 태스크 관련 서브셋만 제공. 최소 권한 원칙 적용 |
| Stripe 구현 | Toolshed(~500개 도구), 태스크 시작 시 필요한 도구 서브셋만 요청 |
| Claude Code 적용 | MCP 서버, 권한 설정(--allowedTools), allowed commands |
| 위험 | 과도한 도구 접근은 의도치 않은 부작용(파일 삭제, 외부 API 호출 등)을 야기한다 |
레이어 4 — 결정론적 게이트 (핵심)
LLM의 창의성을 결정론적 검증으로 경계 설정한다. 이 레이어는 에이전트가 절대 우회할 수 없다.
| 항목 | 내용 |
|---|---|
| 핵심 원칙 | 린터와 테스트는 항상 실행된다. 에이전트가 “테스트를 건너뛰자”고 판단하더라도 시스템이 강제 실행한다 |
| Stripe 구현 | 최대 2회 CI 라운드. 2회 내에 모든 게이트를 통과하지 못하면 PR로 종료 |
| 도구 | ESLint, Pylint, pytest, GitHub Actions, pre-commit 훅 |
| 장점 | 모델 실수를 시스템 레벨에서 차단. “AI가 테스트를 통과했다”는 신뢰성 확보 |
레이어 5 — 라이프사이클 관리
에이전트의 작업 결과를 소프트웨어 개발 수명주기(브랜치, PR, 리뷰, 머지)에 통합한다.
| 항목 | 내용 |
|---|---|
| 핵심 원칙 | 에이전트 작업도 기존 소프트웨어 개발 프로세스를 따른다 |
| Stripe 구현 | 엔지니어 개입 없이 브랜치 생성 → CI → PR 생성까지 자동화 |
| 도구 | GitHub Actions, GitLab CI, Jira 연동 |
레이어 6 — 관찰 가능성
에이전트가 무엇을 했는지, 왜 실패했는지 사후에 파악할 수 있어야 한다.
| 항목 | 내용 |
|---|---|
| 핵심 원칙 | 모든 단계를 캡처한다 — 행동, 도구 호출, 출력, 반복 횟수, 소요 시간 |
| Stripe 구현 | Weave(W&B) 통합, LiteLLM 크로스모델 호환 |
| 도구 | Langfuse, LangSmith, Weave, OpenTelemetry |
| 장점 | 디버깅 시간 단축, 실패 패턴 파악, 모델 개선 데이터 수집 |
5. Claude 멀티에이전트 하네스
Anthropic이 발표한 Claude Agent Teams 패턴은 멀티에이전트 운영 하네스의 대표 사례다.
graph TD Lead["리드 에이전트<br/>조율·계획·의존성 관리"] T1["팀원 에이전트 A<br/>독립된 컨텍스트 윈도우"] T2["팀원 에이전트 B<br/>독립된 컨텍스트 윈도우"] T3["팀원 에이전트 C<br/>독립된 컨텍스트 윈도우"] Board["파일 기반 태스크 보드<br/>의존성 로직 포함"] Lead --> T1 Lead --> T2 Lead --> T3 T1 --> Board T2 --> Board T3 --> Board Board --> Lead
| 항목 | 내용 |
|---|---|
| 리드 에이전트 | 전체 작업을 분해하고 팀원 에이전트에게 위임. 의존성과 우선순위를 관리 |
| 팀원 에이전트 | 독립된 컨텍스트 윈도우에서 서브태스크를 수행. 병렬 실행 가능 |
| 파일 기반 태스크 보드 | 에이전트 간 상태를 파일로 공유. 완료·진행 중·실패 상태를 추적 |
| 성과 | SWE-bench Verified에서 86.8% 달성 (단일 에이전트 대비 유의미한 향상) |
6. 평가 하네스와 운영 하네스의 피드백 루프
두 하네스는 독립적으로 존재하지 않는다. 지속적인 개선 루프를 형성한다.
graph TD Dev["개발 단계<br/>프롬프트·도구·컨텍스트 설계"] OpH["운영 하네스<br/>에이전트 실행"] OBS["관찰 가능성 레이어<br/>실행 추적 수집"] EvalH["평가 하네스<br/>품질 메트릭 측정"] Report["리포트<br/>회귀 감지·실패 패턴"] Improve["개선 결정<br/>프롬프트·모델·하네스 수정"] Dev --> OpH OpH --> OBS OBS --> EvalH EvalH --> Report Report --> Improve Improve --> Dev
| 단계 | 설명 |
|---|---|
| 실행 | 운영 하네스가 에이전트를 샌드박스에서 실행 |
| 수집 | 관찰 가능성 레이어가 모든 단계를 추적 |
| 평가 | 평가 하네스가 수집된 데이터로 메트릭을 계산 |
| 개선 | 메트릭 저하 시 프롬프트, 도구 설정, 또는 하네스 아키텍처를 개선 |
7. lm-evaluation-harness 내부 구조 (심화)
EleutherAI의 lm-evaluation-harness는 가장 널리 사용되는 오픈소스 평가 프레임워크다. Hugging Face Open LLM Leaderboard의 공식 백엔드이기도 하다.
lm_eval/
├── models/ ← LM 백엔드 (HuggingFace, OpenAI, vLLM 등)
├── tasks/ ← YAML 기반 태스크 정의
│ ├── mmlu/ ← MMLU 태스크 그룹
│ ├── hellaswag/
│ └── ...
├── metrics/ ← 평가 메트릭 함수
├── filters/ ← 출력 후처리 필터
└── evaluator.py ← 메인 평가 루프
태스크 YAML 구조
task: hellaswag
dataset_path: hellaswag
test_split: validation
doc_to_text: "{{ctx}}"
doc_to_target: "{{label}}"
doc_to_choice: ["{{endings[0]}}", "{{endings[1]}}", "{{endings[2]}}", "{{endings[3]}}"]
output_type: multiple_choice
metric_list:
- metric: acc
aggregation: mean
higher_is_better: true
- metric: acc_norm
aggregation: mean
higher_is_better: true주요 출력 타입
output_type | 설명 | 적합한 태스크 |
|---|---|---|
loglikelihood | 각 선택지의 로그 확률을 비교 | 객관식, 분류 |
multiple_choice | 여러 선택지 중 가장 높은 확률 선택 | MMLU, HellaSwag |
generate_until | 텍스트 생성 후 특정 토큰에서 중단 | 수학 문제, QA |
loglikelihood_rolling | 전체 시퀀스 로그 확률 계산 | 언어 모델링 |