MemoryLake
모든 글로 돌아가기
Tutorial2026년 9월 9일·12 분 소요

OpenHands 메모리 인덱스에서 가장 오래된 사실이 삭제되지 않도록 유지하는 방법 (2026년 가이드)

OpenHands에서 지속성 메모리(persistent memory)를 켰더니 잘 작동했습니다. 에이전트는 자신이 학습한 내용, 즉 해결하는 데 반나절이 걸렸던 환경의 특이한 점, 서비스가 이상하게 구성된 이유, 네 번이나 반복해야 했던 선호 사항 등을 기록하기 시작했습니다. 세션들이 이전 정보를 기억하기 시작한 것입니다.

하지만 3개월 후, 가장 오래된 항목들이 사라졌습니다. 사용자가 삭제한 것도 아니고, 에이전트 자체의 정리 명령에 의해 삭제된 것도 아니며, 단지 프롬프트에 더 이상 포함되지 않을 뿐입니다. 게다가 사라진 항목들은 가장 초기의 것들입니다. 만약 지금까지 동일한 프로젝트를 진행해 왔다면, 지난주의 사소한 소음이 아니라 프로젝트의 기초가 되는 결정들이 사라진 것입니다.

이것은 버그가 아니라 문서에 명시된 동작 방식입니다. 이 동작의 형태를 이해하고 나면, 파일 하나를 작성하는 방식을 10분 만에 수정하여 해결할 수 있습니다. 이 가이드의 후반부에서는 동일한 문서에 있는 또 다른 문장을 다루며, 이 문장은 해당 파일에 애초에 무엇을 넣어야 하는지를 완전히 바꾸어 놓을 것입니다.

아직 도구를 설정하는 중이라면, migrating from Codex to OpenHands에서 지침 파일 측면의 이전 방법을 다룹니다. 이 가이드는 구체적으로 메모리 기능에 초점을 맞춥니다.

가장 오래된 줄이 먼저 사라지는 이유

OpenHands의 지속성 메모리는 사용자가 요청하지 않는 한 꺼져 있습니다. 문서에 명시되어 있듯이, 이 기능은 "선택 사항(opt-in)이며 기본적으로 꺼져 있습니다." 이 기능이 없으면 "에이전트는 기존 AGENTS.md 기반의 안내를 유지하며 프롬프트는 변경되지 않습니다." 에이전트의 AgentContext에서 load_memory를 true로 설정하여 활성화할 수 있습니다.

활성화되면 두 개의 계층(tier)이 존재합니다. ~/.openhands/memory/에 있는 사용자 계층은 "모든 프로젝트에 적용되는 지식과 선호 사항"을 보관하고, <workspace>/.openhands/memory/에 있는 프로젝트 계층은 "현재 리포지토리에 특화된 지식"을 보관합니다. 각 계층에는 MEMORY.md가 포함되어 있으며, 이는 "지속적인 사실들의 큐레이션된 인덱스입니다. 프롬프트에 주입되는 유일한 파일입니다"라고 설명되어 있습니다. 또한 날짜가 지정된 일일 로그가 있는데, 이는 "자동으로 주입되지 않으며, 에이전트가 MEMORY.md가 이를 가리킬 때 파일 도구를 사용하여 필요에 따라 읽습니다."

이러한 분할이 중요한 아키텍처이며, 바로 여기서 데이터 제거(eviction)가 발생합니다.

"크기 예산(Size budget): 결합된 인덱스는 약 6,000자로 제한됩니다. 예산을 초과하면 용량을 초과한 각 계층의 상단(가장 오래된 콘텐츠)에서 전체 줄이 삭제됩니다. 부분적인 줄은 절대 남지 않으며, 계층 헤더는 항상 유지되고, 줄을 잃은 계층의 헤더 아래에 잘림 안내(truncation notice)가 표시됩니다. 인덱스를 잘 관리(curated)해 주세요."

천천히 읽어보세요. 네 가지 개별적인 동작이 여기에 압축되어 있기 때문입니다.

제한은 두 계층의 결합된 인덱스에 적용되므로, 개인 선호 사항과 프로젝트 사실이 동일한 예산을 두고 경쟁합니다. 장황한 사용자 계층 파일은 프로젝트 계층이 담을 수 있는 용량을 갉아먹습니다.

