Skip to main content

Running OpenClaw + Hermes in parallel

The problem

You have OpenClaw and Hermes Agent installed. Both can connect to the same messengers – and if you're not careful, they share the same Telegram bot, respond in an uncoordinated fashion, or compete for ports, workspaces and long-polling slots. This guide shows you how to run both agents in a clearly separated way, so you always know which one you're chatting with.

1. Why it collides​

Telegram – only one long-poller per bot​

Telegram's Bot API allows only one active getUpdates consumer per bot token. As soon as OpenClaw and Hermes use the same token, one of two things happens:

  • HTTP 409 Conflict – one of them stops receiving updates entirely
  • Race condition – updates get "snatched" alternately, replies come randomly from one or the other

Even if you've created two different bots, you'll quickly get confused in a group containing both, because they have similar response styles.

Gateway ports​

  • OpenClaw gateway: defaults to 127.0.0.1:18789
  • Hermes gateway: its own process (gateway.pid in ~/.hermes/)

Both can run in parallel – but if you also configure Hermes on 18789, it will collide.

Daemons​

On Linux, both tools install systemd units. An unintended restart can affect the other service if toolsets/skills operate on the same workspace.


2. Target state – the golden rules​

RuleOpenClawHermes
Dedicated Telegram bot@JayDee_Claw_bot@JayDee_Hermes_bot
Unique bot name in Telegram"Claw – Coding""Hermes – Personal"
Unique identity emoji🦞πŸͺ½
Reply prefix🦞 Claw:πŸͺ½ Hermes:
Gateway port1878918790 (pick freely)
Workspace~/.openclaw/workspace~/.hermes/
Domain of workCoding, repo operationsPersonal, memory, voice
Why separate by domain?

If both do "everything", both will learn from contradictory skills/memory snippets. A clear domain split makes Hermes's learning more valuable and reduces OpenClaw's tool surface (less prompt-injection risk).


3. Step by step – clean setup​

Step 1 – Back up your current configurations​

cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.before-split
cp ~/.hermes/config.yaml ~/.hermes/config.yaml.before-split
cp ~/.hermes/.env ~/.hermes/.env.before-split

Step 2 – Stop both gateways​

openclaw gateway stop
# Hermes:
hermes gateway stop || pkill -F ~/.hermes/gateway.pid

Step 3 – Create two separate Telegram bots​

In Telegram, go to @BotFather:

/newbot
β†’ Name: JayDee Claw (Coding)
β†’ Username: JayDee_Claw_bot
β†’ Token kopieren β†’ TOKEN_CLAW

/newbot
β†’ Name: JayDee Hermes (Personal)
β†’ Username: JayDee_Hermes_bot
β†’ Token kopieren β†’ TOKEN_HERMES

Then, for each bot in BotFather:

/setdescription   β†’ kurz beschreiben (β€žCoding-Agent" / β€žPersonal-Agent")
/setuserpic β†’ unterschiedliche Avatare!
/setcommands β†’ unterschiedliche Slash-Commands
Never recycle a token

If you've been using the same token for both up to now, revoke it now in BotFather (/revoke) and reassign it to only one agent. The other gets a fresh token.

Step 4 – Configure OpenClaw​

openclaw config edit
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "<TOKEN_CLAW>",
"dmPolicy": "pairing",
"groupPolicy": "allowlist",
"groups": { "*": { "requireMention": true } }
}
},
"gateway": {
"port": 18789,
"bind": "loopback"
}
}

Set the identity (included with every reply):

$EDITOR ~/.openclaw/identity/IDENTITY.md
# Identity
- Name: Claw
- Emoji: 🦞
- DomΓ€ne: Coding, Repo-Operationen, Shell, Browser-Automation
- Antwort-Stil: prÀzise, knapp, immer mit PrÀfix `🦞 Claw:` beginnen.
- Wenn nach β€žbist du Hermes?" gefragt: klarstellen, dass du Claw (OpenClaw) bist.

Step 5 – Configure Hermes​

~/.hermes/.env:

TELEGRAM_BOT_TOKEN=<TOKEN_HERMES>
ANTHROPIC_API_KEY=<dein-key>
HERMES_GATEWAY_TOKEN=<eigener-token>

~/.hermes/config.yaml – Telegram-specific channel prompt:

telegram:
channel_prompts:
default: |
Du bist Hermes (πŸͺ½). Beginne JEDE Antwort mit `πŸͺ½ Hermes:`.
DomΓ€ne: persΓΆnliche Assistenz, Memory, Voice, Skills, Cron.
Wenn nach β€žbist du Claw/OpenClaw?" gefragt: klarstellen, dass du Hermes bist.

Extend ~/.hermes/SOUL.md:

Du bist **Hermes**, der persΓΆnliche Agent von JayDee.
- Emoji: πŸͺ½
- Klare Trennung von Claw (🦞 OpenClaw): Claw macht Coding, du machst Personal.
- Beginne jede externe Antwort mit `πŸͺ½ Hermes:` – auch in Voice-Transkripten.

If you want the Hermes gateway on a different port (to avoid port collisions):

# ~/.hermes/config.yaml
gateway:
port: 18790

Step 6 – Restart both gateways​

openclaw gateway start
hermes gateway start

Check the status:

openclaw gateway status
hermes gateway status

Step 7 – Verification​

In Telegram:

  1. Message @JayDee_Claw_bot: "Who are you?" β†’ reply starts with 🦞 Claw:
  2. Message @JayDee_Hermes_bot: "Who are you?" β†’ reply starts with πŸͺ½ Hermes:
  3. Add both bots to one test group β†’ mention each one explicitly with @… and verify that only the mentioned one responds.

4. Reinforce the visual separation​

