에이전트 운영 회고 (4/7) — Token Guard 훅: 호출 직전 차단으로 토큰 폭주 막기

이 글이 다루는 것

사후 집계만으로는 LLM 에이전트의 토큰 폭주를 막을 수 없다. 폭주가 끝난 뒤 로그에 찍힌 수치는 정확하지만, 그 시점엔 이미 비용이 나간 뒤다. 이 글은 Hermes의 플러그인 시스템 위에서 tool_pre_call 훅으로 호출 직전에 끼어들어 차단하는 구조를 정리한다. 다루는 범위는 세 가지다.

  1. 반복계수 기반 3-tier 임계 설계와 각 숫자의 근거
  2. 훅 시스템의 이벤트 모델과 Token Guard가 어디에 등록되는지
  3. 같은 시스템 위에 얹은 다른 두 훅(schema dedup, delegation tracker)의 역할

임계 숫자는 운영 가설이고 실측 검증 전이라는 점도 글 안에서 분명히 표시한다.

왜 사후 측정으로는 부족한가

Hermes v0.8.0에서 관측된 한 사례: 입력 5건이 도구 호출 111회로 확산되며 누적 토큰 6.5M에 도달했다. 입력 대비 반복계수로 환산하면 42.79× — 요청 한 건이 평균 마흔두 배로 증폭된 셈이다.

문제는 인지 시점이다. 이 수치는 세션 종료 후 로그 집계에서 나왔다. 측정은 정확했지만, 측정이 완료된 시점엔 이미 토큰이 소진되어 있었다. 사후 지표로는 폭주를 차단할 수 없다는 결론이 여기서 나온다. 필요한 건 호출 직전에 개입할 수 있는 자리다. 이 요구를 충족시키기 위해 만든 플러그인이 Token Guard다.

Token Guard 설계 — 반복계수 기반 3-tier 임계

단일 임계로 자르면 정상 워크로드까지 막히고, 너무 느슨하게 두면 사후 측정과 다름없어진다. Token Guard는 단계를 셋으로 나눈다. 기준은 전부 반복계수(누적 도구 호출 토큰 ÷ 입력 토큰)다.

  • T1 (15×) — 경고: 로그에 마킹하고 메인 오케스트레이터에 알림. 차단 없음.
  • T2 (25×) — 동일 도구 재호출 차단: 같은 도구의 재호출만 거부. 다른 도구 호출은 통과. 폭주는 동일 도구 반복 호출 패턴에서 시작되는 경향이 관측됐다.
  • T3 (40×) — 세션 강제 종료: 세션 자체를 닫는다.

각 임계 숫자의 근거

세 숫자는 모두 운영 가설이며 실측 검증된 값이 아니다. 결정에는 두 가지 관측치를 썼다.

  • T2 (25×)의 근거: 사고 당시 42.79×에서 폭주를 인지했고 누적은 6.5M이었다. 25× 시점에서 차단했다면 단순 산수로 약 절반에서 멈춘다.
  • T1 (15×)의 근거: 정상 운영 반복계수가 13.82×로 관측됐다. T1은 이 정상치 바로 위, "아직 정상이지만 이상 신호 가능성이 있는 구간"을 잡기 위한 값.
  • T3 (40×)의 근거: 사고 당시 42.79×보다 약간 아래. 사고 패턴을 다시 만나기 전에 끊는다.

Phase 0의 7일 관측이 끝나면 임계는 재조정 대상이다. 7일 분포에서 정상 워크로드 범위와 T1/T2 발동 빈도를 확인한 뒤 숫자를 다시 결정한다.

훅 시스템 — 이벤트 모델과 등록 지점

Token Guard는 단독 모듈이 아니라 Hermes의 플러그인 시스템 위에서 동작한다. 플러그인 시스템은 훅 기반이며, 정해진 이벤트에 콜백을 등록하면 런타임이 해당 시점에 호출한다.

현재 노출된 이벤트는 네 가지다.

  • tool_pre_call — 도구 호출 직전
  • tool_post_call — 도구 호출 직후
  • session_init — 세션 시작 시
  • session_end — 세션 종료 시

Token Guard는 tool_pre_call에 등록된다. 도구가 실제로 실행되기 전에 개입해야 "차단"이 성립하기 때문이다. 콜백은 호출 직전에 두 가지 작업을 수행한다.

  1. 현재 세션의 누적 도구 호출 토큰과 입력 토큰을 읽어 반복계수를 계산
  2. 계산된 값의 tier를 판정, T2/T3면 호출 거부

tool_post_call은 측정 갱신에 쓰인다. 호출 종료 후 누적 토큰을 업데이트해 다음 tool_pre_call 판정에 반영하는 구조다. 함수 시그니처나 거부 신호 전달 방식 등 구현 세부는 별도 문서로 분리한다. 이 글은 "어디에 끼어들어 무엇을 막는가" 까지를 다룬다.

