에러 처리와 복구 전략
재시도/폴백/서킷브레이커, 에이전트 실패 격리, Human-in-the-Loop, 부분 실패 복구
에이전트 시스템은 언젠가 실패합니다. 중요한 것은 실패를 없애는 것이 아니라, 실패를 예측 가능한 범위 안에 가두고 복구 비용을 통제하는 것입니다.
실패 유형 분류
| 유형 | 예시 | 복구 전략 |
|---|---|---|
| Model Failure | 잘못된 추론, schema 불일치 | 재시도보다 evaluator/fallback 강화 |
| Tool Failure | timeout, rate limit, validation error | retry, alternate tool, queued retry |
| Workflow Failure | 상태 전이 누락, 중복 실행 | checkpoint, idempotency, compensation |
| External System Failure | 서드파티 API 장애 | circuit breaker, cached fallback |
| Human SLA Failure | 승인 지연, reviewer 부재 | timeout escalation, default action |
재시도 여부를 먼저 결정한다
아래 질문에 따라 retry를 나눕니다.
| 질문 | Yes면 |
|---|---|
| 같은 입력으로 다시 호출해도 성공 가능성이 높은가 | retry 가능 |
| side effect가 없는가 | 자동 retry 가능 |
| 외부 시스템의 일시적 장애인가 | backoff retry 고려 |
| 추론 품질 자체가 문제인가 | retry보다 fallback 또는 evaluator |
모델이 틀린 판단을 한 경우에는 같은 프롬프트를 즉시 다시 실행하는 것보다, 입력 보강, 다른 경로, 사람 개입이 더 효과적입니다.
기본 복구 패턴
| 패턴 | 언제 쓰는가 | 주의점 |
|---|---|---|
| Retry with backoff | rate limit, 네트워크 오류 | side effect 중복 방지 필요 |
| Fallback model/tool | 특정 모델 또는 tool이 불안정 | 품질 차이를 eval로 확인 |
| Circuit breaker | 장애가 연속 발생 | 너무 늦게 열리면 전체 시스템 전염 |
| Human handoff | 고위험 또는 low confidence | 사람 큐 적체 관리 필요 |
| Partial replay | 일부 단계만 재실행 가능 | checkpoint 설계가 선행되어야 함 |
에이전트 실패 격리
worker 하나가 실패했다고 run 전체를 무조건 실패로 만들 필요는 없습니다.
격리가 필요한 경우
- fan-out된 병렬 조사 중 일부가 실패한 경우
- 선택적 enrichment step가 실패한 경우
- 품질 점수는 낮지만 최소 응답은 가능한 경우
전체 중단이 필요한 경우
- write 작업 직전 검증이 실패한 경우
- 근거가 없어 답변 정당화가 불가능한 경우
- 승인 없이 진행하면 안 되는 경우
부분 실패 복구 흐름
이 흐름의 핵심은 "실패 = 전체 중단"이 아니라, 위험도에 따라 복구 경로를 다르게 설계하는 것입니다.
서킷브레이커 기준
| 신호 | 권장 동작 |
|---|---|
| 최근 5분 실패율 급증 | 새 호출 차단 또는 fallback 강제 |
| 평균 지연 시간 임계치 초과 | 저품질 fallback 또는 큐잉 |
| validation error 증가 | schema 또는 prompt 회귀 의심 |
| human rejection 급증 | 자동화 범위 축소 |
Human-in-the-Loop 설계
고위험 작업이나 low confidence 상황에서는 human handoff가 핵심 복구 전략입니다. 사람에게 넘길 때는 승인 큐에 충분한 맥락과 근거를 포함해야 운영자가 빠르게 판단할 수 있습니다.
Human handoff 패킷 설계는 에이전트 간 통신 챕터를 참조하세요.
운영 로그 필드
복구 전략을 개선하려면 실패 로그가 구조화되어야 합니다.
type FailureEvent = {
runId: string
stepName: string
errorType: 'model' | 'tool' | 'workflow' | 'external' | 'human_sla'
retryable: boolean
riskLevel: 'low' | 'medium' | 'high'
recoveryAction: 'retry' | 'fallback' | 'handoff' | 'abort'
}안티패턴
| 안티패턴 | 문제 | 개선 |
|---|---|---|
| 모든 실패에 일괄 재시도 | 비용과 중복 side effect 증가 | 실패 유형별 전략 분리 |
| human handoff를 마지막 수단으로만 생각 | 고위험 작업에서 이미 늦음 | 위험도 기반 early handoff |
| fallback 품질을 측정하지 않음 | 숨은 품질 저하 누적 | fallback별 eval 필요 |
| 부분 실패 허용 기준 없음 | 시스템 동작 예측 불가 | degraded mode 정의 |
ADR 스타일 결론
Decision
실패 대응은 재시도 중심이 아니라 위험도 중심으로 설계합니다. retryable한 tool 오류는 backoff와 idempotency로 처리하고, 추론 품질 문제나 고위험 작업은 fallback 또는 human handoff로 전환합니다. 병렬 시스템에서는 부분 실패를 허용할 degraded mode를 명시합니다.
실무 체크리스트
- 실패 유형이 구조화되어 수집되는가
- retryable 여부와 side effect 여부를 함께 판단하는가
- fallback 경로의 품질을 별도로 측정하는가
- human approval queue에 충분한 근거가 전달되는가
- degraded mode와 abort 조건이 정의되어 있는가