hermes - 💡(How to fix) Fix Gateway: route chat/thread messages to Hermes profiles in a single gateway process

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Allow a single Hermes gateway process to route inbound messages from specific platform conversations or threads directly into a named Hermes profile, giving each routed conversation its own isolated config, model, memory, session store, workspace, and role context — without running multiple gateway processes.

Root Cause

Allow a single Hermes gateway process to route inbound messages from specific platform conversations or threads directly into a named Hermes profile, giving each routed conversation its own isolated config, model, memory, session store, workspace, and role context — without running multiple gateway processes.

Fix Action

Fix / Workaround

When a turn is dispatched under a routed profile, the following should be scoped to that profile:

A clean implementation path is to extend the gateway's inbound dispatch to:

Code Example

gateway:
  profile_routes:
    telegram:
      "-1003961179976":
        "6": career
        "7": finance
        "9": research
        "13": systems
    discord:
      "789012345":
        "111222333": my-discord-agent

# Or flattened — any equivalent is fine:
telegram:
  topic_profiles:
    "-1003961179976:6": career
    "-1003961179976:9": research

---

_HERMES_HOME_OVERRIDE  # ContextVar for per-turn home overrides

---

resolve inbound source
  → lookup profile route
with HermesHomeOverride(profile_home):
      load profile config/env
      build/use session store under profile
      create AIAgent under profile
      run turn
  → deliver via original gateway adapter
RAW_BUFFERClick to expand / collapse

Feature Request

Summary

Allow a single Hermes gateway process to route inbound messages from specific platform conversations or threads directly into a named Hermes profile, giving each routed conversation its own isolated config, model, memory, session store, workspace, and role context — without running multiple gateway processes.

Problem

Hermes profiles are fully isolated homes (profiles/<name>/) each with their own config.yaml, .env, SOUL.md, USER.md, memory files, and session DB. Cron jobs and Kanban workers can already run under a named profile via hermes -p <profile>. However, the live gateway currently executes all turns under one active profile (the gateway process's HERMES_HOME), regardless of which chat or thread the message arrived on.

This means:

  • Every Telegram forum topic, Discord channel, etc. handled by the live gateway shares the same profile's memory, session history, model, workspace, and role context.
  • Topic-specific profiles (e.g. career, systems, research) are only used when a worker or cron job explicitly targets them — not for immediate replies in that topic.
  • The /profile command always reports the gateway process's active profile, not the topic's mapped profile.
  • There is no gateway-level configuration to say "messages in this Telegram thread should be handled by profile X".

Proposed Solution

Add a profile_routes block to the gateway config (and/or platform-specific config) that maps platform conversation + optional thread/topic IDs to a named Hermes profile. The gateway should then execute the turn inside a profile-scoped context for that route, falling back to the default profile for unmatched conversations.

Config shape (illustrative)

gateway:
  profile_routes:
    telegram:
      "-1003961179976":
        "6": career
        "7": finance
        "9": research
        "13": systems
    discord:
      "789012345":
        "111222333": my-discord-agent

# Or flattened — any equivalent is fine:
telegram:
  topic_profiles:
    "-1003961179976:6": career
    "-1003961179976:9": research

Expected behaviour

When a message arrives in a routed conversation:

  1. The gateway resolves the platform + conversation + thread triple.
  2. If a profile route matches, the turn is executed inside a profile-scoped execution context for that profile — loading that profile's config.yaml, .env, model, tools, SOUL.md, USER.md, session store, and workspace/cwd.
  3. Response is delivered back through the original gateway adapter to the originating chat/thread.
  4. Unmatched conversations fall through to the default profile (existing behaviour).
  5. /profile in a routed topic should reflect the routed profile, not the gateway process profile.

What profile routing should control

When a turn is dispatched under a routed profile, the following should be scoped to that profile:

ConcernHow
Config / .envLoad from profiles/<profile>/
Model / providerResolve from profile config
Memory files (MEMORY.md, USER.md)Read/write from profile home
Session store (SQLite)Use profile's session DB
Workspace / cwdUse profile's configured workspace
Role context (SOUL.md)Load from profile home
Tools and tool pathsResolve under profile home
Log filesWrite to profile home

Non-goals / out of scope

  • Running multiple gateway processes with the same bot token — not needed; one process handles this via profile routing.
  • Migrating existing session history — each profile starts fresh unless session store is manually copied.
  • Changes to how ACP/subagent sessions route — those are already profile-aware.

Implementation notes

Hermes already has a useful primitive in hermes_constants.py:

_HERMES_HOME_OVERRIDE  # ContextVar for per-turn home overrides

A clean implementation path is to extend the gateway's inbound dispatch to:

resolve inbound source
  → lookup profile route
  → with HermesHomeOverride(profile_home):
      load profile config/env
      build/use session store under profile
      create AIAgent under profile
      run turn
  → deliver via original gateway adapter

Key risks to verify in implementation:

  • os.environ, os.chdir(), and other process-global state must not leak between concurrent turns in different profiles.
  • Config/model/provider caches must be profile-aware (not cached at module level using the gateway's startup home).
  • Tool subprocess HOME and cwd must be scoped per profile.
  • Profile-scoped background processes must not inherit another profile's environment.
  • Memory, session, and search paths must not be cached globally across profile boundaries.

The ACP adapter already demonstrates per-session isolation for cwd and environment overrides (register_task_env_overrides + per-task_id path resolution in file_tools). That machinery is the reference pattern.

Acceptance criteria

  1. Telegram forum topic A maps to profile career; /profile in that topic reports career.
  2. Topic B maps to profile systems; /profile reports systems.
  3. Each profile writes to its own session DB and memory files.
  4. Each profile uses its configured model and provider.
  5. Concurrent turns in different topics do not leak HERMES_HOME, HOME, env vars, cwd, memory, or model settings.
  6. Cron/job delivery and send_message still deliver back to the originating topic when called from a routed profile context.
  7. Fallback behaviour remains: unmapped topics use the default profile.
  8. The default/main profile remains available for DMs and unmatched topics.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING