2 minute read

에이전트에게 자백을 강요하지 마라

AI 에이전트가 헛소리할 때 “너 방금 왜 그랬어?”라고 묻는 것만큼 바보 같은 짓이 없다(내가 맨날 하던 짓이다).

에이전트 루프를 돌리다 보면 얘가 갑자기 눈이 뒤집혀서 엉뚱한 파일을 지우거나, 없는 API를 호출하며 폭주할 때가 있다. 이때 우리 개발자들의 본능적인 첫 반응은 채팅창에 “야, 너 방금 왜 그따위로 행동했냐?” 하고 따져 묻는 거다.

그런데 r/openclaw에 올라온 글을 보고 뒤통수를 세게 맞았다. OpenClaw에 기본 탑재된 OTEL(OpenTelemetry) 트레이싱을 왜 아무도 안 켜고 쓰냐는 글이다. 디버깅하겠다고 에이전트한테 말로 물어보는 건, 술 취해서 필름 끊긴 사람한테 어젯밤 일 브리핑하라는 꼴이다.

“왜 그랬어?”에 답하는 에이전트의 함정

에이전트한테 자기 실행 이력을 물어보면 대답은 기가 막히게 잘한다. “이러이러한 아키텍처를 고려해 최적의 판단을 내린 결과다”라며 번지르르한 소설을 쓴다.

문제는 그 답변이 100% 뇌피셜(소설)일 확률이 높다는 거다.

에이전트가 과거 행동을 회상할 때 참고하는 건 오직 현재 컨텍스트 윈도우에 남아있는 파편뿐이다. 긴 작업 도중 이전 대화가 요약되거나 토큰이 잘려 나갔다면? 에이전트는 빈칸을 메우기 위해 그럴듯한 거짓말을 날조해 낸다. 악의가 있어서가 아니라, 다음 토큰을 채워야 하니까 그럴듯한 가짜 기억을 자신만만하게 생성하는 거다.

r/openclaw의 한 유저가 남긴 일침이 정확하다.

“에이전트의 자기 보고는 실제 도구/시스템 수준에서 일어난 팩트가 아니라, 컨텍스트에 쪼가리로 남은 기억을 재구성한 환각이다. 뭔가 잘리거나 요약된 후 터진 에러라면, 에이전트는 현실과 180도 다른 그럴듯한 소설을 아주 당당하게 읊어댈 뿐이다.”

개발자는 그 가짜 회고를 철석같이 믿고 엉뚱한 곳을 파며 삽질의 늪에 빠진다.

Jaeger 5줄이 바꾸는 것

그래서 외부 관측 도구(OTEL)가 필수다. 트레이스를 켜두면 에이전트의 불완전한 기억에 의존할 필요 없이, 실제로 어떤 툴을 어떤 인자로 때렸고 에러 코드가 뭐가 떴는지 디스크에 냉정한 블랙박스 로그가 박힌다.

세팅도 라면 끓이기보다 쉽다. Docker Compose로 Jaeger 컨테이너 하나 띄우고, 환경변수 OTEL_EXPORTER_OTLP_ENDPOINT 한 줄 먹이면 끝이다.

Jaeger UI 켜서 필터 딱 두 개만 걸면 디버깅 끝이다:

  • 상태가 ERROR인 tool_call 스팬
  • 실행 시간이 30초 이상 늘어진 tool_call 스팬

이 두 개만 보면 “에이전트가 왜 헛발질했는가”의 80%가 즉시 밝혀진다. 나머지 20%는 토큰 폭주(컨텍스트 오버플로)인데, 이것도 트레이스 타임라인 그래프만 보면 한눈에 각이 나온다.

도구 호출 로그만으로도 충분하다

Jaeger 세팅마저 귀찮다면 최소한 도구 호출이 일어날 때마다 tools.log 파일에 JSON 한 줄씩 append하는 로깅이라도 박아두자.

핵심은 관측 가능성(Observability)은 에이전트의 인지 루프 바깥에 격리되어야 한다는 진리다. 에이전트는 뛰어난 일꾼이지만 자기 자신을 돌아보는 메타인지는 바보에 가깝다. 컨텍스트 창이라는 찰나의 단기 기억에 의존하기 때문이다.

왜 다들 안 켜고 있을까

이유는 단순하다. 사고 터지기 전까지는 세팅하기 귀찮으니까(내가 그렇다).

프로덕션 서버에서도 장애 터지고 나서야 “아 로그 좀 더 심어둘 걸…” 후회하듯, AI 에이전트 세계에서도 똑같은 역사적 실수가 되풀이되고 있다.

정리

AI 에이전트의 자기반성(?) 문구에 현혹되지 말자. 에이전트는 훌륭한 일꾼이지만 자기 자신을 돌아보는 메타인지는 바보에 가깝다.

5분 투자해서 OpenTelemetry 연동해두면, 나중에 에이전트의 헛소리에 휘둘려 서너 시간씩 멘붕 오는 참사를 완벽하게 막을 수 있다. 다른 개발자들이 이미 피똥 싸며 겪은 교훈이다.


이 글은 r/openclaw 커뮤니티 토론을 바탕으로 정리했다.