본문으로 건너뛰기

AgenticOps 메트릭 — 운영 중 관측할 Agent KPI

읽는 시간: 약 5분

AI Agent가 프로덕션에 배포되면, 시스템이 정상 응답하는가만으로는 품질을 판단할 수 없다. "사용자 의도를 정확히 이해했는가?", "올바른 도구를 호출했는가?", "답변이 충실한가?"와 같은 **사용자 지각 품질(Perceived Quality)**을 측정해야 한다. 이 문서는 Agent 운영에 필수적인 KPI 카테고리Langfuse·OTel 기반 계측 방법을 다룬다.


1. 왜 Agent 전용 메트릭이 필요한가

1.1 전통 APM의 한계

기존 APM(Application Performance Monitoring)은 HTTP 성공률, 응답 시간, 에러율 등 시스템 지표를 중심으로 설계되었다. 그러나 Agent는 다음과 같은 이유로 추가 메트릭이 필요하다:

전통 APMAgent 품질 지표격차
HTTP 200 OK올바른 답변 여부요청 성공 ≠ 결과 품질
응답 시간 (전체)Time to First Tokenstreaming에서 사용자 체감 속도 다름
에러율Hallucination rateLLM 오류는 HTTP 500이 아닌 정상 응답
CPU/MemoryToken cost클라우드 LLM은 토큰 단위 과금
N/ATool-call accuracy잘못된 도구 호출은 시스템 에러가 아님

1.2 사용자 지각 품질 vs 시스템 지표

Agent의 실제 품질은 사용자가 원하는 작업을 정확히 수행했는가로 판단되며, 이는 시스템 성공 지표와 독립적이다.


2. 핵심 KPI 카테고리

2.1 과제 성공 (Task Success)

사용자가 요청한 작업이 완료되었는가를 측정한다.

메트릭정의측정 방법
Task success rate성공한 대화 세션 비율자동 평가(goal attainment) + HITL 샘플링(10%)
Completion time (p50/p95)작업 완료까지 소요 시간Session duration (초)
Goal attainment scale사용자 목표 달성도 (1-5)명시적 피드백(thumbs up/down) 또는 LLM-as-Judge

예시 (고객 지원 Agent):

# Langfuse 자동 평가 예시
from langfuse import Langfuse
langfuse = Langfuse()

trace = langfuse.trace(
name="customer-support-session",
session_id="sess_abc123",
metadata={"intent": "refund_request", "channel": "web"}
)

# 세션 종료 시 평가
trace.score(
name="task_success",
value=1.0, # 0.0 = 실패, 1.0 = 성공
comment="Refund processed and confirmation sent"
)

2.2 Tool Use 정확성

Agent가 올바른 도구를 정확히 호출하는지 측정한다.

메트릭정의측정 방법
Tool-call accuracy올바른 도구를 호출한 비율(정확한 도구 호출 수) / (전체 도구 호출 수)
Tool invocation rate평균 도구 호출 수 / 세션span hierarchy 분석
Tool failure rate도구 호출 실패 비율HTTP 5xx, Timeout, JSON parsing error

예시:

# Tool call span 기록
span = trace.span(
name="tool_call",
input={"tool": "get_weather", "args": {"location": "Seoul"}},
metadata={"tool_name": "get_weather", "tool_version": "v1.2"}
)

# 평가 기준: 의도="날씨 질문" → 올바른 도구="get_weather"
# 잘못된 예: "get_weather" 대신 "search_web" 호출 → accuracy 0.0
span.score(
name="tool_call_accuracy",
value=1.0, # 올바른 도구 선택
comment="Correct tool selected for weather intent"
)

2.3 품질·안전

답변 품질과 안전 위반 여부를 측정한다.

메트릭정의측정 방법
Hallucination rate근거 없는 정보 생성 비율Ragas Faithfulness / SelfCheckGPT
Guardrails violation rate입출력 차단 발생 비율input/output filter block count
Toxicity incidence유해 콘텐츠 생성 비율Perspective API / OpenAI Moderation

