AI 에이전트를 오래 돌려본 사람은 안다. 에이전트는 학습하지 않는다. 검색할 뿐이다. 어제 알려준 맥락을 오늘 다시 알려줘야 하고, 지난주에 했던 실수를 이번 주에 또 한다. 세션이 끊기면 모든 게 리셋된다. 100번째 대화의 품질이 1번째 대화와 동일하다는 건, 그 사이 99번의 대화가 전부 휘발됐다는 뜻이다.

나는 OpenClaw 기반으로 다섯 개의 에이전트를 운영하면서 이 문제를 매일 겪었다. 제온, 시온, 미온, 사노, 라온에게 각각 다른 역할을 맡기고 레이어드 메모리 구조를 직접 설계해서 붙여봤지만, 결국 대화가 쌓일수록 똑똑해지는 게 아니라 컨텍스트 윈도우만 비대해지는 구조의 한계에 부딪혔다. 에이전트가 경험을 축적하고 스스로 진화하는 시스템이 필요했다. 그 답답함의 끝에서 MemKraft를 만들었다.

만들기 전에 기존 오픈소스 메모리 시스템들을 상당수 직접 써봤다. Mem0는 자동 메모리 추출과 시맨틱 검색이 뛰어났다. 대화에서 팩트를 알아서 뽑아내고 벡터로 저장해서 나중에 유사도 기반으로 꺼내주는 구조가 깔끔했다. 하지만 벡터 DB에 종속되고, 저장된 지식이 사람이 읽을 수 있는 형태가 아니었다. Letta, 옛 이름 MemGPT는 메모리 계층화와 가상 컨텍스트 관리라는 개념을 처음 제대로 구현한 프로젝트였다. 에이전트가 스스로 메모리를 편집하고 컨텍스트 윈도우를 페이징하듯 관리하는 접근은 혁신적이었지만 완전한 에이전트 런타임을 요구했다. 기존 스택에 가볍게 붙이기엔 무거웠다. GBrain은 Compiled Truth와 Timeline이라는 이중 구조가 인상적이었고, Rowboat는 옵시디언 기반의 라이브 트래킹과 미팅 브리프가 실용적이었다. 각각 분명한 장점이 있었고, 동시에 분명한 한계가 있었다.

MemKraft는 이 프로젝트들에서 배운 것을 한곳에 녹여내되, 외부 의존성 제로, Plain Markdown 기반, 프레임워크 무관이라는 원칙 위에 올렸다. 좋은 아이디어가 특정 DB나 특정 런타임에 갇혀 있을 이유가 없다.

핵심 구조는 이렇다. 대화나 텍스트가 들어오면 자동 추출 파이프라인이 인물, 조직, 개념, 수치 팩트를 뽑아낸다. 이걸 RESOLVER라는 MECE 분류 트리가 받아서 정확히 하나의 목적지로 라우팅한다. 사람이면 entities/, 의사결정이면 decisions/, 날것의 캡처면 inbox/ 로.

모든 엔티티 페이지는 두 개의 레이어로 구성된다. Compiled Truth는 현재 상태다. 이 사람이 누구인지, 어떤 조직에 속해 있는지, 지금 뭘 하고 있는지. 변할 때마다 다시 쓴다. Timeline은 변경 이력이다. 언제, 어떤 소스에서, 어떤 정보가 들어왔는지를 시간순으로 쌓는다. 절대 수정하지 않고 오직 추가만 한다.

왜 이중 구조인가. 현재 상태만 있으면 과거가 사라진다. 이력만 있으면 지금 상태를 파악하려면 전체를 읽어야 한다. Compiled Truth는 빠른 판단을 위한 것이고, Timeline은 그 판단의 근거를 추적하기 위한 것이다. 여기에 Source Attribution이 결합된다. 모든 팩트에 [Source: 누가, 언제, 어떤 경로로] 태그가 붙는다. 출처 없는 팩트는 신뢰 부채다. 지금은 작동하지만 언젠가 문제를 일으킨다. MemKraft는 이 부채를 가시화하고, Dream Cycle이 매일 밤 출처 누락을 잡아낸다.

