블로그로 돌아가기

Hermes 같은 코딩 에이전트, 작동 방식 뜯어보기

코드가 아니라 작동 논리로 읽는 Hermes — 입력(TIER 1) → 생각·행동(TIER 2) → 출력(TIER 3)에서 핵심인 가운데 에이전트 루프를 집중해 뜯어봅니다.

15 min2026년 6월 28일

코드가 아니라 작동 논리로 보는 Hermes. 단순히 코드 레벨에서 알아보는 것이 아니라, 우리들이 실제 에이전트를 만드는데 필요한 전체 아키텍처를 알 수 있도록 그 구조를 뜯어봅니다. 전체적인 구조는 인풋을 들여오고(TIER 1) → 생각·행동하고(TIER 2) → 나가는(TIER 3) 흐름인데, 처음과 끝(입구·출구)은 비교적 단순하니, 가운데 **에이전트 루프(TIER 2)**를 집중해서 봅니다.

주요 모듈 정의하기

가운데에 AI 에이전트 코어가 있고, 이 코어의 에이전틱 루프(agentic loop) 방식으로 작동합니다. 여기에 접속하는 길은 세 가지예요.

  • CLI — 터미널에 hermes라고 치면 바로 대화 시작
  • 게이트웨이(gateway) — 항상 떠 있으면서 텔레그램·슬랙·이메일 같은 메신저와 연결
  • API — 응용 프로그램에서 Hermes를 호출

중요한건, CLI든 아니면 텔레그램과 같이 외부의 툴과 연동하는 gateway든, 최대한 모든 컨텍스트를 가져오려고 노력한다는 것이다.

Hermes 아키텍처 한눈에 보기

Tier2에 속한 에이전트 루프는 이런 것들이 pre-built 되어있어요 — 도구(tools), 기술(skills), 기억(memory), 그리고 에이전트의 정체성·사용자 정보를 담는 soul.md·user.md 같은 파일. 기억은 두 갈래인데, 외부 기억(mem0·supermemory 같은 외부 제공자)과 내부 기억(대화 전체가 그대로 쌓이는 세션 트랜스크립트)으로 나뉘어요.

겉보기엔 단순하지만, 진짜 알맹이는 가운데 코어, 즉 루프예요.


TIER 2 ① — 에이전트 루프: 매번 도는 사이클

Hermes 에이전트 논리 구조의 핵심은 다음 기능들로 이루어져 있어요. 사용자가 메시지를 보낼 때마다 이 loop가 한 바퀴 도는데, 크게 보면 생각보다 단순합니다.

  1. 사용자가 메시지를 보낸다.
  2. 컨텍스트를 빌드한다(build context). 갖고 있는 내부 기억과 미리 준비된 프롬프트를 끌어모아 "지금 상황"을 한 덩어리로 차려요. (무엇이 들어가는지는 ②에서)
  3. 전체 컨텍스트 + 메시지 히스토리를 LLM에 보낸다.
  4. LLM이 도구를 부르면, 도구를 실행하고 그 결과를 다시 LLM에 돌려준다. 그리고 LLM이 계속 도구를 써야 한다고 판단하는 한 이 과정을 반복해요. 웹 검색 한 번이면 한두 바퀴, 복잡한 작업이면 더 많이 — 파일을 읽고 쓰고, 명령을 실행하고, 검색합니다.
  5. 더 이상 도구를 사용할 필요 없을 정도로 정보가 충분하면 최종 응답을 준다.
  6. 메모리 업데이트(memory update). 사용자에게 응답을 한다고 끝이 아니에요. 에이전트가 방금 대화를 분석해서 *"기억해 둘 가치가 있는 게 있었나?"*를 보고, 있으면 기억에 적어둬요.

6번이 Hermes를 특별하게 만드는 지점이에요. 매 상호작용에서 배운 걸 남기니까, 다음에 비슷한 걸 물으면 이미 알고 있는 — 쓸수록 나아지는 에이전트가 되는 거죠.


TIER 2 ② — 컨텍스트: 매 턴 LLM에 무엇이 들어가나