Hallucination 측정 예시 (Ragas Faithfulness):

from ragas.metrics import faithfulness
from ragas import evaluate

# RAG Agent 평가
result = evaluate(
dataset=test_dataset,
metrics=[faithfulness],
llm=ChatOpenAI(model="gpt-4o-mini")
)

# Faithfulness 점수 → Langfuse에 기록
trace.score(
name="faithfulness",
value=result["faithfulness"], # 0.0~1.0
comment=f"Context: {len(context)} chars, Answer: {len(answer)} chars"
)

Guardrails violation 측정:

# OpenClaw AI Gateway의 PII redaction 차단
if gateway_response.status == "blocked_pii":
trace.score(
name="guardrails_violation",
value=1.0, # 차단됨
comment="PII detected: email, phone"
)

2.4 비용·효율

Agent 운영 비용과 리소스 효율을 측정한다.

메트릭정의측정 방법
Cost per interaction세션당 평균 비용 (USD)Σ(input_tokens × price_in + output_tokens × price_out)
Token efficiency유효 토큰 비율(응답 토큰) / (총 소비 토큰)
Cache hit rateSemantic cache 적중률(cache hits) / (total queries)

비용 추적 예시:

# Generation span에 토큰 및 비용 기록
generation = trace.generation(
name="llm_call",
model="gpt-4o-2025-01-31",
input="What is the weather in Seoul?",
output="The current weather in Seoul is...",
usage={
"input": 1200,
"output": 80,
"total": 1280,
"input_cost": 0.012, # $10 / 1M tokens
"output_cost": 0.024, # $30 / 1M tokens
"total_cost": 0.036
}
)

Cache hit rate 측정:

# Semantic cache 적중 시
if cache_hit:
trace.event(
name="cache_hit",
metadata={"cache_key": cache_key, "latency_saved_ms": 2500}
)

2.5 사용자 경험

사용자 체감 품질을 측정한다.

메트릭정의측정 방법
Time to First Token (TTFT)첫 응답까지 소요 시간streaming 시작 시각 - 요청 시각
Task-length quartiles작업 복잡도 분포METR Task Standard 기반 분류
Escalation rate인간 핸드오프 비율(human handoff count) / (total sessions)

TTFT 측정 예시:

import time

request_time = time.time()
# LLM 호출 (streaming)
first_token_time = None

async for chunk in llm_stream():
if first_token_time is None:
first_token_time = time.time()
ttft_ms = (first_token_time - request_time) * 1000

trace.event(
name="time_to_first_token",
metadata={"ttft_ms": ttft_ms, "model": "gpt-4o"}
)

Escalation rate 측정:

# Agent가 불확실성 감지 시 인간 핸드오프
if confidence_score < 0.7:
trace.event(
name="escalation",
metadata={
"reason": "low_confidence",
"confidence": confidence_score,
"fallback": "human_agent"
}
)

2.6 시스템 신뢰성

Agent 서비스의 안정성을 측정한다.

메트릭정의측정 방법
Availability서비스 가용 시간 비율(uptime) / (total time)
Error budgetSLO 위반 허용치 소진률1 - (actual SLI / SLO target)
Session continuity rate세션 중단 없이 완료된 비율(완료된 세션) / (시작된 세션)
Retry exhaustion rate재시도 한도 초과 비율(max retries exceeded) / (total requests)

SLO 예시 (Task success rate):

Target SLO: Task success rate ≥ 95% (30일 기준)
Error budget: 5% → 월 36시간 장애 허용

3. Langfuse Trace 스키마 제안

3.1 Span Hierarchy

Agent 실행 흐름을 다음과 같은 계층으로 표현한다:

3.2 기본 태그 (Tags)

모든 trace/span에 다음 태그를 부여한다:

  • agent_name: Agent 식별자 (예: customer-support-agent)
  • model: LLM 모델명 (예: gpt-4o-2025-01-31)
  • prompt_version: 프롬프트 템플릿 버전 (예: v1.2.3)
  • tool: 호출된 도구명 (예: get_weather)
  • guardrails: 적용된 guardrails (예: pii_redaction,prompt_injection)

