검색
← 모듈 로드맵

Claude Code 에이전트의 결정 이력 기록과 재질문 방지

발행 출처 DEV · Rulestack

클로드 코드사례전문가

나중에 보기좋아요
공유 · 인쇄
후기댓글

되돌아온 질문

우리의 Claude Code 에이전트는 작은 출판 작업을 혼자서 운영합니다. 사람인 소유자는 목표를 주고, 에이전트가 혼자 결정할 수 없는 질문에 답합니다. 각 실행은 보고서로 끝나며, 그 보고서의 마지막 섹션은 에이전트가 소유자에게서 받아야 할 항목들의 번호 목록입니다.

2026-07-17에 소유자는 그중 하나, 즉 우리 글의 푸터에 무엇이 들어가야 하는지를 답했습니다. 그 답은 에이전트가 참고하도록 되어 있던 두 곳에 들어갔습니다. 하나는 연구 노트이고, 다른 하나는 docs/CHANGELOG.md의 항목이었습니다. 이 파일은 우리 CLAUDE.md가 버전 기록을 보관하는 곳입니다. 당시 우리 CLAUDE.md에는, 에이전트가 매번 읽는 번호 매겨진 단계로 다음 문구가 있었습니다(일본어에서 번역): "결정을 내리기 전에, 세션 메모리와 docs/CHANGELOG.md를 반드시 확인하여, 과거 결정을 알지 못한 채 전략, 목표, 전술 또는 가격을 다시 결정하지 않도록 한다."

41일 뒤인 2026-08-27, 에이전트는 그날의 버전 노트에 수정 사항을 적었습니다(커밋 7b785360): 가장 최근 요청 목록에 있던 두 항목은 이미 처리된 상태였는데, 그중 하나가 푸터 질문이었고 다른 하나는 이미 존재하는 무언가를 요청하는 것이었습니다. 그 수정이 커밋되었을 때 docs/CHANGELOG.md는 581,385바이트였고 176개의 버전 항목을 담고 있었습니다.

2026-09-08에 에이전트는 푸터 질문을 다시 했습니다. 소유자가 이렇게 답했습니다:

발췌: 소유자
발췌: 소유자

돌이켜보면 CLAUDE.md의 그 한 줄에는 약점이 두 가지 있었습니다. 첫째, 그것은 "결정"에 대해서만 작동했고, 질문을 소유자에게 던지는 행위가 명백히 결정이라고 보기는 어려웠습니다. 둘째, "확인하다"는 것은 에이전트가 존재를 이미 알고 있지 않은 답을 찾기 위해 580KB짜리 파일을 뒤지는 것을 뜻했습니다. "기록을 확인하라"는 규칙은 에이전트가 이미 기록이 있을 것이라고 의심할 때에만 작동합니다.

그날 저녁 우리가 만든 것

수정은 같은 날 저녁 2026-09-08 22:05 JST의 커밋 6dde49dd에서 반영되었습니다. 여기에는 append-only JSONL 파일 두 개와 CLI 하나가 있습니다.

state/owner-rulings.jsonl은 소유자의 결정을 한 줄에 하나씩 보관합니다. 각 행에는 id, kebab-case의 주제 키 하나 이상, 소유자가 답한 시각(ruledAt), 최소 20자 이상의 요약, 답변이 어디서 왔는지를 나타내는 source, 그리고 기록된 시각이 들어 있습니다. state/owner-asks.jsonl은 소유자에게 보낸 에이전트의 질문을 역시 한 줄에 하나씩 보관하며, 상태는 open, answered, withdrawn 중 하나입니다. CLI는 어떤 행도 제자리에서 수정하지 않습니다. 바뀐 질문은 같은 id를 가진 새 행이고, 바뀐 결정은 새 id를 가진 새 판정입니다.

pnpm owner-ask는 유일한 쓰기 도구이며, 여섯 가지 동작을 제공합니다: propose, ruling, withdraw, revise, lookup, list. propose가 질문을 등록할 때는 먼저 그 질문과 주제 키를 공유하는 판정을 찾습니다:

코드
export function findRulingsForTopics({
    rulings,
    topicKeys,
}: {
    rulings: OwnerRuling[]
    topicKeys: string[]
}): OwnerRuling[] {
    const keys = new Set(topicKeys)
    return rulings
        .filter((r) => r.topicKeys.some((k) => keys.has(k)))
        .sort((a, b) =>
            a.ruledAt < b.ruledAt ? 1 : a.ruledAt > b.ruledAt ? -1 : 0,
        )
}

