---
name: hermes-messaging-setup
description: "Configure Hermes Agent messaging channels — Telegram, Discord, iMessage (Photon), Slack, WhatsApp, Signal, and 15+ other platforms via the gateway."
version: 1.3.0
author: Hermes Agent
tags: [hermes, gateway, messaging, photon, imessage, telegram, discord, setup]
---

# Hermes Messaging Gateway Setup

Configure any of the 20+ messaging platforms Hermes supports through the gateway.

## Unified Setup Entry Point

```bash
hermes gateway setup        # Interactive wizard — select your platform
```

This discovers all registered platform plugins and walks you through each one's setup (device login, credentials, webhook registration).

## Platform-Specific Commands

Some platforms have dedicated CLI subcommands for setup and troubleshooting:

| Platform | CLI Command | Notes |
|----------|-------------|-------|
| Photon iMessage | `hermes photon setup --phone +1...` | Device-code login, managed iMessage relay |
| Telegram | `hermes gateway setup` → Telegram | Bot token from @BotFather |
| Discord | `hermes gateway setup` → Discord | Bot token from Developer Portal |

## Headless / Remote Server Patterns

Most platforms with OAuth/device-login flows require user interaction. On a headless server:

1. **Use `--no-browser` flags** — prints the login URL instead of trying to open a browser that doesn't exist
2. **Set `PYTHONUNBUFFERED=1`** — CLI output may buffer when captured by a tool; this forces flush so you see device codes and URLs
3. **Open the URL on your phone or local machine** — device-login flows let you approve from any device

Example for Photon on a headless server:
```bash
PYTHONUNBUFFERED=1 hermes photon setup --phone +15551234567 --no-browser
```
→ Prints a URL like `https://app.photon.codes/sign-in/device?user_code=XXXX`
→ Open on phone, enter the code, approve
→ Setup continues automatically through remaining steps

### Agent-Driven Device-Login Setup (Two-Phase Pattern)

When an **AI agent** (not a human at a terminal) is performing the setup, the CLI's blocking device-login poll introduces a problem: the agent cannot hold a foreground process indefinitely while waiting for human approval. Use this two-phase pattern instead:

**Phase 1 — Generate and present the device code (fast, foreground):**
```python
import sys
sys.path.insert(0, '~/.hermes/hermes-agent/src')
sys.path.insert(0, '~/.hermes/hermes-agent')
from plugins.platforms.photon import auth as photon_auth

code = photon_auth.request_device_code()
target = code.verification_uri_complete or code.verification_uri
print(f"URL: {target}")
print(f"CODE: {code.user_code}")
# Save to temp file for phase 2
import json
with open('/tmp/photon_device_code.json', 'w') as f:
    json.dump(vars(code), f)
```

**Phase 2 — Poll for approval + continue setup (background or deferred):**
Launch as a `terminal(background=true, notify_on_complete=true)` process that reads the saved device code file, polls `photon_auth.poll_for_token(code)`, then runs the remaining setup steps (project creation, Spectrum credentials, phone registration, sidecar install).

**Why not use `hermes photon setup` directly?**
- The CLI's output may buffer invisibly when captured by tool infrastructure
- The agent cannot interact with a polling prompt that requires human approval mid-stream
- Splitting the flow lets the agent present the URL/code clearly, then hand off the long poll to a background process

**Fallback when CLI output is invisible:**
Use the Python `photon_auth` module directly — it exports `request_device_code()`, `poll_for_token()`, `login_device_flow()`, `register_user_if_absent()`, `store_project_credentials()`, and all other setup primitives. This bypasses any CLI output-buffering issues entirely.

## Starting the Gateway

```bash
hermes gateway start         # Foreground (for testing)
hermes gateway install       # User service (persistent)
sudo hermes gateway install --system   # System boot service
hermes gateway stop|status   # Control
```

## Removing a Platform

There is no `hermes gateway remove <platform>` command (as of config_version 30). To fully disconnect a platform, remove it from all three locations:

**1. Config — remove platform entry**
```bash
hermes config unset gateway.platforms.<platform>
```
If `hermes config unset` produces `photon: 'null'` (a string literal, not actual removal), clean up the stale key:
```bash
sed -i '/<platform>: .null./d' ~/.hermes/config.yaml
```
Verify the `platforms:` block becomes `platforms: {}` — empty dict is valid YAML; a bare `platforms:` with no children is not.

**2. Env vars — purge platform secrets**
```bash
sed -i '/^<PLATFORM>_/d' ~/.hermes/.env
```
Platform-specific env vars use `<UPPERCASE_PLATFORM>_` prefix (e.g. `PHOTON_PROJECT_ID`, `PHOTON_PROJECT_SECRET`).

**3. Plugin directory — remove adapter code**
```bash
rm -rf ~/.hermes/hermes-agent/plugins/platforms/<platform>/
```

**4. Restart the gateway** from a **separate shell** (doing it inside the gateway session kills the conversation):
```bash
hermes gateway restart
```

## Post-Setup Verification

```bash
hermes photon status         # Photon-specific: shows token, project, sidecar state
grep -i photon ~/.hermes/.env   # Verify runtime secrets were written
cat ~/.hermes/config.yaml | grep -A3 'gateway:'   # Check gateway config
```

## Common Pitfalls

- **CLI appears to hang with no output** — likely waiting for user input (device code, browser approval) with buffered output. Add `PYTHONUNBUFFERED=1` or use a PTY. For in-session operations, prefer calling the platform's Python auth module directly with explicit `flush=True` on all print() calls.
- **"Unauthorized user" on your own messages** — the setup should auto-allowlist your number/user ID. Verify with `hermes pairing list` or check `<PLATFORM>_ALLOWED_USERS` in `~/.hermes/.env`.
- **Sidecar dependencies fail** — Node.js 18.17+ required. Run `hermes <platform> install-sidecar` to retry npm install.
- **No iMessage line assigned** — re-run setup or check the platform's dashboard (e.g. app.photon.codes).
- **Phone number redacted by platform** — Telegram and other messaging platforms replace middle digits with `****`. This breaks E.164 validation (`^\+[1-9]\d{6,14}$`). **Ask the user for the raw digits** and construct the E.164 string yourself — never pass a redacted number to platform APIs.
- **Cannot restart gateway from inside the gateway** — `systemctl --user restart hermes-gateway` (or `hermes gateway restart`) kills the gateway process, which also kills the current agent conversation (SIGTERM propagates to child processes). Tell the user to run the restart from a separate SSH/terminal shell.
- **`hermes config set` for platform enable** — The `config.yaml` file is soft-guarded against direct editing by the agent. To enable a platform in the gateway config, use: `hermes config set gateway.platforms.<platform>.enabled true`

## References

- `references/photon-imessage.md` — detailed Photon iMessage setup walkthrough

## Related Skills

- `hermes-agent` — general Hermes CLI and config reference
- `hermes-remote-desktop` — deploy Hermes Desktop to remote machines