측정치 — 정상 운영치 13.82× / T1 15× 직하

가장 큰 검증 포인트는 "임계가 정상 워크로드를 막는가"다. 너무 빡빡하면 평소 작업이 차단되고 시스템이 기능하지 못한다.

첫 측정일 관측치:

  • 반복계수: 13.82×
  • T1 임계: 15×

정상 운영 구간이 T1 바로 아래에 위치한다. 경고도, 차단도 발동하지 않는다. 단, 한 점만으로는 일반화할 수 없다. 7일 분포 관측 후 재평가가 필요하다.

T2(25×)와 T3(40×)는 현재까지 발동 사례 없음. 이는 두 가지로 해석된다. (1) 현재 운영에서 폭주가 재발하지 않았다, (2) 임계의 유효성은 아직 검증되지 않았다. 발동되지 않은 임계는 검증된 임계가 아니다.

같은 훅 시스템 위의 다른 플러그인

Token Guard 외에 두 개의 훅이 같은 플러그인 시스템 위에 등록되어 있다.

Schema dedup — 세션 내 도구 schema 반복 전송을 차단. LLM에 도구 정의를 넘길 때 같은 schema를 매 호출마다 재전송하면 그 자체로 입력 토큰이 누적된다. 한 번 전송한 schema는 캐싱하고 변경이 없으면 재전송하지 않는다. 이 훅은 사후 토큰 절감이 아니라 입력 토큰 자체를 줄이는 방향이다.

Delegation tracker — 메인 오케스트레이터가 sub-agent로 위임하는 비율을 추적. 메인이 무거운 작업을 직접 처리하는 패턴(위임률 저하)이 감지되면 마킹한다. 메인이 고옵션 모델(opus급)이라면 단순 작업까지 직접 처리하는 건 비용 관점에서 비효율적이다. 이 훅은 관측만 하며 차단하지 않는다.

세 훅 모두 플러그인 시스템 위에 등록만 하면 동작한다. 훅 추가 여지를 남긴 것도 같은 구조적 이유다.

한계와 적용 가능 범위

자신 있게 말할 수 있는 것은 두 가지다.

  1. 사후 측정으로 막을 수 없던 구간에 호출 직전 개입 자리(tool_pre_call) 를 확보했다.
  2. 첫 측정일 정상 운영치(13.82×)가 T1(15×) 직하에 배치됐다.

말할 수 없는 부분이 더 많다.

  • T1/T2/T3 임계는 전부 운영 가설이다. 실측 검증된 값 아님. Phase 0 7일 관측 후 재조정 예정.
  • T2/T3 실제 발동 사례 없음. 폭주 차단 능력은 아직 입증되지 않았다.
  • 단일 사용자 환경 전용. 다른 환경에서 같은 임계가 적절할지는 별도 검증이 필요하다.

적용 가능 범위 — 다른 지표에도 같은 질문

이 설계에서 뽑아낼 수 있는 패턴은 "사후 측정 → 호출 직전 차단"이라는 이동이다. 다른 지표에도 같은 질문이 성립한다.

  • 현재 사후로만 보고 있는 지표가 있는가?
  • 호출 직전 또는 세션 시작 시점에 개입 가능한 자리가 존재하는가?
  • 차단 대신 마킹만으로도 의미 있는 지표가 있는가?

Schema dedup과 delegation tracker도 이 질문에서 출발한 훅들이다. 차단과 관측 중 어느 쪽을 선택하든, "끼어들 수 있는 자리" 를 먼저 확보하는 것이 이후 정책 결정의 자유도를 결정한다. 7일 관측 후 임계 재조정 결과와 발동 사례 분포는 별도로 정리한다.

열린 질문

  • 반복계수 외에 폭주를 조기에 식별할 수 있는 대체 지표는 무엇인가? (예: 동일 도구 연속 호출 카운트, 입력 대비 세션 지속시간)
  • tool_pre_call이 아닌 session_init 시점에서 사전 차단할 수 있는 워크로드 분류는 가능한가?
  • Multi-user 환경에서 임계를 사용자별/워크로드별로 분리해야 하는가, 전역 단일 임계로 충분한가?

시리즈 전체 안내: 시리즈 목차

댓글

이 블로그의 인기 게시물

"LLM 핵심 학습 (1/6) — 기본: 토큰화·임베딩·어텐션·위치 인코딩"

"LLM 핵심 학습 (2/6) — 파인튜닝: LoRA·QLoRA·증류·Adapter"

"ML 기초 학습 (1/9) — 머신러닝과 sklearn: 학습의 좌표계"