
Claude Code의 「했습니다」를 믿어서는 안 된다 —— 완료 보고에 증거를 요구하는 운용
요약
Claude Code와 같은 AI 에이전트가 '완료했다'고 보고하더라도 실제 의도한 상태(Push 완료, 파일 내용 등)와 다를 수 있음을 경고합니다. 이를 방지하기 위해 에이전트의 자기 신고 대신 명령어 출력값을 포함하도록 보고 형식을 강제하는 운용 규칙을 제안합니다.
핵심 포인트
- 명령어 실행 성공과 의도한 최종 상태 사이에는 간극이 존재함
- 에이전트의 주관적 보고 대신 기계적 출력값(git status 등)을 요구해야 함
- 완료 보고 시 변경 파일 목록과 실재 증명을 포함하도록 지시할 것
- 검증 비용을 줄이기 위해 보고 포맷을 사전에 지정하는 것이 중요함
「커밋했습니다」의 다음 날 아침, 리모트에 아무것도 없었다
Claude Code(이하 CC)에게 구현을 맡기고, 밤에 「구현 및 커밋을 완료했습니다」라는 보고를 받았다. 다음 날 아침 머지(Merge)하려고 리모트(Remote)를 확인하니, 브랜치(Branch)가 존재하지 않는다.
로컬(Local)에서 git branch -vv를 입력하면, 다음과 같이 나왔다.
* feat/xxx a1b2c3d [origin/feat/xxx: ahead 3] ...
ahead 3.
커밋(Commit)은 정말로 되어 있었다. 다만 push되지 않았다. CC가 거짓말을 한 것은 아니다. 「커밋했습니다」는 사실이었다. 하지만 내가 받고 싶었던 보고는 「리모트에 반영되어 리뷰 가능한 상태가 되었다」였으며, 양자는 별개의 것이었다.
이러한 종류의 어긋남은 한 번이 아니었다. 파일 생성을 지시하고 「작성했습니다」라는 보고를 받았지만, 실제로는 도중에 에러가 발생하여 빈 파일만 남아 있었던 적도 있다. 그래서 나는 운용 규칙을 하나 추가했다.
완료 보고에는 검증 가능한 증거를 요구한다. 「했습니다」뿐인 보고는 받지 않는다.
이 기사는 그 유형에 대해 이야기한다.
왜 발생하는가 —— 「실행했다」와 「의도한 상태가 되었다」는 별개다
이것은 CC의 결함이라기보다, 에이전트(Agent) 일반의 구조적인 특성이라고 생각한다.
에이전트의 내부에서 태스크(Task)는 「명령어를 실행하는 것」의 연쇄로서 진행된다. git commit을 실행하고 종료 코드(Exit Code) 0이 반환되면, 에이전트의 관점에서는 「커밋은 성공했다」가 된다. 거기서부터 「태스크 전체가 완료되었다」로 비약하는 것은 인간 신입 사원도 하는 실수다.
문제는, 「명령어가 성공했다」는 것과 「의도한 최종 상태가 되었다」는 것 사이에 간극이 있다는 점이다.
git commit의 성공 ≠ 리모트에 반영되어 있음- 파일 쓰기 명령어의 성공 ≠ 의도한 내용으로 작성됨
- 테스트 명령어의 실행 ≠ 모든 테스트가 pass함 (실행 자체는 실패한 테스트가 있어도 「성공」함)
그리고 검증은 비용이다. 최종 상태를 확인하려면 추가적인 명령어 실행과 출력값의 독해가 필요하다. 요구되지 않으면, 생략하는 방향으로 기울어진다. 인간 조직에서 보고 포맷이나 검수 프로세스가 발명된 것과 같은 이유로, 에이전트 운용에도 검수 유형이 필요하다.
유형: 완료 보고 포맷을 지시에 포함하기
대책은 심플하다. 태스크를 넘기는 시점에 완료 보고의 형식을 지정한다. 내가 사용하고 있는 것은 다음 유형이다.
## 완료 보고 형식(필수)
이하 내용을 보고에 포함할 것. 「완료했습니다」뿐인 보고는 받지 않는다.
1. 변경 파일 목록: `git status --short`의 출력을 붙여넣기
...
포인트는 보고를 에이전트의 말이 아니라 명령어 출력으로 구성하게 하는 것이다. 「push했습니다」라는 문장은 검증할 수 없지만, git branch -vv의 출력은 육안으로 검증할 수 있다. 에이전트의 자기 신고를 기계의 출력으로 대체하는 것이다.
각 항목의 의도
**1~3(git 계열)**은 서두에 언급한 사고의 재발 방지 그 자체다. 특히 git branch -vv는 「ahead가 남아 있으면 미push 상태」임을 한눈에 판정할 수 있어, push 누락 검출의 정석으로 삼고 있다. 참고로 git log 계열은 페이저(Pager)로 인해 멈출 수 있으므로, 지시 측에서 --no-pager를 붙이게 하면 안전하다.
**4(실재 증명)**는 「작성했습니다(사실은 빈 파일)」에 대한 대책이다. 경로의 실재 여부와 행수(Line count)까지 출력하게 하면, 빈 파일이나 도중에 끊긴 생성물이 그 자리에서 발각된다. 문서 생성이라면 목차 목록(grep "^#" <file>)을 출력하게 하는 것도 효과적이다. 구성이 지시대로인지까지 한 번에 검수할 수 있다.
**5(테스트)**는 「테스트를 실행했습니다」와 「테스트가 통과했습니다」를 혼동하는 것에 대한 대책이다. 수치(예: 195 passed / 0 failed)로 출력하게 한다.
**6(지시 외 사항 열거)**는 후술한다.
부수 효과: 조용한 스코프 이탈(Scope Creep)을 검출할 수 있다
항목 6 「지시 외에 수행한 것」은 당초 push 누락 방지를 위한 덤으로 넣은 것이었으나, 실제로 운용해 보니 다른 가치가 있었다.
에이전트는 선의로 지시 외의 일을 한다. 「덤으로 이 파일의 typo도 수정해 두었습니다", "관련이 있을 것 같아 설정 파일도 업데이트했습니다". 개별적으로는 친절하지만, 보고되지 않은 자율 행동은 나중에 원인 불명의 차분(Diff)으로 발견된다. 건드리지 않았으면 하는 파일이 바뀌어 있었다는 사고의 대부분은 여기서 발생한다.
열거를 의무화하면 자율 주행(Self-driving) 자체를 금지할 필요가 없어진다. 해도 좋지만 반드시 신고하라——이런 형식을 취하면, 에이전트의 기동력을 죽이지 않으면서 PO(Product Owner) 측의 파악만을 담보할 수 있다. 신고 내용을 보고 "그것은 되돌려 놓으라"고 말하면 그만이다.
요약: 검수의 형식을 한 번 만들어두면 자산이 된다
- 에이전트의 "했습니다"는 "커맨드(Command)를 실행했다"는 의미이지, "의도한 상태가 되었다"는 보증이 아니다
- 대책은 태스크(Task)를 전달하는 시점에 완료 보고 포맷을 지정하는 것
- 보고는 자기 신고 문장이 아니라, 커맨드 출력(git status / git branch -vv / ls / 테스트 수치)으로 구성하게 한다
- "지시 외에 수행한 일"의 열거를 의무화하면, 자율 주행의 파악과 스코프(Scope) 관리를 양립할 수 있다
이 보고 포맷 자체는 복사해서 재사용할 수 있다. 한 번 만들어두면 이후의 모든 태스크 지시에 붙여넣는 것만으로 검수 비용이 낮아진다——실패를 형식(Pattern)으로 변환하여 재사용한다는 발상이다.
나는 이 "형식화"를 검수 이외에도 확장하여, 설계·구현·검수의 세 역할을 혼자서 수행하는 체제로 운용하고 있다. 그 전체상은 책에 정리했다: 혼자서 세 역할을 수행하기 (제1장 무료)
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기