Back to Course Dashboard

Multi-Platform Gateway

Module 7 of 10

🎬 Full Walkthrough Video

**Course:** Hermes Agent β€” From Zero to Autonomous Agent
**Module:** 7 of 10
**Reading time:** ~20 minutes
**Difficulty:** Intermediate

TL;DR

**What it is** A single daemon process that connects Hermes to Telegram, Discord, Slack, WhatsApp, Signal, and 15+ other platforms β€” all from one agent instance
**Key idea** Same AI agent, different chat interfaces. Your tools, memory, skills, and cron jobs work identically across every platform
**Setup** `hermes gateway setup` β€” interactive wizard, or manual `.env` config
**Service** `hermes gateway install` β€” installs as systemd (Linux) or launchd (macOS)
**Security** Allowlists, DM pairing, admin/user tiers, command approval for dangerous operations
**Cron** Scheduled jobs deliver to your home channel on any platform

What Is the Gateway?

The Hermes Gateway is a **background daemon** that runs your agent and connects it to messaging platforms. Think of it as the bridge between your LLM-powered agent and the apps you use every day.

Without the gateway, you run Hermes in your terminal β€” useful, but tied to your desktop. With the gateway:

- You message your agent from **Telegram on your phone** while commuting

- Your **Discord server** has a shared AI assistant your whole team can DM

- **Cron jobs** (scheduled tasks) run 24/7 and deliver results to your chat

- Your agent is always online, always ready, whether you're at your desk or not

The architecture is clean:


Telegram ─┐
Discord  ──
Slack    ──
WhatsApp ──
Signal   ──              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
Email    ──── platform ─→│   Hermes Gateway    │──→ AIAgent (your LLM)
SMS      ──   adapters   β”‚  (single daemon)    │──→ Tools (shell, files, web)
Matrix   ──              β”‚  Sessions, cron,    │──→ Skills
Home     ──              β”‚   security, voice   │──→ Memory
Assistantβ”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

One gateway process. Many platform adapters. Same agent, tools, skills, and memory everywhere.


Supported Platforms

Hermes ships with built-in adapters for the following platforms. Each adapter receives messages, routes them through a per-chat session store, and dispatches them to the agent for processing.

Platform Voice Images Files Threads Typing Streaming
---------- :-----: :------: :-----: :-------: :------: :---------:
**Telegram** βœ… βœ… βœ… βœ… βœ… βœ…
**Discord** βœ… βœ… βœ… βœ… βœ… βœ…
**Slack** βœ… βœ… βœ… βœ… βœ… βœ…
**WhatsApp** β€” βœ… βœ… β€” βœ… βœ…
**Signal** β€” βœ… βœ… β€” βœ… βœ…
**SMS (Twilio)** β€” β€” β€” β€” β€” β€”
**Email** β€” βœ… βœ… βœ… β€” β€”
**Matrix** βœ… βœ… βœ… βœ… βœ… βœ…
**Mattermost** βœ… βœ… βœ… βœ… βœ… βœ…
**Home Assistant** β€” β€” β€” β€” β€” β€”
**DingTalk** β€” βœ… βœ… β€” βœ… βœ…
**Feishu / Lark** βœ… βœ… βœ… βœ… βœ… βœ…
**WeCom (WeChat Work)** βœ… βœ… βœ… β€” βœ… βœ…
**Weixin** βœ… βœ… βœ… β€” βœ… βœ…
**BlueBubbles (iMessage)** β€” βœ… βœ… β€” βœ… β€”
**QQ** βœ… βœ… βœ… β€” βœ… β€”
**Yuanbao** βœ… βœ… βœ… β€” βœ… βœ…
**Microsoft Teams** β€” βœ… β€” βœ… βœ… β€”
**LINE** β€” βœ… βœ… β€” βœ… β€”
**Google Chat** β€” βœ… βœ… βœ… βœ… β€”
**API Server** (OpenAI-compatible) β€” β€” β€” β€” β€” β€”
**Webhooks** β€” β€” β€” β€” β€” β€”

**Voice** = TTS audio replies and/or voice message transcription. **Images** = send/receive images. **Files** = send/receive attachments. **Threads** = threaded conversations. **Typing** = typing indicator while processing. **Streaming** = progressive message updates.

