같은 명령을 다시 실행하면 무엇이 달라질까요?
테스트가 실패했어요. 에이전트가 잠깐 기다렸다가 같은 코드에 같은 명령을 다시 실행해요. 또 실패하자 이번에는 더 긴 설명을 덧붙이고 다시 실행해요. 출력은 늘었지만 다음 판단에 필요한 정보가 추가됐는지는 별도 문제예요.
일시적인 네트워크 오류라면 재시도가 도움이 될 수 있어요. 반면 잘못된 입력이나 변하지 않은 코드 결함이 원인이면 기다리는 것만으로 결과가 달라지지는 않아요. 그래서 재시도 정책에는 횟수와 시간뿐 아니라 무엇이 바뀌었는지를 묻는 조건도 필요해요.
AGS는 재시도 제안에서 대상과 증거를 비교해요. 여기서 흥미로운 부분은 같은 시도를 반복하지 말라는 지침을 실제 거부 조건으로 옮겼다는 점이에요.
대상도 증거도 그대로라면 거부하기
workflow-service.ts의 재시도 처리에는 다음 코드가 있어요. 새 증거를 판단하는 부분을 그대로 발췌했어요.
const oldEvidence = new Set([...(priorProposal?.priorFailure?.evidenceRefs ?? []), ...burned]);
const hasNewEvidence = proposal.priorFailure.evidenceRefs.some((reference) => !oldEvidence.has(reference));직전 실패의 증거 참조와 이미 소진된 것으로 관리하는 참조를 집합으로 만들어요. 새 제안의 증거 참조 중 이 집합에 없는 값이 하나라도 있는지 확인해요. 같은 대상인지 여부는 앞에서 대상 digest를 비교해 계산해요.
그다음 분기는 sameTarget && !hasNewEvidence 조건에서 재시도를 거부해요. 거부 사유는 stale-evidence이고 진단 경로를 안내해요. 메시지에도 대상과 관측 증거 어느 쪽도 바뀌지 않았다는 이유가 들어 있어요.
코드에서 확인하는 것은 “이번 설명이 더 설득력 있는가”가 아니에요. 같은 대상에 기존 증거만 제출했는지예요. 문장을 길게 다시 쓰는 것으로는 이 조건을 바꿀 수 없어요.
새 참조와 새 정보는 같은 말이 아니에요
이 검사에는 분명한 한계도 있어요. 집합에 없는 문자열이 들어왔다고 그 자료가 원인을 좁히는 새로운 정보라고 보장되지는 않아요. 같은 로그를 다른 경로에 복사해 참조만 바꾸는 경우도 생각할 수 있어요.
따라서 재시도 허용 조건을 통과했다는 사실과 다시 시도할 가치가 있다는 판단을 구분해야 해요. 서버는 비교 가능한 식별 정보로 반복을 제한하고, 전문 진단은 그 관측이 무엇을 뜻하는지 판단해요. 둘 중 하나로 다른 하나를 대체하기는 어려워요.
예를 들어 다음은 모두 서로 다른 변화예요.
| 변화 | 다음 판단에 주는 정보 |
|---|---|
| 명령의 출력 파일 이름만 변경 | 기록 위치는 달라졌지만 원인 판단에 새 정보가 없을 수 있어요 |
| 문제가 생긴 입력을 최소 예제로 축소 | 어떤 입력 조건이 실패를 만드는지 좁힐 수 있어요 |
| 외부 서비스 상태를 새로 확인 | 일시 장애 가설을 다시 판단할 수 있어요 |
| 원인으로 의심한 분기를 수정 | 대상이 바뀌었으므로 같은 검사로 수정 효과를 확인할 수 있어요 |
이 표는 AGS의 자동 분류 결과가 아니라, 증거를 검토할 때 사용할 수 있는 설명용 구분이에요.
오류 메시지를 원인으로 단정하지 않기
AGS의 blocker-diagnostician은 관측한 실패와 원인 가설을 분리하고, 다음 판별 검사를 정하는 역할이에요. 가령 “연결 시간이 초과됐다”는 관측에서 곧바로 “네트워크가 불안정하다”는 원인으로 넘어가지 않아요. 서버의 처리 지연, 연결 제한, 잘못된 주소 같은 다른 가설이 남아 있을 수 있어요.
다음 검사는 가설을 구분할 수 있어야 해요. 같은 요청을 반복하는 대신 연결 단계와 응답 대기 단계를 나눠 관측하면, 적어도 어느 구간에서 시간이 쓰이는지 알 수 있어요. 반대로 입력과 환경이 그대로인데 같은 검사를 반복하면 원인 후보를 줄이지 못할 수 있어요.
이 관점은 AI에만 필요한 특별한 디버깅 방법은 아니에요. 에이전트가 도구를 연속 호출할 때도 기존의 관측, 가설, 판별 검사 순서를 유지하도록 만든다는 데 의미가 있어요.
복구를 위해 과거 실패 기록을 바꾸지 않기
원인이 확인된 뒤에는 실행 가능한 복구 방법을 선택해야 해요. AGS는 이 역할을 recovery-strategy-selector로 분리하고, 선택한 복구를 RecoveryHandoff.v1으로 넘겨요. 기존 실행 기록을 성공한 것처럼 고치는 대신 새 작업과 새 워크플로에서 복구를 수행해요.
이렇게 하면 원래 시도가 왜 실패했는지와 다음 시도가 무엇을 바꿨는지 비교할 수 있어요. 예를 들어 외부 환경에 의존하던 검사를 로컬 재현으로 바꿨다면, 원래 검사가 성공한 것으로 바꾸는 대신 검증 방법을 바꾼 이유를 남길 수 있어요.
다만 복구 방법을 새로 정했다고 사용자 요청을 마음대로 축소할 수 있는 것은 아니에요. 실제 연동 성공이 완료 조건인데 로컬 모의 응답만 확인했다면 남아 있는 차이를 그대로 알려야 해요. 재시도 제어가 완료 기준을 낮추는 수단이 되어서는 안 돼요.
재시도 정책은 실패하는 경로로 확인하기
이 정책을 검증한다면 같은 대상과 같은 증거를 다시 제출했을 때 거부되는지부터 봐야 해요. 대상이 바뀐 경우, 새 증거가 있는 경우, 이미 사용한 증거를 다시 가져온 경우도 나눠 확인해야 해요. 허용된 뒤 실제 작업이 성공했는지는 별도 검사예요.
이번 글에서는 재시도 처리 코드의 대상 비교와 증거 참조 비교, 진단·복구 역할 분리를 확인했어요. 이 설계가 모든 무한 반복을 막거나 비용을 일정 비율 줄인다는 측정 결과는 제시하지 않아요. 얻을 수 있는 것은 다시 실행하기 전에 변화와 근거를 묻는 구체적인 지점이에요.
다음 글과 소스
다음은 에이전트에게 일을 나누기 전에 정할 것들이에요. 한 에이전트의 반복을 통제했다면, 여러 에이전트가 같은 일을 중복하거나 서로의 변경을 덮어쓰지 않도록 역할을 나누는 문제도 살펴볼 수 있어요.