에이전트 도구 호출(Tool Calls)을 위한 제한된 재시도: 무한 루프 사고를 막아준 예산 설정
요약
AI 에이전트의 도구 호출(Tool Call) 과정에서 발생하는 무한 루프와 과도한 토큰 소모 문제를 해결하기 위한 예산 설정 전략을 다룹니다. 호출당 재시도 상한선과 세션당 시도 예산을 도입하여 에이전트의 폭주를 방지하고 안정적인 워크플로를 구축하는 방법을 설명합니다.
핵심 포인트
- 에이전트의 무한 재시도로 인한 API 비용 폭증 및 시스템 부하 방지 필요
- 호출당 재시도 상한선(Per-call retry cap)을 통한 개별 도구 호출 제어
- 세션당 시도 예산(Per-session attempt budget)을 통한 전체 작업 규모 제한
- 예산 소진 시 에이전트에게 명확한 피드백을 전달하여 합리적 결정 유도
우리 에이전트가 일으킨 최악의 사고는 오답이 아니었습니다. 바로 루프(Loop)였습니다.
우리 에이전트가 일으킨 최악의 사고는 오답을 내놓은 것이 아니었습니다. 그것은 루프였습니다. 도구 호출(Tool call)이 실패했고, 에이전트는 재시도(Retry)를 했으며, 재시도 역시 동일한 방식으로 실패했습니다. 그리고 무언가가 이를 멈추기 전까지 에이전트는 계속해서 반복하며 토큰을 소모하고, 1분 동안 수백 번이나 다운스트림 API(Downstream API)를 두들겨 댔습니다. 에이전트는 우리가 지시한 대로 정확히 수행하고 있었습니다. 즉, '도구가 실패하면 다시 시도하라'는 것이었죠. 다만 우리는 언제 멈춰야 하는지는 말해주지 않았을 뿐입니다.
재시도는 올바른 본능입니다. 일시적인 실패(Transient failure)는 재시도해야 합니다. 문제는 에이전트가 "일시적인 것"과 "매번 실패할 것"을 신뢰성 있게 구분하지 못한다는 점입니다. 에이전트의 판단에만 맡겨두면, 외부에서 무언가 강제로 종료하기 전까지 영구적으로 고장 난 호출을 즐겁게 재시도할 것입니다. 사람이 작성한 코드는 수십 년 전에 이 교훈을 배웠습니다. 모든 재시도 루프(Retry loop)에는 제한(Bound)이 있어야 한다는 것입니다. 에이전트의 도구 호출(Tool-calling)은 이 사실을 조용히 잊어버렸습니다. 재시도 결정이 눈에 보이는 for-loop에서 모델의 추론(Reasoning) 내부로 이동하면서, 보이지 않고 제한도 없는 상태가 되었기 때문입니다.
그래서 우리는 모델 외부에서 다시 제한을 설정했습니다. 두 가지 예산(Budget)을 도입했습니다. 하나는 호출당 재시도 상한선(Per-call retry cap, 즉 특정 도구 호출에 N번의 시도만 허용하고, 그 이후에는 에이전트가 다르게 처리해야 하는 강제 실패로 간주함)이고, 다른 하나는 세션당 시도 예산(Per-session attempt budget, 전체 작업에 총 도구 호출 횟수의 상한을 두어, 상한에 도달하면 무한히 회전하게 두는 대신 중단하고 에스컬레이션(Escalate)함)입니다.
class ToolBudget:
def __init__(self, per_call=2, per_session=40):
self.per_call, self.per_session = per_call, per_session
...
중요한 부분은 상한선 그 자체가 아니라, 상한선에 도달했을 때 어떤 일이 일어나는가입니다. 단순히 멈춰버리는 재시도는 에이전트를 막다른 길에 가두게 됩니다. 따라서 호출당 예산이 소진되면 우리는 에이전트에게 특정 메시지("이 호출은 두 번 실패했습니다. 재시도하지 마세요. 다른 접근 방식을 시도하거나 도움을 요청하세요")를 전달합니다. 이를 통해 죽은 루프를 하나의 결정(Decision)으로 전환합니다. 대부분의 경우 에이전트는 이제 재시도가 불가능하다는 것을 알기 때문에 합리적인 행동을 수행하게 됩니다.
저희 로그에서 발견되던 도구 오용 루프(Tool-misuse loops)는 한 달에 몇 건씩 발생하는 골치 아픈 사고에서 사실상 거의 없는 수준으로 줄어들었습니다. 그리고 남아 있는 소수의 사례들도 세션 예산(session budget)에 도달하여 깔끔하게 에스컬레이션(escalate)될 뿐, 폭주하는 API 비용 문제로 새벽 2시에 누군가를 깨우는 일은 발생하지 않습니다.
제가 아직 완전히 해결하지 못한 긴장 관계(tension)가 있습니다. 세션당 예산이 너무 타이트하면 정당하게 긴 작업(실제 다단계 워크플로(multi-step workflow)는 많은 도구 호출(tool calls)을 필요로 할 수 있음)을 중단시켜 버리고, 반대로 너무 느슨하면 루프가 작동을 멈추기 전에 실제 비용이 크게 발생하게 됩니다. 저희는 정상적인 작업 길이의 95백분위수(95th percentile)를 기준으로 삼고 여기에 여유분을 더해 설정하고 있는데, 이는 경험적(empirical)이며 다소 임의적(arbitrary)인 방식입니다. 만약 에이전트의 도구 호출 예산(tool-call budgets)을 제한하는 비임의적인(non-arbitrary) 방법을 찾으셨다면, 제가 읽고 있는 댓글은 바로 그것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기