Skip to content

fix: guard memory provider initialize() against repeated calls (#20939)#20961

Closed
vominh1919 wants to merge 1 commit into
NousResearch:mainfrom
vominh1919:fix/memory-provider-double-init
Closed

fix: guard memory provider initialize() against repeated calls (#20939)#20961
vominh1919 wants to merge 1 commit into
NousResearch:mainfrom
vominh1919:fix/memory-provider-double-init

Conversation

@vominh1919

Copy link
Copy Markdown
Contributor

Problem

Memory providers that spawn resource-heavy processes (e.g. MemOS/memtensor's bridge.cts Node.js pair, ~250MB each) re-initialize on every turn in gateway mode, causing:

  • 60-100 bridge processes per day
  • 15-25GB RAM accumulation
  • Eventually OOM or service degradation

The root cause: MemoryManager.initialize_all() calls each provider's initialize() unconditionally. When the gateway recreates the AIAgent (cache eviction, config change, first message), initialize() runs again, spawning duplicate processes.

Fix

Add an initialization guard to the MemoryProvider base class and MemoryManager.initialize_all():

  1. MemoryProvider.__init__: Track _initialized (bool) and _initialized_session_id (str)
  2. MemoryManager.initialize_all(): Skip providers already initialized for the same session_id; re-initialize when session_id changes (e.g. compression rotation)
  3. Backward compatible: Uses getattr() so subclasses that don't call super().__init__() still work

Changes

File Change
agent/memory_provider.py Add __init__ with _initialized + _initialized_session_id
agent/memory_manager.py Guard in initialize_all() — skip same-session re-init
tests/agent/test_memory_provider.py 2 new tests: same-session skip + backward compat

Tests

78 passed, 6 warnings in 3.37s

New tests:

  • test_initialize_all_skips_same_session — verifies initialize() called once per session, not per turn
  • test_initialize_guard_backward_compat_no_super_init — verifies providers without super().__init__() work via getattr()

Fixes #20939

…esearch#20939)

MemoryManager.initialize_all() now skips providers that are already
initialized for the same session_id.  This prevents resource-heavy
providers (e.g. MemOS/memtensor bridge.cts) from spawning duplicate
processes on every turn when the gateway recreates the AIAgent.

Changes:
- MemoryProvider base class: add _initialized and _initialized_session_id
  tracking attributes (set after successful initialize())
- MemoryManager.initialize_all(): skip providers already initialized for
  the same session_id; re-initialize when session_id changes (e.g.
  compression rotation)
- Uses getattr() for backward compat with subclasses that don't call
  super().__init__()
- 2 new tests: same-session skip + backward compat

Fixes NousResearch#20939
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/memory Memory tool and memory providers P2 Medium — degraded but workaround exists labels May 7, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for identifying the repeated initialization symptom. This is now implemented on main through the gateway cache fix rather than a per-provider flag (automated hermes-sweeper review).

  • d6c53dcdcb49694b382000b53f194b99d97aa72d normalizes the configured model before the post-turn cache-eviction comparison at gateway/run.py:19531, preventing native vendor-prefixed IDs from evicting the cached AIAgent every turn.
  • The same commit removes Discord's volatile triggering message_id from the cached prompt; tests/gateway/test_session.py:238 verifies that prompt construction is stable across message IDs.
  • This shipped in v2026.7.1.
  • The proposed _initialized flag would live only on a provider instance, while agent/agent_init.py:1361-1410 creates a new manager and provider whenever an agent is rebuilt, so it would not address recreation across AIAgent instances.

@teknium1 teknium1 closed this Jul 12, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists sweeper:implemented-on-main Sweeper: behavior already present on current main tool/memory Memory tool and memory providers type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: MemOS memory provider spawns new bridge.cts process on every turn instead of once per session

3 participants