루프 2번 "컨텍스트 빌드"가 사실 에이전트 품질을 좌우하는 가장 중요한 부분이에요. Hermes의 컨텍스트는 의외로 미니멀한데, 몇 개의 마크다운 파일을 기반으로 만들어집니다.

  • soul.md — 에이전트의 성격(시스템 프롬프트). 어떤 말투로, 무엇을 지향하며, 어떻게 행동할지. Claude의 잘 쓰인 시스템 프롬프트를 떠올리면 돼요. 설치 직후엔 보통 비어 있고, 처음에는 "나는 항상 켜져 있는 Hermes 비서다" 정도의 기본 프롬프트만 작성되어있어요. 제대로 쓰려면 자기한테 맞게 직접 작성하는게 좋습니다.
  • memory/user.md당신에 대한 정보. soul.md와 달리 에이전트가 자동으로 갱신해요. 대화 중에 "나는 소프트웨어 엔지니어다" 같은 게 나오면, 그게 당신에 대한 사실임을 알아채고 여기에 적어둬요.
  • memory/memory.md임의의 학습된 사실. 당신에 대한 정보라기보단, 도구 쓰는 법·워크플로우·대화 중 알게 된 유용한 것들. 목표(soul.md)도 함께 참고하여 작업을 하면서 기억할 만하다 싶으면 여기에 쌓여요. 일종의 경험치라고 생각하시면 됩니다.
  • 과거 세션 요약외부 기억을 설정했을 때만 등장하는, 지금 대화와 관련 있을 법한 옛 대화의 요약.
  • 스킬 설명 + 도구 설명 — 쓸 수 있는 기술·도구의 목록과 설명.
  • 최근 메시지 — 지금까지의 대화. 단, 일정 임계치를 넘으면 통째로가 아니라 요약본으로 들어가요.

agent가 기억하기 위해 필요한 파일들은 간단하지만, 이 파일들을 이용한 '컨텍스트'는 사실 간단하게 만들어지지 않아요. 컨텍스트는 **"정체성 + 너에 대한 메모 + 임의 메모 + 할 수 있는 일 목록 + 최근 대화"**의 조합이고, 이게 매 턴 LLM에게 통째로 전달됩니다. 에이전트는 매번 과거의 전체 정보를 다시 보게 되는 셈이죠.

Hermes 메모리 구조 (간단 버전)


TIER 2 ③ — 컨텍스트 압축: 길어지면 어떻게 버티나

대화가 길어지면 컨텍스트가 모델의 한계(컨텍스트 윈도우, 보통 25만~100만 토큰)에 가까워져요. Hermes는 이때 **압축(compression)**을 통해 이 한계점을 극복합니다.

  • 언제: 설정한 비율(기본 85%)을 넘으면 트리거. 체크 시점은 두 군데 — 매 턴(메시지 보내기) 직전과, LLM이 컨텍스트 초과 에러를 냈을 때.
  • 무엇을: 이전 메시지들을 요약해요. 옛 메시지를 요약 한 덩어리로 바꿔 컨텍스트에 붙이고, 원래 메시지들은 삭제해요.
  • 얼마나 찼는지 어떻게 아나: 첫 메시지 땐 아직 모델 응답이 없어 토큰 수를 정확히 모르니, 글자 수 ÷ 4로 어림잡아요(토크나이저를 직접 돌리면 정확하지만 너무 비싸서). 그 다음부터는 모델이 응답과 함께 돌려주는 usage(사용 토큰) 값을 그대로 써요.
  • 구조화된 요약: 단순 요약이 아니라 여러 섹션으로 구조화해요 — 전체 목표, 제약, 완료한 행동, 현재 상태, 진행 경과, 막힌 부분, 내린 핵심 결정, 해결된 질문, 관련 파일, 다음 단계 등. (더 미니멀한 에이전트들 보다 훨씬 더 풍부한 요약 프롬프트를 써요.)

이 압축 덕분에 12시간짜리 긴 작업도 컨텍스트가 끊기지 않고 이어집니다 — 다만 에이전트가 자기 작업을 얼마나 잘 요약하느냐에 품질이 달려 있다는 한계점이 있어요. 더 '논리적인 사고'가 좋은 모델일 수록 컨텍스트 요약 작업을 더 잘 하겠죠.


TIER 2 ④ — 기억: 세 가지 형태 (agent의 근간)

