Skip to content

Gateway Architecture

When Hermes runs in the terminal, it lives as long as your shell session does. Close the terminal, Hermes dies. That's fine for interactive work. It's not fine for an agent you want to reach from your phone at 11 PM when a deployment goes sideways. The gateway is the bridge between Hermes's agent core and the messaging platforms you already use, and it needs to run as a persistent service, not a terminal-bound process.

This lesson covers how the gateway fits into Hermes, what makes it survive restarts, and the decisions you make before connecting any platform. No bot tokens yet, that starts in the next lesson. This is the architecture you need to understand first.

Owl mascot

What you'll learn

  • The gateway is a single process that connects one agent core to multiple messaging platforms simultaneously, Telegram, Discord, Slack, and 20+ others all share the same configuration and session state
  • On Linux and WSL2, the gateway runs as a systemd user service; without systemd, it falls back to nohup and dies when the session closes
  • Gateway logs live at ~/.hermes/logs/gateway.log , this is where you go first when something isn't working, before changing any configuration
  • Per-platform tool controls (hermes tools) let you disable dangerous tools on public-facing platforms while keeping them available on trusted channels

The problem: agents die with your terminal

You've been running Hermes interactively. hermes starts the CLI, you chat, you quit. The process stops. That works for a development machine where you're sitting in front of the keyboard. It breaks down the moment you want Hermes to be reachable when you're not actively connected.

The fundamental requirement for any gateway is durability. The process needs to:

  • Survive SSH logout (Linux servers)
  • Survive terminal window close (WSL2)
  • Auto-restart if it crashes
  • Start when the machine boots

Hermes solves this with systemd user services on Linux and WSL2. On macOS, it uses launchd. On Windows native, it runs as a scheduled task. The setup command handles the platform differences; you need to understand which one applies to your environment and what can go wrong.

Options & when to use each

Gateway setupWhat it doesCosts youWhen to pick it
hermes gateway installCreates a systemd user service (Linux/WSL2) or launchd plist (macOS)Requires systemd on Linux, WSL2 needs systemd=true in /etc/wsl.confProduction servers, always-on agents, any machine where the gateway should survive restarts
hermes gateway runRuns the gateway in the foregroundDies when the terminal closes, temporary onlyTesting configuration changes, debugging a platform adapter, one-off gateways
hermes gateway setupInteractive wizard to configure platformsNone, walks you through the optionsFirst-time setup, adding a new platform to an existing gateway
hermes gateway start/stop/restart/statusControls the systemd serviceRequires the service to be installed firstDay-to-day operations after initial setup

If you're on WSL2, the systemd requirement is the most common gotcha. Open /etc/wsl.conf and make sure it contains:

ini
[boot]
systemd=true

Without this, WSL2 doesn't run systemd at all, and the gateway service install will fail or fall back to nohup (which dies when you close the WSL window). If you change this setting, restart WSL from PowerShell:

powershell
wsl --shutdown

Then reopen your WSL terminal.

On a remote Linux server accessed via SSH, there's another requirement. Even with systemd running, user services are killed when the user's last session ends unless lingering is enabled:

bash
sudo loginctl enable-linger $USER

This tells systemd to keep your user services running after you log out. Skip this step, and your gateway will die the moment your SSH connection drops.

Build it

Step 1: Check your environment

Before installing the gateway, verify your system supports user services. Check if systemd is running and whether lingering is enabled for your user account.

bash
# Are you on systemd?
pidof systemd && echo "systemd is running" || echo "no systemd"

# If on WSL2, check wsl.conf
cat /etc/wsl.conf | grep -A2 "\[boot\]"

# If on a remote server, check linger status
loginctl show-user $USER | grep Linger

If systemd isn't running on WSL2, fix /etc/wsl.conf with the systemd=true block and restart WSL. If linger shows Linger=no on a server, run sudo loginctl enable-linger $USER.

Step 2: Install the gateway service

Install the gateway as a systemd user service. This registers the service definition in your local configuration directory.

bash
hermes gateway install

This creates a systemd user service called hermes-gateway. The service file lives under ~/.config/systemd/user/hermes-gateway.service. You can inspect it to verify the command it runs:

bash
systemctl --user cat hermes-gateway

Step 3: Start the gateway

Start the newly created service. If it fails to start, check the gateway logs for configuration errors.

bash
hermes gateway start

Check that it actually started:

bash
hermes gateway status

The status output should show active (running). If it shows failed or inactive, check the logs:

bash
tail -50 ~/.hermes/logs/gateway.log

Step 4: Verify it survives a restart

Test the service's durability by restarting it. A successful restart confirms the unit file is correctly configured and the gateway can recover from a crash.

bash
hermes gateway restart
hermes gateway status    # Should show active again

If the restart works, the service is installed correctly. If it fails on restart, the most likely cause is a configuration error, the service file is fine, but Hermes can't start because of a bad platform config. The gateway log will tell you which platform failed to initialize.

Step 5: Enable auto-start on boot

Configure the service to start automatically when the system boots. This ensures the gateway comes online without requiring a manual login.

bash
systemctl --user enable hermes-gateway

This starts the gateway automatically when the machine boots, before you even log in. Combined with linger, this means the gateway runs whenever the machine is on, regardless of who's logged in.

What goes wrong

MistakeHow you notice itThe fix
Gateway dies on SSH logouthermes gateway status shows inactive after you reconnectsudo loginctl enable-linger $USER , user services are killed when the last session ends unless lingering is enabled
Gateway won't start on WSL2hermes gateway install succeeds but start fails, logs show systemd errorsAdd systemd=true to /etc/wsl.conf under [boot], then run wsl --shutdown from PowerShell and reopen WSL
Gateway crashes on restart after config changehermes gateway restart produces a failed statusCheck ~/.hermes/logs/gateway.log , a bad platform config (wrong token, missing intent) will crash the entire gateway, not just that platform
Can't enable the service at bootsystemctl --user enable fails with "no graphical session"On headless servers, you may need to set XDG_RUNTIME_DIR manually. Most installs handle this, but if it fails: export XDG_RUNTIME_DIR=/run/user/$(id -u)
Multiple gateway processes runningLogs show "address already in use" errorsStop all instances: hermes gateway stop, verify with `ps aux

Confirm it worked

Verify the installation by checking the service state and inspecting the startup logs. Run the following checks to ensure the gateway is active and auto-start is properly configured.

bash
# 1. Verify the service is running
hermes gateway status

# 2. Check the log for startup messages
grep "gateway.*started\|listening" ~/.hermes/logs/gateway.log | tail -5

# 3. Test durability
hermes gateway restart && sleep 2 && hermes gateway status

# 4. Verify auto-start is enabled
systemctl --user is-enabled hermes-gateway

If step 1 shows active (running), step 3 returns active after a restart, and step 4 prints enabled, the gateway service is working. Step 2 will show startup messages confirming the gateway is listening, but no platforms are connected yet. That's what the next lessons are for.

Next: Telegram Setup , register a bot, connect it to the gateway, and send your first command from your phone.