Skip to content

Accidental issue — superseded by PR #2292 #2291

Description

@kiwipaulrob

Description

When the Hermes gateway runs multiple concurrent sessions (email threads, cron jobs, subagents) in one process, each session gets its own MemTensorProvider instance. Every MemosBridgeClient() construction closes whatever client holds the per-process (agent, no_viewer, runtime_home) singleton slot in _ACTIVE_CLIENTS — which belongs to a different session's provider.

Root cause

The module-level singleton tracker _ACTIVE_CLIENTS in bridge_client.py was keyed by (agent, no_viewer, runtime_home) — one slot per process. This was correct as a guard against issue #1910 (bridge process leak where one provider kept spawning new bridges per turn), but fatal when N provider instances coexist in one gateway process.

Evidence chain:

  • Gateway process hosts 2+ bridge.mjs --no-viewer children, replacing one every 2-3s (PIDs churn constantly)
  • Dashboard (single session, one provider) has one stable bridge, zero churn
  • The only difference: provider-instance count
  • Daemon (bridge.cjs --daemon, systemd, :18800) stable throughout

Fix

Widen the singleton key to (agent, no_viewer, runtime_home, owner_id) so concurrent provider instances in one process coexist instead of fighting.

Changes:

  • bridge_client.py: key type widened tuple[str, bool, str] -> tuple[str, bool, str, str]; owner_id: str | None parameter added to __init__; _singleton_owner field set from owner_id or f\"anon-{id(self)}\"; key construction in both _register_active and _unregister_active updated
  • init.py: both construction sites (initialize() and _reconnect_bridge()) in both shared-bridge and legacy modes pass owner_id=f\"provider-{id(self)}\"

Expected steady state after fix: daemon + 1 bridge per host process = 3 total; reconnect counts -> ~0.

Alternatives

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • Unit Test — the local test script verifies: distinct provider instances coexist in the tracker, same-owner replacement works, and unregister only removes self
  • Living on production (kiwipaulrob's homelab) since 12 Aug 2026 — zero bridge client is closed storms since deployment (was thousands/day)

Checklist

Metadata

Metadata

Labels

ai:pr-readyAI-created PR is ready for review | AI 生成的 PR 已等待评审area:coreMOS 编排层 / 框架底座 / 跨模块问题status:in-progressSomeone or AI is working on it | 人工或 AI 正在处理types:bugSomething isn't working | 功能异常

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions