AgenticOps 메트릭 — 운영 중 관측할 Agent KPI
AI Agent가 프로덕션에 배포되면, 시스템이 정상 응답하는가만으로는 품질을 판단할 수 없다. "사용자 의도를 정확히 이해했는가?", "올바른 도구를 호출했는가?", "답변이 충실한가?"와 같은 **사용자 지각 품질(Perceived Quality)**을 측정해야 한다. 이 문서는 Agent 운영에 필수적인 KPI 카테고리와 Langfuse·OTel 기반 계측 방법을 다룬다.
1. 왜 Agent 전용 메트릭이 필요한가
1.1 전통 APM의 한계
기존 APM(Application Performance Monitoring)은 HTTP 성공률, 응답 시간, 에러율 등 시스템 지표를 중심으로 설계되었다. 그러나 Agent는 다음과 같은 이유로 추가 메트릭이 필요하다:
| 전통 APM | Agent 품질 지표 | 격차 |
|---|---|---|
| HTTP 200 OK | 올바른 답변 여부 | 요청 성공 ≠ 결과 품질 |
| 응답 시간 (전체) | Time to First Token | streaming에서 사용자 체감 속도 다름 |
| 에러율 | Hallucination rate | LLM 오류는 HTTP 500이 아닌 정상 응답 |
| CPU/Memory | Token cost | 클라우드 LLM은 토큰 단위 과금 |
| N/A | Tool-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 rate | Semantic 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 budget | SLO 위반 허용치 소진률 | 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.0faithfulness: 0.0~1.0 (Ragas)cache_hit: 0.0 (miss) / 1.0 (hit)tool_call_accuracy: 0.0~1.0guardrails_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"
}
]
}