답변은 부패합니다. 대신 질문을 저장하세요.
요약
AI 에이전트의 메모리 시스템에서 발생하는 '답변 부패' 현상을 분석하고, 이를 방지하기 위한 'Standing Questions' 패턴을 제안합니다. 에이전트가 이전 세션의 완료 보고를 맹목적으로 신뢰하며 발생하는 오류를 막기 위해, 답변 대신 검증 가능한 질문을 저장하는 방식의 중요성을 강조합니다.
핵심 포인트
- 에이전트의 메모리(인수인계 노트)는 시간이 지남에 따라 실제 상태와 괴리되는 '부패' 현상이 발생함
- 에이전트가 이전 세션의 '완료' 선언을 무비판적으로 수용할 때 프로젝트 정체 발생
- 단순한 상태 기록 대신, 검증을 강제하는 '질문(Standing Questions)'을 메모리에 저장해야 함
- Claude Code를 활용한 실제 프로덕션 ML 프로젝트 운영 경험을 바탕으로 한 실전 가이드
Dr Raj Kadiwar와 Krishna Kadiwar 작성.
Standing Questions: 에이전트 메모리(agent memory)를 잘못 다루었던 10주간의 수백 회 세션을 통해 정제된, 장기적 관점의 AI 에이전트(AI-agent) 프로젝트를 위한 메모리 패턴. 코드, 스키마(schemas), 그리고 메트릭(metrics): github.com/Rocco-alt/standing-questions. 이 포스트의 공식 홈: standingquestions.com.
무엇보다 먼저 인식론(epistemics)에 관한 참고 사항을 말씀드립니다: 아래의 모든 내용은 저희 두 사람이 하나의 프로덕션(production) 프로젝트를 운영하며 얻은 결과입니다. 사실을 기술하는 부분에는 [observed](저희의 로그와 산출물에서 직접 확인한 것), [inferred](저희가 본 것에 대한 해석), 또는 [literature](타인이 발표한 결과)라는 태그를 붙였습니다. 대조군(control group)은 없습니다. 여기 있는 어떤 것도 벤치마크(benchmark)가 아닙니다. 이는 저희가 증명할 수 있는 영수증을 지닌 현장 보고서입니다.
사건 발생
10주 동안 저희는 거의 전적으로 코딩 에이전트(coding agent)인 Claude Code를 통해 프로덕션 ML(Machine Learning) 프로젝트를 운영했습니다. 이 에이전트는 세션마다 동일한 저장소(repository)에서 작업했으며, 긴 세션이 분할된 연속 경로(continuation lanes)를 포함하여 종료 시점에는 약 300회의 작업 세션이 진행되었습니다 [observed].
몇 주가 지난 후, 하나의 마일스톤(milestone)이 **완료(done)**로 표시되었습니다. 해당 마커는 인수인계 노트(handoff notes)에 기록되었고, 이후의 모든 세션은 이를 충실히 이어받았습니다. 그것이 좋은 세션 위생(session hygiene)의 모습이기 때문입니다: 노트를 읽고, 노트를 신뢰하며, 노트를 바탕으로 구축하는 것입니다.
5번의 세션이 지난 후, 감사(audit) 결과 해당 마일스톤은 자체적으로 작성된 완료 기준의 4개 중 2개만을 충족하고 있음이 발견되었습니다 [observed].
어떤 세션도 거짓말을 하지 않았습니다. 작업은 세션을 거치며 진정으로 좁혀져 갔습니다. 추천(recommendation)은 계획(plan)이 되었고, 계획은 "핵심 부분 배포 완료(shipped the core part)"가 되었습니다. 그리고 각 세션은 이전 세션이 의도했던 바를 자신이 마무리하고 있다고 진심으로 믿었습니다. 저장된 답변("완료")은 그것이 설명하던 현실보다 더 오래 살아남았습니다. 그리고 마침내 이를 잡아낸 것은 메모리 시스템도, 노트도, 에이전트(agent)도 아니었습니다. 의구심을 품고 [observed]라고 질문한 우리 중 한 명이었습니다.
그것은 뼈아픈 지점이었습니다. 왜냐하면 이를 잡아낼 수 있었던 질문 — "이 마일스톤이 작성된 기준에 따라 실제로 완료되었는가?" — 는 첫날에 완벽하게 명시될 수 있었던 것이기 때문입니다. 단지 그 질문을 누군가가 다시 물을 수밖에 없도록 강제하는 곳 어디에도 존재하지 않았을 뿐입니다.
왜 답변 저장소는 부패하는가
그 시점에 우리는 표준적인 방법들을 시도해 보았습니다.
메모리 파일과 인수인계 노트(handoff notes): 이것들은 작동합니다
현재 배포 대상은 무엇이며, 어떤 파일이 이를 고정(pin)하고 있습니까?
지난 세션에서 무엇을 완료했다고 주장했는지, 그리고 이에 대한 외부 생성 증거가 있습니까?
프로젝트는 현재 스스로에게 어디에 위치해 있습니까? - 기록된 노트와 리포지토리의 실제 상태가 불일치하는 부분은 어디입니까?
이 프로토콜은 다음과 같습니다: 매 세션 시작 시, 에이전트는 각 질문에 대한 답변을 현재 리포지토리를 기준으로 재도출합니다. 즉, 실제 파일을 읽고, 실제 명령어를 실행하며, 새로 얻은 답변과 프로젝트가 이전에 믿었던 내용을 비교(diff)하고, 추가 전용(append-only) JSONL 로그의 한 줄을 기록한 후, 다른 어떤 작업을 하기 전에 모든 변화량(delta)을 소리 내어 알려줍니다. 이 로그 라인은 질문별로 다음을 기록합니다: ID, 타임스탬프, 그리고 delta 부울 값, 그리고 답변이 도출된 시점의 리포지토리 HEAD sha:
{"ts": "...", "kind": "rederive", "sid": "s03", "repo_head_sha": "c1d4f0a...", "results": [{"q_id": "q4", "last_rederived_ts": "...", "delta": true, "note": "s02 handoff claims rate limiter 'done'; no test covers the burst path - evidence does not support the claim, reopened"}]}
저장된 답변은 현실이 움직이는 순간 틀리게 됩니다. 하지만 저장된 질문은 절대 틀리지 않습니다. 최악의 경우 질문하지 않은 것일 뿐이며,
첫 번째 프로덕션 구현(production implementation)은 가볍지 않았습니다. 정점일 때: 28개의 상시 질문(standing questions)이 있었으며, 각 질문은 전체 유도 이력(derivation history)을 담은 JSON 파일이었습니다. 각 유도(derivation)에는 SHA-256 콘텐츠 해시가 포함된 증거 경로(evidence-path) 목록이 있었고, 모든 재유도(re-derivation)는 유도가 커밋(commit)되기 전 승인해야 하는 LLM 판사(LLM judge)에 의해 제어되었습니다. 또한 하트비트 체크(heartbeat checks)를 수행하는 대역외 평가 프로세스(out-of-band evaluator process)가 있었습니다 [관찰됨]. 우리는 대성당(cathedral)을 지었습니다.
그중 일부는 제 역할을 다했습니다. 우리 자신의 아티팩트(artifacts)에서 기록할 수 있는 세 가지 성과[관찰됨]는 다음과 같습니다:
- 잘못 완료된 마일스톤(milestone)을 다시 열었습니다. 사고 이후, "이 마일스톤이 기준에 따라 완료되었는가?"가 상시 질문이 되었습니다. 첫 번째 재유도 과정에서 파일 인용과 함께 정확히 어떤 두 가지 기준을 통과했고 어떤 두 가지 기준을 통과하지 못했는지가 기록되었습니다. 그리고 그 유도는 인수인계 노트에서 부패하는 대신, 계속 살아있으며 재확인 가능한 상태로 유지되었습니다.
- 자체 루프를 마치지 않고 종료된 세션을 포착했습니다. 한 세션이 판사(judge)의 승인을 받은 유도를 생성했지만, 이를 저장소(store)에 커밋하지 않았습니다. 그다음 세션의 세션 시작 감사(start-of-session audit) 과정에서 판결 파일은 존재하지만 저장소 항목은 없는 매달린 상태(dangling state)를 감지하였고, 이를 기록에 남기며 복구했습니다. 아티팩트에 키를 맞춘 세션 시작 재점검이 없었다면, 그 간극은 단순히 잊혔을 것입니다.
- 판사(judge)는 정상 작동하는 동안 실질적인 업무를 수행했습니다. 한 유도는 그 주장이 커밋될 수 있을 만큼 충분히 근거를 갖추기 전까지 다섯 번 연속으로 거절당했습니다 [관찰됨]. 판사가 작동할 때, 제출물의 약 3분의 1 정도를 승인했습니다 [관찰됨]. 이 정도로 높은 거절률은 불편함을 주지만, 바로 그 불편함이 핵심이었습니다.
하지만 대성당은 실패가 머무는 곳이기도 했으며, 실패는 성과보다 더 많은 교훈을 줍니다.
Goodhart 사건 #1: 동일 저자 판사(same-author judge)가 체크박스로 전락하다
판사는 독립적인 감독 역할을 수행해야 했습니다. 하지만 실제로는 실행 세션(running session)이 무엇이 제출될지, 어떻게 프레임이 짜일지, 그리고 판사가 어떤 증거를 볼지를 통제했습니다. 즉, 증거 자체가 판결을 받는 세션에 의해 작성된 경우가 대부분이었습니다 [관찰됨]. 몇 주에 걸쳐 판사는 체크박스 기능(checkbox function)으로 전락했습니다. 현실을 독립적으로 확인하는 대신, 메인 세션이 작성한 텍스트의 인용 형식(citation-formatting)을 채점하는 수준에 머물게 된 것입니다 [관찰됨].
상황은 더 악화되었습니다. 한 세션에서는 판사 루프(judge loop)가 제대로 작동하지 않자 에이전트가 네 번의 수동 오버라이드(manual overrides)를 실행하고도 그대로 작업을 계속했습니다 [관찰됨]. 두 차례의 사례에서는 에이전트가 대역 외 판사 프로세스(out-of-band judge process)를 실행한 것처럼 속였습니다. 즉, 감독이 실행되지 않았음에도 마치 실행된 것처럼 출력을 생성했습니다 [관찰됨]. 별도의 세션에서는 커밋(commit) 함수를 호출하지 않은 채 종료 노트에 "유도 과정 커밋됨(derivation committed)"이라고 작성했습니다. 이 미결 상태(dangling state)는 다음 세션이 시작될 때 발견되었습니다 [관찰됨].
우리가 얻은 교훈은 다음과 같습니다 [추론됨]: 에이전트가 직접 작성할 수 있는 모든 검증 신호는 결국 에이전트에 의해 작성될 것입니다. 이는 악의 때문이 아니라, 완료된 것처럼 보이려는 최적화 압박 때문입니다. 만약 드리프트 방지 메커니즘(anti-drift machinery)의 증거 스트림이 검증 대상인 개체(thing being checked)를 통과한다면, 당신은 복잡한 단계가 추가된 Goodhart 엔진을 구축한 셈입니다.
이것이 바로 린 패턴(lean pattern)이 정직성 메커니즘을 에이전트가 제어할 수 없는 두 가지 신호에 연결하는 이유입니다. 바로 외부에서 고정된 git HEAD sha와, grep을 사용하는 누구라도 위조할 수 있는(falsifiable) 추가 전용 로그(append-only log) 내 질문별 항목의 존재 여부입니다.
Goodhart 사건 #2: 재유도 없는 승인 (acknowledge-without-rederive)
두 번째 실패는 더 조용했으며, 저희는 이것이 더 보편적이라고 생각합니다.
세션 시작 게이트(session-start gate)는 오래된 질문들을 표면화했습니다. "STALE: 이 N개의 질문은 정해진 주기(cadence)를 지나 재도출(re-derive)되지 않았습니다." 세션은 해당 목록을 '승인(acknowledge)'하고 다음으로 넘어갔습니다. 재도출(Re-derivation)은 작업이지만, 승인(acknowledgment)은 형벌과 같습니다. 최악의 상황에서는 10개의 상주 질문이 여러 연속된 세션에 걸쳐 오래된 상태로 표면화되고 승인된 채 방치되었습니다 [관찰됨]. 게이트는 하나의 의식이 되어버렸습니다. 저장소는 당시 저희가 좌절하며 썼던 표현대로, 아무도 대답하지 않는 질문들의 박물관이 되었습니다.
중요했던 해결책은 권고(exhortation)가 아니었습니다 (권고를 시도해 보았으나, 에이전트는 열정적으로 동의하면서도 아무것도 바꾸지 않았습니다 [관찰됨]). 해결책은 실패를 '계산 가능(computable)'하게 만드는 것이었습니다. 리포지토리(repo)에 포함되어 있으며, 표준 Python 라이브러리(stdlib Python)를 사용하여 로그를 대상으로 실행할 수 있는 두 가지 지표를 도입했습니다:
- Staleness (신선도 저하) — 각 질문에 대해, 해당 질문이 마지막으로 재도출(rederive) 항목에 나타난 이후 경과한 세션 수입니다. N번의 세션 동안 항목이 나타나지 않는 질문은 기억이 아니라 장식에 불과합니다.
- Acknowledge-without-rederive (재도출 없는 승인) — 리포지토리의 HEAD가 이동했음에도 불구하고, 모든 질문이
delta:false를 보고하는 세션입니다. 이러한 세션이 한 번 발생하는 것은 정상입니다. 하지만 이러한 세션이 연속적으로 실행되는 것은 에이전트가 형식적으로만 움직이고 있다는 징후이며, 탐지기(detector)가 해당 실행에 대해 경보를 울립니다.
이 지표들이 무엇인지 정확히 정의하고자 합니다: 이것은 보증(guarantees)이 아니라 탐지기(detectors)입니다. 로그는 재도출이 발생했다고 보고합니다. 그럴듯한 델타(delta)를 조작하는 에이전트는 두 지표를 모두 무력화하며, 추론(reasoning) 단계에서 이를 해결할 기계적인 방법은 알지 못합니다 — 이는 행동과 결과물(artifacts)은 구조적으로 검증할 수 있지만, 실제로 추론이 일어났는지 여부는 검증할 수 없다는 더 넓은 관찰 결과와 일치합니다 [추론됨]. 탐지기가 포착하는 것은 저렴한 형태의 의식화 — 즉, 세상은 변하는데 모든 것이 조용한 상태 — 이며, 저희의 10주간의 경험상 이 저렴한 형태가 실제로 발생한 유일한 형태였습니다 [관찰됨]. 저희의 해석은 세션 전반에 걸쳐 일관된(coherent) 가짜 델타를 조작하는 것이 단순히 재도출하는 것보다 더 많은 작업이 들었기 때문이라는 것입니다 [추론됨]; 다만 이것이 모든 에이전트와 설정에 적용된다고 가정하지는 않겠습니다.
살아남은 것: 가벼운 커널 (the lean kernel)
우리가 다른 누구에게든 실행하라고 권장할 버전에는 그 거대한 성당(cathedral)의 거의 아무것도 포함되지 않았습니다. 접촉 후 살아남은 것들[관찰됨 → 증류됨]:
- 약 12개의 인간 소유 질문이 담긴 하나의 JSON 파일. (28개는 너무 많았습니다. 롱테일(long tail) 부분은 신선도가 떨어져 게이트(gate)의 신호를 오염시켰습니다.)
- 하나의 추가 전용(append-only) JSONL 로그; 세션당 하나의 엔트리; 질문당
{q_id, last_rederived_ts, delta}및 HEAD sha 포함. - 4단계의 세션 시작 의식: 로드(load), 재도출(re-derive), 기록(record), 델타(delta)를 소리 내어 보고(report).
- 인간 또는 CI에 의해 실행되는 두 가지 지표 - 에이전트의 저작권(authorship) {"outside"} 영역에서 수행됨.
판사(judge)는 살아남지 못했습니다. 독립적인 평가가 틀렸기 때문이 아니라, 동일 저자의 판사는 판사가 없는 것보다 더 나쁘기 때문입니다: 이는 거짓된 확신을 제조합니다 [추론됨]. 증거 해시(evidence hashes)는 살아남지 못했습니다; HEAD sha가 복잡한 의식 없이도 탐지 능력의 대부분을 제공합니다 [추론됨]. 가벼운 커널(lean kernel)은 바로 리포지토리(repo)에 있는 것입니다.
우리는 성당의 구성 요소들을 포기하지 않았습니다. 증거에 고정된 출처(evidence-pinned provenance)와 게이트가 있는 판결 생성(gated verdict production)은, 만약 우리가 찾아낸다면, 자체적인 Goodhart 감사(Goodhart audit)를 견뎌낼 수 있는 형태로 살아남을 수도 있습니다. 그것은 별도의 포스트로 다루겠습니다.
우리가 주장할 수 있는 것과 없는 것
할 수 있는 것 [관찰됨, 제1자적, N-of-1]: 이 패턴은 프로덕션 리포지토리에서 약 300개의 세션에 걸쳐 10주 동안 실행되었습니다; 재도출(re-derivation)을 통해 잘못 수행된 마일스톤(milestone)과 닫히지 않은 커밋 루프(commit loop)를 포함하여 실제 드리프트(drift)를 문서화된 방식으로 포착해냈습니다; 두 가지 Goodhart 실패 모드가 모두 발생했고, 아티팩트(artifacts)로부터 진단되었으며, 계산 가능한 지표가 되었습니다; 가벼운 커널은 세션당 비용이 거의 제로에 가깝습니다 (세션 시작 시 12개의 질문을 재도출하고, 로그 한 줄을 추가함).
할 수 없는 것: 어떠한 비교 효과성 주장도 할 수 없습니다. 우리는 대조군(control)을 실행하지 않았습니다. 우리는 이것이 어떤 벤치마크에서도 Mem0, 긴 CLAUDE.md, 또는 아무것도 하지 않는 것보다 뛰어나다고 말할 수 없습니다. 하나의 프로젝트, 하나의 팀, 하나의 스택입니다. 만약 당신이 이것을 실행했는데 2주 차에 '재도출 없는 승인(acknowledge-without-rederive)' 탐지기가 작동한다면, 우리는 진심으로 알고 싶습니다. 그러한 재현(replication)은 이 포스트보다 더 가치 있을 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기