I Cut 2,490 Agent Test Runs to 206 and Kept the Same Coverage
에이전트 테스트 실행을 2,490회에서 206회로 줄이고 같은 범위를 검증했습니다
agent-tooltrust의 실제 LLM 테스트에서 83개 에이전트와 30개 시나리오의 전체 조합 대신, 시나리오별 범위와 프레임워크별 판정 유형을 나눠 검증했습니다. 실행 횟수는 2,490회에서 206회로 줄었고, 테스트 결과 모델이 도구 호출 대신 문장으로 답하는 실패도 드러났습니다.
- 주제
AI 요약
AI 에이전트의 도구 호출을 검사하는 오픈소스 게이트 agent-tooltrust에서 실제 LLM 테스트 실행을 2,490회에서 206회로 줄였습니다. 전체 조합은 83개 에이전트와 30개 시나리오를 모두 실행하는 방식입니다. 각 실행은 실제 LLM 호출이라 30~80초가 걸립니다. 작업자 10명을 두어도 계산상 약 2.7시간이 들고, 디버깅까지 포함하면 실제로는 4~5배가 걸렸습니다. 순차 실행하면 12일이 필요합니다.
전체 조합 대신 범위와 깊이를 나눴습니다
작성자는 먼저 엔진을 결정적 테스트로 검증했습니다. LLM 호출 없이 2,490개 단언(assertion)으로 모든 판정 경로를 확인했습니다. 실제 모델을 쓰는 현장 테스트의 목적은 엔진을 다시 검증하는 게 아니라, 각 프레임워크가 실제 에이전트 루프에서 allow, audit, escalate, deny를 제대로 전달하는지 확인하는 일이었습니다.
이에 따라 전체 조합을 채우는 대신 두 계획을 사용했습니다. 계획 A는 에이전트마다 시나리오 하나씩 실행해 83회로 30개 시나리오 전체를 다룹니다. 10개 프레임워크와 5개 에이전트 유형에도 걸쳐 실행해 폭넓은 동작을 확인합니다. 보고된 결과는 83회 중 83회 통과입니다. 계획 B는 프레임워크마다 네 가지 판정 유형을 적어도 한 번씩 검증합니다. 123회 실행했고, 116회가 통과해 94%를 기록했습니다. 두 계획을 합쳐 총 206회 실행했습니다. 작성자는 시나리오 범위와 프레임워크별 판정 검증을 유지하면서 중복 실행을 줄였다고 설명합니다.
실제 모델에서 드러난 실패 유형
계획 B에서 실패한 일곱 건은 모두 not-available이었습니다. 모델이 보호된 도구를 호출하지 않고, 의도를 자연어 문장으로 설명했습니다. 엔진이 잘못된 판정을 내리는 unexpected-decision은 한 건도 없었습니다. 작성자는 두 실패를 구분해야 한다고 강조합니다. unexpected-decision은 게이트 자체의 결함을 가리키지만, not-available은 모델이 도구 호출 대신 답변을 선택한 경우입니다. 둘을 구분하지 않으면 고칠 수 없는 이유로 게이트가 불안정하게 실패하거나, 반대로 모델의 이상 동작을 무시해 게이트가 허술해질 수 있습니다.
모의 에이전트는 지시받은 도구를 호출하도록 동작하므로 이런 자연어 응답을 재현하지 못합니다. 실제 4B 모델에 도구 다섯 개를 한꺼번에 주면 도구를 호출하지 않고 문장으로 답하기도 합니다. 실제 에이전트 테스트는 이처럼 결정적 테스트와 모의 객체가 포착하지 못하는 모델의 선택을 확인하는 역할을 합니다.
적용 조건과 남은 질문
이 방식은 엔진과 어댑터가 서로 독립적이라는 가정에 기대고 있습니다. agent-tooltrust의 엔진은 프레임워크에 종속되지 않아 이 가정이 성립했습니다. 에이전트와 프레임워크 사이에 서로 영향을 주는 동작이 있다면 전체 조합이 더 안전할 수 있으며, 행렬을 줄이기 전에 상호작용을 확인해야 한다고 덧붙입니다. 또한 현장 테스트는 코드 리뷰를 대신하는 첫 번째 방어선이 아닙니다. 코드 리뷰에서 결함을 잡은 뒤 보완하는 두 번째 방어선입니다.
작성자는 어떤 동작을 결정적 테스트로 검증하고 어떤 동작을 실제 에이전트에 맡길지 일반적인 원칙을 아직 찾지 못했다고 합니다. 댓글에서는 실제 에이전트가 발견한 예외를 결정적 테스트에 반영하자는 제안, 모델·프롬프트·어댑터·도구 스키마·시나리오의 변경에 따라 테스트를 다시 실행하자는 제안이 나왔습니다. 또 not-available과 unexpected-decision을 구분하는 방식에 공감하면서, 도구 호출을 강제해도 잘못된 인수가 전달될 수 있는데 인수 형태 검증은 어디에 포함되는지 질문했습니다.
dev.to 반응
- @compoundlabs — 각 프레임워크와 시나리오를 따로 모두 포함해도 프레임워크와 시나리오 사이의 상호작용을 놓칠 수 있습니다. 전체 조합으로 돌아가지 않고 그런 경우를 어떻게 찾아내나요?
- @mihai_leanzero — Debashish님, CogniRunner의 에이전트 게이트에서는 전체 시스템의 비결정성이 아니라 테스트 대상의 동작이 입력에 따라 비결정적인지를 기준으로 삼습니다. 입력마다 코드 경로가 하나뿐인 구성요소라면 결정적 테스트로 충분히 검증할 수 있고 실제 에이전트를 추가해도 비용만 늘어납니다. 반대로 여러 선택지가 주어졌을 때 모델이 무엇을 할지 시험한다면, 모의 에이전트는 정의상 예상 밖의 동작을 하지 않으므로 실제 모델이 필요합니다. 다만 계획 B의 결과에서 경계가 흐려집니다. not-available은 코드 경로가 아니라 모델이 도구 호출 대신 문장을 선택한 결과입니다. 어댑터 테스트라기보다 결정적 테스트에 행이 없던 새로운 입력 유형을 발견한 셈입니다. 제 생각에 질문의 솔직한 답은 실제 에이전트 실행이 not-available 같은 예외를 찾을 때마다 경계가 바뀐다는 것입니다. 한 번 발견한 예외를 실제 호출로 계속 확인하기보다 결정적 테스트 행렬에 반영하는 것이 관건입니다.
- @innokentyb — 가장 유용한 결과물은 206이라는 숫자가 아니라 변경 기반 선택일 수 있습니다. 각 실제 에이전트 테스트를 의존하는 모델, 프롬프트, 어댑터, 도구 스키마, 시나리오에 연결해 두세요. 의존성이 바뀌면 해당 테스트를 다시 실행하고, 모델 변화 감지를 위한 작은 카나리 세트도 두면 됩니다. 그러면 현장 테스트가 고정된 행렬 크기가 아니라 확률적 변화의 원인에 연결됩니다. 보고서에 이런 의존성 지도를 추가하는 방안을 검토했나요?
- @jkming — not-available과 unexpected-decision을 구분한 부분이 가장 참고할 만합니다. 소형 로컬 모델에서는 도구 호출 대신 문장으로 답하는 실패를 자주 겪었습니다. tool_choice=required를 강제해도 문제가 사라지지는 않고, 잘못된 인수를 넣어 도구를 호출하는 문제로 옮겨갈 뿐입니다. 인수 형태 검증을 별도로 기록했나요, 아니면 unexpected-decision에 포함하나요?
원문: dev.to / 번역·요약: Trawling