Mattermost의 채널마다 전담 Hermes 에이전트를 붙이는 아키텍처를 검증하고 실제로 구축한 전 과정 기록. 작업일: 2026-07-14 · 환경: M1 Mac / Docker · Hermes Agent v0.18.2 (2026.7.7.2) · s6-overlay 3.2.3.0


0. 요약 (TL;DR)

  • 목표: Mattermost의 여러 채널을 각각 다른 Hermes 에이전트가 담당하게 만들기.
  • 채택 아키텍처: RAG 단일 봇이 아니라 "한 Docker 컨테이너 + Hermes 프로필별 게이트웨이". Hermes 이미지가 s6-overlay 위에 지어져 있어 원래 지원하는 방식.
  • 검증 완료: ① 게이트웨이 다중 동시 구동 ② 프로필 완전 격리 ③ 컨테이너 재시작 시 자동 복구 ④ 깔끔한 제거.
  • 구축 결과: default(보존) + 채널 4개(sales/finance/dev/qna) = 총 5개 에이전트 동시 구동.
  • 남은 수동 작업: 각 봇을 Mattermost에서 담당 채널에 초대(Add Members).

1. 배경 — 시작 시점의 상태

최초 질문

"Mattermost에 올라오는 모든 사용자 대화·자료를 Hermes가 학습해 자율 에이전트로 기능하게 하려면?"


2. 아키텍처 결정 — RAG vs. 다중 프로필

2.1 "학습"의 두 의미

  1. 파인튜닝(모델 가중치 재학습) — free plan OAuth 모델로는 불가능(가중치 접근 없음).
  2. RAG/메모리(검색 증강) — 대화를 색인해두고 답변 시 꺼내 씀. 실무의 정석. Hermes의 memories/가 이 구조.

2.2 두 접근의 비교

RAG 단일 봇 채널별 다중 프로필 (채택)
방식 봇 1개가 전 채널 수집·색인 채널마다 전담 에이전트
문맥 전체 뒤섞임(64k 한계) 채널별 집중 → 답 품질↑
구현 난이도 높음(수집·임베딩·벡터DB) 낮음(프로필 추가만)
무료/작은 모델 불리 유리

결정: 채널별 다중 프로필. RAG는 나중에 "채널 횡단 통합 지식"이 필요해지면 얹는 순서.


3. 핵심 기술 — s6-overlay와 Hermes 프로필

3.1 s6-overlay란

  • 한 Docker 컨테이너 안에서 여러 프로세스를 안정적으로 띄우고·감독하고·재시작하는 초경량 init 시스템 (PID 1에 앉음).
  • 책임: 다중 서비스 감독, 자동 재시작, 시작 순서/의존성, 좀비 청소, graceful shutdown.
  • 확인: 이 컨테이너의 PID 1 = s6-svscan (s6-overlay 3.2.3.0). 기본으로 main-hermes, dashboard, gateway-default 서비스를 감독 중.

3.2 이미지 설계 의도 (소스 코멘트에서 발견)

/etc/s6-overlay/s6-rc.d/main-hermes/run 코멘트:

"per-profile gateways register dynamically via /run/service/ at runtime (Phase 4)."

프로필별 게이트웨이를 런타임에 동적 등록하도록 이미 설계됨.

3.3 Hermes 프로필 = 격리된 인스턴스

  • hermes profile = "Manage profiles — multiple isolated Hermes instances".
  • 프로필마다 자체 config.yaml·.env·SOUL.md(성격)·skills·memories·sessions/opt/data/profiles/<name>/ 아래 격리 보관.
  • 프로필 선택: -p <name> 플래그 또는 HERMES_PROFILE 환경변수 또는 생성된 wrapper alias.

3.4 부팅 자동기동 메커니즘

  • cont-init.d/02-reconcile-profiles 리컨실러(container_boot.reconcile_profile_gateways)가 부팅 시 모든 프로필을 훑어 각자의 gateway_state.json(running/stopped)을 읽고, running인 프로필의 s6 게이트웨이 슬롯을 재등록·기동.
  • → "운영자가 켜둔 건 재시작해도 켜지고, 꺼둔 건 꺼진 채 유지".

