AI 하네스를 만들다 보니 자연스럽게 다음 질문이 생겼다. 규칙과 도구를 갖췄다고 해도 한 번의 요청으로 긴 작업이 끝나지 않는데, 중간에 실패하면 어디에서 다시 시작해야 할까.
처음에는 단순한 반복으로 생각했다.
문제 확인 -> 수정 -> 테스트 -> 실패하면 다시 수정
작은 버그에는 충분했다. 하지만 저장소가 여러 개이고 배포와 실제 화면 확인까지 이어지면 같은 “실패” 안에도 전혀 다른 상황이 섞였다. 코드가 틀린 경우, 테스트 환경이 없는 경우, 배포는 됐지만 브라우저가 이전 자산을 보는 경우, 외부 요청은 보냈지만 성공 응답만 받지 못한 경우가 모두 달랐다.
이 차이를 상태와 전이로 표현하기 시작하면서 단순 반복이 루프 엔지니어링으로 바뀌었다.
루프의 최소 상태
내가 사용한 가장 작은 루프는 아래와 같다.
PLANNED
-> ANALYZED
-> IMPLEMENTED
-> LOCAL_VERIFIED
-> DEPLOYED
-> RUNTIME_VERIFIED
-> COMPLETE
상태 이름보다 중요한 건 각 상태에 들어가기 위한 증거다.
| 상태 | 필요한 증거 |
|---|---|
ANALYZED |
재현 조건, 실제 호출 경로, 원인 후보의 근거 |
IMPLEMENTED |
변경 파일, diff, 영향 범위 |
LOCAL_VERIFIED |
실패 후 통과한 테스트와 빌드 결과 |
DEPLOYED |
대상 환경과 배포된 산출물 식별자 |
RUNTIME_VERIFIED |
실제 요청, 화면, 활성 로그의 결과 |
COMPLETE |
목표 충족과 남은 위험 기록 |
IMPLEMENTED에서 바로 COMPLETE로 이동하지 못하게 한 것이 핵심이었다. 코드를 썼다는 사실과 문제가 해결됐다는 사실 사이에 검증 상태가 들어갔다.
전이에 붙인 가드 조건
상태 머신에서 가드는 다음 단계로 이동할 수 있는 조건이다. AI 작업에도 같은 개념을 적용했다.
transition(ANALYZED, IMPLEMENTED) when
scope_is_clear and
branch_is_safe and
writable_files_are_known
transition(LOCAL_VERIFIED, DEPLOYED) when
deployment_is_approved and
artifact_is_identified and
rollback_is_ready
transition(DEPLOYED, RUNTIME_VERIFIED) when
served_artifact_matches and
live_scenario_passes
가드가 없으면 “다음 단계로 가도 될 것 같다”는 판단이 대화의 분위기에 좌우된다. 조건을 적으면 무엇이 부족해서 멈췄는지 설명할 수 있다.
실패 상태를 하나로 만들지 않은 이유
모든 실패를 FAILED로 보내면 다시 시작할 위치를 알 수 없다. 그래서 실패를 네 종류로 나눴다.
REWORK_REQUIRED
구현이 목표를 충족하지 못한 상태
ENVIRONMENT_BLOCKED
의존성, 권한, 네트워크 때문에 검증하지 못한 상태
EXTERNAL_UNCERTAIN
외부 작업의 성공 여부를 확인할 수 없는 상태
BASELINE_FAILED
이번 변경과 관계없는 기존 실패가 확인된 상태
REWORK_REQUIRED만 구현 단계로 돌아간다. ENVIRONMENT_BLOCKED는 환경이 바뀐 뒤 같은 검증에서 재개한다. BASELINE_FAILED는 변경 전 증거와 비교해 범위에 영향이 있는지 판단한다.
EXTERNAL_UNCERTAIN은 가장 조심해야 했다. 예를 들어 배포 요청을 보낸 뒤 연결이 끊겼다면 실패라고 보고 다시 실행해서는 안 된다. 실제로는 첫 요청이 성공했을 수 있기 때문이다. 이 상태에서는 쓰기를 반복하지 않고 조회부터 한다.
멱등성 키와 중복 실행 방지
같은 작업을 두 번 실행해도 결과가 한 번과 같도록 만드는 성질을 멱등성이라고 한다. 모든 작업을 완전히 멱등하게 만들 수는 없지만, 적어도 루프가 같은 외부 행동을 무심코 반복하지 않게 할 수는 있다.
action_key: deploy:staging:client-app:abc1234
status: success
evidence:
artifact: abc1234
checked_at: 2026-08-01T14:20:00+09:00
루프는 외부 작업 전에 action_key를 확인한다.
if receipt(action_key) == SUCCESS:
reuse_evidence()
elif receipt(action_key) == UNCERTAIN:
read_external_state()
else:
execute_once()
코드 검색이나 테스트처럼 안전하게 반복할 수 있는 작업은 다시 실행해도 된다. 배포, DB 변경, 외부 메시지처럼 부작용이 있는 작업은 실행 기록과 현재 상태 조회가 먼저다.
체크포인트와 재개 지점
긴 작업이 끊겼을 때 전체 대화를 다시 읽는 대신 마지막으로 증명된 상태에서 시작했다.
{
"goal": "로그인 후 화면 복구",
"state": "LOCAL_VERIFIED",
"sourceCommit": "abc1234",
"evidence": {
"tests": "18 passed",
"build": "artifact created"
},
"next": "deployment approval",
"blockedBy": []
}
이 기록에는 비밀값이나 긴 로그를 넣지 않는다. 큰 증거는 별도 파일이나 시스템에 두고, 상태에는 위치와 결과만 남긴다. 체크포인트가 너무 커지면 다시 컨텍스트가 오염되기 때문이다.
재개할 때는 상태 파일만 믿지 않고 시간이 지나면 바뀌는 사실을 다시 확인했다.
- 현재 브랜치와 커밋
- 작업공간의 새 변경
- 배포 대상의 현재 버전
- 자격 증명과 권한의 존재 여부
- 외부 작업의 실제 상태
체크포인트는 과거에 확인한 사실이고, 현재 상태의 보증서는 아니다.
재시도에 넣은 한도
AI는 목표가 주어지면 계속 방법을 바꾸며 시도할 수 있다. 하지만 같은 오류를 반복하는 건 끈기가 아니라 비용이다. 재시도에는 횟수보다 분류 규칙을 넣었다.
for attempt in range(1, 4):
result = verify()
if result.ok:
return VERIFIED
cause = classify(result)
if cause in [PERMISSION, UNKNOWN_TARGET, EXTERNAL_UNCERTAIN]:
return STOP_WITH_EVIDENCE
change_one_variable(cause)
return STOP_AFTER_REPEATED_CAUSE
같은 원인으로 세 번 실패했다면 네 번째 실행보다 입력이나 권한을 확인하는 편이 낫다. 반대로 새로운 증거가 생겨 원인 분류가 바뀌었다면 다음 시도는 의미가 있다.
루프의 종료 조건
자동화에서 가장 어려웠던 건 시작보다 종료였다. “될 때까지”라는 조건은 실제로 측정할 수 없다. 그래서 종료를 세 가지로 나눴다.
성공 종료
목표와 검증 증거가 모두 충족
안전 종료
권한, 대상, 데이터 위험 때문에 더 진행하지 않음
정보 부족 종료
필요한 외부 상태나 사용자 선택을 기다림
어느 종료든 마지막에는 같은 형식으로 남겼다.
final_state: RUNTIME_VERIFIED
completed:
- 코드 수정
- 로컬 테스트
- 배포 자산 확인
- 실제 화면 확인
not_completed: []
next_action: none
완료하지 못한 작업을 숨기지 않는 것도 루프의 기능이다. 안전하게 멈춘 상태는 실패한 자동화가 아니라 정확한 자동화에 가깝다.
루프 엔지니어링에 대한 현재 결론
루프 엔지니어링은 AI에게 같은 지시를 반복하는 기술이 아니었다. 작업을 상태로 표현하고, 전이에 증거를 요구하고, 외부 행동의 중복을 막고, 실패 원인에 따라 재개 지점을 선택하는 설계였다.
하네스가 AI가 일할 환경을 만든다면 루프는 그 환경 안에서 작업이 시간에 따라 어떻게 진행되는지를 만든다. 둘을 분리해서 생각하니 규칙 파일과 자동화 스크립트의 역할도 선명해졌다.
하네스: 어디에서 어떤 규칙과 도구로 일하는가
루프: 어떤 상태를 거쳐 언제 다시 시도하고 멈추는가
결국 내가 만들고 싶었던 건 답변을 잘하는 AI가 아니라, 중간에 끊겨도 근거를 잃지 않고 다시 이어갈 수 있는 개발 과정이었다.
관련 연재: Codex AI 하네스 엔지니어링 설계 1 — 작업 경계
다음 글: Codex AI 하네스 엔지니어링 설계 6 — 검증 체계
후속 확인 항목
이 문제를 고친 뒤 관련 공식 자료를 찾아 읽으면서, 당시 코드에서 우연히 맞았던 부분과 규칙으로 남겨야 할 부분을 나눠 봤다.
에이전트 활용 자료를 다시 읽으며 workflow와 agent를 먼저 구분했다. 순서와 분기가 정해진 일은 workflow로 고정하고, 탐색이 필요한 부분만 도구 선택을 맡기는 편이 결과를 비교하기 쉽다. 저장소 작업도 격리된 환경, 명시적 권한, 실행한 테스트와 diff가 함께 있어야 검토 가능한 변경이 된다.
하네스는 지시문 모음보다 입력 범위, 허용 도구, 중단 조건, 증거 형식을 코드와 문서로 고정하는 층에 가깝다.
다음에 Codex AI 루프 엔지니어링 설계 — 상태 전이 같은 문제를 보면 아래 순서부터 확인하려고 한다.
- 읽기·수정·실행·배포 권한 구분
- 작업마다 허용한 파일과 도구 범위
- diff·테스트·실행 화면 증거
- 반복 상한과 사람에게 돌려줄 조건
성공 문장보다 실제 diff·테스트 출력·배포 화면을 우선하고, 쓰기·배포·비밀 접근은 별도 권한 경계로 남겨야 한다.
공식 참고 자료
- OpenAI Codex 소개 — 격리된 저장소 작업·테스트·권한 경계
- Building effective agents — workflow와 agent 구분, 단순한 조합 패턴과 평가
- Codex app 소개 — 병렬 작업·sandbox·권한·검토 흐름