LLM에게 컨텍스트를 주기도 하고, LLM의 결과를 저장하는 것이 Memory, 즉 기억 체계이기 때문에, 이 기억 저장 방식이 결국 Hermes agent의 가장 근간이라고 할 수 있어요. 이 Hermes의 기억은 세 가지 형태가 있어요.

  • 마크다운 파일 — 앞서 본 soul.md·memory.md·user.md. 시스템 프롬프트 바로 뒤에 항상 컨텍스트에 붙어요.
  • SQLite 데이터베이스 — Hermes는 과거 대화를 불러올 수 있어야 하니, 모든 세션의 **전체 트랜스크립트(full transcript)**를 SQLite에 저장해요. 그리고 사용자와 대화를 이어갈 때 여기서 히스토리를 끌어와요. 추가로 bare-text(순수 텍스트만 저장한 SQL 테이블)이 있어 유사도 검색을 쉽게 할 수도 있어요.
  • 외부 기억(external memory) — mem0·supermemory·honcho 같은 외부 메모리 모듈. 기본적으로는 off 되어 있어요. 켜두면 첫 메시지 이후에 외부 기억을 조회해 "다음 질문은 뭘까"를 미리 떠올려요. 이건 사람이 생각하는 것과 비슷해요. 인간은 특정 질문을 들으면 그 질문에 답하면서 동시에 과거 비슷한 대화를 떠올리죠. 외부 메모리도 이런 방식으로 방금 사용자가 한 질문과 비슷한 질문을 생성하고, 그 질문들을 과거 DB로부터 서치를 합니다.

Hermes 메모리 아키텍처


TIER 1 — 들어오는 길: 게이트웨이 (조금 더 자세히)

입구 중 가장 흥미로운 건 게이트웨이예요. Hermes를 대중적으로 만든 부분이기도 하고요.

게이트웨이는 asyncio 루프를 돌리면서 텔레그램·디스코드·이메일·SMS·왓츠앱 같은 여러 메신저를 계속 듣고 있어요. 각 메신저는 듣는 방식이 달라서(어떤 건 웹훅, 어떤 건 매초 한 번 API를 찔러보는 작은 루프, 어떤 건 웹소켓), 메신저마다 따로 설정해야 해요(hermes setup gateway로 봇 ID·허용 사용자 ID 등록).

핵심은, 게이트웨이는 메시지를 받기만 하는 게 아니라는 점이에요. 텔레그램에서 오면 그 한 줄만 받으니까, 게이트웨이가 컨텍스트와 메시지 히스토리를 매번 새로 조립해야 해요. 세션 식별자를 텔레그램 + 세션 id + …로 만들어 SQLite에서 그 대화의 히스토리를 통째로 끌어와 컨텍스트에 붙이고, 그걸 코어에 넘기죠. 즉 게이트웨이 ↔ SQLite 기억 ↔ 코어 루프가 한 묶음으로 돌아가요.

또 게이트웨이엔 세션 매니저가 있어서, 에이전트가 일하는 중에 새 메시지를 보내면 그걸 중단(interrupt)할지, 방향을 틀(steer)지, 대기열에 넣(queue)을지 정해요. 텔레그램에서 /interrupt를 쓰면 멈추고, /steer를 쓰면 방향을 틀고, 그냥 보내면 큐에 쌓이는 식이에요.


TIER 3 — 나가는 길 + 자동화: 크론

여기에 더해, Hermes의 특징적인 모듈이 크론(cron) 이에요. 이것 덕분에 몇 가지 자동화 기능을 수행할 수 있어요.

서버에서 쓰던 cron을 떠올리면 되는데, 한 가지 다른 점이 있어요. Hermes의 크론은 서버 cron 프로세스에 묶여 있지 않고, 자체적으로 매분 도는 루프예요. 매분 tick()이라는 함수가 돌면서, 그 순간에 실행할 잡(job)이 있는지 확인하고 바로 실행해요. 크론 덕분에 "매일 아침 AI 뉴스를 이메일로 보내줘", "매주 금요일 상사에게 보고 보내줘" 같은 걸 자동화할 수 있죠.


한 장 정리

한 문장으로: Hermes는 매 메시지마다 컨텍스트를 차리고 → LLM에 넘겨 생각하게 하고 → 도구를 쓰고 결과를 되먹여 반복하다가 → 응답하고 → 배운 걸 기억에 남기는 루프예요. 입구(게이트웨이)와 출구(크론)는 이 루프에 메시지를 넣고 빼주는 역할이고요.