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. 배경 — 시작 시점의 상태
- Nous Research의 Hermes Agent를 Docker로 구동 중 (
~/.hermes→ 컨테이너/opt/data마운트). - Mattermost와 연동하여 봇 1개(@hermes-bot)가 응답하는 것까지 확인된 상태.
- 모델: NousResearch free plan (
tencent/hy3:free), OAuth 연결. - 관련 기존 글: Hermes Agent — M1 Mac Docker 설치, Hermes Agent — Ubuntu 서버 Docker 설치 + Mattermost 연동,
docker-compose.yml.
최초 질문
"Mattermost에 올라오는 모든 사용자 대화·자료를 Hermes가 학습해 자율 에이전트로 기능하게 하려면?"
2. 아키텍처 결정 — RAG vs. 다중 프로필
2.1 "학습"의 두 의미
- 파인튜닝(모델 가중치 재학습) — free plan OAuth 모델로는 불가능(가중치 접근 없음).
- 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)
- 봇 3개 채널 초대 (Mattermost → 각 채널 → Add Members):
@finance-bot→ 재무 /@dev-bot→ 개발 /@qna-bot→ 고객응대
- 각 채널에서 멘션 테스트로 응답 확인.
- (선택) 각 프로필
SOUL.md수정으로 채널별 성격 부여 (현재는 default 복제본). - (선택) Docker Desktop 메모리 8GB 상향.
- (향후) 채널 횡단 통합 지식이 필요해지면 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>전역 플래그