줄은 상단에서부터 삭제되며, 문서는 상단을 "가장 오래된 콘텐츠"로 설명합니다. 에이전트는 학습하면서 내용을 뒤에 추가하므로, 파일의 상단은 에이전트가 가장 먼저 기록한 내용입니다. 대부분의 제한 방식은 가장 최신 항목을 제거하거나 쓰기에 실패하지만, 이 방식은 기초부터 먼저 제거합니다.

삭제는 줄 단위로 깔끔하게 이루어집니다("부분적인 줄은 절대 남지 않음"). 따라서 의미가 왜곡되는 반쪽짜리 문장이 남지 않습니다. 훌륭한 설계이며, 이는 긴 한 줄이 통째로 유지되거나 통째로 사라짐을 의미합니다.

그리고 신호가 존재합니다. "줄을 잃은 계층의 헤더 아래에 잘림 안내가 표시됩니다." 주의 깊게 본다면 아무것도 소리 없이 사라지지 않습니다. 문제는 일반적인 작업 세션 중에 주입된 시스템 프롬프트 블록을 들여다보는 사람은 아무도 없다는 점입니다.

여러 도구를 실행하는 분들을 위해 참고할 만한 점은, 6,000자는 Devin Desktop이 글로벌 규칙 파일에 대해 문서화한 예산과 동일하다는 것입니다. 약 6,000자 부근은 여러 벤더가 항상 로드되는 파일이 그 비용만큼의 가치를 하지 못한다고 독립적으로 판단한 지점이며, 어떤 도구를 사용하든 기억해 두면 유용한 수치입니다.

사람들이 대신 시도하는 방법들

예산 늘리기. 첫 번째 본능이지만, 문서는 이를 조절 가능한 설정으로 제공하지 않습니다. 이 제한은 기능의 고유한 속성으로 설명되어 있습니다. 설령 조정이 가능하더라도, 항상 로드되는 블록이 커지는 것은 how much memory you should give an AI agent에서 다룬 이유들 때문에 더 나은 거래가 아니라 더 나쁜 거래가 됩니다.

몇 주마다 MEMORY.md를 수동으로 재작성하기. 이 방법은 작동하며, "인덱스를 잘 관리하라"는 요구에 부합합니다. 하지만 이는 트리거가 없는 번거로운 작업이므로 두 번 정도 하다가 멈추게 되고, 파일은 다시 커지게 됩니다.

모든 것을 AGENTS.md로 이동하여 절대 삭제되지 않도록 하기. 솔깃한 방법이지만, 이는 문서가 설정한 역할 분담을 잘못 해석한 것입니다. 에이전트는 "리포지토리에서 작업하는 모든 에이전트에게 전달되는 지침을 위해 AGENTS.md를 유지하고, 메모리는 에이전트가 스스로 학습한 내용을 위한 것"이라는 지침을 받습니다. 학습된 이력을 지침 파일에 쏟아붓는 것은 이름만 다르고 삭제 경고도 없는, 항상 로드되는 긴 파일을 만드는 것과 같습니다.

중요한 사실을 스킬(skill)에 넣어 필요할 때 로드하도록 하기. 합리적인 직관이지만, why agent skills aren't memory에서 설명한 이유로 잘못된 메커니즘을 사용하는 것입니다. 스킬은 "이 작업을 어떻게 수행하는가"에 답합니다. 거부된 아키텍처 대안은 작업이 아닙니다.

.openhands/memory/를 커밋하고 팀 문서로 취급하기. 문서에서는 이를 명시적으로 허용합니다. "프로젝트 팀은 에이전트가 학습한 지식을 공유하기 위해 .openhands/memory/를 커밋할 수도 있습니다." 이는 실제로 유용합니다. 하지만 이제 여러 사람의 에이전트가 동일한 6,000자 제한을 두고 공유 인덱스에 내용을 추가하게 되므로, 삭제 문제는 오히려 더 악화됩니다.

이러한 방법들이 완전히 작동하지 않는 또 다른 이유가 있으며, 이는 사람들이 놓치는 문장 때문입니다.

