홈/AI 자동화/AI 에이전트 신뢰성 2편: 실패 감지와 자동 복구
AI 자동화AI에이전트신뢰성

AI 에이전트 신뢰성 2편: 실패 감지와 자동 복구

에이전트 실패를 헬스체크·가드레일·재시도로 감지하고, 보상 트랜잭션과 사람 승인으로 복구하는 실무 패턴.

AI 에이전트 신뢰성 2편: 실패 감지와 자동 복구
목차
  1. 왜 일반 테스트가 에이전트에 통하지 않는가
  2. 에이전트 테스트의 4 레이어
  3. Layer 1: 출력 스키마 검증
  4. Layer 2: 확률적 어설션
  5. Layer 3: 툴 호출 정확도 테스트
  6. Layer 4: Replay 테스트 (LangSmith)
  7. CI 파이프라인 통합
  8. 실패 감지 시그널 (최소 세트)
  9. 자동 복구 패턴
  10. Replay·확률적 테스트가 들쭉날쭉 깨질 때
  11. 참고 자료
  12. 검증 환경·편집자 주
  13. 자주 묻는 질문 (FAQ)

왜 일반 테스트가 에이전트에 통하지 않는가

단위 테스트의 전제는 결정론입니다. 같은 입력 → 항상 같은 출력. 그런데 LLM 에이전트는 temperature, 컨텍스트 노이즈, 모델 업데이트에 따라 다른 결과를 냅니다. 이번 편에서는 비결정 시스템을 체계적으로 검증하는 테스트 전략을 다룹니다.

에이전트 테스트의 4 레이어

CODE
Layer 4: End-to-End 시나리오 테스트
Layer 3: 툴 호출 정확도 테스트
Layer 2: 프롬프트 회귀 테스트
Layer 1: 출력 형식 / 스키마 검증

하위 레이어부터 안정화해야 상위 레이어 테스트가 의미 있습니다.

Layer 1: 출력 스키마 검증

Python
from pydantic import BaseModel, ValidationError

class AgentResponse(BaseModel):
    action: str
    parameters: dict
    confidence: float  # 0.0 ~ 1.0

def test_schema(raw_output: str):
    try:
        r = AgentResponse.model_validate_json(raw_output)
        assert 0.0 <= r.confidence <= 1.0
        return True
    except ValidationError as e:
        print(f"Schema error: {e}")
        return False

Structured Output(JSON mode)을 강제하면 이 레이어 실패율을 0에 가깝게 만들 수 있습니다.

Layer 2: 확률적 어설션

동일 입력으로 N번 실행 후 통계적으로 검증합니다.

Python
async def probabilistic_assert(agent, prompt, expected, n=20, threshold=0.8):
    results = await asyncio.gather(*[agent.run(prompt) for _ in range(n)])
    rate = Counter(r.action for r in results)[expected] / n
    assert rate >= threshold, f"통과율 {rate:.0%} < 목표 {threshold:.0%}"

임계값 가이드:

  • 크리티컬 경로: 0.95 이상
  • 일반 기능: 0.80 이상
  • 창의적 생성: 0.60 이상 (정성 평가 병행)

Layer 3: 툴 호출 정확도 테스트

Python
class ToolCallRecorder:
    def __init__(self): self.calls = []
    def __call__(self, tool_name, **kwargs):
        self.calls.append({"tool": tool_name, "params": kwargs})
        return mock_response(tool_name, **kwargs)

def test_tool_selection():
    recorder = ToolCallRecorder()
    agent = build_agent(tools=recorder)
    agent.run("고객 ID 12345의 최근 주문을 조회해줘")
    assert recorder.calls[0]["tool"] == "get_orders"
    assert recorder.calls[0]["params"]["customer_id"] == "12345"

Layer 4: Replay 테스트 (LangSmith)

Python
from langsmith import Client

client = Client()
def export_golden_tests(project: str, limit=100):
    # 긍정 피드백을 받은 트레이스를 골든 데이터셋으로
    runs = client.list_runs(
        project_name=project,
        filter="eq(feedback_score, 1)",
        limit=limit
    )
    return [{"input": r.inputs, "expected": r.outputs} for r in runs]