3.3 Score 이벤트

품질 평가는 score 이벤트로 기록한다:

  • task_success: 0.0~1.0
  • faithfulness: 0.0~1.0 (Ragas)
  • cache_hit: 0.0 (miss) / 1.0 (hit)
  • tool_call_accuracy: 0.0~1.0
  • guardrails_violation: 0.0 (pass) / 1.0 (block)

3.4 JSON 예시

{
"id": "trace_abc123",
"name": "customer-support-session",
"session_id": "sess_xyz789",
"user_id": "user_456",
"tags": ["agent_name:support-agent", "environment:production"],
"metadata": {
"channel": "web",
"intent": "refund_request",
"customer_tier": "premium"
},
"spans": [
{
"id": "span_001",
"name": "agent_run",
"start_time": "2026-04-18T10:00:00Z",
"end_time": "2026-04-18T10:00:05Z",
"input": "I want to request a refund for order #12345",
"output": "I've processed your refund request...",
"metadata": {
"reasoning_steps": 3,
"tools_called": ["get_order", "process_refund", "send_email"]
}
},
{
"id": "span_002",
"parent_span_id": "span_001",
"name": "tool_call",
"type": "span",
"start_time": "2026-04-18T10:00:01Z",
"end_time": "2026-04-18T10:00:02Z",
"input": {"tool": "get_order", "args": {"order_id": "12345"}},
"output": {"status": "delivered", "amount": 129.99},
"metadata": {
"tool_name": "get_order",
"tool_version": "v2.1",
"latency_ms": 850
}
},
{
"id": "gen_001",
"parent_span_id": "span_001",
"name": "llm_generation",
"type": "generation",
"model": "gpt-4o-2025-01-31",
"input": [{"role": "system", "content": "You are a support agent..."}, {"role": "user", "content": "I want a refund..."}],
"output": "Based on your order status...",
"usage": {
"input": 1200,
"output": 80,
"total": 1280,
"input_cost": 0.012,
"output_cost": 0.024,
"total_cost": 0.036
},
"metadata": {
"temperature": 0.7,
"prompt_version": "v1.2.3"
}
}
],
"scores": [
{
"name": "task_success",
"value": 1.0,
"comment": "Refund processed successfully"
},
{
"name": "faithfulness",
"value": 0.92,
"comment": "High context adherence"
},
{
"name": "tool_call_accuracy",
"value": 1.0,
"comment": "All tools correctly selected"
}
]
}

4. OpenTelemetry Semantic Conventions

4.1 GenAI Semantic Conventions (2026-04 기준)

OpenTelemetry는 Gen AI Semantic Conventions를 통해 LLM 계측 표준을 정의한다 (v1.28.0 experimental).

핵심 attribute:

Attribute예시설명
gen_ai.systemopenaiLLM 제공자
gen_ai.request.modelgpt-4o-2025-01-31모델명
gen_ai.request.temperature0.7샘플링 온도
gen_ai.request.max_tokens2048최대 출력 토큰
gen_ai.usage.input_tokens1200입력 토큰 수
gen_ai.usage.output_tokens80출력 토큰 수
gen_ai.response.finish_reasonstop종료 이유 (stop, length, tool_calls)

4.2 Span Kind

  • client: Agent → LLM API 호출
  • internal: Agent 내부 추론 로직

4.3 OTel → Langfuse 브리지

# OpenTelemetry instrumentation → Langfuse 자동 전송
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

# OTLP Exporter → Langfuse OTLP endpoint
exporter = OTLPSpanExporter(
endpoint="https://langfuse.example.com/api/public/otlp",
headers={"Authorization": "Bearer <LANGFUSE_API_KEY>"}
)

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)