"설계상 신뢰할 수 없음(Untrusted by design): 주입된 블록은 <UNTRUSTED_CONTENT>로 감싸집니다. 메모리 파일은 일반적으로 에이전트가 작성하지만, 작업 공간이나 리포지토리에 액세스할 수 있는 사람은 누구나 이를 편집하거나 커밋할 수 있으므로(복제된 리포지토리에 .openhands/memory/MEMORY.md가 포함되어 있을 수 있음), 에이전트는 여기에 프롬프트 주입이 포함되어 있을 수 있다고 안내받으며, 이를 절대 권위 있는 지침이 아닌 검증되지 않은 힌트로 취급하도록 지시받습니다."

에이전트는 자신의 메모리를 검증되지 않은 힌트로 취급하도록 지시받습니다. 이는 올바른 보안 태세이며(복제된 리포지토리에 실제로 메모리 파일이 포함되어 있을 수 있으므로), 설계상의 의문을 해결해 줍니다. 반드시 준수해야 하는 사항은 메모리에 존재할 수 없습니다. 메모리는 명시적으로 권위가 없기 때문입니다. 메모리는 에이전트가 유용하게 사용할 수 있는 컨텍스트를 위한 것입니다. 지침은 모든 에이전트에게 전달되고 지침으로 읽히는 AGENTS.md에 있어야 합니다.

따라서 문서화된 두 가지 속성은 하나의 규칙으로 결합됩니다. 메모리 인덱스는 작고, 권위가 없으며, 상단에서 손실이 발생하는 포인터 파일입니다. 그 이상으로 취급하면 두 가지 방식 중 하나로 실망하게 될 것입니다.

해결책: 인덱스를 저장소가 아닌 포인터로 유지하기

세 단계가 있습니다. 처음 두 단계는 10분이 소요되며, 세 번째 단계는 문제가 재발하는 것을 방지합니다.

1단계: MEMORY.md를 포인터 인덱스로 전환하기

문서에서는 이미 의도된 형태를 알려주고 있습니다. MEMORY.md는 "지속적인 사실들의 큐레이션된 인덱스"이며, 에이전트는 "긴 세부 사항은 일일 로그에 기록"하도록 지시받고, 로그는 "MEMORY.md가 가리킬 때 파일 도구를 사용하여 필요에 따라" 읽힙니다.

따라서 인덱스의 모든 줄은 짧아야 하며 어딘가를 가리켜야 합니다. 사실당 한 줄씩, 에이전트가 무엇이 사실인지와 세부 정보가 어디에 있는지 모두 알 수 있도록 표현해야 합니다. 줄글 문단, 코드 샘플, 긴 설명은 날짜가 지정된 로그 파일로 이동하며, 이 파일들은 필요할 때만 읽히고 예산에 전혀 영향을 주지 않습니다.

이렇게 하면 6,000자 제한은 더 이상 제약이 되지 않습니다. 100개의 한 줄짜리 포인터는 여유롭게 들어가는 반면, 12개의 문단은 들어가지 못합니다.

2단계: 상단이 삭제되어도 무방하도록 인덱스 순서 재정렬하기

데이터 제거는 상단에서부터 줄을 삭제하고 상단은 가장 오래된 콘텐츠이므로, 파일의 시간순 정렬은 사용자에게 불리하게 작용합니다. 순서를 시간순이 아닌 의미론적 순서로 변경하여 이를 해결하세요.

잃어버리면 아쉬운 사실들(아키텍처, 제약 조건, 장기적인 결정 사항 등)을 각 계층 인덱스의 맨 아래에 배치하세요. 일시적인 운영 노트는 맨 위에 배치하세요. 이제 예산이 초과되어 삭제되는 줄은 어차피 정리했을 줄들이 될 것입니다.

그 다음 계층 간의 균형을 맞추세요. 제한은 결합되어 적용되므로, 개인 선호 사항으로 가득 찬 비대한 ~/.openhands/memory/MEMORY.md는 프로젝트 사실이 들어갈 공간을 직접적으로 빼앗습니다. 사용자 계층은 진정한 프로젝트 간 선호 사항으로만 유지하고, 프로젝트 계층에 공간을 양보하세요.

작업하는 동안 각 계층 헤더 아래에 잘림 안내가 있는지 확인하세요. 만약 표시되어 있다면 이미 일부 줄을 잃은 것이며, 일일 로그에서 그 내용을 찾아야 합니다. 이는 1단계를 먼저 수행해야 하는 좋은 이유가 됩니다.

