โ† Back to blog
[ Blog ]

Setup Hermes with Slack: from install to first message

May 29, 2026ยทJeet
Hermes setup guide cover image

Hermes is one of the more capable self-hosted AI agents you can run today, especially if you want something that lives on a server, builds up memory and skills over time, and reaches you through whatever messaging app you actually open. Standing it up end to end, install, provider, Slack, persistence, takes more steps than any single doc page lays out, and a handful of them will leave you with a silently dead bot if you miss them.

This is a practical Hermes setup walkthrough, written after putting one together on a sandbox. No theory, no pitch. Pick a host, install, wire up Slack, keep it alive.

What Hermes actually is

Hermes is an autonomous agent that runs as a long-lived process. One Gateway connects to whatever messaging platforms you configure, manages your sessions, fires scheduled jobs, and talks to your chosen LLM provider. It also persists memory and auto-generated skills to disk, so it gets sharper at your specific patterns the longer it runs.

The framing that made it click for me: you are not installing a chatbot. You are running a personal AI service that you happen to talk to over Slack. Once that lands, the rest of the setup follows.

Prerequisites

Two things before you touch anything:

  • An API key from a model provider, plus a model with at least 64K context. Anthropic, OpenAI, Google, OpenRouter, or any of the ~19 providers Hermes supports. Smaller-context models get rejected at startup, so do not bother with a 32K endpoint.
  • A machine to run it on. The next step covers your options.

You also need Python 3.11 and Node 22 on the host, but depending on what you pick, the installer handles that.

Step 1: Choose your machine

The Gateway is a long-running process, and where it lives shapes the rest of the setup. Four reasonable picks:

A Mac mini or NUC at home. Cheap to run, snappy, fine for a personal agent. Con: dedicated hardware that has to stay on, and reaching it from outside your LAN needs work.

Your laptop. Decent for a first run-through. Con: closing the lid kills the Gateway, and the agent runs shell commands on the same filesystem you do everything else on.

A VPS (DigitalOcean, Hetzner, etc). Always on, isolated from your daily machine. Con: you handle the OS, Python, Node, firewall, persistence, and DNS yourself.

A Superserve sandbox. Firecracker microVM with pause/resume and snapshot persistence, isolated by default. The superserve/hermes template ships with Hermes, Python 3.11, Node 22, tmux, and ripgrep already in place, so the bootstrap collapses to nothing. Con: depends on a managed service, which is the usual tradeoff against running your own box.

The rest of this guide assumes a Superserve sandbox because the install is the shortest and the microVM is genuinely the right isolation model for an agent with terminal access. The Slack and config steps are identical on any other machine, you just install Python, Node, and Hermes yourself first.

Create a Superserve sandbox

  1. Go to console.superserve.ai and click Create sandbox.
  2. Pick the superserve/hermes template. Python, Node, Hermes, tmux, ripgrep, and ffmpeg are all preinstalled.
  3. Open Advanced Options and add your model provider key under Environment Variables, for example ANTHROPIC_API_KEY or OPENROUTER_API_KEY. You will add the Slack tokens here too once you have them.
  4. Create the sandbox and open its Terminal.

Confirm Hermes is on PATH:

bash
hermes --version

If you went with a non-sandbox machine, run the one-line installer first. It pulls Python 3.11, Node 22, ripgrep, ffmpeg, and uv, then sets up the venv and the global hermes command:

bash
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

Step 2: Wire up a model

Hermes has no default provider. You have to tell it which one to use before anything runs. The fastest path is hermes model, which walks you through provider selection and writes the choice to config:

bash
hermes model

Providers light up in the picker based on which API keys it finds in your environment, so make sure the relevant key is set first. Pick a model with a 64K+ context window: Claude Opus or Sonnet 4.x, the GPT-5 series, and Gemini 2.5+ all qualify. Anything smaller gets refused at startup.

If you prefer the explicit path, set both values directly:

bash
hermes config set model anthropic/claude-opus-4.7
hermes config set provider anthropic

Skip the optional skills, voice, and tool steps for now. Get one clean conversation running before layering features on. Sanity check it:

bash
hermes chat

Send a quick "hi". If you get a reply, the provider side is good. If you see No inference provider configured. Run 'hermes model' to choose a provider and model, the env var did not land in this shell or the config does not have a provider set. Fix it before going further, since Slack will fail with the same error.

Step 3: Set up the Slack gateway

This is where most of the friction lives. Slack needs an app, two tokens, the right scopes, and event subscriptions. Miss any one of them and the bot stays silent with no useful error in chat.

Create the Slack app

  1. Go to api.slack.com/apps and create a new app from scratch (not from a manifest).
  2. Name it (Hermes is fine) and pick your workspace.

Classic Slack apps were fully deprecated in March 2025, so the modern Bolt-based flow is the only one that works. If you find an older walkthrough telling you to use a classic app, ignore it and start fresh.

Enable Socket Mode