Platforms without built-in adapters can be added via the plugin system. See `ADDING_A_PLATFORM.md` in the gateway source.


How the Gateway Works

Architecture Detail

Each platform has its own **adapter** β€” a Python module that handles the platform-specific protocol (Telegram's polling/webhook API, Discord's WebSocket gateway, Signal's CLI bridge, etc.).

When a message arrives:

1. **Authorization check** β€” Is this user allowed? (Allowlist, DM pairing, or admin check)

2. **Session lookup** β€” Does this chat have an existing conversation context?

3. **Platform-specific handling** β€” Mention checks, free-response channels, thread isolation

4. **Agent dispatch** β€” The message is sent to the AIAgent with the correct session context

5. **Response delivery** β€” The agent's response is streamed back to the platform with typing indicators

Same Tools Everywhere

Every platform gets the same toolset β€” just with a different toolset name for logging:

Platform Toolset Name Capabilities
Telegram `hermes-telegram` Full tools including terminal
Discord `hermes-discord` Full tools including terminal
Slack `hermes-slack` Full tools including terminal
WhatsApp `hermes-whatsapp` Full tools including terminal
SMS `hermes-sms` Full tools including terminal
Email `hermes-email` Full tools including terminal
Home Assistant `hermes-homeassistant` Full tools + HA device control

This means the **same agent** that runs shell commands in your terminal can do it from Telegram, Discord, or any other platform.

Session Management

Sessions persist across messages until they reset. The agent remembers your conversation context.

Reset policies (configurable):

- **Daily** β€” Reset at a specific hour (default: 4:00 AM)

- **Idle** β€” Reset after N minutes of inactivity (default: 1440 min)

- **Both** β€” Whichever triggers first (default)

- **None** β€” Never auto-reset (controlled by compression only)

Configure per-platform overrides in `~/.hermes/gateway.json`:


{
  "reset_by_platform": {
    "telegram": { "mode": "idle", "idle_minutes": 240 },
    "discord": { "mode": "idle", "idle_minutes": 60 }
  }
}

Telegram Setup

This is the most common gateway setup. Let's walk through it step by step.

Step 1: Create a Bot via BotFather

1. Open Telegram and search for **@BotFather**, or visit [t.me/BotFather](https://t.me/BotFather)

2. Send `/newbot`

3. Choose a **display name** (e.g., "My Hermes Agent")

4. Choose a **username** that ends in `bot` (e.g., `my_hermes_bot`)

5. BotFather replies with your **API token**:


123456789:ABCdefGHIjklMNOpqrSTUvwxYZ

**Keep this token secret.** Anyone with it can control your bot. If it leaks, use `/revoke` in BotFather immediately.

Step 2: Optional Customization

Message BotFather and use:

Command Purpose
`/setdescription` What the bot can do β€” shown before a user chats
`/setabouttext` Short text on the bot's profile
`/setuserpic` Upload an avatar
`/setcommands` Define the command menu

A useful starting set for `/setcommands`:


help - Show help information
new - Start a new conversation
sethome - Set this chat as the home channel

Step 3: Privacy Mode (Critical for Groups)

Telegram bots have **privacy mode enabled by default**. This is the #1 source of confusion.

**With privacy mode ON**, your bot can only see:

- Messages starting with `/`

- Replies to its own messages

- Service messages (joins, leaves, pins)

**With privacy mode OFF**, the bot sees every message in the group.

To disable it:

1. Message **@BotFather**

2. Send `/mybots` β†’ select your bot

3. Go to **Bot Settings β†’ Group Privacy β†’ Turn off**

**Important:** You must remove and re-add the bot to any group after changing this setting. Telegram caches the privacy state when the bot joins.

Step 4: Find Your User ID

Your Telegram user ID is a number like `123456789`. Message [@userinfobot](https://t.me/userinfobot) to get it instantly.

Step 5: Configure Hermes

**Option A: Interactive Setup (Recommended)**


hermes gateway setup

Select **Telegram** when prompted. The wizard asks for your bot token and allowed user IDs, then writes the configuration.

**Option B: Manual Configuration**

Add to `~/.hermes/.env`:


TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
TELEGRAM_ALLOWED_USERS=123456789

For multiple users, comma-separate the IDs:


TELEGRAM_ALLOWED_USERS=123456789,987654321

Step 6: Start the Gateway


hermes gateway

The bot comes online within seconds. Send it a message on Telegram to verify.


Discord Setup

Step 1: Create a Discord Application

1. Go to the [Discord Developer Portal](https://discord.com/developers/applications)

2. Click **New Application** β†’ enter a name β†’ **Create**

3. Note your **Application ID** β€” you'll need it for the invite URL

Step 2: Create the Bot

1. In the left sidebar, click **Bot**

2. Set **Public Bot** to **ON** (recommended)

3. Set a custom avatar if desired

Step 3: Enable Privileged Gateway Intents

**This is the most critical step.** Scroll down to **Privileged Gateway Intents** and enable:

Intent Required? Why
-------- :---------: -----
**Presence Intent** Optional See online/offline status
**Server Members Intent** **Required** Resolve usernames for allowed users
**Message Content Intent** **Required** Read the text content of messages

**Without Message Content Intent enabled, your bot receives messages but the text content is empty.** It's the #1 reason Discord bots appear online but never respond.

Step 4: Get the Bot Token

Still on the **Bot** page, click **Reset Token**. Copy it immediately β€” it's only shown once.

Step 5: Generate the Invite URL

Use the **Installation** tab (if Public Bot is ON) or create a manual URL:


https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot+applications.commands&permissions=274878286912

Replace `YOUR_APP_ID` with the ID from Step 1.

Minimum permissions: View Channels, Send Messages, Embed Links, Attach Files, Read Message History.

Step 6: Invite to Your Server

Open the invite URL β†’ select your server β†’ **Authorize**. The bot appears in your server's member list.

Step 7: Find Your User ID

1. Open Discord β†’ **Settings** β†’ **Advanced** β†’ enable **Developer Mode**

2. Right-click your username β†’ **Copy User ID**

Step 8: Configure Hermes

**Interactive:**


hermes gateway setup

**Manual β€” add to `~/.hermes/.env`:**


DISCORD_BOT_TOKEN=your-bot-token
DISCORD_ALLOWED_USERS=284102345871466496

Step 9: Start the Gateway


hermes gateway

The bot comes online. Send it a DM or `@mention` it in a channel.


Gateway as a Systemd Service

For 24/7 operation, install the gateway as a background service.

Installation


hermes gateway install

On Linux, this creates a systemd user service at `~/.config/systemd/user/hermes-gateway.service`.

For a boot-time system service (recommended for VPS):


sudo hermes gateway install --system

Service Management


hermes gateway start      # Start the service
hermes gateway stop       # Stop the service
hermes gateway restart    # Restart the service
hermes gateway status     # Check if it's running

Enable Lingering (Linux)

Keeps user services running after you log out:


sudo loginctl enable-linger $USER

View Logs


# Systemd journal (user service)
journalctl --user -u hermes-gateway -f

# Systemd journal (system service)
journalctl -u hermes-gateway -f

# Direct log file
tail -f ~/.hermes/logs/gateway.log

macOS (launchd)


hermes gateway install               # Install as launchd agent
hermes gateway start                 # Start
hermes gateway stop                  # Stop
hermes gateway status                # Check status
tail -f ~/.hermes/logs/gateway.log   # View logs

The plist lives at `~/Library/LaunchAgents/ai.hermes.gateway.plist` and captures your PATH at install time. If you add new tools later, re-run `hermes gateway install` to update it.


Gateway Status

Check what's running:


hermes gateway status

This shows:

- Whether the service is active

- How long it's been running

- Which platforms are connected

- Last log entries

From within any connected chat, use:


/status     β€” Show session info
/whoami    β€” Show your access tier and allowed commands
/platforms β€” Show all active platform adapters

The `/platform` command lets you inspect and steer individual adapters without restarting:


/platform list                β€” Show all adapters and their state
/platform pause <name>        β€” Stop dispatching new messages to one adapter
/platform resume <name>       β€” Re-enable a paused adapter

Gateway Logs

Logs are written to `~/.hermes/logs/gateway.log`. This is your primary debugging resource.

Important log locations:

What Where
Gateway log `~/.hermes/logs/gateway.log`
Agent log `~/.hermes/logs/agent.log`
Errors `~/.hermes/logs/errors.log`
Systemd journal (user) `journalctl --user -u hermes-gateway -f`
Systemd journal (system) `journalctl -u hermes-gateway -f`

Each adapter logs its name in brackets, making it easy to filter:


[telegram] Connected to Telegram (polling mode)
[discord] Connected to Discord
[telegram] Message from @username: /new

Security

Allowlists

By default, the gateway denies all users who are not explicitly allowed. This is the safe default for a bot with terminal access.


# Per-platform
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=284102345871466496
SIGNAL_ALLOWED_USERS=+15551234567

# Global (applies to all platforms)
GATEWAY_ALLOWED_USERS=123456789

# Or explicitly allow everyone (NOT recommended if the bot has terminal access)
GATEWAY_ALLOW_ALL_USERS=true

DM Pairing

Instead of manually configuring user IDs, unknown users receive a one-time pairing code when they DM the bot:


# User sees: "Pairing code: XKGH5N7P"
# You approve them with:
hermes pairing approve telegram XKGH5N7P

# Other commands:
hermes pairing list              # View pending + approved users
hermes pairing revoke telegram 123456789   # Remove access

Pairing codes expire after 1 hour and use cryptographic randomness.

Admin vs Regular Users

Every allowed user falls into one of two tiers per scope:

- **Admin** β€” full access to all slash commands and capabilities

- **Regular user** β€” can chat normally but only run explicitly enabled slash commands

Configure in `~/.hermes/config.yaml`:


gateway:
  platforms:
    discord:
      extra:
        allow_from: ["111", "222", "333"]
        allow_admin_from: ["111"]
        user_allowed_commands: [status, model]

Use `/whoami` from any platform to see your current tier and allowed commands.

Command Approval

When the agent wants to run a dangerous command (e.g., `rm -rf /`), the gateway sends an **approve/deny** button (Telegram) or prompts you to use `/approve` / `/deny`. This prevents the agent from executing destructive operations without your confirmation.


Home Channel Concept

The **home channel** is the default delivery destination for your platform. When a cron job specifies `deliver: telegram` without a specific chat ID, messages are sent to the home channel.

Setting a Home Channel

The easiest way β€” in any chat, use:


/sethome

The gateway confirms with something like:


βœ… This chat is now the home channel for Telegram.

Manual Configuration

In `~/.hermes/.env`:


TELEGRAM_HOME_CHANNEL=-1001234567890
TELEGRAM_HOME_CHANNEL_NAME="My Notes"

DISCORD_HOME_CHANNEL=987654321098765432
DISCORD_HOME_CHANNEL_NAME="Team Chat"

Group chat IDs are negative numbers on Telegram.


Cron Deliveries

When Hermes executes a scheduled task (cron job), the result needs to go somewhere. The gateway handles delivery seamlessly.

How It Works

1. Cron job fires at the scheduled time

2. Agent executes the task in a fresh session

3. Result is delivered to the configured destination

Delivery Options

When creating a cron job, specify where results go:


# Deliver to the home channel
hermes cron create "0 8 * * *" "Check server status" --deliver telegram

# Deliver to Discord home channel
hermes cron create "0 8 * * *" "Check server status" --deliver discord

# Save to local files
hermes cron create "0 8 * * *" "Check server status" --deliver local

From a chat session, just tell the agent naturally:


Every morning at 9am, check the server status and send me a summary on Telegram.

Hermes creates the cron job and configures delivery automatically.


Running the Gateway 24/7 on a VPS

For a permanently online agent, run the gateway on a VPS:

1. Provision a VPS ($4-6/month β€” see Module 8)

2. Install Hermes with the standard one-liner

3. Configure your API keys and platform tokens in `.env`

4. Install the gateway as a system service:


sudo hermes gateway install --system
sudo hermes gateway start --system
sudo loginctl enable-linger $USER

5. Verify with:


sudo hermes gateway status --system

The gateway restarts automatically at boot, runs your cron jobs, and delivers results to your home channel.


Troubleshooting

Gateway Crash Loop

**Symptom:** The gateway starts and immediately crashes. `systemctl` shows `failed` status.

**Diagnosis:**


journalctl --user -u hermes-gateway -n 50 --no-pager

**Common causes:**

- **Missing API keys** β€” Your `.env` file doesn't have a required API key for your LLM provider. Check that the provider's API key is set.

- **Invalid bot token** β€” The Telegram or Discord token is wrong. Verify it in `.env`.

- **Platform auth failure** β€” Check logs for `authentication failed` messages.

**Fix:**

1. Verify `.env` has all required keys

2. Run `hermes gateway` in foreground to see real-time errors

3. If a platform token is invalid, regenerate it and update `.env`

4. Restart: `hermes gateway restart`

Discord Silent (Bot Online but Not Responding)

**Symptom:** The bot shows as online/active in your server but never responds to messages.

**Almost always caused by missing Message Content Intent.**

**Check:**

1. Go to [Discord Developer Portal](https://discord.com/developers/applications)

2. Select your application β†’ **Bot** β†’ **Privileged Gateway Intents**

3. Is **Message Content Intent** toggled ON?

**Fix:**

1. Toggle **Message Content Intent** ON

2. Click **Save Changes**

3. Restart the gateway: `hermes gateway restart`

**Still not working?** Check:

- Is your user ID in `DISCORD_ALLOWED_USERS`?

- Are you mentioning the bot? (In channels, you need `@mention` unless free-response channels are configured)

- Check the gateway log for authorization denials

Telegram Not Responding

**Symptom:** The bot is online but doesn't reply to messages.

**Check:**


tail -f ~/.hermes/logs/gateway.log

**Common causes:**

- **Wrong bot token** β€” Verify in `.env`

- **User not authorized** β€” Is your user ID in `TELEGRAM_ALLOWED_USERS`?

- **Privacy mode blocking** β€” If the bot is in a group, check privacy mode

- **Rate limiting** β€” Telegram rate-limits bots that send too many requests. Wait a few minutes.

**Fix:**

1. Send a message and watch the logs in real time

2. If you see `Not authorized`, add your user ID to the allowlist

3. If you see nothing at all, the bot token is likely wrong

4. Restart the gateway

Circuit Breaker Paused an Adapter

**Symptom:** A platform that was working suddenly stops. Log shows "paused-by-breaker".

**Cause:** The adapter encountered repeated failures (network blips, rate-limit replies, websocket disconnects) and the circuit breaker tripped.

**Fix:**


# From another platform or CLI
/platform resume <name>

The breaker does **not** auto-resume β€” this prevents the gateway from thrashing reconnects during a sustained outage.

Logs Show "Failed" but Gateway Seems Fine

The gateway uses **circuit breakers** per adapter. Repeated retryable failures cause the breaker to trip. Check:

1. `~/.hermes/logs/gateway.log` β€” search for `circuit breaker`, `paused`, or `disabled`

2. `/platform list` output β€” shows current state and last reason

3. The platform's status page (Telegram API status, Discord status, etc.)

Once upstream is healthy, use `/platform resume ` to re-arm the adapter.


Summary

- The **gateway** is a single daemon connecting Hermes to 20+ messaging platforms

- Each platform has its own **adapter** β€” but all share the same agent, tools, memory, and skills

- **Telegram** setup: BotFather β†’ get token β†’ `hermes gateway setup` β†’ done

- **Discord** setup: Developer Portal β†’ create bot β†’ **enable Message Content Intent** β†’ invite β†’ configure

- Install as a **systemd service** for 24/7 operation: `hermes gateway install`

- **Security** is multi-layered: allowlists, DM pairing, admin/user tiers, command approval

- The **home channel** (`/sethome`) is where cron deliveries land

- **Troubleshooting** starts with the gateway log: `~/.hermes/logs/gateway.log`

In the next module, we'll deploy the gateway to a VPS for always-on, production-grade operation.

Module 6 Dashboard Module 8