블로그
안정성 및 프로덕션

게시일 수정일

Anshu 및 Shouryamaan

AI agent failure recovery: retry, checkpoint, human approval

Markdown으로 읽기

AI agent failure recovery는 실패한 step을 중단할지, 재시도할지, 결과를 조정할지, 승인을 기다릴지, 보상할지, checkpoint에서 재개할지 결정합니다. 결정은 error class와 외부 effect가 이미 완료되었을 가능성에 따라 달라집니다.

자동 retry는 operation contract가 반복을 안전하게 만들 때만 안전합니다. timeout은 실패를 증명하지 않습니다.

대응하기 전에 failure를 분류하세요

실패 기본 대응
잘못된 input 또는 schema 중단하고 request 수정
authentication 또는 authorization 중단하고 유효한 access 요청
policy denial 중단하거나 지정된 approval 요청
retry time이 있는 rate limit 기다린 뒤 operation budget 안에서 재시도
일시적인 read failure bounded backoff로 재시도
outcome을 알 수 없는 write timeout 재시도 전에 reconciliation
영구적인 provider failure 실패 처리하거나 문서화된 alternate path 사용
worker crash persisted state에서 재개
여러 system 중 일부만 완료 policy에 따라 계속 진행, compensation 또는 escalation

도구에서 안정적인 error code를 제공하세요. “something went wrong” 같은 prose를 보고 model이 retry safety를 추론하게 하지 마세요.

논리적 쓰기 하나에 operation ID 하나를 부여하세요

결과가 큰 call 전에 operation record를 만드세요. action, tenant, resource, normalized input hash, idempotency key, state, attempt, provider reference, result를 저장합니다.

같은 logical effect를 재시도할 때마다 동일한 idempotency key를 사용하세요. 다른 parameter로 재사용하면 거부합니다. Stripe의 idempotent request 문서는 반복된 key에 저장된 result를 반환하는 server-side contract를 보여 줍니다. retention rule은 provider별로 다르므로 현실적으로 가능한 가장 긴 resume path를 기준으로 기간을 정하세요.

provider가 idempotency를 지원하지 않더라도 operation table은 두 local worker가 의도적으로 같은 action을 시작하는 것을 막습니다. 하지만 provider가 작업한 뒤 response가 사라진 상황은 해결하지 못합니다. provider lookup, webhook, human reconciliation step을 추가하세요.

검증된 progress를 checkpoint에 기록하세요

model이 완료됐다고 말한 뒤가 아니라 system이 외부 effect를 확인한 뒤 checkpoint하세요. provider identifier나 operation reference를 저장합니다. 재개할 때 model을 다시 호출하기 전에 checkpoint와 기준 backend state를 불러오세요.

durable execution 가이드는 workflow history, deterministic replay, persisted wait를 설명합니다. failure recovery는 각 state의 운영상 선택을 더합니다.

retry owner를 하나로 지정하세요

HTTP client, queue, workflow engine, model SDK, tool, provider가 모두 재시도할 수 있습니다. failure class마다 owner를 하나씩 선택하고 같은 operation 아래에서 모든 attempt를 셉니다.

maximum attempt, elapsed time, backoff, terminal result를 설정하세요. validation, authorization, policy failure에는 중단합니다. model call의 경우 retry가 같은 prompt와 tool을 사용하는지 아니면 새로운 decision을 만드는지 결정하세요. 이 차이는 evaluation을 바꾸므로 기록해야 합니다.

결과를 알 수 없을 때 조정하세요

write가 timeout되면 다음 순서를 따르세요.

  1. operation을 unknown으로 표시하고 failed로 표시하지 않습니다.
  2. idempotency key, provider reference, expected business state로 query합니다.
  3. effect가 존재하면 completed로 표시합니다.
  4. provider가 실행되지 않았다고 확인한 경우에만 재시도합니다.
  5. 어느 쪽도 확인할 수 없으면 human review를 요청합니다.

unknown state를 success message 뒤에 숨기지 마세요. reconciliation이 진행되는 동안 사용자는 request를 반복하지 않아야 할 수 있습니다.

high-impact attempt 전에 approval을 배치하세요

approval은 action, resource, parameter, actor, expiry에 묶여야 합니다. execution이 재개될 때 authorization을 다시 확인하세요. “continue” 같은 broad approval이 변경된 payment나 deletion parameter까지 허용해서는 안 됩니다.

Railway의 agent deletion incident를 계기로 Railway는 API deletion에 48시간 soft-delete 기간을 적용했습니다. reversible effect는 recovery 부담을 줄이지만 scoped identity와 audit record는 여전히 필요합니다.

cancellation과 compensation을 구분하세요

cancellation은 이후 작업을 막습니다. 이미 완료된 email, payment, external publication을 되돌릴 수는 없습니다. compensation은 invoice를 무효화하거나 soft-delete된 resource를 복원하는 별도의 action입니다.

compensation에는 자체 authorization, idempotency, operation record, failure path가 필요합니다. 여러 external system에 shared transaction이 없는데도 automatic rollback이라고 설명하지 마세요.

사람이 실행할 수 있는 runbook을 작성하세요

high-impact workflow마다 다음 내용을 문서화하세요.

  • 새 run과 active worker를 중단하는 방법
  • revoke할 credential
  • 범위 안의 task와 operation을 찾는 방법
  • unknown outcome을 분류하는 방법
  • 안전한 retry
  • compensate할 수 있는 effect
  • recovery 승인자와 완료 검증 방법

runbook을 trace 및 operation query에 연결하세요. observability 가이드는 incident를 처음부터 끝까지 추적하는 데 필요한 identifier를 나열합니다.

경계 사이에 failure를 주입해 연습하세요

call 전, provider가 받은 뒤, 성공했지만 response가 도착하기 전, checkpoint 후, approval 중, cancellation 중에 failure를 주입하세요. local state가 없는 새 worker에서 재개하고 effect count와 final business state를 확인합니다.

아래 프롬프트는 production을 건드리지 않고 가장 많은 정보를 주는 훈련을 설계합니다. runbook이 “failed”와 “may have succeeded”를 구분하지 못한다면 autonomy를 늘리기 전에 그 branch부터 고치세요.