나의 장기 실행 AI 에이전트가 세션 간에 기억을 유지하는 방법 — 상태 로그로서의 git history
요약
장기 실행 AI 에이전트가 세션 종료 후에도 상태를 유지하기 위해 벡터 DB 대신 git history와 상태 파일을 활용하는 효율적인 방법을 제안합니다. 에이전트가 작업 이력을 '인수인계 노트'처럼 읽게 함으로써 컨텍스트 소실 문제를 해결할 수 있습니다.
핵심 포인트
- 벡터 DB는 시맨틱 검색에는 유용하나 단순 작업 이력 유지에는 과도한 도구임
- git log를 통해 실제 발생한 변경 사항의 타임스탬프와 기록을 확보 가능
- CYCLE-STATE.md와 같은 구조화된 상태 파일을 통해 작업의 의도와 다음 단계를 기록
- 에이전트 시작 시 git log와 상태 파일을 먼저 읽는 습관이 핵심
나의 에이전트 시스템은 사이클(cycle) 단위로 작동합니다. 몇 시간 동안 작업을 수행한 뒤 프로세스가 종료되면, 비어 있는 컨텍스트 윈도우 (context window)와 함께 새로운 프로세스가 시작됩니다. 매 사이클마다 에이전트는 방금 수행한 모든 일을 잊어버립니다. 이것은 버그가 아니라, 컨텍스트 윈도우 (context window)의 본질입니다. 즉, 고정된 창일 뿐 메모리 (memory)가 아닙니다.
이 문제가 처음 나를 괴롭혔을 때, 에이전트는 이틀 전에 이미 해결했던 문제를 다시 진단했습니다. 동일한 근본 원인, 동일한 해결책, 그리고 그 결과에 도달하기 위해 동일한 파일들을 다시 읽는 데 소비된 동일한 시간. 작업 내용이 사라진 것은 아니었습니다. 그것은 바로 git 로그 (git log)에 남아 있었습니다. 단지 에이전트가 시작하기 전에 자신의 이력을 읽는 습관이 없었을 뿐입니다.
누구나 가장 먼저 떠올리는 본능
"메모리 (memory)를 부여하라"는 말은 거의 항상 "벡터 DB (vector DB)를 구축하고, 모든 것을 임베딩 (embed)한 뒤, 과거 실행 결과에 대해 시맨틱 검색 (semantic search)을 수행하라"로 번역됩니다. 그것은 특정 작업에는 적합한 도구입니다. 즉, _거대하고 모호한 코퍼스 (corpus)에서 개념적으로 유사한 것을 찾는 작업_에는 말이죠. 하지만 대부분의 장기 실행 에이전트가 실제로 필요로 하는 작업은 훨씬 더 작으며, 이를 위해 벡터 DB는 과한 도구입니다. 그 작업이란 바로 '내가 방금 무엇을 했는가, 그리고 내가 다음에 하겠다고 말한 바로 다음 단계는 무엇인가' 입니다.
이것은 시맨틱 회상 (semantic recall)이 아닙니다. 이것은 인수인계 노트 (hand-off note)입니다. 5분 전, 혹은 5시간 전에 무엇을 하고 있었는지 기억하기 위해 임베딩 (embeddings)이 필요한 것은 아닙니다. 당신에게 필요한 것은 그것을 적어둘 장소와 그것을 다시 읽어올 수 있는 신뢰할 수 있는 방법입니다.
실제로 작동하는 게으른 버전
새로운 기술은 아니지만, 두 가지 요소가 있습니다:
- 에이전트가 매 사이클이 끝날 때마다 작성하는 작은 상태 파일 (state file). 단순한 트랜스크립트 (transcript)나 로그 덤프 (log dump)가 아니라, 무엇이 변했는지, 무엇이 아직 열려 있는지, 다음에 무엇을 해야 하는지를 담은 짧고 구조화된 노트입니다.
- 시간에 따른 이러한 인수인계의 로그로서의 git 커밋 히스토리 (git commit history). 어차피 작업을 커밋 (commit)하고 있을 것이기 때문입니다.
인수인계 파일의 이름을 CYCLE-STATE.md라고 부릅시다:
## Cycle 2026-08-03 09:00
- did: queue loader의 null-check 버그 수정 (commit abc1234 참조)
- open: 재시도 경로(retry path)가 아직 테스트로 커버되지 않음
...
에이전트가 깨어난 후 취하는 가장 첫 번째 행동은 "레포지토리 (repo)의 모든 파일을 읽는 것"이 아니라, 다음과 같습니다:
git log --oneline -20 # 최근에 실제로 일어난 일
cat CYCLE-STATE.md # 마지막 사이클이 아직 열려 있다고 믿었던 상태
이것이 메커니즘의 전부입니다. git log는 *무슨 일이 일어났는지 (what happened)*를 제공합니다. 작업을 저장하기 위해 어차피 커밋을 수행할 것이기 때문에, 모든 커밋은 이미 실제 변경 사항에 대한 타임스탬프와 작성자가 기록된 기록물입니다. CYCLE-STATE.md는 그것이 무엇을 의미하는지 (what it means), 즉 해석과 의도를 제공합니다. 이는 커밋 메시지만으로는 보통 전달되지 않는 정보입니다 (예: "queue bug 수정"이라는 메시지만으로는 재시도 경로(retry path)가 여전히 열려 있는지 알려주지 않습니다).
매 사이클마다 CYCLE-STATE.md에 내용을 추가(append)하는 대신 덮어쓰는(overwrite) 것은 의도적인 설계입니다. 모델 앞에 과거의 모든 인수인계 노트를 띄워둘 필요는 없습니다. 더 멀리 거슬러 올라가 확인해야 할 일이 생기면 git log에 이미 모든 버전이 남아 있으므로, 이는 이득 없이 컨텍스트만 낭비(context bloat)하는 일입니다:
git log --oneline -- CYCLE-STATE.md
git show <commit>:CYCLE-STATE.md
이 파일은 아카이브(archive)가 아니라 화이트보드(whiteboard)입니다. 아카이브는 이미 커밋(commits)으로서 존재합니다.
이것이 예상보다 더 자주 충분한 이유
"시맨틱 검색 (semantic search)이 필요하다"는 주장이 해결하고자 하는 실패 모드는 다음과 같습니다: 관련 있는 부분이 어디에나 있을 수 있는, 거대하고 구조화되지 않은 과거 출력물의 더미가 있는 경우입니다. 하나의 코드베이스에서 집중적인 작업을 수행하는 장기 실행 에이전트는 대부분의 경우 그런 문제를 겪지 않습니다. 에이전트는 관련 정보가 거의 항상 최근에 위치하는 작고 선형적인 히스토리를 갖기 때문입니다. git log -20과 두 단락 정도의 인수인계 노트는 파일 쓰기 한 번과 몇 개의 쉘 명령어를 사용하는 비용만으로, 압도적으로 많은 사이클에서 "내가 무엇을 하고 있었는가"를 커버합니다. 임베딩 모델(embedding model)도, 계속 유지해야 할 인덱스(index)도, 새벽 3시에 실행해야 할 새로운 서비스도 필요 없습니다.
또한 이것은 우연이 아니게도, Anthropic이 장기 실행 에이전트 작업(agentic work)을 위한 효과적인 하네스(harness)를 설명하는 방식과 유사합니다. 실행 간에 깔끔하게 전달되는 저렴하고 구조화된 상태(state)는, 에이전트가 단순히 읽는 대신 그 자체에 대해 추론(reason about)해야 하는 더 화려한 메모리 시스템보다 더 낫습니다.
한 가지 솔직한 주의사항
이 패턴은 **의미론적 회상 (semantic recall)**이 아니라 **상태 전송 (state transfer)**입니다. 이를 구현하여 배포하기 전에 스스로 이 차이점을 명확히 인지해야 합니다. 이 방식은 "진행 중이었던 작업(what was in flight)이 무엇이었는가"라는 질문에는 훌륭하게 답합니다. 하지만 "6개월 전, 400개의 커밋 전, 완전히 다른 문구로 표현되었던 이와 유사한 버그를 본 적이 있는가"라는 질문에는 답하지 못합니다. 만약 당신의 에이전트가 지원 티켓, 지식 베이스 (knowledge base), 수개월간의 느슨하게 연결된 장애 노트와 같이 크고 무질서하며 계속 성장하는 코퍼스 (corpus) 전체에서 _개념 (concepts)_을 검색해야 한다면, 그것은 진정한 벡터 데이터베이스 (vector-DB)의 영역이며, 그 어떤 git log 스크롤링으로도 이를 대체할 수 없습니다.
메모리 문제의 실제 형태에 맞는 도구를 선택하십시오. 제가 구축한 대부분의 장기 실행 에이전트들은 아카이브 보관실이 아닌 화이트보드만을 필요로 했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기