개요
에이전트 하네스(Agent Harness) 란 AI 에이전트를 체계적으로 테스트, 평가, 실행하기 위한 프레임워크 또는 인프라를 말합니다. 마치 공장에서 전기 배선을 묶어 관리하는 “하네스(harness)“처럼, AI 에이전트의 입력·출력·도구 호출·메모리를 하나의 구조로 묶어 제어하는 역할을 합니다.
쉽게 말해: 에이전트가 잘 작동하는지 검증하고, 반복 실행을 자동화하는 테스트 환경입니다.
왜 필요한가?
AI 에이전트는 단순한 함수 호출과 달리 다음과 같은 복잡성을 가집니다.
| 문제 | 설명 |
|---|---|
| 비결정성 | 같은 입력이라도 LLM 응답이 매번 다를 수 있음 |
| 다단계 추론 | 여러 툴 호출과 중간 상태가 연쇄적으로 발생 |
| 외부 의존성 | 웹 검색, DB, API 등 외부 시스템과 상호작용 |
| 회귀 위험 | 프롬프트나 모델 변경이 예상치 못한 동작을 유발 |
이런 복잡성을 다루기 위해 에이전트 하네스가 필요합니다.
핵심 구성 요소
┌─────────────────────────────────────────────────┐
│ 에이전트 하네스 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ 입력 │ → │ 에이전트 │ → │ 출력 검증 │ │
│ │ 로더 │ │ 실행기 │ │ (Evaluator) │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
│ ↑ ↓ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 테스트 │ │ 도구 │ │
│ │ 케이스 │ │ 모킹 │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────┘
1. 테스트 케이스 (Test Cases)
에이전트에게 줄 입력 시나리오의 집합입니다.
# 예시: test_cases.yaml
- id: "search_and_summarize_01"
input: "2024년 노벨 물리학상 수상자를 검색해서 요약해줘"
expected_tools: ["web_search"]
expected_output_contains: ["노벨", "물리학"]
max_steps: 5
2. 에이전트 실행기 (Agent Runner)
테스트 케이스를 에이전트에게 전달하고, 전체 실행 과정을 기록합니다.
class AgentRunner:
def run(self, test_case: TestCase) -> AgentTrace:
trace = AgentTrace()
result = self.agent.invoke(test_case.input)
trace.record(result)
return trace
3. 도구 모킹 (Tool Mocking)
실제 외부 API 대신 가짜 응답을 반환하여 테스트를 빠르고 안정적으로 만듭니다.
# 실제 웹 검색 대신 고정된 응답 반환
mock_tools = {
"web_search": lambda q: "검색 결과: 2024 노벨 물리학상 수상자는 ..."
}
4. 평가기 (Evaluator)
에이전트의 출력이 기준을 충족하는지 검증합니다.
| 평가 방식 | 설명 | 예시 |
|---|---|---|
| 규칙 기반 | 특정 키워드 포함 여부 | "노벨" in output |
| 모델 기반 | LLM이 출력 품질 채점 | GPT-4로 1~5점 평가 |
| 참조 기반 | 정답과 유사도 비교 | ROUGE, BLEU 스코어 |
| 도구 추적 | 올바른 도구를 사용했는지 | web_search 호출 여부 |
에이전트 하네스의 주요 기능
✅ 배치 평가 (Batch Evaluation)
수백 개의 테스트 케이스를 자동으로 실행하고 결과를 집계합니다.
총 테스트: 200개
통과: 172개 (86%)
실패: 28개 (14%)
평균 소요 단계: 3.4
평균 응답 시간: 4.2초
🔁 회귀 테스트 (Regression Testing)
프롬프트나 모델을 변경할 때 이전 버전과 성능을 비교합니다.
v1.0 → v1.1 변경사항:
정확도: 82% → 86% (+4%)
응답 속도: 5.1초 → 4.2초 (-18%)
도구 오남용: 12% → 7% (-5%)
📊 트레이스 기록 (Trace Logging)
에이전트의 모든 중간 단계를 기록하여 디버깅에 활용합니다.
{
"trace_id": "abc123",
"steps": [
{"step": 1, "type": "thought", "content": "검색이 필요하다고 판단"},
{"step": 2, "type": "tool_call", "tool": "web_search", "input": "노벨상 2024"},
{"step": 3, "type": "tool_result", "content": "...검색 결과..."},
{"step": 4, "type": "final_answer", "content": "2024년 노벨 물리학상은..."}
]
}
대표적인 에이전트 하네스 도구
| 도구 | 설명 | 특징 |
|---|---|---|
| LangSmith | LangChain 공식 평가 플랫폼 | 트레이스 시각화, 데이터셋 관리 |
| Braintrust | LLM 앱 평가 전문 플랫폼 | A/B 테스트, 점수 추적 |
| Promptfoo | 오픈소스 LLM 테스트 도구 | CLI 기반, YAML 설정 |
| AgentBench | 학술 연구용 벤치마크 | 다양한 환경 시뮬레이션 |
| 직접 구현 | Python + pytest | 완전한 커스터마이징 가능 |
간단한 구현 예시 (Python)
import pytest
from myagent import ResearchAgent
# 테스트 대상 에이전트
agent = ResearchAgent()
# 테스트 케이스 정의
test_cases = [
{
"input": "파이썬 최신 버전은?",
"must_contain": ["Python", "3."],
"max_steps": 3,
},
{
"input": "기후 변화 원인 요약",
"must_contain": ["온실가스", "탄소"],
"max_steps": 5,
},
]
@pytest.mark.parametrize("case", test_cases)
def test_agent_output(case):
result = agent.run(case["input"])
# 출력 내용 검증
for keyword in case["must_contain"]:
assert keyword in result.output, f"'{keyword}' 누락"
# 단계 수 제한 검증
assert result.step_count <= case["max_steps"], "최대 단계 초과"
print(f"✅ 통과 | 단계: {result.step_count} | 출력: {result.output[:100]}")
에이전트 하네스 설계 시 고려사항
1. 재현성 확보
- 랜덤 시드 고정 (
temperature=0사용) - 외부 API는 모킹 처리
- 날짜/시간 의존성 제거
2. 평가 기준 명확화
- “좋은 응답”의 기준을 수치로 정의
- LLM-as-Judge 활용 시 평가 프롬프트 신중하게 설계
3. 비용 관리
- 개발 중: 저렴한 모델로 빠른 반복 테스트
- 최종 검증: 실제 사용 모델로 전체 테스트
4. 점진적 테스트
단위 테스트 → 통합 테스트 → E2E 테스트
(개별 도구) (도구 조합) (전체 시나리오)
실제 활용 흐름
1. 테스트 케이스 작성
↓
2. 하네스로 배치 실행
↓
3. 실패 케이스 트레이스 분석
↓
4. 프롬프트 / 로직 수정
↓
5. 재실행 → 성능 비교
↓
6. 기준 충족 시 배포
에이전트 하네스 vs 에이전트 아키텍처
이 둘은 자주 혼동되지만 역할과 관심사가 완전히 다릅니다.
한 줄 요약
| 개념 | 한 줄 정의 |
|---|---|
| 에이전트 아키텍처 | 에이전트가 어떻게 생각하고 행동하는지 설계하는 구조 |
| 에이전트 하네스 | 그 에이전트가 제대로 동작하는지 검증하고 실행을 관리하는 인프라 |
비유: 아키텍처는 자동차 설계도, 하네스는 자동차 검사 라인입니다.
개념 비교표
| 구분 | 에이전트 아키텍처 | 에이전트 하네스 |
|---|---|---|
| 목적 | 에이전트의 동작 구조 정의 | 에이전트의 품질 검증 및 실행 관리 |
| 관심사 | ”어떻게 추론하고 행동할까?" | "올바르게 동작하고 있는가?” |
| 구성 요소 | LLM, 메모리, 도구, 플래너 | 테스트 케이스, 실행기, 평가기, 모킹 |
| 산출물 | 실제 동작하는 에이전트 | 테스트 결과, 성능 리포트, 트레이스 |
| 적용 시점 | 설계·개발 단계 | 테스트·검증·배포 단계 |
| 변경 주체 | 개발자 (로직 설계) | QA / MLOps 엔지니어 |
| 핵심 질문 | ”무엇을 만들까?" | "잘 만들어졌는가?” |
구조적 위치 관계
┌──────────────────────────────────────────────────────┐
│ 에이전트 하네스 │
│ (테스트 환경 / 실행 관리 / 평가 인프라) │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ 에이전트 아키텍처 │ │
│ │ │ │
│ │ 입력 → [플래너] → [도구 실행] → 출력 │ │
│ │ ↕ ↕ │ │
│ │ [메모리] [LLM] │ │
│ └────────────────────────────────────────────┘ │
│ │
│ 테스트 케이스 주입 ──────────────────→ 결과 평가 │
└──────────────────────────────────────────────────────┘
하네스는 아키텍처를 감싸는(wrapping) 외부 레이어입니다. 아키텍처 내부를 바꾸지 않고, 외부에서 입력을 주입하고 출력을 측정합니다.
에이전트 아키텍처의 주요 패턴
아키텍처는 에이전트의 내부 구조를 결정합니다. 대표적인 패턴은 다음과 같습니다.
ReAct (Reasoning + Acting)
생각(Thought) → 행동(Action) → 관찰(Observation) → 반복
LLM이 생각하고, 도구를 호출하고, 결과를 보고 다시 생각하는 반복 구조입니다.
Plan-and-Execute
계획 수립(Planner) → 단계별 실행(Executor) → 결과 통합
전체 작업을 먼저 계획한 뒤 순서대로 실행합니다. 복잡한 멀티스텝 작업에 적합합니다.
Multi-Agent
오케스트레이터 → 전문 에이전트 A
→ 전문 에이전트 B
→ 전문 에이전트 C
역할별로 분리된 여러 에이전트가 협력합니다.
언제 무엇을 고민해야 하나?
"에이전트가 복잡한 작업을 어떻게 처리하게 할까?"
→ 아키텍처 선택 문제
"에이전트가 기대한 대로 동작하는지 어떻게 확인하지?"
→ 하네스 구축 문제
"새 모델로 교체했을 때 성능이 떨어지지 않았는지 확인하려면?"
→ 하네스의 회귀 테스트
"에이전트가 여러 도구를 조합해서 추론하게 하려면?"
→ 아키텍처 설계 (ReAct, CoT 등)
실제 프로젝트에서의 역할 분리
개발자 A (아키텍처 담당)
└── LLM 선택, 프롬프트 설계, 도구 연결, 메모리 구조 결정
개발자 B (하네스 담당)
└── 테스트 시나리오 작성, 평가 기준 정의, CI/CD 파이프라인 연결
→ 둘이 협력해야 완성도 높은 에이전트 서비스가 됩니다.
정리
| 항목 | 내용 |
|---|---|
| 정의 | AI 에이전트의 테스트·평가·실행을 자동화하는 인프라 |
| 핵심 목적 | 신뢰성 확보, 회귀 방지, 성능 측정 |
| 주요 구성 | 테스트 케이스, 실행기, 평가기, 도구 모킹 |
| 적용 시점 | 에이전트 개발 초기부터 지속적으로 |
| 기대 효과 | 빠른 반복 개발, 안정적인 배포, 품질 보장 |
에이전트 하네스는 AI 에이전트를 프로덕션 수준으로 끌어올리는 필수 인프라입니다. 단순한 데모를 넘어 실제 서비스에서 신뢰할 수 있는 에이전트를 만들려면 반드시 구축해야 합니다.