다국어 처리는 MemKraft를 만든 가장 실질적인 이유 중 하나다. 나는 에이전트와 한국어, 영어를 섞어가며 대화하고, 투자 리서치에서는 중국어와 일본어 소스도 다룬다. 기존 메모리 시스템 대부분은 영어 중심이고, CJK 처리는 있어도 부수적이다. MemKraft는 처음부터 4개 언어를 동등하게 설계했다.

영어는 Title Case 패턴 매칭과 일반 단어 블록리스트 필터링으로 인명을 잡아낸다. 한국어는 Hangul 음절 추출 후 조사를 분리한다. 이, 을, 를, 은, 는, 에, 로 같은 조사와 동사 어미를 제거해서 순수한 이름을 뽑는다. 중국어는 내장된 100개 성씨를 기반으로 성 + 이름 패턴을 감지하고, 일본어는 85개 성씨로 매칭한다. 806개의 한중일 불용어가 내장되어 있고, 이 모든 게 LLM 호출 없이 정규식과 표준 라이브러리만으로 돌아간다. 비행기 안에서도, 오프라인에서도, CI 파이프라인 안에서도 동일하게 동작한다.

메모리는 쌓는 것보다 관리하는 게 어렵다. 시간이 지나면 중복이 생기고, 출처가 빠진 팩트가 슬금슬금 쌓이고, 어떤 페이지는 비대해지고, 어떤 페이지는 이름만 있고 내용이 없다. 이걸 사람이 수동으로 관리하면 메모리 시스템 자체가 또 하나의 짐이 된다.

Dream Cycle은 이 문제를 자동화한다. 매일 밤 여섯 가지 점검을 돌린다. 데일리 노트 자동 생성, 출처 누락 플래그, 빈약한 페이지 경고, 슬러그 정규화를 통한 중복 감지(simon-kim과 김서준이 같은 사람일 수 있다는 걸 잡아내는 식이다), inbox 방치 항목 플래그, 비대해진 페이지 압축 대상 표시. --dry-run으로 먼저 확인하고, 문제가 없으면 적용하는 구조다.

Memory Tier는 지식을 Core, Recall, Archival 세 등급으로 나눈다. Core는 항상 컨텍스트에 포함, Recall은 검색 시 노출, Archival은 과거 기록 보관. Progressive Disclosure는 검색할 때 토큰을 단계적으로 꺼내 쓴다. Level 1은 인덱스 스캔으로 약 50토큰, Level 2는 섹션 헤더, Level 3에서 전체 파일. 컨텍스트 윈도우를 쓸데없이 채우지 않으면서 필요한 깊이까지만 파고드는 구조다.

설치는 한 줄이면 끝이다. Python 3.9 이상이면 되고, 그 외에 아무것도 필요 없다. 모든 지식은 Plain Markdown 파일로 저장되기 때문에 git push 한 번이면 전체 지식 베이스가 백업된다. 2026년에 쓴 마크다운 파일은 2036년에도 똑같이 읽을 수 있다. 특정 모델의 임베딩은 그 모델이 사라지면 디코딩조차 못 할 수 있지만, 텍스트 파일은 영원하다.

프레임워크도 가리지 않는다. OpenClaw든, LangChain이든, CrewAI든, 직접 만든 에이전트든 CLI를 호출하거나 Python 라이브러리로 임포트하면 된다. 20개 이상의 커맨드가 첫날부터 전부 사용 가능하고, Backlink, Fuzzy Search, Agentic Search, Meeting Brief, Open Loop Tracking, Decision Distillation까지 에이전트 운영에 필요한 워크플로우가 다 들어있다.

대화할수록 멍청해지는 에이전트 대신, 대화할수록 똑똑해지는 에이전트를 만들고 싶다면 한번 써보고 피드백을 달아주시길. MIT 라이선스, 맘대로 쓰면 된다. 스타, 포크, PR 전부 환영!

https://github.com/seojoonkim/memkraft