Reviewed technical note

에이전트의 DONE은 말이 아니라 증거로 결정해야 한다

AI 에이전트가 완료를 주장할 때 상태 전환을 실행 증거로 통제하는 방법.

에이전트가 “완료했다”고 말하는 순간을 완료 상태로 취급하면 자동화는 쉽게 망가진다. 모델의 자연어 응답은 상태가 아니라 주장이다. 실제 상태 전환은 최신 코드, 실행 결과, 리뷰 기록처럼 기계적으로 확인 가능한 증거가 게이트를 통과할 때만 허용해야 한다.

완료 주장은 제어 신호가 아니다

코딩 에이전트는 tested, reviewed, ready to merge 같은 말을 그럴듯하게 할 수 있다. 문제는 그 말이 현재 작업 상태와 연결되어 있지 않을 수 있다는 점이다. 테스트가 이전 커밋에서 실행됐거나, 실패 로그를 무시했거나, 리뷰가 현재 diff를 보지 않았을 수도 있다.

따라서 런타임은 에이전트 응답을 곧바로 신뢰하지 말고 다음 흐름을 강제해야 한다.

flowchart TD
  claim[완료 주장] --> gate[필요한 게이트 식별]
  gate --> fresh[증거의 최신성 확인]
  fresh --> bound[현재 변경과 연결 확인]
  bound --> verify[기계적으로 검증]
  verify --> pass{조건 충족?}
  pass -->|| advance[다음 상태로 전환]
  pass -->|아니오| stop[중단 또는 재작업]

이 구조의 목적은 에이전트를 불신하는 것이 아니라, 에이전트의 출력과 시스템의 생명주기 상태를 분리하는 것이다.

proof는 완전한 수학 증명이 아니다

여기서 말하는 증거는 프로그램 전체가 의미론적으로 완벽하다는 보장이 아니다. 특정 게이트를 통과하기에 충분한 실행 증거다. 예를 들어 “배포 가능” 게이트라면 빌드 성공, 변경된 경로의 테스트 성공, 마이그레이션 검증, 리뷰 승인처럼 미리 정한 조건을 만족해야 한다.

중요한 조건은 네 가지다.

  1. 어떤 상태 전환을 승인할 증거인지 명확해야 한다.
  2. 증거가 현재 변경에 연결되어 있어야 한다.
  3. 증거가 오래되지 않아야 한다.
  4. 사람이 읽는 설명이 아니라 도구가 확인할 수 있는 형식이어야 한다.

테스트를 실행했다는 사실만으로도 부족하다. 어떤 커밋에서 실행했는지, 어떤 설정으로 실행했는지, 어떤 실패를 제외했는지가 함께 남아야 한다.

리뷰는 조언이 아니라 게이트여야 한다

자동화 루프에서 리뷰어를 하나 더 붙이는 것만으로는 충분하지 않다. 리뷰 결과가 생명주기 전환을 막을 수 있어야 한다. 리뷰가 “위험”이라고 했는데도 머지가 계속된다면 그 리뷰는 관측값일 뿐 제어 장치가 아니다.

실무에서는 다음처럼 상태를 나누는 편이 안전하다.

stateDiagram-v2
  [*] --> claimed
  claimed --> evidence_collected
  evidence_collected --> verified
  verified --> approved
  approved --> released
  evidence_collected --> failed
  failed --> blocked

claimed에서 verified로 직접 뛰지 못하게 하는 것이 핵심이다. 에이전트는 작업을 수행하고 주장할 수 있지만, 상태를 올리는 권한은 게이트가 가져야 한다.

적용 체크리스트

  • 에이전트의 완료 문구와 실제 상태 필드를 분리했는가?
  • 상태 전환마다 필요한 증거 목록이 있는가?
  • 증거가 현재 커밋, 입력 데이터, 실행 환경과 연결되는가?
  • 실패한 검증을 “나중에 확인”으로 넘기지 못하게 막는가?
  • 사람이 승인해야 하는 변경과 자동 승인 가능한 변경을 구분했는가?

증거 기반 루프의 장점은 느려지는 것이 아니다. 실패한 자동화가 다음 단계로 퍼지는 것을 막는 것이다. 에이전트가 더 많은 일을 맡을수록 완료는 말이 아니라 증거로 결정해야 한다.