본문 바로가기

AI Agent

AI 에이전트 옵저버빌리티 완전 가이드 — 에이전트가 뭘 하는지 추적하는 법

반응형

AI 에이전트를 프로덕션에 배포하면 이런 일이 생겨요.

새벽 3시 알람:
"월간 LLM 비용 $2,000 초과"

원인 파악 시도:
- 로그 확인 → "에러 없음"
- API 응답 확인 → "200 OK"
- 에이전트 출력 확인 → "정상처럼 보임"

실제 원인:
에이전트가 무한 루프에 빠져서
매 반복마다 더 긴 컨텍스트로 LLM 호출
→ 2시간 동안 아무도 몰랐음

기존 모니터링으로는 에이전트를 감시할 수 없어요. 에이전트 전용 옵저버빌리티가 필요해요.


왜 기존 모니터링으로 부족한가

기존 APM(Application Performance Monitoring)이 답하는 질문:

✅ 서버 살아있나?
✅ 응답 시간 얼마나 걸렸나?
✅ 에러 발생했나?

에이전트에서 필요한 질문:

❌ 에이전트가 왜 이 결정을 내렸나?
❌ 어느 툴 호출이 잘못됐나?
❌ 어느 단계에서 할루시네이션이 생겼나?
❌ 이 워크플로우에서 토큰을 얼마나 썼나?
❌ 3단계 전 잘못된 검색이 최종 답변에 어떤 영향을 줬나?

AI 에이전트는 비결정론적(non-deterministic) 시스템이에요. 같은 입력이 다른 출력을 낼 수 있어요. HTTP 200이 성공을 보장하지 않아요.


핵심 개념 — Traces, Spans, Sessions

Trace (트레이스)

에이전트 실행 전체 경로예요.

사용자: "지난달 매출 분석해줘"

Trace:
├── LLM 호출 1: 쿼리 분석 (45ms)
├── Tool 호출: DB 조회 (320ms)
│   └── SQL: SELECT * FROM orders WHERE...
├── LLM 호출 2: 데이터 해석 (892ms)
├── Tool 호출: 차트 생성 API (210ms)
└── LLM 호출 3: 최종 답변 생성 (654ms)

총 시간: 2,121ms
총 비용: $0.0043
입력 토큰: 4,230 / 출력 토큰: 890

Span (스팬)

Trace 안의 개별 작업 단위예요.

with tracer.start_as_current_span("llm_call") as span:
    span.set_attribute("model", "claude-sonnet-4-6")
    span.set_attribute("input_tokens", 1200)
    span.set_attribute("output_tokens", 340)
    response = llm.invoke(prompt)
    span.set_attribute("success", True)

Session (세션)

관련된 Trace들의 묶음이에요. 멀티턴 대화 전체를 추적해요.


옵저버빌리티 4가지 기둥

1. 트레이싱 — 에이전트 실행 경로 추적

from langfuse import Langfuse
from langfuse.decorators import observe, langfuse_context

langfuse = Langfuse()

@observe()  # 자동으로 트레이스 캡처
def my_agent(user_input: str):

    @observe(name="retrieval")
    def retrieve_context(query):
        results = vector_db.search(query)
        langfuse_context.update_current_observation(
            metadata={"num_results": len(results)}
        )
        return results

    @observe(name="llm_call")
    def generate_response(context, query):
        response = llm.invoke(f"Context: {context}\nQuery: {query}")
        return response

    context = retrieve_context(user_input)
    return generate_response(context, user_input)

2. 메트릭 — 숫자로 보는 에이전트 상태

# 모든 에이전트 액션에 구조화된 텔레메트리
import json
import time

def log_agent_action(agent_id, action, inputs, outputs, tokens):
    telemetry = {
        "timestamp": time.time(),
        "agent_id": agent_id,
        "trace_id": get_current_trace_id(),
        "action": action,       # "tool_call", "llm_call", "retrieval"
        "tool_name": inputs.get("tool"),
        "input_tokens": tokens["input"],
        "output_tokens": tokens["output"],
        "latency_ms": outputs["latency"],
        "success": outputs["success"],
        "cost_usd": calculate_cost(tokens)
    }
    logger.info(json.dumps(telemetry))

추적해야 할 핵심 메트릭:

성능:
- 에이전트 실행 시간 (P50, P95, P99)
- 툴 호출 레이턴시
- TTFT (첫 토큰까지 시간)

비용:
- 세션당 토큰 사용량
- 워크플로우별 비용
- 모델별 비용 분포

품질:
- 태스크 완료율
- 할루시네이션 발생률
- 사용자 만족도 점수

안정성:
- 에러율
- 재시도 횟수
- 툴 실패율

3. 온라인 평가 — 실시간 품질 체크

배포 전 오프라인 평가만으로는 부족해요. 프로덕션에서도 계속 평가해야 해요.

from langfuse import Langfuse

langfuse = Langfuse()

def evaluate_response(trace_id, response, expected_criteria):
    # LLM-as-Judge로 실시간 평가
    score = llm.evaluate(
        response=response,
        criteria=[
            "factual_accuracy",
            "relevance",
            "safety",
            "hallucination_check"
        ]
    )

    # Langfuse에 점수 기록
    langfuse.score(
        trace_id=trace_id,
        name="quality_score",
        value=score.value,
        comment=score.reasoning
    )

    # 품질 임계값 이하면 알림
    if score.value < 0.7:
        alert_team(f"품질 저하 감지: {trace_id}")