3단계: 현재 하나의 파일을 공유하고 있는 세 가지 요소 분리하기

현재 인덱스는 서로 다른 보관처가 필요한 세 가지 종류의 콘텐츠를 담고 있습니다.

지침(Instructions) — 반드시 준수해야 하는 사항 — 은 문서 자체의 구분 방식에 따라 AGENTS.md에 속합니다. 이는 메모리가 아니며, 메모리는 권위가 없습니다.

에이전트가 학습한 운영 세부 정보 — 환경의 특이점, 불안정한 테스트, 실제로 작동하는 명령 등 — 는 원래 있어야 할 곳, 즉 인덱스의 포인터 줄과 일일 로그의 세부 정보에 속합니다. 이것이 바로 이 기능의 목적입니다.

프로젝트 결정 사항 및 그 이유 — 큐 라이브러리가 거부된 이유, 규정 준수 제약 조건이 실제로 요구하는 사항, 3월에 시도했으나 실패한 작업 등 — 은 둘 다에 속하지 않습니다. 지침이 아니므로 AGENTS.md는 맞지 않습니다. 손실되거나 권위가 없어서는 안 되므로 메모리 인덱스도 맞지 않습니다. 그리고 이 정보는 load_memory가 켜진 도구뿐만 아니라 팀이 사용하는 모든 도구에서 답변할 수 있어야 합니다.

MemoryLake에서 설정하기

MemoryLake는 이 세 번째 카테고리를 위한 공간입니다. 단일 에이전트 외부에서 결정 사항과 그 이유를 보관하므로 경쟁해야 할 '항상 로드되는 예산'이 없으며, MCP나 API를 통해 이에 대한 질문에 답변합니다. MEMORY.md는 짧은 포인터 인덱스로 유지되고 OpenHands는 문서에 기재된 대로 정확하게 이를 계속 유지 관리합니다. 지속적인 추론은 글자 수 제한이 닿지 않는 곳에 보관됩니다.

1단계: API 키 생성하기

키를 생성하고 약 30초 만에 첫 번째 요청을 보내보세요. 위의 2단계를 수행하기 전에 이 작업을 완료하여, 인덱스를 재정렬할 때 각 결정을 이동할 공간을 마련해 두세요.

MEMORY.md의 용량을 초과하는 사실들이 지속적으로 보관될 수 있도록 MemoryLake API 키 생성하기
MEMORY.md의 용량을 초과하는 사실들이 지속적으로 보관될 수 있도록 MemoryLake API 키 생성하기

2단계: 첫 번째 메모리 업로드하기

현재 인덱스와 인덱스가 가리키는 일일 로그를 읽어보세요. 단순한 관찰이 아닌 결정 사항에 해당하는 모든 항목은 선택된 것, 거부된 것, 그리고 그 이유와 함께 기록됩니다. 지원 문서와 파일도 같은 위치에 저장됩니다.

제한된 인덱스에 보관하는 대신 기초적인 프로젝트 결정 사항을 MemoryLake에 업로드하기
제한된 인덱스에 보관하는 대신 기초적인 프로젝트 결정 사항을 MemoryLake에 업로드하기

3단계: AI 및 에이전트 연결하기

OpenHands, Claude, Codex 및 기타 에이전트에 MCP 또는 API를 통해 액세스 권한을 부여하세요. 이들 중 누구라도 프로젝트가 왜 이렇게 구성되었는지 알아야 할 때, 시스템 프롬프트의 공간을 두고 경쟁하는 대신 추론이 첨부된 답변을 받게 됩니다.

MCP 및 API를 통해 OpenHands 및 기타 에이전트를 MemoryLake에 연결하기
MCP 및 API를 통해 OpenHands 및 기타 에이전트를 MemoryLake에 연결하기

실제 적용 시 달라지는 점

첫 번째 변화는 데이터 제거가 더 이상 중요하지 않게 된다는 점입니다. 삭제 가능한 콘텐츠를 상단에 배치하여 정렬된 포인터 인덱스는 사용자가 어차피 정리했을 내용만 잃게 되며, 모든 포인터 뒤에 있는 세부 정보는 에이전트가 열어볼 수 있는 로그 파일에 여전히 남아 있습니다.