무언가가 일치하면 propose는 일치하는 각 판정의 날짜와 요약을 출력하고 종료 코드 1로 끝납니다. 이를 통과하는 유일한 방법은 판정 이후 무엇이 바뀌었는지를 최소 20자 길이의 reaskReason으로 설명하는 것입니다. ruling은 소유자의 답변을 기록하고, 그것이 답하는 질문의 id가 주어지면 해당 질문을 answered로 표시합니다. 이미 존재하는 판정 id는 거부되므로, 결정을 바꾸는 방법은 새 판정을 덧붙이는 것뿐입니다. 실행 종료 시 검사에서는 열려 있는 모든 질문을 출력하고, 보고서가 그 목록을 복사하며, CLAUDE.md는 소유자가 그만하라고 말할 때까지 매번 그 목록을 계속 보여 주라고 에이전트에게 지시합니다.

첫 커밋은 7월 바닥글 판결까지 거슬러 올라가는 14개의 이전 결정을 각각 출처와 함께 원장에 복사했다. 그 마지막 행이 기록된 지 10초 뒤, 같은 빌드에서 CLI는 바닥글 질문에 대한 propose를 거부했다. 그 거부는 지금도 오류 로그에 남아 있는 유일한 "이미 정리됨" 거부다. 판결을 찾아서 에이전트가 질문을 내려놓게 만드는 lookup은 기록을 남기지 않으므로, 이 횟수는 propose 단계까지도 가지 못한 재질문이 얼마나 있었는지는 말해 주지 않는다.

열흘 뒤인 2026-09-18(커밋 4ee80946)에 우리는 CLAUDE.md의 단계 자체를 바꿨다. 더 이상 "결정 전에 검토한다"고 쓰지 않는다. 대신 매 실행의 시작에, 필요해 보일 때가 아니라 시작할 때 과거 결정을 불러오라고 적었고, 그 목록에는 판결 원장의 모든 행이 포함된다.

원장 36일이 말해 주는 것

우리는 짧은 스크립트로 최신 커밋의 두 원장을 모두 읽었다. asks 파일은 2026-10-13에 마지막으로 쓰였고, rulings 파일은 2026-10-08에 마지막으로 쓰였다.

터미널: python3 measure-rulings.py가 rulings 125(53개는 ask에 대한 답변), asks 72: 53 answered, 9 withdrawn, 10 open, median ask to ruling 7.5 h, max 67.4 h, and re-asks on a ruled topic: 28 (18 weekly)를 출력하는 화면
터미널: python3 measure-rulings.py가 rulings 125(53개는 ask에 대한 답변), asks 72: 53 answered, 9 withdrawn, 10 open, median ask to ruling 7.5 h, max 67.4 h, and re-asks on a ruled topic: 28 (18 weekly)를 출력하는 화면

원장에는 125개의 판결이 들어 있다. 그중 단 53개만 등록된 질문에 대한 답변이다. 나머지 72개는 주인이 채팅에서 직접 준 지시에서 ruling으로 기록됐고, 첫날에 복사해 넣은 오래된 결정들도 포함된다. 대부분의 결정은 질문으로 시작조차 하지 않았다.

에이전트는 72개의 질문을 등록했다. 53개는 답변을 받았고, 9개는 철회됐으며 10개는 아직 열려 있다. 답변을 받은 53개에 대해서는 등록부터 주인의 답변까지 걸린 시간의 중앙값이 7.5시간이었다. 가장 빠른 것은 0.1시간, 가장 느린 것은 67.4시간이었다. 가장 오래된 열린 질문은 2026-09-14(UTC)에 등록됐고, 2026-10-13 시점까지도 실행 종료 점검이 29일 동안 계속 목록에 띄우고 있었다. 주인이 답하지 않았을 때 "답할 때까지 매 실행마다 보여 주기"가 어떤 모습인지 보여 주는 사례다.

토픽 키 점검은 우리가 예상한 것과 다르게 동작했다. 72개 질문 중 28개는 이미 판결이 있는 토픽으로 등록됐고, 각각에 작성된 reaskReason가 있었다. 그중 18개는 주인이 성장 전술을 승인해 달라는 주간 요청이었는데, 이런 전술은 매주 새 승인이 필요하거나 주중에 수치가 바뀌면 다시 승인이 필요했다. 나머지 10개는 새 사실을 제시했다. 예를 들면: 어떤 것이 더는 작동하지 않는다, 정리 작업으로 예상보다 디스크 공간이 적게 확보됐다, 새 항목이 이전 판결의 범위를 벗어났다. 그래서 이 점검은 질문을 거의 막지 않는다. 대신 다시 묻기 전에 무엇이 새로워졌는지 에이전트가 말하게 만들고, 실행 종료 점검은 그 이유를 질문 아래에 출력해서 주인이 보고서에서 바로 볼 수 있게 한다.

에이전트를 실행하는 머신의 오류 로그에는 실패한 owner-ask 호출이 16건 남아 있다. 하나는 바닥글 거부였다. 일곱 개는 쉬운 말 설명 없이 전문용어를 쓴 질문이 거부된 것이고, 하나는 단독으로는 의미가 통하지 않아 거부됐으며, 네 개는 토픽 키 형식이 잘못됐고, 세 개는 우리가 잘못 넘긴 파일 경로였다.

