hermes - 💡(How to fix) Fix feat(honcho): isolate Honcho session per profile when multiple profiles share one external chat (sessionPeerPrefix + ai_peer for gateway_session_key) [1 pull requests]

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…

When multiple Hermes profiles (sub-agents on the same HERMES_HOME) receive messages from the same external chat (e.g. one Telegram user DMing several profile-specific bots, where each bot is a different Hermes profile but all share one human counterpart), every profile resolves the same gateway_session_key and therefore the same Honcho session — even though they have distinct aiPeer values. Messages from different AI personas end up co-mingled in one session, and Honcho's derived representation gets cross-contaminated.

Reproducible: gateway/session.py:636-640 constructs f"agent:main:{platform}:dm:{dm_chat_id}" — literal "main", no profile/aiPeer/bot identifier. Two containers (or two systemd services) running different profiles for the same Telegram user → identical key → identical Honcho session id.

Root Cause

The behavior matches the other prefix branches already in resolve_session_name for session_title / session_id / per-repo / per-directory, which also use the existing session_peer_prefix knob — except those prefix with peer_name (the human) rather than ai_peer (the profile). Both prefix-fields make sense for different deployments, and we deliberately picked ai_peer for the gateway path because gateway sessions are inherently per-chat (one human), so multi-AI separation needs to come from the AI side, not the human side.

Fix Action

Fix / Workaround

This was confirmed empirically — peers/<X>/sessions/list against the personal workspace showed both the unprefixed (legacy) and a therapy- prefixed session co-existing for periods after the patch was applied, demonstrating both the original bug and the fix in production.

  • PR #10570 (merged) closed #5947 "Bug A: gateway never threads session_title through to honcho." That fix solved per-chat scoping (session_title now flows through to MemoryProvider.initialize()) but did not address per-profile-within-chat scoping.
  • Issue #34480 (open) describes a different but related multi-container symptom (s6-log lock collision).
  • The bigger umbrella RFC #34352 "Multi-Tenant Hermes Problem" and #9514 "Single-Daemon Multi-Agent" point at the proper long-term solution. Our patch is a minimal tactical fix that uses the existing sessionPeerPrefix config knob and the existing ai_peer attribute — no new config, no new schema, no API change.

Tests included in the patch attached below — two cases, prefix off (legacy behavior preserved) and prefix on (new isolation behavior).

Code Example

if gateway_session_key:
    raw_key = gateway_session_key
    if self.session_peer_prefix and self.ai_peer:
        raw_key = f"{self.ai_peer}:{gateway_session_key}"
    sanitized = re.sub(r'[^a-zA-Z0-9_-]+', '-', raw_key).strip('-')
    if sanitized:
        return self._enforce_session_id_limit(sanitized, raw_key)

---

diff --git a/plugins/memory/honcho/client.py b/plugins/memory/honcho/client.py
@@ HonchoClientConfig.resolve_session_name @@
         # for Honcho session ID compatibility. This takes priority over strategy-
         # based resolution because gateway platforms need per-chat isolation that
         # cwd-based strategies cannot provide.
+        #
+        # Multiple Hermes profiles can legitimately talk to the same external
+        # chat (for example default + architect-cme + monitor-cme in one Telegram
+        # DM). Without an opt-in profile prefix, those profiles would all write
+        # into the same Honcho session despite having distinct AI peers. Reuse
+        # the existing sessionPeerPrefix knob for that case, but prefix with the
+        # AI peer (profile identity), not peerName (the human, often shared).
         if gateway_session_key:
-            sanitized = re.sub(r'[^a-zA-Z0-9_-]+', '-', gateway_session_key).strip('-')
+            raw_key = gateway_session_key
+            if self.session_peer_prefix and self.ai_peer:
+                raw_key = f"{self.ai_peer}:{gateway_session_key}"
+            sanitized = re.sub(r'[^a-zA-Z0-9_-]+', '-', raw_key).strip('-')
             if sanitized:
-                return self._enforce_session_id_limit(sanitized, gateway_session_key)
+                return self._enforce_session_id_limit(sanitized, raw_key)

---

class TestHonchoGatewaySessionPrefix:
    """Test profile isolation for gateway-backed Honcho sessions."""

    def test_gateway_session_key_unprefixed_by_default(self):
        cfg = HonchoClientConfig(ai_peer="monitor-cme", session_peer_prefix=False)
        assert (
            cfg.resolve_session_name(gateway_session_key="agent:main:telegram:dm:12345")
            == "agent-main-telegram-dm-12345"
        )

    def test_gateway_session_key_prefixed_with_ai_peer_when_enabled(self):
        cfg = HonchoClientConfig(ai_peer="monitor-cme", session_peer_prefix=True)
        assert (
            cfg.resolve_session_name(gateway_session_key="agent:main:telegram:dm:12345")
            == "monitor-cme-agent-main-telegram-dm-12345"
        )
RAW_BUFFERClick to expand / collapse

Summary

When multiple Hermes profiles (sub-agents on the same HERMES_HOME) receive messages from the same external chat (e.g. one Telegram user DMing several profile-specific bots, where each bot is a different Hermes profile but all share one human counterpart), every profile resolves the same gateway_session_key and therefore the same Honcho session — even though they have distinct aiPeer values. Messages from different AI personas end up co-mingled in one session, and Honcho's derived representation gets cross-contaminated.

Reproducible: gateway/session.py:636-640 constructs f"agent:main:{platform}:dm:{dm_chat_id}" — literal "main", no profile/aiPeer/bot identifier. Two containers (or two systemd services) running different profiles for the same Telegram user → identical key → identical Honcho session id.