4. 실증 테스트

4.1 테스트 A — 게이트웨이 다중 동시 구동

  • 일회용 프로필 test-poc 생성 → 게이트웨이 기동.
  • 결과: 프로세스 2개 동시 구동 확인.
    149 (부모 s6-supervise gateway-default)   hermes gateway run
    730 (부모 s6-supervise gateway-test-poc)  hermes -p test-poc gateway run
    
  • test-poc가 실제 Mattermost WebSocket 연결까지 성공. /run/service/gateway-test-poc 슬롯 자동 생성 확인 → Phase 4 동적 등록이 실제로 작동.
  • 테스트 후 profile delete test-poc -y 로 정리(슬롯까지 자동 제거).

4.2 테스트 B(재시작 생존성) — 별도 프로필 rtest

  • rtest 기동(gateway_state=running) → docker restart hermes.
  • 재시작 후 아무 조작 없이 두 게이트웨이가 새 PID로 자동 부활:
    재시작 전            재시작 후 (자동)
    default PID 149  →  default PID 165  ✓
    rtest   PID 1116 →  rtest   PID 146  ✓ (리컨실러가 부활)
    
  • rtest는 재부팅 후 Mattermost 재연결까지 자동 완료. 이후 삭제.

종합 판정: ① 동시 구동 ✅ ② 완전 격리 ✅ ③ 재시작 자동 복구 ✅ ④ 깔끔한 제거 ✅ → 아키텍처 확정.


5. 실제 구축 — 채널 에이전트

5.1 채널당 표준 절차 (검증됨)

# ① 프로필 생성 (default 설정 복제)
hermes profile create <name> --clone --description "…담당 설명…"

# ② 그 프로필 .env 에서 전용 봇토큰 + 담당 채널ID 주입
#    /opt/data/profiles/<name>/.env
#    MATTERMOST_TOKEN=<전용 봇 토큰>
#    MATTERMOST_HOME_CHANNEL=<채널 ID(26자)>
#    (MATTERMOST_URL, MATTERMOST_ALLOWED_USERS 는 복제본 유지)

# ③ 게이트웨이 기동 (s6 감독 서비스로 등록)
hermes -p <name> gateway run --replace

# ④ Mattermost에서 전용 봇을 담당 채널에 Add Members (수동)

# ⑤ 확인
hermes gateway list

5.2 중요 포인트

  • 채널 식별자는 ID(26자) 사용. handle(URL 슬러그)·display_name 아님. Hermes 셋업이 명시적으로 "Home channel ID" 요구.
  • MATTERMOST_HOME_CHANNEL은 크론/알림 delivery 대상일 뿐, "어느 채널에서 응답하나"를 제한하지 않음. 봇이 채널 멤버이면 그 채널의 멘션에 반응.
  • 로그의 Channel directory built: N target(s)능동 추적 대상 수이며 멘션 반응과 무관. (실제로 0 targets 상태에서도 영업 채널 응답 정상.)
  • 채널마다 별도 봇 계정/토큰 필수. 같은 토큰 재사용 시 한 메시지에 중복 응답. 원칙: 채널1 : 봇1 : 프로필1.

5.3 sales 에이전트 — end-to-end 검증

  • sales 프로필 생성 → @sales-bot 토큰 + 영업 채널ID 주입 → 기동 → 채널 초대.
  • 실제 대화 로그(라이브 확인):
    09:17:59  inbound message: user=moztiq chat=b9ee…(영업) msg='누구야?'
    09:18:15  response ready: time=15.4s api_calls=1 response=304 chars
    09:18:15  [Mattermost] Sending response (304 chars) to b9ee…(영업)
    
  • 응답 주체 검증: 해당 대화는 sales 프로필 로그에만 존재, default 로그엔 0건 → default(@hermes-bot)는 무관, @sales-bot이 처리했음을 확정.

6. 최종 구성 (2026-07-14 기준)

