Gateway Internals
기준일: 2026-07-26
공식 기준: Gateway Internals
Gateway Internals 문서는 Hermes Agent 공식 문서(developer-guide/gateway-internals)를 한국어로 정리한 가이드입니다. How the messaging gateway boots, authorizes users, routes sessions, and delivers messages 명령·설정 키·코드 예시는 공식 문서를 그대로 보존하며, 해석과 절차 안내는 한국어로 제공합니다. 최종 동작은 설치 버전과 공식 원문을 확인하세요.
핵심 요약
How the messaging gateway boots, authorizes users, routes sessions, and delivers messages
한국어 가이드 범위: developer-guide/gateway-internals 경로의 설정·명령·제약·예시를 학습용으로 재구성합니다.
문서 구성
공식 문서의 주요 섹션은 다음과 같습니다.
- Gateway Internals
- Key Files
- Architecture Overview
- Message Flow
- Session Key Format
- Two-Level Message Guard
- Authorization
- DM Pairing Flow
- Slash Command Dispatch
- Running-Agent Guard
- Config Sources
- Platform Adapters
- Token Locks
- Delivery Path
- Hooks
- Gateway Hook Events
- Memory Provider Integration
- Memory Flush Lifecycle
- Background Maintenance
- Process Management
- Related Docs
상세 내용
Gateway Internals
The messaging gateway is the long-running process that connects Hermes to 20+ external messaging platforms through a unified architecture.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Key Files
| File | Purpose |
|---|---|
gateway/run.py |
GatewayRunner — main loop, slash commands, message dispatch (large file; check git for current LOC) |
gateway/session.py |
SessionStore — conversation persistence and session key construction |
gateway/delivery.py |
Outbound message delivery to target platforms/channels |
gateway/pairing.py |
DM pairing flow for user authorization |
gateway/channel_directory.py |
Maps chat IDs to human-readable names for cron delivery |
gateway/hooks.py |
Hook discovery, loading, and lifecycle event dispatch |
gateway/mirror.py |
Cross-session message mirroring for send_message |
gateway/status.py |
Token lock management for profile-scoped gateway instances |
gateway/builtin_hooks/ |
Extension point for always-registered hooks (none shipped) |
gateway/platforms/ |
Platform adapters (one per messaging platform) |
Architecture Overview
┌─────────────────────────────────────────────────┐
│ GatewayRunner │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Telegram │ │ Discord │ │ Slack │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └─────────────┼─────────────┘ │
│ ▼ │
│ _handle_message() │
│ │ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ Slash command AIAgent Queue/BG │
│ dispatch creation sessions │
│ │ │
│ ▼ │
│ SessionStore │
│ (SQLite persistence) │
└───────┴─────────────┴─────────────┴─────────────┘
Message Flow
When a message arrives from any platform:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
주요 항목:
- If agent is running for this session → queue message, set interrupt event
- If
/approve,/deny,/stop→ bypass guard (dispatched inline) - Resolve session key via
_session_key_for_source()(format:agent:main:{platform}:{chat_type}:{chat_id}) - Check authorization (see Authorization below)
- Check if it's a slash command → dispatch to command handler
- Check if agent is already running → intercept commands like
/stop,/status - Otherwise → create
AIAgentinstance and run conversation
Session Key Format
Session keys encode the full routing context:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
agent:main:{platform}:{chat_type}:{chat_id}
Two-Level Message Guard
When an agent is actively running, incoming messages pass through two sequential guards:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Authorization
The gateway uses a multi-layer authorization check, evaluated in order:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
DM Pairing Flow
Pairing state is persisted in gateway/pairing.py and survives restarts.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Admin: /pair
Gateway: "Pairing code: ABC123. Share with the user."
New user: ABC123
Gateway: "Paired! You're now authorized."
Slash Command Dispatch
All slash commands in the gateway flow through the same resolution pipeline:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Running-Agent Guard
Commands that must NOT execute while the agent is processing are rejected early:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
if _quick_key in self._running_agents:
if canonical == "model":
return "⏳ Agent is running — wait for it to finish or /stop first."
Config Sources
The gateway reads configuration from multiple sources:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
| Source | What it provides |
|---|---|
~/.hermes/.env |
API keys, bot tokens, platform credentials |
~/.hermes/config.yaml |
Model settings, tool configuration, display options |
| Environment variables | Override any of the above |
Platform Adapters
Most messaging platforms ship as plugin adapters under plugins/platforms//adapter.py; a few legacy adapters still live directly in gateway/platforms/. All extend BasePlatformAdapter from gateway/platforms/base.py:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
주요 항목:
connect()/disconnect()— lifecycle managementsend_message()— outbound message deliveryon_message()— inbound message normalization →MessageEvent
plugins/platforms/ # plugin-packaged adapters (one dir each)
├── telegram/adapter.py # Telegram Bot API (long polling or webhook)
├── discord/adapter.py # Discord bot via discord.py
├── slack/adapter.py # Slack Socket Mode
├── whatsapp/adapter.py # WhatsApp Business Cloud API
├── matrix/adapter.py # Matrix via mautrix (optional E2EE)
├── mattermost/adapter.py # Mattermost WebSocket API
├── email/adapter.py # Email via IMAP/SMTP
├── sms/adapter.py # SMS via Twilio
├── dingtalk/adapter.py # DingTalk WebSocket
├── feishu/adapter.py # Feishu/Lark WebSocket or webhook
├── wecom/adapter.py # WeCom (WeChat Work) callback
├── line/adapter.py # LINE Messaging API
├── teams/adapter.py # Microsoft Teams
├── irc/adapter.py # IRC (canonical scoped-lock example)
├── homeassistant/adapter.py # Home Assistant conversation integration
└── … # google_chat, ntfy, photon, raft, simplex, …
gateway/platforms/ # core base + legacy direct adapters
├── base.py # BasePlatformAdapter — shared logic for all platforms
├── signal.py # Signal via signal-cli REST API
├── weixin.py # Weixin (personal WeChat) via iLink Bot API
├── bluebubbles.py # Apple iMessage via BlueBubbles macOS server
├── qqbot/ # QQ Bot (Tencent QQ) via Official API v2 (sub-package)
├── yuanbao.py # Yuanbao (Tencent) DM/group adapter
├── msgraph_webhook.py # Microsoft Graph change-notification webhook (Teams, Outlook, etc.)
├── webhook.py # Inbound/outbound webhook adapter
└── api_server.py # REST API server adapter
Token Locks
Adapters that connect with unique credentials call acquire_scoped_lock() in connect() and release_scoped_lock() in disconnect(). This prevents two profiles from using the same bot token simultaneously.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Delivery Path
Outgoing deliveries (gateway/delivery.py) handle:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
주요 항목:
- Direct reply — send response back to the originating chat
- Home channel delivery — route cron job outputs and background results to a configured home channel
- Explicit target delivery — the send engine specifying
telegram:-1001234567890, exposed via thehermes sendCLI for shell scripts and via crondeliver:targets - Cross-platform delivery — deliver to a different platform than the originating message
Hooks
Gateway hooks are Python modules that respond to lifecycle events:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Gateway Hook Events
Hooks are discovered from gateway/builtin_hooks/ (an extension point — currently empty in the shipped distribution; _register_builtin_hooks() is a no-op stub) and ~/.hermes/hooks/ (user-installed). Each hook is a directory with a HOOK.yaml manifest and handler.py.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
| Event | When fired |
|---|---|
gateway:startup |
Gateway process starts |
session:start |
New conversation session begins |
session:end |
Session completes or times out |
session:reset |
User resets session with /new |
agent:start |
Agent begins processing a message |
agent:step |
Agent completes one tool-calling iteration |
agent:end |
Agent finishes and returns response |
command:* |
Any slash command is executed |
Memory Provider Integration
When a memory provider plugin (e.g., Honcho) is enabled:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
AIAgent._invoke_tool()
→ self._memory_manager.handle_tool_call(name, args)
→ provider.handle_tool_call(name, args)
Memory Flush Lifecycle
When a session is reset, resumed, or expires: 1. Built-in memories are flushed to disk 2. Memory provider's on_session_end() hook fires 3. A temporary AIAgent runs a memory-only conversation turn 4. Context is then discarded or archived
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
Background Maintenance
The gateway runs periodic maintenance alongside message handling:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
주요 항목:
- Cron ticking — checks job schedules and fires due jobs
- Session expiry — cleans up abandoned sessions after timeout
- Memory flush — proactively flushes memory before session expiry
- Cache refresh — refreshes model lists and provider status
Process Management
The gateway runs as a long-lived process, managed via:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문을 확인하세요.
주요 항목:
hermes gateway start/hermes gateway stop— manual controlsystemctl(Linux) orlaunchctl(macOS) — service management- PID file at
~/.hermes/gateway.pid— profile-scoped process tracking
Related Docs
주요 항목:
- Session Storage
- Cron Internals
- ACP Internals
- Agent Loop Internals
- Messaging Gateway (User Guide)
실습 체크리스트
- 공식 문서와 설치된 Hermes 버전을 대조합니다.
- 관련 CLI는
hermes --help및 하위 명령--help로 확인합니다. - Gateway·메시징 변경 후
hermes gateway재시작을 검토합니다. - 시크릿·토큰은 환경 변수/시크릿 매니저에만 둡니다.
자주 쓰는 명령·설정 예시
┌─────────────────────────────────────────────────┐
│ GatewayRunner │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Telegram │ │ Discord │ │ Slack │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └─────────────┼─────────────┘ │
│ ▼ │
│ _handle_message() │
│ │ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ Slash command AIAgent Queue/BG │
│ dispatch creation sessions │
│ │ │
│ ▼ │
│ SessionStore │
│ (SQLite persistence) │
└───────┴─────────────┴─────────────┴─────────────┘
agent:main:{platform}:{chat_type}:{chat_id}
Admin: /pair
Gateway: "Pairing code: ABC123. Share with the user."
New user: ABC123
Gateway: "Paired! You're now authorized."
if _quick_key in self._running_agents:
if canonical == "model":
return "⏳ Agent is running — wait for it to finish or /stop first."
plugins/platforms/ # plugin-packaged adapters (one dir each)
├── telegram/adapter.py # Telegram Bot API (long polling or webhook)
├── discord/adapter.py # Discord bot via discord.py
├── slack/adapter.py # Slack Socket Mode
├── whatsapp/adapter.py # WhatsApp Business Cloud API
├── matrix/adapter.py # Matrix via mautrix (optional E2EE)
├── mattermost/adapter.py # Mattermost WebSocket API
├── email/adapter.py # Email via IMAP/SMTP
├── sms/adapter.py # SMS via Twilio
├── dingtalk/adapter.py # DingTalk WebSocket
├── feishu/adapter.py # Feishu/Lark WebSocket or webhook
├── wecom/adapter.py # WeCom (WeChat Work) callback
├── line/adapter.py # LINE Messaging API
├── teams/adapter.py # Microsoft Teams
├── irc/adapter.py # IRC (canonical scoped-lock example)
├── homeassistant/adapter.py # Home Assistant conversation integration
└── … # google_chat, ntfy, photon, raft, simplex, …
gateway/platforms/ # core base + legacy direct adapters
├── base.py # BasePlatformAdapter — shared logic for all platforms
├── signal.py # Signal via signal-cli REST API
├── weixin.py # Weixin (personal WeChat) via iLink Bot API
├── bluebubbles.py # Apple iMessage via BlueBubbles macOS server
├── qqbot/ # QQ Bot (Tencent QQ) via Official API v2 (sub-package)
├── yuanbao.py # Yuanbao (Tencent) DM/group adapter
├── msgraph_webhook.py # Microsoft Graph change-notification webhook (Teams, Outlook, etc.)
├── webhook.py # Inbound/outbound webhook adapter
└── api_server.py # REST API server adapter
AIAgent._invoke_tool()
→ self._memory_manager.handle_tool_call(name, args)
→ provider.handle_tool_call(name, args)
관련 링크
이 가이드는 공식 문서를 한국어 학습용으로 재구성한 것입니다. 옵션 기본값·API 이름은 설치 버전에 따라 달라질 수 있습니다.