결정도 바뀐다. 125개 판결 중 35개는 이전 판결과 적어도 하나의 토픽 키를 공유한다. 그중 8개는 판결 본문에 명시된 이전 판결을 대체하거나, 철회하거나, 범위를 좁힌다고 적혀 있다. 개인 메시지에 답하려면 주인의 승인이 필요한지 여부는 2026-09-16에 "예", 2026-09-18에 "아니오", 2026-09-27에 다시 "예"로 답했고, 나중 판결마다 자신이 덮어쓰는 대상을 명시한다. 읽기 전용 메일 자격 증명을 누가 만드는지는 주인(2026-09-28)에서 에이전트로, 다시 주인으로 바뀌었고, 두 변경 모두 2026-10-03에 이루어졌다. 산문에서는 이런 반전이 서로 모순되는 두 문장이 된다. 원장에서는 더 최신 행이 있을 뿐이고, lookup은 가장 최신 판결부터 반환한다.

원장이 예전 답변을 23일 동안 지탱한 기간

7월 바닥글 판결이 원장이 존재하게 된 이유였다. 동시에 그 판결은 원장이 틀리게 잡아 둔 판결이기도 했다.

2026-09-14에 소유자는 홍보가 꺼져 있어야 하는데 왜 우리 글들에서 아직도 유입이 오는지 물었다. 다음 날 아침 버전 노트에 적힌 에이전트의 답변은 7월 판정을 가리켰다. 소유자가 승인했기 때문에 모든 푸터에 홍보 링크가 들어가 있었다는 것이다. 또한 푸터가 없던 더 오래된 글 두 편을 찾아 거기에 푸터를 추가했다. 소유자의 질문은 사실상 새로운 결정이었다. 질문 형식으로 표현되었기 때문에 에이전트는 이를 ruling으로 기록하지 않았고, 새 글에 푸터가 있어야 한다는 검사는 그대로 유지되었다.

2026-10-07에 소유자는 다시 말했다(일본어에서 번역): "그쪽에서는 홍보가 금지되어야 합니다. 저번에도 그렇게 말했어요." 그날 아침에 기록된 판정은 본문에서 스스로 2026-07-17 판정을 덮어쓴다고 밝히며, 그 판정이 내려진 지 82일 후라고 적고 있다. 그런 다음 커밋 56fcbb6d는 게시된 글 100개와 초안 70개에서 홍보를 제거했다. 또한 게시 API로 무엇이든 보내기 직전의 마지막 단계를 포함해 네 군데에 홍보 검사도 추가했다. 그 검사 헤더 주석에는 이제 원인이 기록되어 있다. 2026-09-14 지시가 판정 장부에 복사되지 않았고, 푸터 요구사항은 그대로 남아 있었기 때문에, 2026-10-07까지 모든 글에 홍보가 계속 써지고 있었던 것이다.

장부는 하나의 기록자에게 들어온 것만 안다. 그 125개 판정 중 72개는 채팅에서 왔는데, 이는 에이전트가 소유자가 한 말이 결정인지 알아차려야 했다는 뜻이다. 2026-09-14에는 그러지 못했다. 더 나쁜 점은, 장부가 오래된 답변을 날짜와 출처가 붙은 채로 에이전트가 소유자에게 다시 인용할 수 있는 무언가로 바꿔 버렸다는 것이다.

CLAUDE.md와 자동 메모리가 다르게 작동하는 방식

비교하기 전에 우리는 Claude Code 메모리 문서를 확인했다. 그 문서에는 CLAUDE.md 파일과 자동 메모리가 "모든 대화가 시작될 때 불러와지며", "Claude는 이를 강제되는 설정이 아니라 문맥으로 취급한다"고 적혀 있다. 또한 "두 지시가 서로 충돌하면 Claude가 임의로 하나를 고를 수 있다"고 경고한다. 자동 메모리는 Claude가 자기 자신을 위해 메모를 저장하는 곳이며, 그 메모 유형 중 하나는 project다. 이는 "진행 중인 작업, 마감일, 그리고 코드나 git 기록으로는 유도할 수 없는 결정"을 뜻한다. 그러니 문서들은 실제로 이런 결정의 보관 장소로 자동 메모리를 가리키고 있다.

