작동하지 않았는데 「작동했다」고 보고했던 이야기
AMA-teras는 대화하며 계획 → 구현 → 디버그 → 테스트를 진행하고, 부족한 기능을 발견하면 스스로 도구를 생성하여 도입하는 (자기 진화하는) 데스크톱 AI 코딩 에이전트(AI coding agent)입니다. 이 기사는 AMA-teras가 작동하지 않았는데 「작동했다」고 보고했던 실화와, 그것을 어떻게 수정했는지에 대한 기록입니다.
403을 무시하고 있던 코드
문제가 발생한 것은 외부로의 게시 처리였습니다. 게시 API가 403을 반환하고 있음에도 불구하고, 코드는 해당 에러를 무시(swallow)해 버렸고, 처리 전체는 성공으로 취급되었습니다. 결과적으로 보고는 "게시했습니다"라고 나왔지만, 실제로는 아무것도 게시되지 않았습니다.
도식화하면 다음과 같은 구조였습니다.
// 수정 전(도식화): 실패해도 성공으로 보고됨
try {
await postToExternal(payload);
...
에이전트 본인에게 악의는 없습니다. "게시 처리를 호출했다"는 것과 "게시가 성립되었다"는 것을 구분하지 않는 코드를 작성해 버리면, 보고는 자동으로 거짓말이 됩니다.
깨닫게 된 계기와 실기에서의 확인
계기는 보고와 실제 결과물을 대조해 본 것이었습니다. "게시했습니다"라는 보고에 대해 게시 대상을 실기(actual device)에서 확인한 결과, 게시물이 존재하지 않았습니다. 로그를 거슬러 올라가 보니 403이 반환되어 있었습니다.
"테스트가 통과했다", "에러가 나오지 않았다"가 아니라, 실기에서 결과물 그 자체를 확인하는 것. 이 프로젝트에서는 실기 스모크 테스트(smoke test)를 검증의 한 단계로 반드시 포함하고 있지만, 이번 건은 "실기에서 확인하지 않으면 거짓말을 알아챌 수 없다"는 것을 스스로에게 각인시킨 사례가 되었습니다.
수정 방법: 「냈다」와 「낼 준비가 되었다」를 분리하기
수정의 본질은 상태의 어휘를 분리하는 것이었습니다.
「냈다」: API가 성공 응답(success response)을 반환한 사실이 있는 경우에만 -
「낼 준비가 되었다」: 페이로드(payload)의 생성·검증까지는 완료되었으나, 전송은 성립되지 않은 경우 - 그 외에는 에러로서 그대로 밖으로 드러냄(무시하지 않음)
"성공"이라는 한 단어에 두 가지를 모두 밀어 넣었던 것이 원흉입니다. 준비 완료를 성공이라고 보고하는 경로를 차단하고, 에러 응답(error response)은 호출 측까지 반드시 전달되도록 했습니다.
자기 진화는 worktree 안에서만 일어난다
"AI가 스스로 도구를 생성하여 도입한다"라고 하면 불안하게 느껴질 것입니다. 위의 403 건과 같은 거짓말이 본체에 섞여 버리면 끝이기 때문입니다. 그래서 AMA-teras의 자기 진화는 구조적으로 격리되어 있습니다.
검증 게이트(typecheck · 테스트 · 실기 스모크)를 통과하지 않으면 승격되지 않는다
생성물은 본체의 트리가 아니라, 격리된 git worktree 안에 만들어집니다. 그리고 본체로의 승격 후보가 되기 위해서는 다음을 통과해야 합니다.
- typecheck
- 테스트
- 실기 구동 스모크 테스트
Discussion