계기는 단순했다. GitHub에서 agentmemory라는 리포를 하나 봤는데, “코딩 에이전트가 세션이 끝나도 다 기억한다”는 슬로건이 눈에 띄어서, 지금 쓰고 있는 Hermes의 메모리 시스템과 비교했을 때 이걸 새로 붙일 만한지 확인하려고 시작한 일이었다. 그런데 확인해보니, Hermes에 이미 비슷한 게 있었다.
이미 있었다, 그것도 8개나
Hermes는 MEMORY.md/USER.md 기반의 내장 메모리가 항상 켜져 있고, 그 위에 외부
메모리 프로바이더를 플러그인으로 붙일 수 있는 구조였다. hermes memory status를
쳐보니 이미 설치까지 돼 있는 프로바이더가 8개나 있었다 — mem0, honcho, hindsight,
byterover, holographic, openviking, retaindb, supermemory. 단지 활성화된 게
하나도 없었을 뿐.
그래서 방향이 “이 리포 하나를 새로 붙일까”에서 “이미 있는 8개 중 뭐가 제일 나을까”로 바뀌었다. 8개 각각 소스 코드를 열어서 방식만 먼저 훑었다 — byterover(로컬 CLI 기반 계층형 저장), openviking(ByteDance, 파일시스템 구조 메모리), retaindb(클라우드 전용, 기능은 제일 풍부함), supermemory(제일 가볍지만 API 키 필수, 로컬 옵션 없음)는 이 훑어보는 단계에서 후순위로 밀렸다. 나머지 4개는 좀 더 깊게 들여다봤다.
- mem0: GitHub 스타 6만 개, 이 바닥에서 제일 크고 성숙한 프로젝트. 다만 self-host (OSS 모드)로 쓰려면 벡터 DB를 따로 붙여야 했다.
- holographic: 완전 로컬, 외부 의존성이 표준 라이브러리뿐이라 비용이 사실상 0원. 근데 벤치마크 자료도, 사용 사례도 거의 없었다 — 검증이 안 된 선택지였다.
- hindsight: MIT 라이선스, 벤치마크 점수가 제일 높다는 자료도 있었다. 로컬로 돌리는 모드가 있긴 한데, 그 안에서도 결국 LLM 호출이 필요해서 완전 무료는 아니었다.
- honcho: 스타는 4천 개대로 작지만 최근 성장세가 빨랐고, 벤치마크에서 오히려 mem0보다 높은 점수가 나온 비교 자료들이 있었다. “사실을 저장”하는 대신 “이 사람이 어떻게 생각하는지 패턴 자체를 모델링”하는 컨셉이 마음에 들었다.
결국 이 넷 중 Honcho로 골랐다. self-host가 가능하고(AGPL이지만 혼자 쓰는 거라 문제없음), LLM 연결을 이미 갖고 있는 Gemini API 키로 그대로 붙일 수 있었다.
붙이는 과정에서 계속 걸린 것들
여기서부터가 진짜 삽질이었다. Honcho를 Hermes에 self-host로 붙이는 커뮤니티 템플릿 (elkimek/honcho-self-hosted)이 있어서 그걸 기준으로 시작했는데, 컨테이너를 띄우자마자 이런 에러가 났다.
pydantic_core._pydantic_core.ValidationError: 1 validation error for DeriverSettings
Value error, REPRESENTATION_BATCH_MAX_TOKENS has been split into
REPRESENTATION_BATCH_WORK_UNIT_TARGET_TOKENS ... and
REPRESENTATION_BATCH_TARGET_INPUT_TOKENS ...
처음엔 필드 이름 하나만 바뀐 줄 알았다. 그런데 고치고 나니 다음 필드에서 또 걸리고,
더 파보니 훨씬 근본적인 변화였다 — 예전엔 각 항목마다 PROVIDER = "vllm",
MODEL = "z-ai/glm-4.7-flash" 식으로 평평하게 쓰던 구조가, 지금은
[deriver.model_config] 밑에 transport/model/overrides/fallback을
중첩해서 쓰는 구조로 통째로 바뀌어 있었다. 임베딩 설정도 마찬가지로, 예전엔
[llm] EMBEDDING_PROVIDER랑 LLM_EMBEDDING_* 환경변수로 잡던 게 지금은
아예 별도의 [embedding] 섹션으로 옮겨갔고, 옛날 환경변수 이름은 이제 코드
어디에서도 안 읽힌다. 결국 upstream 리포에 있는 config.toml.example(그 시점
코드 기준 최신 전체 옵션 예시)을 기준으로 설정 파일을 처음부터 다시 썼다.
그다음 걸린 건 임베딩 차원이었다.
psycopg.errors.ProgramLimitExceeded: column cannot have more than 2000 dimensions for hnsw index
Gemini의 임베딩 모델(gemini-embedding-001)은 기본으로 3072차원짜리 벡터를 뱉는데,
Postgres의 벡터 검색 인덱스(HNSW)는 2000차원까지만 지원한다. 다행히 Gemini 임베딩은
차원을 줄여서 받는 옵션(output_dimensionality)을 지원해서, 1536차원으로 잘라
받도록 설정해서 해결했다.
그다음엔 설정 파일을 고쳐도 반영이 안 되는 문제를 만났다 — 알고 보니 config.toml이
컨테이너 빌드 시점에 이미지 안으로 복사되는 구조라, 파일만 고치고 재시작해서는
소용없고 매번 다시 빌드해야 했다.
컨테이너를 다 띄우고 나서는 보안 쪽에서 하나 걸렸다. 템플릿의 docker-compose.yml이
API 포트(8000)를 0.0.0.0에 그대로 열어두고 있었다 — Postgres/Redis는 이미
127.0.0.1에만 묶어놨으면서, 정작 API는 아니었다. 이 Honcho 인스턴스는 인증
(AUTH_USE_AUTH)이 기본으로 꺼져 있는데, 그 상태로 VPS 공인 IP에 그대로 노출돼
있었던 거다. DB/Redis랑 똑같이 127.0.0.1에만 바인딩하도록 고쳤다.
마지막으로, 다 설정해놓고 Hermes 쪽에서 hermes memory status를 쳐보니 여전히
“활성화 안 됨”으로 나왔다. Honcho 쪽 설정 파일(honcho.json)만 갖다 놓으면 되는
줄 알았는데, Hermes의 config.yaml에 memory.provider: honcho를 따로 명시해야
했다. 이걸 빼먹으면 파일은 다 맞게 있는데 그냥 조용히 무시된다.
PR 감이 세 개 나왔다
겪은 문제를 하나씩 정리하다 보니, 이 중 몇 개는 나만 겪고 넘어갈 게 아니라 다음 사람도 똑같이 겪을 문제라는 생각이 들었다.
- 커뮤니티 self-host 템플릿(
elkimek/honcho-self-hosted)의config.toml이 구버전 스키마 그대로라, 이 가이드를 따라가는 다음 사람도 똑같은 크래시를 겪을 거다. - Honcho 본체(
plastic-labs/honcho) 쪽엔, Gemini를 임베딩 provider로 쓰면 기본 차원(3072)이 pgvector 인덱스 한도(2000)를 넘는다는 경고가 어디에도 없다. - Hermes(
NousResearch/hermes-agent) 쪽엔, 설정 파일은 다 맞는데memory.provider하나를 빼먹으면 아무 에러 없이 조용히 무시되는 부분이 있다.
세 개 다 실제로 PR을 넣어볼 만하다고 판단했다. 다만 이번 글에서 다루진 않는다 —
지난번 AstroPaper PR 때는 gh 토큰에 fork 권한이 없어서 직접 손으로 진행했었는데,
이번엔 권한을 갖춘 토큰으로 명령어를 통해 직접 진행해보려고 한다. 그 과정은 따로
글로 남길 생각이다.
예상 못 했던 좋은 점
설정을 다 맞추고 나서 진짜 대화를 하나 보내봤다. 그런데 활성화되는 순간, 기존에
쌓여있던 MEMORY.md/USER.md 내용이 자동으로 Honcho 안으로 마이그레이션됐다.
지금까지 쌓아온 메모리(블로그 현황, 작업 습관 같은 것들)가 하나도 안 사라지고
그대로 넘어간 거다. 이런 마이그레이션 경로까지 신경 써서 만들어놨을 줄은 몰랐다.
그리고 테스트 삼아 문장 몇 개를 보내봤더니, 거기서 서로 다른 사실 14개를 정확하게 뽑아낸 것도 인상적이었다. “제일 좋아하는 프로그래밍 언어는 C”, “셀프호스팅을 선호함” 같은, 문장 안에 흩어져 있던 정보들을 하나씩 분리해서 저장해놨다.
앞으로 기대되는 것
지금까지 Hermes의 내장 메모리는 2,200자로 압축된 요약본이라, 오래된 디테일은 결국 요약 과정에서 잘려나갔다. 이제는 대화 전체를 의미 기반으로 검색할 수 있으니까, “그때 그 CouchDB 백업 스크립트를 어떻게 짰었지” 같은 세부적인 질문에도 몇 주 전 대화까지 다시 끌어올 수 있을 거다. 그리고 텔레그램이든 CLI든, 같은 사람이 쓰고 있다는 걸 더 확실하게 유지해줄 거라는 기대도 있다.
돌아보면 시작은 “이 GitHub 리포 뭐 하는 거야?”라는 가벼운 질문이었는데, 그 질문을 따라가다 보니 이미 갖고 있던 도구를 더 깊이 알게 됐고, 결국 그걸 직접 운영하는 데까지 왔다. 원래 붙이려던 리포는 결국 안 썼다.