slowlp
← 블로그
이야기 2026.06.11 · 6분 읽기

Discord 메시지가 위키에 자동으로 쌓이는 루프 만들기 — hermes-discord 구축기

폰에서 아이디어를 던지면 second 위키에 쌓이는 루프, ops 레포 하나로 구현하기

이야기

Discord 메시지가 위키에 자동으로 쌓이는 루프 만들기 — hermes-discord 구축기

폰에서 아이디어를 던지면 second 위키에 쌓이는 루프, ops 레포 하나로 구현하기


시작한 이유

이런 상황, 익숙하지 않으신가요. 지하철에서 뭔가 떠올랐습니다. 아이디어인지 메모인지 모르겠지만 붙잡아두고 싶어요. 폰을 꺼내서 옵시디언을 열고, 폴더 찾고, 제목 정하고… 그러는 사이 맥락이 증발합니다.

저는 이 마찰을 없애고 싶었습니다. 왜 Discord를 선택했는지는 이전 글에 썼고, 이미 Discord는 하루에도 몇 번씩 열어보는 앱입니다. 여기서 말을 걸면 그게 바로 위키에 들어가는 루프가 있으면 어떨까요.

hermes-agent라는 LLM 에이전트 프레임워크가 Discord 게이트웨이를 공식 지원한다는 걸 확인한 뒤(처음에 “Discord 지원 안 한다”고 잘못 알고 있다가 나중에 확인했습니다), 작업을 시작했습니다.


ops 레포라는 설계 결정

제가 만든 hermes-discord 레포는 독특한 성격을 갖습니다. 앱 소스가 없습니다. upstream의 hermes-agent Docker 이미지를 가져다 감싸는 ops 레포입니다. Dockerfile과 docker-compose.yml, 환경변수 관리 스크립트, 그리고 문서들만 있습니다.

왜 이렇게 했냐면, hermes 자체를 고칠 생각이 없었기 때문입니다. 제가 관리하고 싶은 건 “어떻게 배포하느냐”와 “second 볼트를 어떻게 연결하느냐”뿐이었거든요.

핵심 구조는 세 가지로 정리됩니다:

  • 실행 위치: [[집서버-앱-공존-구성|개발 서버(hong)에서 24/7 운영]]. 로컬은 git 관리 전용입니다. 맥북을 덮어도 봇은 살아있어야 하니까요.
  • 토큰 제약: Discord 봇 토큰 하나당 게이트웨이 연결은 하나입니다. 로컬과 서버에서 동시에 띄우면 같은 봇이 두 개 응답하거나 세션이 충돌합니다. 인스턴스는 반드시 하나만.
  • second 연결: ~/hermes-discord/workspace/second에 second 레포를 클론해두고, hermes 컨테이너가 그 디렉터리를 직접 마운트합니다. hermes가 위키 파일을 직접 읽고 쓸 수 있게 됩니다.

배포 흐름은 git 한 줄

로컬에서 설정을 바꾸면 git push합니다. 서버에서는 git pull && docker compose up -d로 끝입니다. deploy.sh 스크립트 하나에 이 두 명령이 들어있습니다.

처음에는 “로컬에서도 돌려볼 수 있어야 하지 않을까”라고 생각해서 로컬 구동 설정을 쫙 깔았다가, 사실 서버가 이미 잘 돌고 있고 로컬은 git 관리용으로만 쓴다는 걸 다시 확인하고 싹 지웠습니다. 이미지 4.92GB, docker-compose.override.yml, 로컬 .env… 깔아두었다가 다 정리했습니다. 간단한 게 낫습니다.


config 함정: 2시간 날린 삽질

이 구축기에서 제일 뼈아팠던 부분입니다. Tavily 검색 백엔드를 붙이는 과정에서 생긴 일입니다.

기본 검색 백엔드가 “DDGS” 폴백이었고, 검색 품질이 형편없었습니다. Tavily로 교체하기로 했습니다. 공식 hermes 문서를 보고 이렇게 입력했습니다:

hermes config set tool_search.search_default_limit 8

config check가 통과했습니다. 재기동했습니다. 설정이 적용된 것 같았습니다. 근데 실제 행동은 달랐습니다.

나중에 config 파일을 직접 열어보니, 제가 입력한 설정이 원래 키(tools.tool_search.search_default_limit)와 완전히 다른 최상위에 가짜 키로 생성돼 있었습니다. config check는 파싱만 검증하지 값이 올바른 경로에 있는지는 안 봐줍니다.

올바른 명령은 이겁니다:

hermes config set tools.tool_search.backend_id tavily
hermes config set tools.tool_search.search_default_limit 8

짧은 경로로 쓰면 최상위에 무시되는 가짜 키가 생깁니다. 반드시 전체 경로를 써야 합니다.


”오 이거 되네” 순간

Discord에서 봇에게 아이디어를 던졌습니다. second 위키의 파일이 실제로 생성됐습니다.

그냥 Discord 채팅이 wiki 페이지로 변환된 순간이었습니다. 마찰이 없었습니다. 폰에서 메시지 하나 보내면, 다음에 노트북을 열었을 때 옵시디언에 정리된 내용이 들어있습니다.

물론 지식 소화의 품질이나 깊이는 별개의 문제입니다. 하지만 “채팅 → 위키”라는 루프 자체가 작동한다는 건, 처음 상상했던 그 마찰 제거가 실제로 가능하다는 증거였습니다.


second 볼트 양방향 동기화

한 가지 더 해결해야 했습니다. second 위키는 여러 경로로 업데이트됩니다. 로컬 옵시디언, Claude Code 세션, 그리고 hermes 봇 자체도 파일을 씁니다. 이 상태에서 hermes가 편집한 내용을 서버에서 push하려면, 그 이전에 remote가 앞서있으면 충돌이 납니다.

서버 second 레포를 확인해봤더니 정확히 그 상황이었습니다. 06-05 이후 멈춰있고, dirty한 미커밋 작업이 쌓여 있었습니다. --ff-only로 설정된 cron은 충돌 위험이 있으면 그냥 skip하고 넘어가거든요.

양방향으로 모두가 쓰는 레포에서는 git pull --ff-only가 아니라 git pull --rebase --autostash가 맞습니다. hermes의 미push 커밋을 remote 위로 올려두는 방식입니다. 이렇게 해야 야간 push가 fast-forward로 깔끔하게 나갑니다.


지금 이 루프가 돌아가는 방식

현재 서버에서 도는 자동화는 이렇습니다:

  • 20분마다: second 레포를 rebase pull로 최신 동기화
  • 밤 10시: hermes 세션 로그를 raw/로 수집
  • hermes 봇은 24/7 Discord 게이트웨이에 연결

저는 로컬에서 코드를 수정하고 push합니다. 폰에서 Discord 채팅을 합니다. 나머지는 서버가 알아서 처리합니다.

처음 생각했던 루프가 실제로 돌아가고 있습니다. 아이디어가 떠오르면 Discord를 엽니다. 위키는 알아서 채워집니다.


<- 이전 편: 아이디어가 폰에서 사라지는 게 아까워서 Discord 봇을 만들었다 · 다음 편 ->: 두 AI 에이전트를 같이 쓰는 법 배경: second 위키 설계 결정들 · 심화: 세컨드브레인 자동화 방법 · 함께 보기: 에이전트 컨텍스트와 세컨드브레인 통합

댓글