에이전트는 당신이 준 검색 도구나 지식 베이스를 호출하지 않고 파라메트릭 메모리에서 답할 때 도구를 건너뛴다. 건너뛴 호출은 더 빠르고, 오류를 반환하지 않으며, 지연 시간 대시보드에서 초록색으로 표시된다. 하지만 그것은 틀렸다. 모델이 근거를 잡는 대신 추측했기 때문이다. 해결책은 결정론적이다. 모든 도구 호출 트레이스를 로깅하고, 신선한 데이터가 필요한 쿼리에 대해 도구가 실제로 호출되었는지 검증하고, 호출이 없으면 평가를 실패시켜라.
왜 지연 시간 대시보드는 건너뛴 호출을 숨기는가
도구 호출은 왕복 시간을 더한다. POST /api/v1/google를 치고, 결과를 기다리고, 다시 모델에 넣어주는 데는 수백 밀리초와 1크레딧이 든다. 에이전트가 그걸 건너뛰고 가중치에서 바로 답하면 요청은 더 빠르고 싸진다. p50이 내려간다. 오류율은 0에 머문다. 추측은 런타임이 볼 수 있는 오류가 아니기 때문이다.
그래서 대시보드는 당신이 신경 쓰는 바로 그 실패를 보상한다. 검색을 트리거했어야 하는데 안 한 사실 쿼리는, 정당하게 도구가 필요 없던 잡담 턴과 똑같아 보인다. 지연 시간, 오류율, 토큰 수로는 둘을 구분할 수 없다. 당신에게 필요한 신호는 도구가 발화했는지이고, 그것은 지표가 아니라 트레이스에 있다.
LLM 심판이 아니라 결정론적으로 도구 사용을 검증하라
"에이전트가 도구를 호출했는가"라는 질문에는 결정론적 검사가 LLM 심판을 이긴다. 심판은 또 다른 모델이라 환각할 수 있고, 토큰이 들고, 느리다. 하지만 당신은 이미 정답을 갖고 있다. 도구 호출 트레이스다. 검색 도구 호출이 트레이스에 있거나 없거나 둘 중 하나다. 그것을 검증하라.
더 강한 검사는 두 부분으로 이뤄진다. 첫째, 도구가 호출되었는지 검증한다. 둘째, 최종 답변이 도구가 반환한 무언가를 실제로 참조하는지 검증해서, 에이전트가 도구를 호출하고도 무시하지 못하게 한다. Scavio의 Google 엔드포인트는 실제 URL이 담긴 organic 결과를 돌려주므로, 답변이 그중 하나를 인용하는지 확인할 수 있다.
import requests
API_KEY = "sk-your-key"
def search(query):
r = requests.post(
"https://api.scavio.dev/api/v1/google",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"query": query, "light_request": False},
)
r.raise_for_status()
return r.json()
def assert_grounded(query, agent_answer, tool_calls):
# 1) 결정론적: 검색 도구가 실제로 호출되었다
assert any(c["name"] == "search" for c in tool_calls), \
f"agent skipped search for fact query: {query!r}"
# 2) 결정론적: 답변이 도구가 반환한 URL을 인용한다
results = search(query)
returned_urls = [item["link"] for item in results.get("organic", [])]
assert any(url in agent_answer for url in returned_urls), \
"answer does not reference any retrieved source"
# 평가 케이스 예시
assert_grounded(
query="latest stable python release",
agent_answer="Python 3.13 is current. Source: https://www.python.org/downloads/",
tool_calls=[{"name": "search", "args": {"query": "latest stable python release"}}],
)루프 안에 모델은 없다. 검사는 당신이 볼 수 있는 사실에 대해 통과하거나 실패한다.
사실 쿼리에는 그라운딩을 강제하라
건너뛴 호출을 사후에 잡아내는 것은 평가에 좋다. 프로덕션에서 막는 것이 더 좋다. 신선한 데이터가 필요하다고 아는 쿼리에는 모델의 판단에 맡기지 말고 검색 호출을 강제하라.
대부분의 에이전트 프레임워크는 tool_choice를 노출한다. 사실 쿼리 경로에서는 이것을 required로 설정하라(또는 검색 도구를 명시적으로 지정하라). 그러면 모델은 응답하기 전에 POST /api/v1/google를 치고 실제 오가닉 결과에서 답해야 한다. 그라운딩이 중요한지를 에이전트에게 결정하게 하는 것이 아니다. 답이 학습 데이터에서 나올 수 없다고 이미 아는 경우에 대해 당신이 대신 결정하는 것이다.
이는 약간의 지연 시간과 호출당 1크레딧을 정말로 최신인 답변과 맞바꾼다. 사실 경로에서는 매번 원하는 거래다.
정직한 한계
결정론적 도구 호출 검증은 "호출했는가"에 대해 LLM 심판을 이기지만, 애초에 어떤 쿼리가 도구를 필요로 했는지는 알려주지 않는다. 그건 누군가 라벨을 달아야 한다. 평가 세트에는 도구 필수로 표시된 케이스가 필요하고, 그래야 어서션이 빠진 호출이 버그인지, 아니면 올바르게 도구가 필요 없었는지를 안다.
그 라벨링이 진짜 일이다. 정답이 현재 데이터에 의존하는 사실 쿼리 세트를 만들고, 각각을 도구 필수로 표시하고, 모든 케이스에 대해 두 부분 어서션을 돌려라. 결정론적 검사는 라벨만 있으면 싸고 정확하다. 라벨을 얻는 것은 어떤 자동화도 대신 해주지 않는 부분이다.