AI 에이전트 Observability — 사내 플랫폼 관측 계층
사내 DevOps 플랫폼에 AI 에이전트 관측 계층을 구축했습니다. Claude Code와 오픈소스 에이전트 런타임(Hermes)의 OpenTelemetry 신호를 VictoriaLogs/VictoriaMetrics로 수집하고 Grafana로 시각화해, 개발 조직의 에이전트 사용량·비용·성공률을 사용자와 에이전트 단위로 귀속합니다.
Architecture
동기
에이전트를 도구로 쓰기 시작하면 얼마나 쓰는지가 먼저 흐릿해집니다. 부모 세션이 서브에이전트를 띄우면 그 비용은 어디에 잡히는지, 어떤 사용 패턴이 캐시를 못 쓰는지, 어떤 에이전트가 조용히 실패하고 있는지 — 청구서 한 줄과 “잘 돌아간다” 는 체감으로는 안 잡히는 질문들입니다.
조직 단위로 쓰기 시작하면 이 질문이 운영 문제가 됩니다. 사내 DevOps 플랫폼의 관측 계층에 에이전트 도메인을 더한 것이 이 카드입니다. 사람과 인프라를 보던 것과 같은 방식으로 에이전트와 비용을 봅니다.
내가 담당한 트랙
신호를 내보내는 쪽 설정부터 수집 파이프라인, 보관, 대시보드까지 제가 했습니다. 항목별 내역은 오른쪽 「주요 업무」에 있습니다.
| 트랙 | 경계 |
|---|---|
| 플랫폼의 나머지 관측 도메인과 접근 통제 | 이 카드는 에이전트 도메인만 다룹니다. 플랫폼 운영 전반은 DevOps 플랫폼 운영·접근 관리 카드 쪽입니다 |
각자의 노트북에서 오는 신호
보드를 아무리 잘 만들어도 신호가 안 오면 빈 화면입니다. 그리고 신호는 서버가 아니라 각자의 노트북에서 나옵니다. 사람마다 도구를 켜서 쓰는 것이라, 수집하려면 각 클라이언트에 내보내기 설정이 들어가 있어야 합니다.
그래서 그 설정을 사내 마켓플레이스 항목으로 만들어 배포했습니다. 팀원이 그것을 받아 켜면 같은 규격으로 같은 곳에 신호가 갑니다. 이 단계가 없으면 보이는 것은 제 사용량뿐이고, 그러면 이 카드가 답하려던 조직 단위 질문에 아무 답도 못 합니다.
파이프라인
에이전트 런타임의 OpenTelemetry 내보내기를 켜고, 이벤트는 VictoriaLogs 로, 메트릭은 VictoriaMetrics 로, 트레이스는 VictoriaTraces 로 받습니다. 셋 다 Grafana 에서 같은 데이터소스 계층으로 묶어 한 패널에서 로그와 수치를 같이 놓습니다.
로그 저장소를 VictoriaLogs 로 고른 것은 이벤트를 오래 들고 있어야 하는데 인덱스와 조회 비용이 낮기 때문이고, 메트릭 쪽은 기존 플랫폼 관측 스택과 같은 질의 언어를 쓰려고 Prometheus 호환을 골랐습니다. 새 언어를 하나 더 배우게 하지 않는 것이 조건이었습니다.
에이전트를 세는 단위도 손봐야 했습니다. 처리 시간을 수치로 뽑을 때 어느 모델과 어느 제공자가 낸 것인지로 갈라야 비용 이야기와 이어지는데, 처음 설정은 그 축이 어긋나 있었습니다.
두 개의 보드
생산성 보드는 활성 세션과 비용, 월 소비 속도와 토큰을 맨 위에 두고, 요금제 상한을 값으로 받아 지금 속도로 언제 그 상한을 넘는지 보여 줍니다. 모델 계열별 비용·토큰 분포로 실제 청구서를 만드는 구간을 가르고, 사용자와 에이전트별 표에서 캐시 적중률과 출력 비율을 나란히 놓습니다.
운영 보드는 활성 에이전트 수와 세션 생성률, 분당 턴, 시간당 도구 호출, 오류율을 봅니다. 여기서 신경 쓴 것은 성공률을 숫자 하나로 두지 않은 것입니다. 결과를 완료·미완·중단·시간초과로 갈라야 실패가 모델 문제인지 사람이 끊은 것인지 시간이 다 된 것인지 나뉘고, 셋은 대응이 서로 다릅니다. 부하가 대화형 세션에서 오는지 예약 작업에서 오는지도 함께 봅니다 — 같은 오류율이라도 우선순위가 달라집니다.
에이전트와 호스트 이름, 내부 주소는 화면에서 가렸습니다.
프롬프트를 로그로 남긴다는 것
이 관측의 재료 중 하나가 프롬프트 본문입니다. 그런데 사람이 에이전트에게 말할 때는 토큰이든 키든 그냥 붙여 넣습니다. 그것을 그대로 수집하면 관측을 켠 것이 새 유출 경로가 됩니다.
그래서 수집 단계에서 본문의 시크릿 형태를 찾아 가리고, 몇 건을 가렸는지는 따로 수치로 남깁니다. 가리기만 하면 그 규칙이 언제부터 안 듣는지 알 수 없어서, 탐지 건수 자체를 보는 값으로 둔 것입니다.
보관도 같이 정리했습니다. 로그와 메트릭을 오브젝트 스토리지로 내려 두고, 백업은 따로 도는 작업에서 저장소 옆에 붙는 형태로 바꿨습니다. 실패했을 때 하루를 기다리지 않고 60초 뒤에 다시 시도하게 한 것도 이때입니다.
배운 점
- 부모와 자식의 비용 귀속이 가장 어려웠습니다. 부모 세션이 서브에이전트를 띄우면 그 토큰은 자식에게 잡혀야 하는데 부모에게 잡히면 비용 출처가 흐려집니다. 세션 계보를 라벨로 표준화하면서 풀렸습니다.
- 캐시 적중률을 주체별로 보면 사용 패턴의 차이가 드러납니다. 같은 작업이라도 어떤 쪽은 캐시를 거의 못 쓰고 어떤 쪽은 90퍼센트대를 유지하는데, 프롬프트 구조와 맥락을 다시 쓰는 방식의 차이가 그대로 비용이 됩니다.
- 프롬프트 길이는 평균이 아니라 상위 분포를 봐야 합니다. 평균만 보면 안 잡히는 비정상적으로 긴 프롬프트가 비용 급증을 만듭니다.
- 오류율을 유형으로 쪼개기 전까지는 아무 조치도 못 합니다. 성공률 숫자 하나는 무언가 안 좋다는 것까지만 알려 주고 다음에 무엇을 할지는 지시하지 못합니다.
- 관측을 켜는 일 자체가 새 위험을 만들 수 있습니다. 프롬프트를 모으기로 한 순간 거기 섞여 들어올 것을 같이 처리해야 했고, 쌓인 뒤에 지우는 대신 들어오는 자리에서 가리는 쪽을 골랐습니다.