사용자 긍정 피드백을 golden dataset으로 축적하면 모델 업데이트 시 자동 회귀 테스트가 가능합니다.

CI 파이프라인 통합

YAML
# .github/workflows/agent-test.yml
on: [pull_request]
jobs:
  test:
    steps:
      - run: pytest tests/test_schema.py       # 항상, 빠름
      - run: pytest tests/test_tool_calls.py   # PR마다
      - run: pytest tests/test_replay.py       # 야간 스케줄

3편에서는 테스트를 통과한 에이전트가 프로덕션에서 실패할 때 자동 복구하는 Circuit Breaker·Fallback 패턴을 다룹니다.

실패 감지 시그널 (최소 세트)

시그널임계 예조치
툴 오류율5분 창 10%↑해당 툴 차단·폴백
스텝 수max_steps 80%↑루프 강제 종료
지연(p95)SLA 초과큐잉·축소 모델
환각/정책 위반필터 히트응답 차단·재생성
Python
# 의사코드: 스텝 가드레일
if state.steps >= MAX_STEPS or state.tool_errors >= 3:
    return escalate_to_human(state)  # 티켓/대기열

자동 복구 패턴

  1. 재시도: 멱등 툴만, 지수 백오프 + 지터
  2. 폴백 모델/툴: primary → secondary provider
  3. 보상(compensate): 부분 성공 시 롤백 핸들러
  4. HITL: 금액·삭제·외부 발송은 사람 승인 게이트

Replay·확률적 테스트가 들쭉날쭉 깨질 때

에이전트 테스트를 CI에 넣으면 코드 변경이 없는데도 통과와 실패가 번갈아 나오는 "flaky" 문제가 먼저 옵니다.

원인

  • 모델 별칭(예: 최신 버전을 가리키는 이름)이 공급사 측에서 새 스냅샷으로 바뀜
  • 도구 응답이 시간·외부 데이터에 의존해 매 실행마다 달라짐
  • temperature가 0이 아니거나, 0이어도 공급사 특성상 출력이 완전히 고정되지 않음

재현: 같은 테스트를 N회 반복해 통과율 측정

Bash
for i in $(seq 1 20); do pytest -q tests/agent/test_refund_flow.py >/dev/null && echo pass || echo fail; done | sort | uniq -c

통과율이 100%가 아니면 해당 테스트는 결정적 테스트가 아니라 확률적 테스트로 다뤄야 합니다.

해결

  • 모델은 날짜가 붙은 스냅샷 이름으로 고정하고, 버전 변경은 별도 PR로 진행합니다.
  • 도구 응답은 녹화·재생(record/replay) 방식으로 고정합니다. 첫 실행 때 외부 응답을 파일로 저장하고 이후에는 파일을 반환하게 하면, 모델 출력 외의 변동 요인이 사라집니다.
  • 확률적 테스트는 "20회 중 18회 이상 통과"처럼 임계값으로 판정하고, 임계값은 테스트 코드에 명시합니다.

재발 방지

  • 통과율이 임계값 아래로 떨어진 테스트는 격리(quarantine) 목록으로 옮기고 담당자와 기한을 붙입니다. 격리 목록이 커지면 모델 교체나 프롬프트 변경의 품질 신호로 봅니다.

참고 자료

검증 환경·편집자 주

  • 2026-09 편집. 임계값은 트래픽·도메인에 맞게 조정하세요.

자주 묻는 질문 (FAQ)

Q. 모든 실패를 자동 복구할까요?
아니요. 비가역 작업은 자동 재시도보다 격리·알림이 안전합니다.

✦ ✦ ✦
출처·검증 안내

글마다 출처와 확인 범위가 다릅니다. 아래에 확인일·확인 범위·출처가 기록된 글만 그 범위에서 확인된 것입니다. 기록이 없는 글은 적용 전 사용 중인 버전의 공식 문서로 직접 확인하고, 오류는 이메일로 알려주세요. 편집 정책 · 이메일로 제보

이 글에는 사람이 확인한 날짜·범위 기록이 아직 없습니다.

발행 ·
주제 관련 공식 문서(자동 연결 · 문장별 근거 아님)NIST CSRC (보안 표준) ↗

댓글

첫 번째 댓글을 남겨보세요.