# 이제 모든 OTel trace가 Langfuse로 전송됨
tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("agent_run") as span:
span.set_attribute("gen_ai.system", "openai")
span.set_attribute("gen_ai.request.model", "gpt-4o")
# ... Agent 실행

5. Grafana/CloudWatch 대시보드 예시

5.1 Top-line 메트릭 (경영진용)

┌─────────────────────────────────────────────────────────────┐
│ Task Success Rate (30일) │ 96.2% (↑ 1.2% WoW) │
│ Avg Cost per Interaction │ $0.12 (↓ $0.03 WoW) │
│ Hallucination Rate │ 2.1% (↑ 0.3% WoW) │
│ Escalation Rate │ 3.5% (→ 0.0% WoW) │
└─────────────────────────────────────────────────────────────┘

Grafana Panel 설정:

# Task success rate (30일 평균)
sum(rate(langfuse_trace_score_total{name="task_success", value="1"}[30d]))
/
sum(rate(langfuse_trace_score_total{name="task_success"}[30d]))

5.2 Drill-down 대시보드 (운영팀용)

Tool Call 분석:

Tool Call Success Rate by Tool
┌──────────────┬──────────┬──────────┐
│ Tool │ Calls │ Success │
├──────────────┼──────────┼──────────┤
│ get_weather │ 1,234 │ 99.2% │
│ search_web │ 892 │ 94.5% │
│ send_email │ 456 │ 100% │
│ get_order │ 789 │ 98.7% │
└──────────────┴──────────┴──────────┘

Guardrails Violation 추이:

Guardrails Violation Rate (7일)
┌─────────────────────────────────────────┐
│ 5% ┤ │
│ 4% ┤ ╭╮ │
│ 3% ┤ ╭╯╰╮ ╭╮ │
│ 2% ┤╭╯ ╰╮╭╯╰╮ │
│ 1% ┼╯ ╰╯ ╰───────────────── │
│ 0% ┴──────────────────────────────── │
└─────────────────────────────────────────┘
Mon Tue Wed Thu Fri Sat Sun

5.3 SLO 대시보드

Error Budget Burn Rate (Task Success SLO: 95%)
┌────────────────────────────────────────────────────┐
│ Current SLI: 96.2% │
│ Error Budget: 5% → 36h/month │
│ Consumed: 12.5h (34.7%) │
│ Remaining: 23.5h (65.3%) │
│ │
│ ██████████████████░░░░░░░░░░░ 34.7% consumed │
│ │
│ Status: 🟢 HEALTHY │
│ Estimated Days Until Budget Exhausted: 45 days │
└────────────────────────────────────────────────────┘

6. 경보·이상 탐지

6.1 이상 패턴 예시

이상 유형탐지 규칙대응 액션
Guardrails rate 급증3σ 초과 (rolling 1시간)PagerDuty P2, 프롬프트 검토
Cost spike시간당 비용 > $100 (baseline $20)Slack 알림, rate limit 활성화
Escalation rate 증가10% 초과 (baseline 3%)온콜 엔지니어 알림, Agent 로직 검토
Tool failure rate특정 도구 > 20% 실패자동 circuit breaker, fallback 활성화

6.2 Baseline 설정과 탐지 알고리즘

Rolling window 평균 기반 이상 탐지:

# 예시: Guardrails violation rate 이상 탐지
import numpy as np

def detect_anomaly(current_rate, historical_rates, threshold_sigma=3):
"""
Args:
current_rate: 현재 시간대 violation rate
historical_rates: 과거 7일 동일 시간대 rates
threshold_sigma: 표준편차 배수 임계값
"""
baseline_mean = np.mean(historical_rates)
baseline_std = np.std(historical_rates)

z_score = (current_rate - baseline_mean) / baseline_std

if z_score > threshold_sigma:
return {
"anomaly": True,
"severity": "high" if z_score > 5 else "medium",
"z_score": z_score,
"baseline": baseline_mean,
"current": current_rate
}
return {"anomaly": False}

