두려움 없이 AI 에이전트를 배포하기 위해 쓰는 평가 하니스
두려움 없이 에이전트를 배포하는 것은 단 한 가지, 평가 하니스에서 나온다. 채점된 테스트 케이스의 고정된 집합을 자동으로 점수화하고(어서션과 LLM 심판), 모든 프롬프트나 모델 변경 전에 실행한다. 점수가 유지되면 배포한다. 테스트 세트는 실제 운영 장애로부터 구축된다.
매주 수요일. 28,400명+ 구독자. 핵심만.
✓ 받은편지함을 확인하세요 — 확인 링크를 클릭해 가입을 완료하세요.
✓ 구독이 완료되었습니다!
✓ 이미 목록에 있습니다.
목차
2026년 6월 업데이트.
요약: 운영 중인 에이전트에서 프롬프트를 바꾸거나 모델을 교체하면서도 숨을 죽이지 않아도 되는 이유는 단 한 가지, 평가 하니스다. 채점된 테스트 케이스의 고정된 집합을 자동으로 점수화한다 — 쓸 수 있는 곳에는 엄격한 어서션을, 쓸 수 없는 곳에는 LLM 심판을 — 그리고 모든 변경 전에 실행한다. 점수가 유지되면 배포한다. 점수가 떨어지면 배포하지 않는다. 테스트 세트는 합성이 아니다. 실제 운영 장애로부터 구축되므로, 모든 버그가 영구적인 회귀 테스트가 된다.
운영자의 해석: 100개가 넘는 에이전트를 거치면서, 자신 있게 손대는 것과 두려운 것의 차이는 평가가 있느냐다. 평가 하니스가 없으면 모든 프롬프트 조정이 도박이다. 평가 하니스는 “이게 더 나은 것 같다”를 “이건 측정 가능하게 4점 더 낫고 아무것도 망가뜨리지 않았다”로 바꾼다. 그것이 잠금 해제의 전부다.
테스트 없이 코드를 배포하지는 않을 것이다. 사람들은 평가 없이 에이전트를 끊임없이 배포하고, 그러고는 “사소한 프롬프트 조정”이 왜 운영을 망가뜨렸는지 의아해한다. 평가 하니스는 비결정론적 소프트웨어를 위한 테스트 스위트다. 이것이 내가 실제로 돌리는 것이다.
실제 장애로부터 구축한 테스트 세트로 시작하라
하니스는 그 테스트 케이스만큼만 좋고, 최고의 테스트 케이스는 상상이 아니라 운영에서 나온다. 에이전트가 현장에서 실패할 때마다, 나는 정확한 입력을 포착하고(모든 실행을 트레이스 ID와 함께 로깅한다 — 운영에서 에이전트를 디버깅하는 법 참조), 그것을 평가 케이스로 바꾼다.
interface EvalCase {
id: string;
input: AgentInput; // 정확한 운영 입력
expected?: string; // 정답이 있을 때의 그라운드 트루스
assertions: Assertion[]; // 통과해야 하는 엄격한 검사
rubric?: string; // 출력이 개방형일 때 LLM 심판용
}여기서 중요한 실천이 둘이다. 운영에서 끌어와라. 그래야 평가가 추측한 것이 아니라 실제로 망가지는 것을 테스트한다. 그리고 범위를 넓게 덮어라 — 해피 패스, 엣지 케이스, 적대적 입력, 그리고 조용한 실패를 일으키는 빈/잘못된 입력. 잘 고른 30~50개 케이스의 테스트 세트는 게으른 500개보다 훨씬 많이 잡아낸다. 모두 같은 쉬운 경로를 테스트하는 천 개보다, 각각이 실제 실패 모드를 대표하는 40개 케이스를 갖는 편이 낫다.
먼저 어서션으로, 다음에 LLM 심판으로 채점하라
모든 출력에 모델 채점이 필요한 것은 아니다. 나는 작동하는 가장 저렴한 채점기에 손을 뻗는다.
구조화된 모든 것에는 엄격한 어서션을. 출력이 유효한 JSON으로 파싱되는가? 필수 필드를 담고 있는가? 추출된 날짜가 범위 안에 있는가? 올바른 인수로 올바른 도구를 호출했는가? 이것들은 결정론적이고, 무료이며, 명확하다 — 쓸 수 있는 만큼 써라.
const assertions: Assertion[] = [
(out) => isValidJSON(out),
(out) => parse(out).category in ALLOWED_CATEGORIES,
(out) => parse(out).confidence >= 0 && parse(out).confidence <= 1,
];개방형인 나머지에는 LLM 심판을 — 어조, 유용성, “이것이 정말 질문에 답했는가”. 여기서는 모델에 입력, 출력, 루브릭을 주고 채점을 요청한다. 심판을 정직하게 유지하는 규칙은 둘이다. 루브릭을 구체적으로 만들 것(설명된 기준점이 있는 1~5 척도가 “품질을 평가하라”보다 낫다), 그리고 강한 모델을 심판으로 쓸 것 — 판단은 추론 과제이므로, 에이전트 자체가 비용 계산에 따라 Haiku로 돌더라도 나는 여기서 기꺼이 Sonnet 비용을 지불한다. 모호한 루브릭이나 약한 심판은 신호처럼 보이는 잡음을 준다.
모든 변경 전에 하니스를 실행하라
하니스는 한 가지 질문에 답하기 위해 존재한다. 이 변경이 에이전트를 더 좋게 만들었는가 나쁘게 만들었는가? 그래서 나는 모든 프롬프트 편집, 모델 교체, 도구 변경 전에 그것을 실행한다.
# main의 베이스라인
npm run eval -- --suite=booking-agent > baseline.json
# 변경한 다음 다시 실행
npm run eval -- --suite=booking-agent > candidate.json
# 비교
npm run eval:diff baseline.json candidate.jsondiff는 집계 점수, 케이스별 합격/불합격, 그리고 — 결정적으로 — 어떤 특정 케이스가 회귀했는지를 보여준다. 세 케이스가 조용히 깨지는 동안 집계가 올라가는 것은 개선이 아니다. 그것은 내가 보고 승인하고 싶은 트레이드오프이지, 몰래 통과하는 것이 아니다. 케이스별 diff를 지켜보는 것이 “하나 고치고 둘 깨뜨리기” — 사람들이 자기 프롬프트를 두려워하게 만드는 실패 모드 — 를 피하는 방법이다.
회귀 게이트를 설정하고 차단하게 하라
하니스를 신뢰하게 되면, 그것을 게이트로서 운영으로 가는 경로에 연결하라. 내 규칙은 단호하다. 점수를 베이스라인 임계값 아래로 떨어뜨리는 변경은 배포하지 않는다. “나중에 살펴볼게”가 아니다 — 실패한 CI 테스트와 똑같이 차단된다.
const PASS_THRESHOLD = 0.90; // 케이스의 90%가 통과해야 한다
if (candidate.passRate < PASS_THRESHOLD || candidate.passRate < baseline.passRate) {
throw new Error(`Eval regression: ${candidate.passRate} < ${baseline.passRate}`);
}이것이 평가를 “있으면 좋은 것”에서 빠르게 움직일 수 있게 해주는 것으로 바꾼다. 게이트는 “두려움 없이 배포한다”를 문자 그대로 참으로 만든다. 나쁜 변경의 최악의 경우는 빨간 평가 실행이지, 운영 사고가 아니다. 그리고 테스트 세트는 무언가 깨질 때마다 자라므로, 게이트는 시간이 지나며 스스로 더 엄격하고 더 보호적이 된다.
채점에서 비결정성을 고려하라
사람들이 걸려 넘어지는 미묘한 점. 같은 입력도 실행마다 다르게 점수가 나올 수 있다. 모델이 다르게 샘플링하기 때문이다. 각 케이스를 한 번만 실행하면 유령 회귀를 보게 된다 — “깨진” 케이스가 실은 그저 샘플링 잡음이다.
완화책 둘. 분산을 줄이기 위해 평가를 **temperature: 0**으로 실행하라(완전히 없애지는 못한다). 그리고 깜빡이는 것을 본 케이스는, 단일 합격/불합격이 아니라 N번 실행하고 합격률을 취하라. 10번 중 9번 통과하는 케이스는, 둘 다 단일 실행에서 초록을 보일 수 있더라도, 10번 중 5번 통과하는 케이스보다 상태가 낫다. 이것은 간헐적 실패를 디버깅할 때 쓰는 것과 같은, 일화보다 물량의 원칙이다 — 한 번의 실행은 의견이고, 쉰 번의 실행은 데이터다.
운영 모니터링으로 루프를 닫아라
평가 하니스는 알려진 케이스에 대해 테스트한다. 운영은 새로운 케이스를 던진다. 그래서 루프는 이렇다. 실시간 동작을 모니터링하고, 새 실패 모드를 잡고, 그것을 평가 케이스로 바꾸고, 고치면, 이제 그것은 영구적으로 보호된다. 모니터링 측면 — 실시간 트래픽에서 성공률, 출력 유효성, 실행당 비용을 추적하는 것 — 은 AI 에이전트가 실제로 작동하는지 어떻게 측정하는가에서 다룬다. 평가와 모니터링은 같은 시스템의 두 절반이다. 모니터링이 버그를 찾고, 평가가 그것들이 죽은 채로 있게 보장한다.
그 피드백 루프가 진짜 제품이다. 어떤 단일 평가 세트든 낡는다. 하지만 모든 운영 장애를 영구적인 테스트로 변환하는 프로세스는 매주 강해진다. 이것이 에이전트가 “손대기 무서운” 것에서 금요일 오후에 움찔하지 않고 리팩터링할 무언가로 바뀌는 방식이다.
자주 묻는 질문
AI 에이전트 평가 세트에는 무엇이 들어가는가?
실제 운영 입력을 채점된 케이스로 바꾼 것 — 해피 패스, 엣지 케이스, 적대적 및 잘못된 입력 — 각각에 엄격한 어서션을, 개방형 출력에는 LLM 심판 루브릭을 붙인다. 실제 장애에서 끌어온 30~50개 케이스가 모두 쉬운 경로를 테스트하는 수백 개의 합성 케이스를 이긴다.
에이전트 출력을 채점하는 데 LLM을 써야 하는가?
출력이 구조화된 곳(유효한 JSON, 올바른 필드, 올바른 도구 호출)이면 어디서든 엄격한 어서션을 써라 — 무료이고 결정론적이다. 어조와 유용성 같은 개방형 특성에는, 구체적인 루브릭과 강한 심판 모델을 갖춘 LLM 심판을 아껴 두어라. 그래야 잡음이 아닌 신호를 얻는다.
프롬프트 변경이 운영을 조용히 망가뜨리는 것을 어떻게 막는가?
모든 변경 전에 평가 하니스를 실행하고 베이스라인과 diff를 내며, 집계 점수만이 아니라 케이스별 회귀를 지켜봐라. 그런 다음 결과로 배포를 게이트하여, 베이스라인 임계값 아래로 떨어지는 어떤 변경이든 실패한 테스트처럼 차단하라.
평가에서 비결정성을 어떻게 다루는가?
분산을 줄이기 위해 온도 0으로 실행하고, 깜빡이는 케이스는 여러 번 실행하여 단일 실행 대신 합격률로 채점하라. 10번 중 9번 통과하는 케이스는, 단일 실행이 둘 다 초록으로 보이더라도, 10번 중 5번 통과하는 케이스보다 건강하다.
매주 수요일. 28,400명+ 구독자. 핵심만.
✓ 받은편지함을 확인하세요 — 확인 링크를 클릭해 가입을 완료하세요.
✓ 구독이 완료되었습니다!
✓ 이미 목록에 있습니다.
AI 플레이북을 받아보세요
매주 수요일. 28,400명+ 구독자. 핵심만.
받은편지함을 확인하세요.
확인 이메일을 보냈습니다 — 링크를 클릭해 구독을 완료하세요. 1분 안에 보이지 않으면 스팸함을 확인하세요.
구독이 완료되었습니다.
환영합니다 — 다음 호가 곧 받은편지함에 도착합니다.
이미 목록에 있습니다 — 매주 수요일에 확인하세요.