프로필 담당 채널 채널 ID 게이트웨이 채널 초대
◆ default @hermes-bot (기존) ✅ running — (보존)
sales @sales-bot 영업 b9eeyusefibxdezz6ikmqks34c ✅ running ✅ 완료·응답확인
finance @finance-bot 재무 q6rebrxfztd55bkcxsxqzm76rr ✅ running ⏳ 초대 필요
dev @dev-bot 개발 b15acwum5bfg9gbhzrfuhh8nee ✅ running ⏳ 초대 필요
qna @qna-bot 고객응대 f5xr9tuzgjg1fek8zudekixfbc ✅ running ⏳ 초대 필요
  • 전부 모델 tencent/hy3:free, WebSocket 연결 완료, 재시작 자동 복구 상태.
  • default 프로필은 절대 삭제/변경하지 않음 (사용자 명시 요청).

7. 운영 노트 · 주의사항

7.1 메모리

  • Hermes 컨테이너: 게이트웨이 1개 ~271MB → 5개 ~721MB (1개당 약 +110MB).
  • Docker VM 총 1.94GB 중 사용 ~1.37GB(mattermost 391M + postgres 256M + hermes 721M) → 여유 빠듯.
  • 권장: Docker Desktop → Settings → Resources → Memory를 8GB로 상향 (호스트 16GB). 채널 더 늘리기 전 필수.
  • 참고: compose의 memory: 4G는 상한선일 뿐 실제 예약이 아님.

7.2 모델

  • tencent/hy3:free는 무료지만 응답 ~15초. 트래픽 몰리면 병목 가능.
  • 프로필별 교체 가능: hermes -p <name> config set model.default <모델>.

7.3 게이트웨이 기동 팁

  • hermes -p <name> gateway run --replace는 s6로 핸드오프 후 리턴("now running under s6 supervision"). 이미 감독 중인 프로세스엔 no-op.
  • 연속 루프 기동 주의: 여러 개를 루프로 연달아 기동하면 세 번째쯤 핸드오프가 블로킹돼 타임아웃날 수 있음. 하나씩 백그라운드로 기동하거나 각각 확인하며 진행.
  • 프로세스만 재시작하려면: 해당 python PID를 kill → s6-supervise가 자동 부활.

7.4 프로필 관리 명령

hermes profile list                 # 전체 프로필/게이트웨이 상태
hermes gateway list                 # 게이트웨이별 running 여부 + PID
hermes -p <name> gateway status     # 특정 프로필 상태
hermes profile delete <name> -y     # 프로필 삭제(-y 무확인), s6 슬롯 자동 정리
  • 로그 위치: 프로필별 /opt/data/profiles/<name>/logs/gateway.log, default는 /opt/data/logs/.

8. 남은 작업 (To-Do)

  1. 봇 3개 채널 초대 (Mattermost → 각 채널 → Add Members):
    • @finance-bot → 재무 / @dev-bot → 개발 / @qna-bot → 고객응대
  2. 각 채널에서 멘션 테스트로 응답 확인.
  3. (선택) 각 프로필 SOUL.md 수정으로 채널별 성격 부여 (현재는 default 복제본).
  4. (선택) Docker Desktop 메모리 8GB 상향.
  5. (향후) 채널 횡단 통합 지식이 필요해지면 RAG 계층 추가 검토.

9. 참고 — 발견한 이미지 내부 구조

  • PID 1: s6-svscan (s6-overlay 3.2.3.0)
  • s6 서비스 정의: /etc/s6-overlay/s6-rc.d/ (type: longrun/oneshot/bundle)
    • dashboard(longrun), main-hermes(longrun, no-op sleep), user/user2(bundle)
  • 런타임 감독 슬롯: /run/service/gateway-<profile> (동적 등록)
  • 부팅 훅: /etc/cont-init.d/ (01-hermes-setup, 015-supervise-perms, 02-reconcile-profiles)
  • 프로필 데이터: /opt/data/profiles/<name>/
  • Hermes CLI 핵심: profile {create,list,use,delete,…}, gateway {run,list,status,setup,…}, -p <name> 전역 플래그