# 실시간 모니터링 예시
current_rate = 0.08 # 8% violation rate
historical = [0.02, 0.021, 0.019, 0.022, 0.018, 0.023, 0.020] # 과거 7일

result = detect_anomaly(current_rate, historical)
if result["anomaly"]:
print(f"🚨 Anomaly detected: {result['current']:.1%} (baseline {result['baseline']:.1%})")
# PagerDuty 알림 전송

6.3 PagerDuty/Slack 연동

CloudWatch Alarm → SNS → Lambda → PagerDuty:

# Lambda handler: CloudWatch Alarm → PagerDuty
import boto3
import requests

def lambda_handler(event, context):
alarm_name = event["detail"]["alarmName"]
metric = event["detail"]["metric"]
value = event["detail"]["state"]["value"]

# PagerDuty Events API v2
payload = {
"routing_key": "PAGERDUTY_ROUTING_KEY",
"event_action": "trigger",
"payload": {
"summary": f"Agent KPI Anomaly: {alarm_name}",
"severity": "warning",
"source": "cloudwatch",
"custom_details": {
"metric": metric,
"current_value": value,
"threshold": event["detail"]["threshold"]
}
}
}

response = requests.post(
"https://events.pagerduty.com/v2/enqueue",
json=payload
)
return {"statusCode": 200, "body": "Alert sent"}

Slack 알림 예시:

🚨 Agent Metrics Alert

**Cost Spike Detected**
- Current hourly cost: $142.50 (baseline $18.20)
- Time: 2026-04-18 14:30 UTC
- Agent: customer-support-agent
- Model: gpt-4o-2025-01-31

**Probable Cause**: Unusual traffic spike (3.2k requests vs 800 baseline)

Actions:
- Rate limit activated (100 req/min → 50 req/min)
- Fallback to gpt-4o-mini for non-critical queries

📊 Dashboard: https://grafana.example.com/d/agent-cost
📖 Runbook: https://wiki.example.com/agent-cost-spike

7. AIDLC 단계별 활용

7.1 Inception: Baseline 정의

프로젝트 초기에 목표 KPI를 정의한다.

KPITarget (90일 후)Baseline (현재)
Task success rate≥ 95%88% (사람 기준선)
Tool-call accuracy≥ 90%N/A (신규)
Hallucination rate≤ 3%12% (초기 프로토타입)
Cost per interaction≤ $0.15$0.32
Escalation rate≤ 5%18%

7.2 Construction: CI 회귀 게이트

각 PR에서 메트릭 회귀를 자동 감지한다.

# .github/workflows/agent-quality-gate.yml
name: Agent Quality Gate
on: [pull_request]

jobs:
evaluate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run Ragas evaluation
run: |
pytest tests/test_agent_quality.py --ragas

- name: Check metrics regression
run: |
python scripts/check_regression.py \
--baseline metrics/baseline.json \
--current metrics/current.json \
--threshold 0.05 # 5% 이상 하락 시 fail

7.3 Operations: 실시간 경보

프로덕션 배포 후 실시간 모니터링.

Agent KPI SLO (프로덕션)
┌──────────────────────┬──────────┬──────────┬──────────┐
│ Metric │ SLO │ Current │ Status │
├──────────────────────┼──────────┼──────────┼──────────┤
│ Task success rate │ ≥ 95% │ 96.2% │ 🟢 OK │
│ Tool-call accuracy │ ≥ 90% │ 93.5% │ 🟢 OK │
│ Hallucination rate │ ≤ 3% │ 2.1% │ 🟢 OK │
│ Cost per interaction │ ≤ $0.15 │ $0.12 │ 🟢 OK │
│ Escalation rate │ ≤ 5% │ 3.5% │ 🟢 OK │
│ TTFT (p95) │ ≤ 2s │ 1.8s │ 🟢 OK │
└──────────────────────┴──────────┴──────────┴──────────┘

8. 참고 자료

8.1 Langfuse 문서

8.2 OpenTelemetry

8.3 평가 프레임워크

8.4 관련 문서