Show HN: Remembrane – 단일 SQLite 파일로 구현하는 AI 에이전트 메모리, 의존성 제로
요약
remembrane은 단일 SQLite 파일로 구현된 AI 에이전트 전용 로컬 영구 메모리 솔루션입니다. 외부 의존성 없이 정확한 하이브리드 검색(vector + BM25)과 설명 가능한 랭킹, 시간 여행 기능을 제공합니다. LangChain 및 CrewAI 어댑터와 MCP 서버를 통해 다양한 에이전트에 통합할 수 있습니다.
핵심 포인트
- 단일 SQLite 파일로 구현되어 의존성이 거의 없습니다.
- 근사치가 아닌 정확한 하이브리드 검색을 보장합니다.
- 메모리 강화(reinforce) 및 망각(forget) 기능을 제공합니다.
- LangChain, CrewAI 등 주요 프레임워크와 연동 가능합니다.
remembrane
AI 에이전트를 위한 로컬 우선 영구 메모리. 하나의 SQLite 파일과 필요한 의존성이 없습니다. 정확한 하이브리드 검색(vector + BM25 — 절대 근사치 사용 안 함), 설명 가능한 랭킹, 메모리 히스토리의 시간 여행, 불확실성을 인정하는 충돌 인식 검색, 작업 결과로부터 학습된 중요도, 예산 제한 컨텍스트 패킹(numpy가 있을 때 정확히 최적임), 그리고 CI에서 단위 테스트할 수 있는 결정론적 동작을 제공합니다. LangChain 및 CrewAI용 어댑터와 내장 MCP 서버를 갖추고 있습니다.
pip install remembrane
왜 필요한가 (Why)
에이전트는 세션 사이에 모든 것을 잊어버립니다. 기존의 메모리 솔루션들은 클라우드 API를 사용하거나, 벡터 데이터베이스를 요구하거나, 무거운 프레임워크를 끌어들입니다. remembrane는 그 반대입니다:
- 단일 파일. 에이전트의 전체 메모리가 복사, 백업, diff(차이점 비교), 또는 삭제할 수 있는 SQLite 데이터베이스입니다.
- 필요한 의존성 제로. 기본 임베더는 순수 stdlib입니다.
pip install remembrane를 실행해도 다른 것은 가져오지 않습니다. - 인간과 같은 검색 (Human-like recall). 결과는 유사도, 최근성 감쇠(기본적으로 매주 절반으로 감소), 중요도, 그리고 결과로 얻은 유용도의 가중치 합계에 따라 랭킹됩니다. 검색된 메모리는 강화됩니다 — 에이전트를 위한 간격 반복 학습 (spaced repetition)입니다.
- 근사치가 아닌 정확한 값. 대규모 시스템은 근접 이웃 탐색(approximate nearest-neighbor search)을 사용하고 결과 누락을 감수합니다. 에이전트 메모리 규모에서는 remembrane이 모든 메모리를 점수화합니다 — 하이브리드 벡터 + BM25 키워드를 한 번의 과정에서 처리하여 완전함을 보장합니다.
- 디버깅 가능한 메모리. 모든 저장/망각/강화 작업은 저널링됩니다. 특정 시점에 에이전트가 무엇을 알고 있었는지 스냅샷, diff를 찍고 재구성할 수 있습니다. 모든 검색 결과는 왜 해당 순위에 놓였는지 정확하게 설명합니다.
- CI에서 테스트 가능. 결정론적 임베더 + 고정 시간 검색 = 재현 가능한 메모리 동작입니다.
remembrane.testing은 pytest 친화적인 어설션을 제공합니다. - 프레임워크 독립적. 이를 순수하게 사용하거나, LangChain 또는 CrewAI 어댑터를 통해 사용하거나, MCP 기능을 갖춘 모든 에이전트(예: Claude)에 MCP 서버로 노출할 수 있습니다.
빠른 시작 (Quick start)
from remembrane import MemoryStore
mem = MemoryStore(
### 메모리 라이프사이클
```python
mem.reinforce(memory_id) # 강화: 느린 감쇠, 높은 순위
mem.forget(memory_id) # 삭제 (하나)
mem.forget(namespace="ops") # 네임스페이스 전체 삭제
...
검색력 튜닝 (Tuning recall)
from remembrane import MemoryStore, ScoringConfig
mem = MemoryStore(
...
임베더(Embedders)
기본 HashEmbedder는 결정론적이며, 오프라인으로 작동하고 의존성이 없습니다. 이 임베더는 단어 및 문자 n-gram을 해싱합니다. 따라서 유사성은 의미론적(semantic)이 아니라 *어휘적(lexical)*입니다. 이는 일반적인 에이전트 메모리(사실, 선호도, 짧은 진술)에 잘 작동합니다. 진정한 의미론적 검색(semantic recall)을 위해서는 실제 모델을 연결하세요:
from remembrane import MemoryStore, SentenceTransformerEmbedder, OpenAIEmbedder
mem = MemoryStore("agent.db", embedder=SentenceTransformerEmbedder()) # 로컬 사용 시: pip install remembrane[sentence-transformers]
...
embed(texts) -> List[List[float]] 메서드와 dimension 속성을 가진 모든 객체가 작동합니다.
참고: 하나의 데이터베이스에 여러 임베더를 섞어 사용하지 마세요. 서로 다른 임베더에서 생성된 벡터는 비교할 수 없습니다.
LangChain
현재 LangChain (langchain-core 1.4 기준 검증):
from langchain_core.runnables.history import RunnableWithMessageHistory
from remembrane import MemoryStore
from remembrane.adapters import RemembraneChatMessageHistory
...
pip install langchain-core가 필요합니다 (지연 임포트됨 — 나머지 remembrane은 의존성 없이 작동). 레거시 pre-1.x 코드를 위해서는, RemembraneChatMemory가 여전히 의미론적 검색과 함께 이전의 save_context / load_memory_variables 인터페이스를 제공하며, LangChain 설치가 전혀 필요 없습니다.
CrewAI
from remembrane import MemoryStore
from remembrane.adapters import RemembraneStorage
...
저장소 헬퍼(storage helper)이며, 덕 타이핑(duck-typed) 방식으로 작동합니다 (save/search/delete/update/list_records/get_record/count/reset 등, kwargs 허용). 알려진 한계점: 이는 등록된 crewai.StorageBackend 서브클래스가 아니며, (MemoryRecord, score) 튜플 대신 딕셔너리(dict)를 반환하므로, crewai 1.14 기준으로는 crewai.Memory(...)에 직접 연결할 수 없습니다 — 직접 사용하거나 얇은 래퍼(thin shim) 뒤에서 사용하십시오. 네이티브 StorageBackend 통합 기능은 로드맵에 있습니다. 참고로 CrewAI 자체는 데이터를 전송합니다 (telemetry.crewai.com); 만약 이것이 중요하다면 CREWAI_DISABLE_TELEMETRY=true를 설정하십시오 — 순수한 remembrane은 어떤 소켓도 열지 않습니다 (Python audit hooks 하에서 감사 완료).
MCP 서버
어떤 MCP(Multi-Capability Protocol) 지원 에이전트(예: Claude Desktop, Claude Code)에게 영구 메모리를 제공하세요:
pip install remembrane[mcp]
remembrane-mcp --db ~/agent-memory.db
{
"mcpServers": {
"remembrane": {
...
노출되는 도구(Tools) 목록: memory_store, memory_recall, memory_forget, memory_reinforce, memory_conflicts, memory_resolve, memory_feedback, memory_pack, memory_stats. 저장된 콘텐츠는 메모리당 10만 자로 제한됩니다 (REMEMBRANE_MAX_CONTENT를 변경하여 조정 가능).
CLI (명령줄 인터페이스)
remembrane --db agent.db store "the user prefers dark mode" --importance 0.8
remembrane --db agent.db recall "what theme?"
remembrane --db agent.db list
...
충돌 인식 리콜(Conflict-aware recall)
다른 모든 메모리 시스템은 모순을 조용히 해결하고 하나의 확신에 찬 답변만 반환합니다 — 이것이 에이전트가 자신감 있게 틀리는 이유입니다. remembrane은 이러한 긴장 상태를 표면화하여 에이전트가 판결(adjudicate)하도록 하거나 (또는 사용자에게 질문하게 합니다):
mem.store("the user lives in London")
mem.store("the user moved to Tokyo, no longer in London")
...
탐지(Detection)는 결정론적이며 무료입니다 (앵커 단어 중복, 부정 마커, 숫자 불일치, 값 대체 등—숨겨진 LLM 판단이 아닌 정직한 휴리스틱). 두 가지 신뢰도 계층으로 나뉩니다: likely(강하게 부정되거나, 보강 증거가 있는 숫자/요일/월 불일치, 또는
에이전트는 '상위 5개 결과'를 원하는 것이 아니라, 남아있는 컨텍스트 창 공간을 가장 잘 활용하는 것을 원합니다:
context = mem.pack("user preferences", budget_tokens=800)
sum(r.tokens for r in context) # <= 800, 보장됨
pack()은 모든 후보를 정확하게 점수화하고, 근접한 중복을 억제하여 예산이 같은 내용을 두 번 말하는 데 쓰이지 않도록 하며, 이후 0/1 배낭(knapsack) 문제로 선택을 해결합니다. 이 예산은 모든 구성에서 하드 보장됩니다 (무작위로 수천 번의 테스트를 거쳐 검증됨). 최적성은 경로에 따라 달라집니다: numpy가 설치된 경우 솔루션은 1 토큰 단위로 정확하며; 순수 파이썬 폴백(fallback)은 거칠게 조정된 가중치와 탐욕적인 채움(greedy refill)을 사용하며, 이는 최적이라기보다는 근사적으로 최적이라고 문서화되어 있습니다 (최악의 관측 손실은 적대적인 무작위 인스턴스에서 16% — 실제 메모리 저장소는 그에 훨씬 못 미칩니다). 결정론적이며 LLM을 사용하지 않습니다. 정확한 카운트를 위해 token_estimator=your_tokenizer를 전달하세요.
타임 트래블 (Time travel)
모든 변경 사항은 저널링(journaled)되므로, 과거가 조회 가능합니다:
mem.snapshot("before-research")
# ... 에이전트 실행, 학습, 망각 과정 진행 ...
...
또는 CLI에서: remembrane snapshot v1, remembrane diff v1, remembrane log.
"내 에이전트는 지난 화요일에 무엇을 믿었고, 무엇이 그 생각을 바꾸었나?"가 이제 답변 가능한 질문입니다.
설명 가능한 회상 (Explainable recall)
블랙박스는 없습니다 — 모든 결과는 전체 순위 분석 내역을 가지고 있습니다:
r = mem.recall("what theme does the user like?")[0]
r.explain()
# {'score': 0.6087, 'components': {'vector_similarity': 0.71, 'keyword_bm25': 1.0,
...
에이전트 메모리 테스트하기
결정론적 회상은 메모리 동작을 단위 테스트(unit-testable)할 수 있게 합니다 — 클라우드 메모리 API가 제공할 수 없는 기능입니다:
from remembrane.testing import assert_recalls, assert_recalls_first, assert_not_recalls
def test_agent_remembers_allergies():
...
recall()에 now=...를 전달하여 시간을 고정하고 최신성 점수(recency scoring)를 재현 가능하게 만드세요.
메모리 병합 (Merging memories)
메모리 파일은 이식성이 뛰어나므로 — 근접한 중복 흡수 기능을 통해 두 에이전트의 지능을 합칠 수 있습니다:
mem.merge_from("other-agent.db") # {'added': 12, 'merged': 3}
mem.merge_from("backup.db", namespaces=["prefs"], dedupe_threshold=0.95)
CLI: remembrane --db a.db merge b.db
성능 (Performance)
성능 수치는 기기 간에 전파되지 않으므로, 먼저 직접 측정해 보세요:
python -m remembrane.bench
두 가지 기준점(하이브리드 검색률, 512차원 기본 임베더, 따뜻한 캐시):
| memories | recall / pack (Linux sandbox, py3.10, numpy) | recall / pack (independent audit: Windows, py3.12, numpy) | recall (pure python, audit machine) |
|---|---|---|---|
| 1,000 | ~2 ms / ~17 ms | ~5 ms / ~32 ms | ~113 ms |
| ... |
The 핵심은 의존성 없이 작동합니다. 만약 numpy를 가져올 수 있다면 자동으로 사용됩니다 (pip install remembrane[fast]), 그리고 numpy 설치 오류는 치명적이기보다는 무시됩니다. 10,000개의 메모리 이상에서 10ms 미만의 검색률을 원하거나, 50,000개를 넘어설 경우, 이는 설계 범위를 벗어난 것입니다 — 그 영역은 벡터 데이터베이스(vector-database)의 영역이며, remembrane는 그렇지 않다고 가장하지 않습니다.
동시성 (Concurrency)
여러 연결, 스레드 및 프로세스가 하나의 메모리 파일을 공유할 수 있습니다: 파일 기반 저장소는 기본적으로 SQLite WAL 모드를 사용하며 바쁜 시간 초과(busy timeout)와 즉각적인 쓰기 트랜잭션(immediate write transactions)을 처리합니다. 캐시는 SQLite의 data_version을 통해 외부 쓰기를 감지하고, 잔여 잠금 경쟁은 재시도됩니다. 저희 테스트 스위트는 단일 파일에 대해 3개의 연결 × 6개의 스레드 및 8개의 프로세스를 가동하여 오류 없이 작동함을 확인했습니다. 두 가지 주의사항이 있습니다: WAL은 DB 옆에 일시적인 -wal/-shm 사이드카 파일을 유지하므로 (엄격한 단일 파일 동작을 원하면 `journal_mode=
점수(Scoring)는 가중치 합산 방식이며 (가중치는 1로 정규화됨), 하나의 엄격한 규칙이 있습니다: 메모리가 반환되려면 유사성(similarity)은 반드시 양수여야 합니다. 최근성(recency)과 중요도(importance)는 관련 있는 메모리를 순위화할 뿐, 관련성(relevance)을 대체하지는 않습니다.
age는 메모리 생성 시점이 아닌 마지막 접근 시간을 기준으로 측정됩니다. 모든 회상(recall)은 감쇠 타이머를 재설정합니다. 자주 사용되는 메모리는 선명하게 유지되고, 건드리지 않은 것은 희미해집니다. 기본 하이브리드 모드에서는 유사성이 0.65·코사인 + 0.35·bm25로 계산됩니다. 모든 가중치, 모드, 그리고 반감기(half-life)는 설정 가능합니다.
설계 선택 (Design choices)
- 벡터 DB 대신 SQLite 사용 — 에이전트 메모리 저장소는 작습니다 (수십억 개가 아닌 수천 개의 행). 그 규모에서 정확한 무차별 대입(brute-force) 점수 계산은 충분히 빠르며 (측정된 숫자는 성능 섹션 참조), 트랜잭션, 단일 휴대용 파일, 그리고 인프라 제로를 얻을 수 있습니다.
- 백그라운드 데몬 없음 — 감쇠는 읽기 시간(read time)에 계산되므로, 에이전트가 작동하지 않을 때는 아무것도 실행되지 않습니다.
- 덕 타이핑 어댑터 (Duck-typed adapters) —
remembrane은 langchain이나 crewai를 절대 가져오지 않습니다. 어댑터들은 인터페이스를 구조적으로 일치시키기 때문에 버전 고정(version-pinning) 충돌이 없습니다.
범위 참고 사항 (Scope notes)
AI 자동 생성 콘텐츠
본 콘텐츠는 HN Claude Code Search의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기