두 번째는 메모리 기능이 본연의 역할에 충실해진다는 점입니다. 통합 테스트에 특정 환경 변수가 필요하다는 점을 기록하는 것은 에이전트가 관리하는 저장소가 해야 할 정확한 역할이며, 팀의 결정 기록 역할까지 요구받지 않을 때 이 역할을 훌륭히 수행합니다.

세 번째는 '신뢰할 수 없는 콘텐츠'라는 프레임이 더 이상 문제가 되지 않는다는 점입니다. 메모리에 중요한 내용이 남아 있지 않게 되면, 에이전트가 이를 검증되지 않은 힌트로 취급하는 것은 지극히 당연한 일이 됩니다. 그리고 권위가 필요한 사항들은 AGENTS.md에 보관되어 지침으로 읽히게 됩니다.

네 번째는 .openhands/memory/를 팀 규모에서 안전하게 커밋할 수 있게 된다는 점입니다. 여러 에이전트가 6,000자 예산을 두고 포인터 줄을 추가하는 것은, 여러 에이전트가 문단을 추가하는 것과는 달리 지속 가능합니다. 그리고 두 항목이 실제로 충돌할 때, 알파벳순이나 시간순의 우연에 의해 결정되도록 내버려 두는 대신 이를 해결할 수 있는 공간이 생깁니다. 이는 memory conflict detection이 해결하고자 하는 문제입니다.

OpenHands 지속성 메모리를 위한 모범 사례

한 줄, 하나의 사실, 하나의 포인터. 인덱스는 큐레이션된 인덱스로 문서화되어 있습니다. 한 줄보다 긴 내용은 인덱스가 가리키는 일일 로그에 속해야 합니다.

시간순이 아닌 중요도순으로 정렬하세요. 데이터 제거는 상단에서 줄을 가져갑니다. 잃어도 상관없는 내용을 그곳에 두세요.

두 계층의 예산을 서로 비교하여 관리하세요. 제한은 결합되어 적용되므로, 장황한 사용자 계층은 프로젝트 계층을 소리 없이 축소시킵니다.

잘림 안내를 확인하세요. 줄을 잃은 계층의 헤더 아래에 표시됩니다. 이것이 유일한 신호이며, 주의 깊게 본다면 신뢰할 수 있습니다.

메모리에 자격 증명을 절대 넣지 마세요. 에이전트 자체 지침에도 비밀번호나 자격 증명을 절대 기록하지 말라고 되어 있습니다. 직접 추가하여 이를 어기지 마시고, 주기적으로 감사하세요. auditing what your AI remembers에서 이 습관을 다룹니다.

쉽게 재발견할 수 있는 것은 건너뛰세요. 유지 관리 지침에도 나와 있듯이, 디렉터리 목록이나 뻔한 명령은 예산만 차지할 뿐 아무것도 가르쳐주지 못합니다.

지침은 메모리에서 완전히 제외하세요. 메모리는 검증되지 않은 힌트로 문서화되어 있습니다. 반드시 준수해야 하는 사항이라면 AGENTS.md로 가야 합니다.

메모리는 세션에 저장되는 것이 아니라 다시 읽힌다는 점을 기억하세요. 문서에 따르면 확인된 텍스트는 대화 지속성 및 API 페이로드에서 제외되고 매 세션마다 디스크에서 다시 읽히므로, 파일을 수동으로 편집하면 다음 대화에 바로 반영됩니다.

결론

OpenHands는 지속성 메모리를 정확하게 문서화하고 있습니다. 선택 사항이며 기본적으로 꺼져 있고, 두 개의 계층이 존재하며, MEMORY.md만 주입되고, 결합된 제한은 약 6,000자이며, 예산을 초과한 계층의 상단에서 전체 줄이 삭제되고 헤더 아래에 잘림 안내가 표시되며, 전체 블록은 에이전트가 권위 있는 지침이 아닌 검증되지 않은 힌트로 취급하도록 지시받는 신뢰할 수 없는 콘텐츠 마커로 감싸집니다. 이 모든 것은 합리적인 결정입니다. 이들이 모여 작고, 손실이 발생하며, 권장 사항을 담은 포인터 파일을 정의합니다. 이는 실제로 유용한 도구이지 프로젝트의 추론 과정을 보관할 장소는 아닙니다.