MeasureEffect
Different bot avatars in BotFatherinstant recognition in the chat header
Emoji prefix in every reply (🦞/πŸͺ½)recognisable in notifications
Pinned message per bot with domain descriptiononboarding for yourself
Telegram folders – Claw and Hermes in their own foldersseparation inside the Telegram app
Different slash command sets (/setcommands)autocomplete makes it clear who can do what

Example /setcommands for Claw:

build - Repo bauen
test - Tests ausfΓΌhren
deploy - Deployment auslΓΆsen

For Hermes:

remind - Erinnerung anlegen
note - Notiz speichern
voice - Voice-Mode aktivieren

5. Domain separation via tools/toolsets​

OpenClaw: coding profile, restrictive for Telegram​

{
"tools": { "profile": "coding" },
"agents": {
"telegram-default": {
"tools": {
"deny": ["camera.snap", "screen.record", "sms.send", "calendar.add"]
}
}
}
}

You're already using tools.profile: coding – fitting for Claw.

Hermes: personal toolsets only on Telegram​

# ~/.hermes/config.yaml
platform_toolsets:
cli: [hermes-cli, skills, code_execution]
telegram: [hermes-telegram, memory, session_search, cronjob, tts]

That way, on Telegram, Hermes has no repo/code-execution tools – Claw's domain won't be inadvertently taken over.


6. Cleanly separating memory & skills​

PathBelongs toContents
~/.openclaw/workspace/ClawAGENTS.md, SOUL.md, IDENTITY.md, coding notes
~/.openclaw/workspace/skills/Clawcoding skills only
~/.hermes/memories/MEMORY.mdHermespersonal facts
~/.hermes/memories/USER.mdHermesyour profile
~/.hermes/skills/Hermespersonal skills
No cross-symlinks

Don't be tempted to symlink skills/ between the two – the formats are similar but not identical (Hermes uses progressive disclosure with reference files, OpenClaw doesn't). On conflict, copy a skill and adapt it manually.


7. Conflict avoidance – checklist​

[ ] Zwei separate Telegram-Bots mit eindeutigen Usernames
[ ] Avatare und Beschreibungen unterschiedlich
[ ] OpenClaw-Gateway-Port β‰  Hermes-Gateway-Port
[ ] IDENTITY.md (Claw) und SOUL.md (Hermes) gesetzt
[ ] Antwort-PrΓ€fix mit Emoji konfiguriert
[ ] platform_toolsets in Hermes setzt Telegram-Werkzeuge ein
[ ] tools.profile / tools.deny in OpenClaw begrenzt Channel-Rechte
[ ] Pairing-/Allowlist auf beiden Seiten aktiv (kein Wildcard)
[ ] Beide Bots in Test-Gruppe verifiziert (mention-only)
[ ] Secrets rotiert, falls je geteilt

8. Diagnostics when something does collide​

"Telegram isn't responding / 409 Conflict"​

Most likely both are still using the same token, or an old process is stuck:

# alle laufenden Polling-Prozesse finden
ps -ef | grep -E "openclaw|hermes" | grep -v grep

# zombie-Polling killen
pkill -F ~/.openclaw/gateway.pid 2>/dev/null
pkill -F ~/.hermes/gateway.pid 2>/dev/null

# sauberer Neustart
openclaw gateway start
hermes gateway start

"The reply comes from the wrong agent"​

  • Open BotFather to check which username owns the token: /mybots β†’ show token
  • Cross-check with the correct tool (grep botToken ~/.openclaw/openclaw.json, grep TELEGRAM_BOT_TOKEN ~/.hermes/.env)

"Both bots reply in a group at the same time"​

  • requireMention: true (OpenClaw) is set – βœ…
  • Hermes counterpart: discord.require_mention: true exists; for Telegram there's analogous behaviour via channel prompts and pairing. Set this explicitly in the Hermes config:
telegram:
channel_prompts:
"*": |
Antworte in Gruppen NUR, wenn du explizit per @-Mention adressiert wurdest.

"Which daemon is currently running?"​

systemctl --user status openclaw-gateway 2>/dev/null
systemctl --user status hermes-gateway 2>/dev/null
ss -ltnp | grep -E "1878[0-9]" # Ports

9. Operations – daily hygiene​

  • View logs together:
    tail -F ~/.openclaw/logs/*.log ~/.hermes/logs/*.log
  • Keep backups separate – two private repos: openclaw-workspace and hermes-workspace. Don't mix them.
  • Run updates separately:
    npm i -g openclaw@latest
    curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
  • Secret hygiene: never share the Telegram token in Slack/issues/pastebins. If in doubt: @BotFather β†’ /revoke.

10. Advanced strategies​

Variant A – Deliberate division of duties​

ChannelResponsible
Telegram DM with the Claw botCoding, repo, deployments
Telegram DM with the Hermes botReminders, cron, memory, voice
Discord serverHermes only (hobby/personal)
iMessage/SignalHermes only (private)
Slack (work)Claw only (repo bots, CI)

Variant B – Router bot in front​

If you really want one Telegram bot:

  1. Create a third bot (@JayDee_Router_bot)
  2. Build a small piece of webhook logic (e.g. a Cloudflare Worker) that routes messages based on a prefix (/c … β†’ Claw, /h … β†’ Hermes) to the corresponding internal bot
  3. Claw and Hermes use their own bots, reachable only internally

More effort, but one point of contact in Telegram.

Variant C – Only one active, depending on context​

# Morgens / Coding-Tag
hermes gateway stop && openclaw gateway start

# Abends / Personal
openclaw gateway stop && hermes gateway start

A simple ~/bin/agent-mode coding|personal script flips between them. Saves RAM, structurally eliminates the conflict.


11. Further reading​

Quote

Two agents on one machine isn't a problem – two agents on one bot is. Separate the channel, not just the config.