Socket Mode is the right choice for almost every Hermes setup. It uses an outbound WebSocket from your host to Slack, so you do not need a public URL or any inbound port open. That matters on sandboxes and home machines, where exposing ports is a hassle.

  1. In the app settings, go to Socket Mode and toggle it on.
  2. Go to Basic Information, scroll to App-Level Tokens, and generate a token with the connections:write scope. This is your xapp- token. Save it somewhere safe.

Add bot scopes

Go to OAuth & Permissions, scroll to Bot Token Scopes, and add at minimum:

text
app_mentions:read
channels:history
chat:write
groups:history
im:history
im:read
im:write
mpim:history

The two *:history scopes are the ones people skip most often. Without them, the bot works fine in DMs but silently ignores everything posted in channels. That is the most common setup failure on Slack, and the symptom is misleading because the bot looks healthy.

Subscribe to events

Skip this step and Socket Mode connects without complaint, but Slack has no idea which events to forward, so nothing actually reaches Hermes. This is the second most common silent failure.

  1. Go to Event Subscriptions and toggle Enable Events on.
  2. Under Subscribe to bot events, add:
text
app_mention
message.channels
message.groups
message.im
  1. Save changes.

Install and grab the bot token

Install the app to your workspace. Copy the xoxb- Bot User OAuth Token from the OAuth & Permissions page.

Important: any time you change scopes or events after this, Slack requires a reinstall, and the reinstall is what actually grants the new permissions. If you skip the reinstall, your "new" scopes are not active. When in doubt, reinstall.

Store tokens as environment variables

Two tokens, both treated as secrets:

  • SLACK_BOT_TOKEN, the xoxb- bot token from OAuth & Permissions.
  • SLACK_APP_TOKEN, the xapp- app-level token from Basic Information.

On a Superserve sandbox, add both under Environment Variables in the console, alongside your model key. Setting them there injects them into the sandbox environment itself, so every new shell and every process started in the sandbox sees them. This matters more than it sounds, see the env var note in the gotchas.

On any other machine, persist them in ~/.hermes/.env with strict permissions. The folder may not exist yet:

bash
mkdir -p ~/.hermes
cat >> ~/.hermes/.env <<'EOF'
SLACK_BOT_TOKEN=xoxb-your-token
SLACK_APP_TOKEN=xapp-your-token
EOF
chmod 600 ~/.hermes/.env

The single-quoted 'EOF' matters: it tells bash not to expand $ inside the block, which is what you want for opaque token strings.

Allow the right users

By default, the gateway denies every incoming message as a safety measure. You have to explicitly allowlist either specific users or everyone. For a team bot in a shared channel, opening it up is what you usually want:

bash
echo 'GATEWAY_ALLOW_ALL_USERS=true' >> ~/.hermes/.env

If you would rather keep it tight, grab the Slack Member IDs of the people who should have access (profile menu, three dots, Copy member ID) and list them instead:

bash
echo 'SLACK_ALLOWED_USERS=U01ABC2DEF3,U02DEF4GHI5' >> ~/.hermes/.env

Configure Slack behavior

Behavioral config lives in ~/.hermes/config.yaml. The defaults are sane for most cases. The block I ran with:

bash
cat > ~/.hermes/config.yaml <<'EOF'
platforms:
  slack:
    require_mention: true
    extra:
      reply_in_thread: true
EOF

A few notes on what these flags actually do:

  • require_mention: true is the default and the right setting for a channel bot. The bot only replies when someone @-mentions it. Drop this and you risk auto-engagement, where Hermes remembers being addressed in a thread and starts following up on every reply.
  • reply_in_thread: true keeps channel responses inside threads. Hermes streams tool progress as it works (๐Ÿ’ป ls -la..., ๐Ÿ” web_search...), so without threading, a single question can spam a channel with five messages. Threads keep the channel readable.
  • Slack sessions are keyed by thread, not by user. This is specific to Slack, Telegram and Discord key sessions by user. Multiple teammates in the same thread share one conversation, one context, one history. It is the right behavior for a team bot, and it is the main reason to put Hermes on Slack over the other platforms.

Set a home channel

Hermes uses a "home channel" for proactive messages: cron output, cross-platform notifications, scheduled task results. On your first message the gateway will hint about this. Set it either via env var:

bash
echo 'SLACK_HOME_CHANNEL=C01ABC2DEF3' >> ~/.hermes/.env

(Right-click the channel in Slack, View channel details, scroll to the bottom for the channel ID.)

Or in chat, from inside the channel you want as home:

text
/hermes sethome

A small footgun here: the onboarding hint currently tells you to type /sethome, which does not work on Slack. The Slack adapter registers everything under a single /hermes parent command, so the actual invocation is /hermes sethome. If /sethome returns "the app did not respond", that is why. There is a tracking issue open against this.

If you do not need cron or proactive output, you can ignore the hint entirely. The bot still works fine without a home channel set; you just lose scheduled-job delivery.