Repro on our deployment

_personal HERMES_HOME has 4 profiles. Each has its own Telegram bot token (4 bots). User is the same human (one daughter). Without the fix below, all 4 profiles wrote to one session id agent-main-telegram-dm-6412607285. With the fix and sessionPeerPrefix: true per-profile, each gets therapy-agent-main-telegram-dm-6412607285, school-..., etc.

This was confirmed empirically — peers/<X>/sessions/list against the personal workspace showed both the unprefixed (legacy) and a therapy- prefixed session co-existing for periods after the patch was applied, demonstrating both the original bug and the fix in production.

Related upstream context

  • PR #10570 (merged) closed #5947 "Bug A: gateway never threads session_title through to honcho." That fix solved per-chat scoping (session_title now flows through to MemoryProvider.initialize()) but did not address per-profile-within-chat scoping.
  • Issue #34480 (open) describes a different but related multi-container symptom (s6-log lock collision).
  • The bigger umbrella RFC #34352 "Multi-Tenant Hermes Problem" and #9514 "Single-Daemon Multi-Agent" point at the proper long-term solution. Our patch is a minimal tactical fix that uses the existing sessionPeerPrefix config knob and the existing ai_peer attribute — no new config, no new schema, no API change.

Proposed change

plugins/memory/honcho/client.py, in HonchoClientConfig.resolve_session_name() at the gateway_session_key branch (~lines 711-714 on current main):

if gateway_session_key:
    raw_key = gateway_session_key
    if self.session_peer_prefix and self.ai_peer:
        raw_key = f"{self.ai_peer}:{gateway_session_key}"
    sanitized = re.sub(r'[^a-zA-Z0-9_-]+', '-', raw_key).strip('-')
    if sanitized:
        return self._enforce_session_id_limit(sanitized, raw_key)

That's three changed lines (introducing raw_key) plus a comment block explaining the rationale.

The behavior matches the other prefix branches already in resolve_session_name for session_title / session_id / per-repo / per-directory, which also use the existing session_peer_prefix knob — except those prefix with peer_name (the human) rather than ai_peer (the profile). Both prefix-fields make sense for different deployments, and we deliberately picked ai_peer for the gateway path because gateway sessions are inherently per-chat (one human), so multi-AI separation needs to come from the AI side, not the human side.

Tests included in the patch attached below — two cases, prefix off (legacy behavior preserved) and prefix on (new isolation behavior).

Patch

Attached as honcho_session_peer_prefix.patch (see also link below) — ~3 changed lines of behavior + comment + tests. We've been running this in production across 4 Hermes instances since 2026-05-24 without issue. Re-applied on each instance after the v0.14.0 → v0.15.1 upgrade by simply copying the patched client.py into the container — change is fully forward-compatible with the v0.15.x s6 architecture refactor.

If there's interest, happy to clean this up into a proper PR with whatever code-style touch-ups maintainers want.

diff --git a/plugins/memory/honcho/client.py b/plugins/memory/honcho/client.py
@@ HonchoClientConfig.resolve_session_name @@
         # for Honcho session ID compatibility. This takes priority over strategy-
         # based resolution because gateway platforms need per-chat isolation that
         # cwd-based strategies cannot provide.
+        #
+        # Multiple Hermes profiles can legitimately talk to the same external
+        # chat (for example default + architect-cme + monitor-cme in one Telegram
+        # DM). Without an opt-in profile prefix, those profiles would all write
+        # into the same Honcho session despite having distinct AI peers. Reuse
+        # the existing sessionPeerPrefix knob for that case, but prefix with the
+        # AI peer (profile identity), not peerName (the human, often shared).
         if gateway_session_key:
-            sanitized = re.sub(r'[^a-zA-Z0-9_-]+', '-', gateway_session_key).strip('-')
+            raw_key = gateway_session_key
+            if self.session_peer_prefix and self.ai_peer:
+                raw_key = f"{self.ai_peer}:{gateway_session_key}"
+            sanitized = re.sub(r'[^a-zA-Z0-9_-]+', '-', raw_key).strip('-')
             if sanitized:
-                return self._enforce_session_id_limit(sanitized, gateway_session_key)
+                return self._enforce_session_id_limit(sanitized, raw_key)

Tests in tests/test_honcho_client_config.py:

class TestHonchoGatewaySessionPrefix:
    """Test profile isolation for gateway-backed Honcho sessions."""

    def test_gateway_session_key_unprefixed_by_default(self):
        cfg = HonchoClientConfig(ai_peer="monitor-cme", session_peer_prefix=False)
        assert (
            cfg.resolve_session_name(gateway_session_key="agent:main:telegram:dm:12345")
            == "agent-main-telegram-dm-12345"
        )

    def test_gateway_session_key_prefixed_with_ai_peer_when_enabled(self):
        cfg = HonchoClientConfig(ai_peer="monitor-cme", session_peer_prefix=True)
        assert (
            cfg.resolve_session_name(gateway_session_key="agent:main:telegram:dm:12345")
            == "monitor-cme-agent-main-telegram-dm-12345"
        )

cc maintainers — happy to follow up with a PR if the change shape is acceptable. The same patch can be applied to plugins/memory/honcho/client.py cleanly against current main.

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

hermes - 💡(How to fix) Fix feat(honcho): isolate Honcho session per profile when multiple profiles share one external chat (sessionPeerPrefix + ai_peer for gateway_session_key) [1 pull requests]