Slack 설정
Socket Mode 사용해 Hermes Agent를 봇으로 Slack에 연결. Socket Mode는 WebSocket 사용, 공용 HTTP 엔드포인트 대신. Hermes 인스턴스 공개 접근 불필요 — 방화벽 뒤, 노트북, 사설 서버에서 동작.
클래식 Slack 앱(RTM API 사용) 2025년 3월 완전 폐기. Hermes는 최신 Bolt SDK와 Socket Mode 사용. 구 클래식 앱 있으면, 아래 단계 따라 새로 만들어야 함. 필수.
개요
| 구성요소 | 값 |
|---|---|
| 라이브러리 | Python용 slack-bolt / slack_sdk (Socket Mode) |
| 연결 | WebSocket — 공용 URL 불필요 |
| 필요 인증 토큰 | Bot Token (xoxb-) + App-Level Token (xapp-) |
| 사용자 식별 | Slack Member ID (예: U01ABC2DEF3) |
1단계: Slack App 생성
가장 빠른 경로는 Hermes가 생성한 manifest 붙여넣기. 내장 슬래시 명령
모두 선언(/btw, /stop, /model, …),
필수 OAuth 스코프 모두, 이벤트 구독 모두, Socket Mode 활성화 —
한번에 모두.
옵션 A: Hermes 생성 manifest 사용 (권장)
- manifest 생성:
hermes slack manifest --write
``~/.hermes/slack-manifest.json` 작성, 붙여넣기 지침 출력. - https://api.slack.com/apps 이동 → Create New App → From an app manifest
- 워크스페이스 선택, JSON 내용 붙여넣기, 검토, Next 클릭 → Create
- 6단계: Install App to Workspace로 건너뛰기. manifest가 스코프, 이벤트, 슬래시 명령 처리 완료.
옵션 B: 처음부터 (수동)
- https://api.slack.com/apps 이동
- Create New App 클릭
- From scratch 선택
- 앱 이름 입력 (예: "Hermes Agent"), 워크스페이스 선택
- Create App 클릭
앱의 Basic Information 페이지 도착. 아래 2~6단계 진행.
2단계: Bot Token 스코프 설정
사이드바에서 Features → OAuth & Permissions 이동. Scopes → Bot Token Scopes 스크롤, 다음 추가:
| 스코프 | 용도 |
|---|---|
chat:write | 봇으로 메시지 전송 |
app_mentions:read | 채널에서 @멘션 감지 |
channels:history | 봇이 속한 공개 채널의 메시지 읽기 |
channels:read | 공개 채널 목록 및 정보 조회 |
groups:history | 봇이 초대된 비공개 채널 메시지 읽기 |
im:history | DM 기록 읽기 |
im:read | 기본 DM 정보 조회 |
im:write | DM 열기 및 관리 |
users:read | 사용자 정보 조회 |
files:read | 첨부 파일 읽기 및 다운로드, 음성 메모/오디오 포함 |
files:write | 파일 업로드 (이미지, 오디오, 문서) |
channels:history 및 groups:history 없으면, 봇 채널 메시지 수신 불가 —
DM에서만 동작. files:read 없으면, Hermes 채팅 가능하지만 사용자 업로드 첨부 안정적으로 읽기 불가.
가장 흔히 누락되는 스코프.
선택 스코프:
| 스코프 | 용도 |
|---|---|
groups:read | 비공개 채널 목록 및 정보 조회 |
3단계: Socket Mode 활성화
Socket Mode로 공용 URL 대신 WebSocket으로 연결 가능.
- 사이드바에서 Settings → Socket Mode 이동
- Enable Socket Mode ON 토글
- App-Level Token 생성 안내:
hermes-socket같은 이름 (이름 무관)connections:write스코프 추가- Generate 클릭
- 토큰 복사 —
xapp-로 시작. 이것이SLACK_APP_TOKEN
Settings → Basic Information → App-Level Tokens에서 항상 app-level 토큰 조회/재생성 가능.
4단계: 이벤트 구독
이 단계 중요 — 봇이 볼 수 있는 메시지 제어.
- 사이드바에서 Features → Event Subscriptions 이동
- Enable Events ON 토글
- Subscribe to bot events 펼치고 추가:
| 이벤트 | 필수? | 용도 |
|---|---|---|
message.im | 예 | 봇이 DM 수신 |
message.channels | 예 | 봇이 추가된 공개 채널에서 메시지 수신 |
message.groups | 권장 | 봇이 초대된 비공개 채널에서 메시지 수신 |
app_mention | 예 | 봇 @멘션 시 Bolt SDK 오류 방지 |
- 페이지 하단 Save Changes 클릭
봇이 DM에서 동작하나 채널에서 미동작이면, 거의 확실히
message.channels (공개 채널용) 또는 message.groups (비공개 채널용) 누락.
이 이벤트 없으면 Slack이 채널 메시지 봇에게 전달 안 함.
5단계: Messages 탭 활성화
이 단계로 봇에 DM 가능. 없으면 봇 DM 시도 시 "Sending messages to this app has been turned off" 표시.
- 사이드바에서 Features → App Home 이동
- Show Tabs 스크롤
- Messages Tab ON 토글
- "Allow users to send Slash commands and messages from the messages tab" 체크
모든 스코프와 이벤트 구독 올바르더라도, Messages Tab 활성화 없으면 Slack은 사용자가 봇에 DM 보내는 것 차단. Slack 플랫폼 요구사항, Hermes 설정 문제 아님.
6단계: 워크스페이스에 앱 설치
- 사이드바에서 Settings → Install App 이동
- Install to Workspace 클릭
- 권한 검토 후 Allow 클릭
- 승인 후,
xoxb-로 시작하는 Bot User OAuth Token 표시 - 이 토큰 복사 — 이것이
SLACK_BOT_TOKEN
이후 스코프나 이벤트 구독 변경 시, 앱 재설치 필수, 변경 사항 적용 위해. Install App 페이지에 재설치 안내 배너 표시.
7단계: 허용 목록용 사용자 ID 찾기
Hermes는 허용 목록에 Slack Member ID 사용 (사용자명/표시명 아님).
Member ID 찾기:
- Slack에서 사용자 이름/아바타 클릭
- View full profile 클릭
- ⋮ (more) 버튼 클릭
- Copy member ID 선택
Member ID 형식 U01ABC2DEF3. 최소한 본인 Member ID 필요.
8단계: Hermes 설정
~/.hermes/.env 파일에 다음 추가:
# Required
SLACK_BOT_TOKEN=xoxb-your-bot-token-here
SLACK_APP_TOKEN=xapp-your-app-token-here
SLACK_ALLOWED_USERS=U01ABC2DEF3 # Comma-separated Member IDs
# Optional
SLACK_HOME_CHANNEL=C01234567890 # Default channel for cron/scheduled messages
SLACK_HOME_CHANNEL_NAME=general # Human-readable name for the home channel (optional)
또는 대화형 설정 실행:
hermes gateway setup # Select Slack when prompted
이후 gateway 시작:
hermes gateway # Foreground
hermes gateway install # Install as a user service
sudo hermes gateway install --system # Linux only: boot-time system service
9단계: 채널에 봇 초대
gateway 시작 후, 봇이 응답할 채널마다 봇 초대 필요:
/invite @Hermes Agent
봇이 채널에 자동 참여 안 함. 각 채널마다 개별 초대 필수.
슬래시 명령
모든 Hermes 명령 (/btw, /stop, /new, /model, /help,...)
네이티브 Slack 슬래시 명령 — Telegram, Discord와
동일 방식. Slack에서 / 입력하면 자동완성이 모든
Hermes 명령과 설명 나열.
내부 동작: Hermes는 생성된 Slack 앱 manifest 포함 (1단계,
옵션 A 참조),
COMMAND_REGISTRY의
모든 명령 슬래시 명령으로 선언. Socket Mode에서 Slack은 manifest ... 필드와 무관하게
WebSocket으로 명령 이벤트 라우팅.
업데이트 후 슬래시 명령 새로고침
Hermes에 새 명령 추가 시 (예: hermes update 이후), manifest 재생성
및 Slack 앱 업데이트:
hermes slack manifest --write
이후 Slack에서:
- https://api.slack.com/apps 열기 → Hermes 앱
- Features → App Manifest → Edit
- 새
~/.hermes/slack-manifest.json내용 붙여넣기 - Save. 스코프나 슬래시 명령 변경되면 Slack이 앱 재설치 안내.
레거시 /hermes <subcommand> 여전히 작동
구 manifest와의 하위 호환성 위해, 여전히
/hermes btw run the tests 입력 가능 — Hermes는 /btw run the tests. Free-form questions also work: /hermes what's the weather?와 동일하게 라우팅, 일반 메시지로 처리.
스레드 내 명령 사용 (!cmd 접두사)
Slack 자체가 스레드 답글 내 네이티브 슬래시 명령 차단 — 스레드에서
/queue 시도하면 Slack이 "/queue is not supported
in threads. Sorry!" 응답. 재활성화하는 앱 측 설정 없음;
Slack이 Hermes에 전달 안 함.
대안으로 Hermes는 선두 !를 대체 명령 접두사로 인식,
스레드 (및 다른 곳) 동작. 일반 스레드 답글로
!queue, !stop, !model gpt-5.4 등 입력 —
Hermes가 슬래시 형식과 동일하게 처리, 같은 스레드에
응답.
첫 토큰만 알려진 명령 목록과 대조, 따라서
!nice work 같은 일상 메시지는 변경 없이 에이전트로 전달.
고급: slash-commands 배열만 출력
Slack manifest 수동 관리, 슬래시 명령 목록만 필요할 때:
hermes slack manifest --slashes-only > /tmp/slashes.json
기존 manifest의 features.slash_commands 키에 배열 붙여넣기.
봇 응답 방식
서로 다른 컨텍스트에서 Hermes 동작 이해:
| 컨텍스트 | 동작 |
|---|---|
| DM | 봇이 모든 메시지에 응답 — @멘션 불필요 |
| 채널 | @멘션 시에만 응답 (예: @Hermes Agent what time is it?). 채널에서 Hermes는 해당 메시지에 연결된 스레드로 응답. |
| 스레드 | 기존 스레드 내에서 Hermes @멘션하면 같은 스레드에 응답. 스레드에 활성 세션 생기면, 이후 스레드 답글은 @멘션 불필요 — 봇이 대화 자연스럽게 따라감. |
채널에서는 대화 시작 시 항상 봇 @멘션. 봇이 스레드에서 활성화되면, 멘션 없이 스레드 답글 가능. 스레드 밖에서는 @멘션 없는 메시지 무시, 바쁜 채널 소음 방지.
설정 옵션
8단계의 필수 환경 변수 외, ~/.hermes/config.yaml로 Slack 봇 동작 커스터마이즈 가능.
스레드 및 응답 동작
platforms:
slack:
# Controls how multi-part responses are threaded
# "off" — never thread replies to the original message
# "first" — first chunk threads to user's message (default)
# "all" — all chunks thread to user's message
reply_to_mode: "first"
extra:
# Whether to reply in a thread (default: true).
# When false, channel messages get direct channel replies instead
# of threads. Messages inside existing threads still reply in-thread.
reply_in_thread: true
# Also post thread replies to the main channel
# (Slack's "Also send to channel" feature).
# Only the first chunk of the first reply is broadcast.
reply_broadcast: false
| 키 | 기본값 | 설명 |
|---|---|---|
platforms.slack.reply_to_mode | "first" | 멀티파트 메시지 스레드 모드: "off", "first", "all" |
platforms.slack.extra.reply_in_thread | true | false이면, 채널 메시지가 스레드 대신 직접 답글. 기존 스레드 내 메시지는 여전히 스레드 내 응답. |
platforms.slack.extra.reply_broadcast | false | true이면, 스레드 답글이 메인 채널에도 게시. 첫 청크만 브로드캐스트. |
세션 격리
# Global setting — applies to Slack and all other platforms
group_sessions_per_user: true
``true` (기본값)이면, 공유 채널의 각 사용자가 자신의 격리된 대화 세션 보유. `#general`에서 Hermes와 대화하는 두 사람은 별도 기록과 컨텍스트 가짐.
전체 채널이 하나의 대화 세션 공유하는 협업 모드 원하면 `false`로 설정. 단, 사용자들이 context 증가와 토큰 비용 공유, 한 사용자의 `/reset`이 전원의 세션 삭제.
### 멘션 및 트리거 동작 \{#option-b-from-scratch-manual}
```yaml
slack:
# Require @mention in channels (this is the default behavior;
# the Slack adapter enforces @mention gating in channels regardless,
# but you can set this explicitly for consistency with other platforms)
require_mention: true
# Prevent thread auto-engagement: only reply to channel messages that
# contain an explicit @mention. With this OFF (default), Slack can
# "auto-engage" — remembering past mentions in a thread and following
# up on bot-message replies, and resuming active sessions without a
# fresh mention. With strict_mention ON, every new channel message
# must @mention the bot before Hermes will respond.
strict_mention: false
# Custom mention patterns that trigger the bot
# (in addition to the default @mention detection)
mention_patterns:
- "hey hermes"
- "hermes,"
# Text prepended to every outgoing message
reply_prefix: ""
strict_mentionSlack 기본 "봇이 이 스레드 기억" 동작이 사용자 놀라게 하는 바쁜 워크스페이스에서 true로 설정 — 예: 봇이 초반에 도왔던 긴 기술지원 스레드, 명시적 재핑 전까지 침묵 원할 때. DM과 활성 인터랙티브 세션은 영향 없음.
Slack은 두 패턴 모두 지원: 기본은 대화 시작 시 @mention 필요, 단 특정 채널은 SLACK_FREE_RESPONSE_CHANNELS (쉼표 구분 채널 ID) 또는 config.yaml의 slack.free_response_channels로 제외 가능. 봇이 스레드에 활성 세션 보유하면, 이후 스레드 답글은 멘션 불필요. DM에서는 봇이 항상 멘션 없이 응답.
미인증 사용자 처리
slack:
# What happens when an unauthorized user (not in SLACK_ALLOWED_USERS) DMs the bot
# "pair" — prompt them for a pairing code (default)
# "ignore" — silently drop the message
unauthorized_dm_behavior: "pair"
모든 플랫폼에 전역 설정도 가능:
unauthorized_dm_behavior: "pair"
``slack:` 하위 플랫폼별 설정이 전역 설정보다 우선.
### 음성 전사 \{#voice-transcription}
```yaml
# Global setting — enable/disable automatic transcription of incoming voice messages
stt_enabled: true
``true` (기본값)이면, 수신 오디오 메시지가 에이전트 처리 전 설정된 STT 제공자로 자동 전사.
### 전체 예제 \{#step-3-enable-socket-mode}
```yaml
# Global gateway settings
group_sessions_per_user: true
unauthorized_dm_behavior: "pair"
stt_enabled: true
# Slack-specific settings
slack:
require_mention: true
unauthorized_dm_behavior: "pair"
# Platform config
platforms:
slack:
reply_to_mode: "first"
extra:
reply_in_thread: true
reply_broadcast: false
홈 채널
SLACK_HOME_CHANNEL를 채널 ID로 설정하면 Hermes가 예약된 메시지,
cron 작업 결과, 기타 능동적 알림 전달. 채널 ID 찾기:
- Slack에서 채널명 우클릭
- View channel details 클릭
- 하단 스크롤 — Channel ID 표시
SLACK_HOME_CHANNEL=C01234567890
봇이 채널에 초대됨 확인 (/invite @Hermes Agent).
멀티 워크스페이스 지원
Hermes는 단일 gateway 인스턴스로 여러 Slack 워크스페이스에 동시 연결 가능. 각 워크스페이스는 자체 봇 사용자 ID로 독립 인증.
설정
SLACK_BOT_TOKEN에 쉼표 구분 목록으로 여러 봇 토큰 제공:
# Multiple bot tokens — one per workspace
SLACK_BOT_TOKEN=xoxb-workspace1-token,xoxb-workspace2-token,xoxb-workspace3-token
# A single app-level token is still used for Socket Mode
SLACK_APP_TOKEN=xapp-your-app-token
또는 ~/.hermes/config.yaml에서:
platforms:
slack:
token: "xoxb-workspace1-token,xoxb-workspace2-token"
OAuth 토큰 파일
환경 변수나 설정 파일 토큰 외, Hermes는 다음 위치의 OAuth 토큰 파일에서도 토큰 로드:
~/.hermes/slack_tokens.json
이 파일은 팀 ID를 토큰 항목에 매핑하는 JSON 객체:
{
"T01ABC2DEF3": {
"token": "xoxb-workspace-token-here",
"team_name": "My Workspace"
}
}
이 파일의 토큰은 SLACK_BOT_TOKEN로 지정된 토큰과 병합. 중복 토큰 자동 중복제거.
동작 방식
- 목록의 첫 토큰이 기본 토큰, Socket Mode 연결(AsyncApp)에 사용.
- 각 토큰은 시작 시
auth.test로 인증. gateway는 각team_id을 자체WebClient와bot_user_id에 매핑. - 메시지 도착 시, Hermes는 올바른 워크스페이스별 클라이언트로 응답.
- 기본
bot_user_id(첫 토큰)는 단일 봇 identity 기대하는 기능과의 하위 호환성에 사용.
음성 메시지
Hermes는 Slack에서 음성 지원:
- 수신: 음성/오디오 메시지가 설정된 STT 제공자로 자동 전사: 로컬
faster-whisper, Groq Whisper (GROQ_API_KEY), OpenAI Whisper (VOICE_TOOLS_OPENAI_KEY) - 송신: TTS 응답이 오디오 파일 첨부로 전송
채널별 프롬프트
특정 Slack 채널에 일시적 시스템 프롬프트 할당. 프롬프트는 매 턴 런타임에 주입 — 트랜스크립트 기록에 절대 저장 안 됨 — 변경 즉시 적용.
slack:
channel_prompts:
"C01RESEARCH": |
You are a research assistant. Focus on academic sources,
citations, and concise synthesis.
"C02ENGINEERING": |
Code review mode. Be precise about edge cases and
performance implications.
키는 Slack 채널 ID (채널 자세히 보기 → "About" → 하단 스크롤로 확인). 매칭 채널의 모든 메시지에 프롬프트가 일시적 시스템 지침으로 주입.
채널별 Skill 바인딩
특정 채널이나 DM에서 새 세션 시작 시 skill 자동 로드. 채널별 프롬프트(매 턴 주입)와 달리, skill 바인딩은 세션 시작 시 사용자 메시지로 skill 내용 주입 — 대화 기록의 일부가 되며 이후 턴마다 재로드 불필요.
DM이나 전용 목적 채널(플래시카드, 도메인 특화 Q&A 봇, 지원 분류 채널 등)에 적합. 짧은 답변마다 모델의 자체 skill selector가 로드 여부 결정하는 것 원치 않을 때 사용.
slack:
channel_skill_bindings:
# DM channel — always runs in "german-flashcards" mode
- id: "D0ATH9TQ0G6"
skills:
- german-flashcards
# Research channel — preload multiple skills in order
- id: "C01RESEARCH"
skills:
- arxiv
- writing-plans
# Short form: single skill as a string
- id: "C02SUPPORT"
skill: hubspot-on-demand
참고 사항:
- 바인딩은 channel ID 기준으로 매칭됨. 바인딩된 channel 내 threaded message는 thread가 부모 channel 바인딩 상속.
- skill은 session 시작 시에만 로드됨 (새 session 또는 auto-reset 후). binding 변경 시, 적용 위해
/new실행하거나 session auto-reset 대기. channel_prompts와 결합하여 skill 지침 위에 채널별 톤/제약 추가.
Hermes Agent 문제 해결
| 문제 | 해결 방법 |
|---|---|
| DM에 봇이 응답하지 않음 | message.im이(가) 이벤트 구독에 포함되어 있는지 확인하고 앱을 재설치하세요 |
| DM에서는 봇이 작동하지만 채널에서는 작동 안 함 | 가장 흔한 문제. message.channels 및 message.groups 을 event subscriptions 에 추가하고, 앱을 재설치한 후, /invite @Hermes Agent 로 봇을 채널에 초대하세요 |
| 봇이 채널에서 @mentions에 응답 안 함 | 1) message.channels 이벤트 구독 확인. 2) 봇이 채널에 초대되어 있어야 함. 3) channels:history scope 추가 확인. 4) scope/event 변경 후 앱 재설치 |
| 봇이 비공개 채널 메시지 무시 | message.groups 이벤트 구독과 groups:history scope를 모두 추가한 후, 앱을 재설치하고 봇을 /invite 하세요 |
| DM에서 "이 앱으로의 메시지 전송이 비활성화되었습니다" | App Home 설정에서 Messages Tab 활성화 (Step 5 참조) |
| "not_authed" 또는 "invalid_auth" 오류 | Bot Token과 App Token을 재발급하고 .env 업데이트 |
| 봇이 응답하지만 채널에 게시 불가 | /invite @Hermes Agent 로 봇을 채널에 초대하세요 |
| 봇이 채팅은 가능하지만 업로드된 이미지/파일은 읽지 못함 | files:read 추가 후 앱 재설치. Hermes는 Slack이 scope/auth/permission 실패 반환 시 첨부 파일 접근 진단을 채팅 내 표시. |
missing_scope 오류 | OAuth & Permissions에서 필요한 scope 추가 후 앱 재설치 |
| 소켓 연결이 자주 끊김 | 네트워크 확인; Bolt 자동 재연결되나 불안정한 연결 시 지연 발생 |
| 스코프/이벤트 변경했지만 아무것도 안 바뀜 | 스코프나 이벤트 구독 변경 후 워크스페이스에 앱을 반드시 재설치 해야 함 |
빠른 체크리스트
봇이 채널에서 작동하지 않으면 다음 사항을 모두 확인:
- ✅
message.channels이벤트 구독됨 (공개 채널용) - ✅
message.groups이벤트 구독됨 (프라이빗 채널용) - ✅
app_mention이벤트 구독됨 - ✅
channels:historyscope 추가됨 (공개 채널용) - ✅
groups:historyscope 추가됨 (private 채널용) - ✅ scope/event 추가 후 앱 재설치 완료
- ✅ 봇이 채널에 초대되었습니다 (
/invite @Hermes Agent) - ✅ 메시지에서 봇을 @멘션하고 있음
보안
SLACK_ALLOWED_USERS를 반드시 설정하여 인증된 사용자의 Member ID를 지정하세요. 이 설정 없이는
gateway는 안전 조치로 기본적으로 모든 메시지를 거부합니다. bot token은 절대 공유하지 마세요 —
비밀번호처럼 다루세요.
- 토큰은
~/.hermes/.env에 저장해야 함 (파일 권한600) - Slack 앱 설정에서 토큰을 주기적으로 교체
- Hermes config 디렉터리 접근 권한 보유자 감사
- Socket Mode는 공개 endpoint가 노출되지 않음을 의미 — 공격 표면 하나 감소