Step 4: Run doctor

hermes doctor checks your install, config, and provider auth for the obvious mistakes. Run it before starting the gateway:

bash
hermes doctor

It catches missing provider credentials, unreachable model endpoints, broken backends, and a handful of other footguns. It is also the first thing to run any time the bot starts behaving strangely later. Most misconfigurations show up here.

On a sandbox without systemd, doctor also notes that service installation is unavailable and tells you to run the Gateway as a foreground process. That is expected. The next step handles persistence with tmux.

Step 5: Start the gateway

If your machine has systemd available (most VPS images and home Linux installs), the cleanest path is the built-in service installer:

bash
hermes gateway install

This registers a user systemd service that auto-restarts on crash and survives reboots. Verify with:

bash
systemctl --user status hermes-gateway
journalctl --user -u hermes-gateway -f

On a Superserve sandbox, the Firecracker rootfs does not run systemd as a user service host, so hermes gateway install refuses with:

text
Service installation not supported on this platform.
Run manually: hermes gateway run

That is fine. Use tmux instead:

bash
tmux new -s hermes
hermes gateway run

Watch the logs. You want to see Socket Mode connecting cleanly and your channel resolving by ID. Then detach without killing the gateway: press Ctrl+B, release, then press D. Back at a normal shell, the gateway keeps running.

To come back later:

bash
tmux ls                   # list sessions
tmux attach -t hermes     # reattach

One subtlety: if you already started hermes gateway run directly in your shell and now want to move it into tmux, you cannot. Ctrl+C it first, then start it fresh inside tmux. A few seconds of downtime.

If tmux is not available either, nohup works as a last resort:

bash
nohup hermes gateway run > ~/.hermes/gateway.log 2>&1 &
disown

disown removes the process from the shell's job table so closing the terminal does not send it SIGHUP. Logs land in ~/.hermes/gateway.log. Stop it with pkill -f "hermes gateway".

Step 6: Test in Slack

In Slack:

  1. Invite the bot to a channel: /invite @Hermes. The bot does not auto-join, you have to invite it to every channel where it should listen.
  2. Mention it: @Hermes hello.

If it replies inside a thread, you are done. From there, anyone in that thread can keep talking to it without re-mentioning. Outside threads, every new request needs a fresh @-mention.

For first-time DM access from someone who is not on the allowlist, Hermes uses a one-time pairing code flow. The user gets a code in chat, you approve it from the terminal:

bash
hermes pairing list
hermes pairing approve slack <code>

This only matters if you stuck with SLACK_ALLOWED_USERS instead of GATEWAY_ALLOW_ALL_USERS=true.

A few gotchas worth knowing

Channels go quiet after scope changes. If the bot replies in DMs but not in channels, the cause is almost always missing channels:history and groups:history scopes, plus forgetting to reinstall the app after adding them. Both have to be fixed. One alone is not enough.

Env vars and the running gateway. A process only sees the environment variables that existed when its shell started. The gateway lives inside a tmux session, and that tmux shell captured its environment at creation time. If you add or change a token after that, the already-running gateway will not see the new value. After any token change, restart the gateway: inside the tmux session, Ctrl+C the gateway, then hermes gateway run again. On a Superserve sandbox, console-level env vars get injected into new shells, but the gateway process itself still needs a restart to pick them up.

Pause and resume kills the WebSocket. When the microVM pauses (or your laptop sleeps), the Slack WebSocket dies. The Slack SDK reconnects automatically on resume, but messages sent during the pause window are lost. Slack does not replay socket events. If your sandbox pauses aggressively, configure it to stay awake, or accept the lost-messages-while-paused tradeoff for a personal bot.

Process supervision matters. Without systemd, your tmux session is the only thing keeping the gateway alive. If the host reboots, the tmux session is gone, the gateway is gone, and your 24/7 assistant is actually a "until next reboot" assistant. For a personal sandbox that rarely restarts, manually restarting is fine. For anything you want others to depend on, drop the start command in ~/.bashrc or set up a real init system.

Blast radius. The moment Hermes is on Slack, anyone in the allowed user list (or anyone in the channel, if you flipped GATEWAY_ALLOW_ALL_USERS=true) can issue commands to a process with terminal access. Keep approval prompts on for destructive actions. If you are exposing it to a wider team, lock the terminal backend down with hermes config set terminal.backend docker, or lean on the microVM as your isolation boundary and disable tools you do not need.

Wrapping up

That is a full Hermes setup, from picking a host through a working Slack channel and a gateway running in tmux. The pattern across every failure mode I hit was the same: a silent breakage with no error in chat, and the actual cause buried in scopes, event subscriptions, env var scope, or process lifecycle.

Run hermes doctor whenever something feels off, it catches most issues on its own. And remember that a running gateway only sees the environment it started with, so restart it after any token change.

For more on the Superserve side, see the Hermes integration doc.