인덱스를 한 줄짜리 포인터로 유지하고, 상단에 잃어도 상관없는 내용이 오도록 정렬하며, 현재 인덱스를 공유하고 있는 세 가지 종류의 콘텐츠를 분리하세요. 지침은 AGENTS.md로 보냅니다. 관찰 결과는 이 기능의 원래 목적인 메모리와 로그에 유지합니다. 결정 사항과 그 이유는 글자 수 제한이 없고 만료되지 않는 곳으로 보냅니다. 왜냐하면 이 정보들은 1년 후에도 여전히 필요할 것이기 때문입니다. 그리고 keeping less in agent memory에서 주장하듯이, 나머지 정보가 제자리를 찾고 나면 항상 로드되는 파일은 작을수록 모든 면에서 더 좋습니다.

자주 묻는 질문

왜 가장 오래된 메모리 항목이 사라졌나요?

그것이 문서에 명시된 데이터 제거 순서이기 때문입니다. 결합된 메모리 인덱스는 약 6,000자로 제한되며, 예산을 초과하면 용량을 초과한 각 계층의 상단(문서에서 가장 오래된 콘텐츠로 식별함)에서 전체 줄이 삭제됩니다. 줄을 잃은 계층의 헤더 아래에 잘림 안내가 표시됩니다.

메모리 크기 제한을 늘릴 수 있나요?

문서에서는 약 6,000자의 제한을 구성 가능한 설정이 아닌 기능의 고유한 속성으로 제시하고 있으며, 인덱스를 잘 관리할 것을 권장합니다. 예산 내에 더 많은 내용을 담는 실질적인 방법은 각 줄을 짧은 포인터로 만들고 세부 정보를 자동으로 주입되지 않는 일일 로그 파일로 이동하는 것입니다.

MEMORY.md와 일일 로그의 차이점은 무엇인가요?

MEMORY.md는 큐레이션된 인덱스이자 프롬프트에 주입되는 유일한 파일입니다. 날짜가 지정된 일일 로그는 자동으로 주입되지 않는 자유 형식의 작업 노트이며, 에이전트는 인덱스가 이를 가리킬 때 파일 도구를 사용하여 필요에 따라 읽습니다. 이것이 의도된 분할 방식이며, 이를 통해 제한 용량을 관리할 수 있게 됩니다.

왜 메모리 블록이 신뢰할 수 없는 콘텐츠로 표시되나요?

메모리 파일은 다른 사람들이 쓸 수 있는 작업 공간이나 리포지토리의 디스크에 존재하며, 복제된 리포지토리에 자체 메모리 파일이 포함되어 있을 수 있기 때문입니다. 문서에 따르면 에이전트는 해당 콘텐츠에 프롬프트 주입이 포함되어 있을 수 있다는 안내를 받으며, 이를 절대 권위 있는 지침이 아닌 검증되지 않은 힌트로 취급하도록 지시받습니다. 그렇기 때문에 반드시 준수해야 하는 사항은 대신 AGENTS.md에 있어야 합니다.

.openhands/memory/를 리포지토리에 커밋해야 하나요?

문서에서는 에이전트가 학습한 지식을 팀과 공유하는 방법으로 이를 명시적으로 허용하고 있으며, 실제로 잘 작동합니다. 다만 인덱스를 짧은 포인터로 변환한 후에만 수행하세요. 단일 결합 예산을 두고 여러 에이전트가 공유 인덱스에 내용을 추가하면 혼자 사용할 때보다 훨씬 더 빨리 제한에 도달하기 때문입니다.

지속성 메모리는 기본적으로 켜져 있나요?

아니요. 문서에서는 이를 선택 사항이며 기본적으로 꺼져 있는 것으로 설명하며, 에이전트의 컨텍스트에서 load_memory를 설정하여 활성화한다고 명시하고 있습니다. 또한 이 기능이 없으면 에이전트는 기존 AGENTS.md 기반의 안내를 유지하며 프롬프트는 변경되지 않습니다. 이 기능을 켜면 시스템 프롬프트의 메모리 섹션도 파일 유지 관리에 대한 지침으로 전환됩니다.