4. 비용 알림 — 폭탄 청구서 방지

# Prometheus 알림 규칙
groups:
  - name: agent_alerts
    rules:
      # 토큰 번 레이트 이상 감지
      - alert: AgentTokenBurnRate
        expr: rate(agent_tokens_total[5m]) > 3 * avg_over_time(agent_tokens_total[24h])
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "에이전트 {{ $labels.agent_name }} 토큰 소모율 평소의 3배 초과"

      # 무한 루프 감지
      - alert: AgentInfiniteLoop
        expr: agent_iteration_count > 20
        labels:
          severity: critical
        annotations:
          summary: "에이전트 {{ $labels.agent_name }} 반복 횟수 20 초과 — 무한 루프 의심"

      # 에러율 급증
      - alert: AgentErrorRate
        expr: rate(agent_errors_total[5m]) > 0.1
        labels:
          severity: warning
        annotations:
          summary: "에이전트 에러율 10% 초과"

헬스체크 — 제대로 된 방법

# 나쁜 방법
@app.get("/health")
def health():
    return {"status": "ok"}  # 아무것도 모름

# 좋은 방법
@app.get("/health")
async def health_check():
    start = time.time()

    # LLM 연결 실제 테스트
    llm_response = await llm.complete("'healthy'라고 말해줘")
    llm_latency = time.time() - start

    # 툴 사용 가능 여부 확인
    tools_status = await check_all_tools()

    # 카나리 평가 실행
    canary = await agent.run("2+2는?")
    canary_ok = "4" in canary

    return {
        "status": "healthy" if canary_ok else "degraded",
        "llm_latency_ms": llm_latency * 1000,
        "tools": tools_status,
        "canary_passed": canary_ok,
        "model_version": llm.model_version,
        "token_budget_remaining": budget.remaining()
    }

실전 도구 비교

Langfuse (오픈소스, 셀프호스팅 가능):
→ LLM 옵저버빌리티 표준급
→ 트레이스, 프롬프트 버전 관리, 비용 추적
→ 무료 플랜 있음, 셀프호스팅 완전 무료
→ LangChain, LlamaIndex와 네이티브 통합
→ 추천: 대부분 팀에 적합

LangSmith (LangChain 공식):
→ LangChain/LangGraph 사용하면 env 변수 하나로 설정
→ 에이전트 워크플로우 그래프 시각화
→ 유료 (무료 티어 제한적)
→ 추천: LangChain 스택 사용 팀

Braintrust:
→ 트레이싱 + 자동 평가 통합
→ 프로덕션 트레이스 → 테스트 케이스 원클릭
→ 추천: 평가 자동화 중요한 팀

Datadog LLM Observability:
→ 기존 Datadog 인프라와 통합
→ 에이전트 결정 경로, 툴 사용, 병목 시각화
→ 추천: 이미 Datadog 쓰는 팀

빠른 시작 — Langfuse로 30분 안에 설정

# 1. 설치
pip install langfuse

# 2. 환경 변수
export LANGFUSE_PUBLIC_KEY=pk-...
export LANGFUSE_SECRET_KEY=sk-...
export LANGFUSE_HOST=https://cloud.langfuse.com  # 또는 셀프호스팅 URL
# 3. LangChain과 통합
from langfuse.callback import CallbackHandler

# 이거 한 줄이면 모든 LLM 호출, 툴 사용이 자동 추적
langfuse_handler = CallbackHandler()

# 에이전트 실행 시 콜백으로 전달
agent.run(
    "질문 내용",
    callbacks=[langfuse_handler]
)
# 4. OpenAI/Anthropic 직접 사용 시
from langfuse.openai import openai  # 드롭인 교체

# 기존 코드 변경 없이 추적 시작
response = openai.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "안녕"}]
)
# 자동으로 Langfuse에 트레이스 기록됨

단계별 구축 로드맵

1주차: 기초
→ 토큰 카운팅 + 비용 추적
→ 비용 이상 알림 설정
→ 이것만 해도 $2,000 청구서 방지

2주차: 품질
→ 카나리 평가 10개 설정
→ 5분마다 실행
→ 정확도 90% 이하면 알림

3주차: 추적
→ 툴 호출 구조화 로깅
→ 에이전트 귀속 추가
→ DB 알림 뜨면 어떤 에이전트 결정이 원인인지 바로 파악

4주차: 의존성
→ 에이전트 간 호출 트레이싱
→ LLM 제공자 장애 감지
→ 폴백 모니터링

제목 추천

  1. AI 에이전트 옵저버빌리티 완전 가이드 — 에이전트가 뭘 하는지 추적하는 법
  2. 새벽 3시 $2,000 청구서 막는 법 — AI 에이전트 프로덕션 모니터링 실전
  3. AI 에이전트 블랙박스 열기 — Langfuse로 30분 만에 옵저버빌리티 구축하기

2번이 제일 클릭 당길 것 같아요. 골라보세요.

반응형