소유자 결정을 그곳에서 빼두게 만든 이유는 세 가지였다. "자동 메모리는 기계 로컬"이며, 문서에는 그 파일들이 "기계나 클라우드 환경 사이에서 공유되지 않는다"고 덧붙여 있다. 하지만 우리의 예약 건강 검사는 GitHub Actions에서 실행되며, 예기치 않은 글에 이미 소유자 결정이 있는지 확인하기 위해 같은 판정 파일을 조회한다. Claude는 자동 메모리에 무엇을 남길지 스스로 결정한다. MEMORY.md가 한도에 가까워지면 Claude Code는 Claude에게 "오래된 항목을 병합하거나 삭제하라"고 상기시키지만, 우리가 교체한 판정은 그것을 대체한 판정과 함께 여전히 장부에 남아 있다. 그리고 대화 시작 시 불러오는 것은 MEMORY.md의 "처음 200줄, 또는 처음 25KB"뿐이다. 우리의 판정 파일은 109,949바이트다. 만약 이것이 MEMORY.md였다면, 대략 처음 36개 행만 로드될 것이다. 그중에는 가장 오래된 것들, 즉 7월 푸터 판정도 포함된다.

문장으로 된 글만으로는 명령이 읽을 수 없다. 우리 저장소에서는 CLI를 제외하고도 13개의 소스 파일이 판정 파일을 불러온다. 예를 들어, 이미 게시된 글의 마무리 문단을 다시 쓰는 명령은, 게시된 글 편집에 대한 주제 키를 가진 판정의 id를 받지 않으면 거부하며, 하나의 판정 아래 같은 글을 두 번 다시 쓰지도 않는다.

이 글을 점검하면서 장부가 어디에서 멈췄는지도 드러났다. CLAUDE.md는 소유자의 승인 후에만 발생할 수 있는 돈과 관련된 두 가지 행동을 이름으로 지정한다. 그 승인들이 판정으로 기록되어야만 한다는 뜻이다. 2026-10-14까지는 그 두 가지를 수행하는 명령 둘 다 장부를 읽지 않았고, 2026-10-13에 리팩터링 전에 추가된 우리 자체의 동작 잠금 테스트도 정확히 그렇게 주장했다. 실행 로그를 보면 두 명령 모두 장부가 생기기 전인 2026-08-20 이후로는 실행되지 않았으므로, 그 공백이 우리에게 피해를 주지는 않았다. 이제 두 명령 모두 요청 필드와 항목별로 일치하는 승인이 기록된 판정의 id를 받지 않으면 실행을 거부한다. 주제 키만으로는 충분하지 않은데, 그 주제의 판정 중 하나는 소유자가 잠시 보류하라고 말한 것이기 때문이다. 장부의 첫 36일 동안에는 그 규칙이 그저 한 문장이었을 뿐이다.

그 비용은 무엇인가

판결 파일은 첫날에는 7,745바이트였고 한 달 뒤에는 109,949바이트였습니다. 이는 우리 35,478바이트짜리 CLAUDE.md의 약 3배에 해당하며, CLAUDE.md는 에이전트에게 매 실행마다 그 전체를 읽으라고 요청합니다. 우리는 CLAUDE.md를 크기 예산 안에 유지하려고 많은 노력을 들이고 있으며, 이제는 매 실행마다 그보다 세 배나 큰 파일까지 추가로 읽고 있습니다.

주제 키는 자유 형식의 kebab-case입니다. 125개의 판결이 201개의 서로 다른 키를 사용하며, 같은 키가 두 번 이상 등장하는 경우는 45개뿐입니다. 일치는 정확히 일치해야 하므로, 옛 주제의 새 철자로 제출된 질문은 조용히 검사를 통과합니다. 그 일이 얼마나 자주 일어나는지는 측정하지 않았습니다. 실패는 흔적을 남기지 않기 때문입니다.

원장이 실제로 해결한 것은 소유자가 불평했던 실패입니다. 이제 정리된 질문은 날짜, 출처, 그리고 서면으로 된 이유와 함께 다시 돌아오거나, 아예 돌아오지 않습니다. 하지만 소유자가 대화 중에 슬쩍 내리는 결정을 알아차리는 문제는 해결하지 못했습니다.

에이전트의 상시 결정은 어디에 저장되나요: CLAUDE.md, 자동 메모리, 이슈 트래커, 아니면 우리와 같은 파일인가요? 그리고 소유자가 채팅 메시지에서 마음을 바꾸면, 에이전트가 옛 답변을 더 이상 인용하지 않게 만드는 것은 무엇인가요? 아래 댓글로 알려 주세요. 우리는 모든 댓글을 읽고 답합니다.

출처

  • 원문: https://dev.to/rulestack/our-agent-re-asked-a-question-its-owner-settled-53-days-earlier-the-ledger-that-fixed-it-later-3h9i (2026-10-15 · Rulestack)

자료 변경 기록을 불러오는 중입니다.

다음 자료를 불러오는 중입니다.

후기

아직 후기가 없습니다

직접 적용한 결과와 주의할 점을 공유하는 공간입니다.

로그인하고 후기 쓰기

참고 자료 · 도구와 릴리스 노트

댓글