에이전트의 안을 열다 — Hermes Agent 뜯어보기
오픈소스 개인 AI 에이전트 Hermes Agent의 소스를 뜯어봤습니다. 기억을 단일 SQLite에 담고, 무한 대화를 '압축 계보'로 잇고, 프롬프트 캐시를 신성불가침으로 지키는 설계. 에이전트를 직접 만들어 본 입장에서 인상 깊었던 지점을 정리했습니다.

지난 시리즈에서 제 손으로 에이전트 파이프라인을 만들어 봤더니, 잘 만든 에이전트는 안을 어떻게 짰는지가 궁금해졌습니다. 그래서 오픈소스 개인 AI 에이전트 Hermes Agent(Nous Research)의 소스를 뜯어봤습니다. 약 1만 개 파일에 이르는 큰 프로젝트라, 인상 깊었던 설계만 골라 정리합니다.
에이전트의 기억은 어디에 사는가
가장 먼저 궁금했던 건 "대화와 기억을 어디에 저장하나"였습니다. 답은 의외로 소박했습니다. 단일 SQLite 파일 하나(state.db)입니다. 별도의 DB 서버도, 클라우드도 없이 파일 하나에 세션·메시지·통계·검색 인덱스를 전부 담습니다.
대신 그 파일 하나를 안전하게 다루는 데 공을 들였습니다. WAL 저널 모드로 다중 프로세스(게이트웨이·CLI·터미널 UI)가 동시에 붙고, 한 세션을 두 프로세스가 동시에 굴리지 못하도록 **turn lease(턴 임대)**로 직렬화합니다. 파일이 손상되면 오류를 종류별로 분류해 복구하거나 격리하고요. "가벼운 로컬 우선(local-first)" 저장소를 이렇게까지 튼튼하게 만들 수 있다는 게 인상적이었습니다.
무한 대화의 비밀: 압축 계보
LLM에는 문맥 한계가 있습니다. 대화가 길어지면 언젠가 넘칩니다. Hermes는 이걸 **압축 계보(compression lineage)**로 풉니다.
문맥이 차면 현재 세션을 요약해 접고, 새 세션을 부모-자식으로 연결해 회전시킵니다. 물리적으로는 여러 세션이지만, 계보를 따라가면 하나의 논리적 대화로 복원됩니다. 문맥 한계와 영속성을 깔끔하게 분리한 설계입니다. "대화가 끊기지 않는 것처럼" 보이는 비결이 여기 있었습니다.
"캐시는 신성불가침"
가장 인상 깊었던 철학은 이것이었습니다 — 대화별 프롬프트 캐시를 세션 도중에는 절대 흔들지 않는다.
LLM은 같은 앞부분(시스템 프롬프트·히스토리)을 재사용하면 프리픽스 캐시가 적중해 비용과 지연이 확 줄어듭니다. 그런데 에이전트가 세션 도중에 메모리나 스킬을 갱신하면, 시스템 프롬프트가 바뀌어 이 캐시가 깨집니다. Hermes는 이걸 막으려고, 갱신 내용을 디스크에는 즉시 반영하되, 지금 세션의 프롬프트에는 반영하지 않고 다음 세션에 스냅샷으로 주입합니다. "지금의 속도"와 "다음의 최신성"을 맞바꾸지 않는 것이죠. 비용에 민감한 프로덕션 에이전트의 실전 감각이 느껴지는 대목이었습니다.
좁은 허리, 넓은 가장자리
구조 철학도 분명했습니다. 코어는 얇게(narrow waist), 능력은 가장자리에.
새 능력을 붙일 때 코어를 건드리지 않습니다. 툴은 import되는 순간 스스로 레지스트리에 등록(self-registration)되고, 코어는 그저 등록된 걸 조회해 실행할 뿐입니다. 그래서 CLI든 슬랙이든 데스크톱 앱이든, 같은 코어를 그대로 여러 인터페이스에서 돌립니다. 코어를 얇게 지킨 덕에 확장이 쉬워지는, 오래된 그러나 강력한 설계 원칙입니다.
배우는 에이전트: 절차 vs 선언
Hermes는 세션을 거치며 스스로 배웁니다. 여기서 기억을 두 종류로 나눈 게 깔끔했습니다.
- 선언적 기억(메모리): 사용자 선호, 관찰한 사실 같은 "무엇" — 짧은 파일에 저장.
- 절차적 기억(스킬): 성공했던 작업 절차 같은 "어떻게" — 재사용 가능한 스킬로 저장.
게다가 매 몇 턴마다 백그라운드에서 "이걸 스킬이나 메모리로 남길까?"를 스스로 자문하고, 별도 큐레이터가 중복을 정리합니다. 자동 삭제는 금지하고 기록을 남겨 되돌릴 수 있게 한 안전장치까지, 배우되 함부로 잊지 않도록 설계돼 있었습니다.
가장 솔직한 한 문장
문서에서 가장 마음에 남은 건 보안에 대한 태도였습니다. 요지는 이렇습니다 — "적대적 LLM에 대한 유일한 보안 경계는 OS 수준 격리다." 프로세스 안의 승인 게이트나 툴 허용목록은 봉쇄가 아니라 협조 모드용 휴리스틱일 뿐이라고 못박습니다.
에이전트를 안전해 보이게 포장하기보다, "이건 진짜 벽이 아니다"라고 솔직하게 선을 긋는 태도가 오히려 신뢰가 갔습니다. 자동화 에이전트를 실제로 운영할 때, 어디까지 믿고 어디서 격리할지를 정하는 데 중요한 관점입니다.
만드는 사람으로서
제가 만든 건 훨씬 작은 파이프라인이었지만, 뜯어보며 겹치는 원칙이 많아 반가웠습니다. 상태를 파일 하나로 안전하게 관리한 것, 코어를 얇게 두고 스킬로 확장한 것처럼요. 좋은 에이전트일수록, 결국 모델의 똑똑함이 아니라 그 똑똑함을 담는 그릇을 잘 만들어 뒀다는 걸 다시 확인했습니다.
무엇보다, 이렇게 잘 만든 프로젝트가 오픈소스라 소스를 다 읽어볼 수 있다는 게 가장 큰 배움이었습니다. 남이 고민한 설계를 그대로 읽고 훔쳐 배울 수 있으니까요.
정리
- 상태 저장소는 단일 SQLite + WAL + FTS5, 파일 하나를 turn lease·복구로 안전하게 공유.
- 압축 계보로 물리 세션을 회전시켜 무한 대화를 하나의 논리 대화로 유지.
- 프롬프트 캐시 보존 제일주의 — 갱신은 디스크 즉시·프롬프트는 다음 세션에.
- 좁은 허리 + 자기등록으로 코어는 얇게, 능력은 가장자리에.
- 학습은 절차(스킬)·선언(메모리) 분리 + 백그라운드 큐레이션, 자동 삭제 금지.
- 보안은 솔직하게 — OS 격리만이 진짜 경계.
참고