Skip to content

fix: foreground turn.start RPC starved by background pipeline (embedding + LLM resource contention) #2186

Description

@pittosporum-seu

Pre-submission checklist

  • I have searched existing issues and this hasn't been mentioned before
  • I have read the project documentation and confirmed this issue doesn't already exist
  • This issue is specific to MemOS and not a general software issue

Bug Description

When the memos-local-plugin bridge is used as a memory provider for hermes-agent (via stdin/stdout JSON-RPC), the foreground turn.start RPC call frequently times out (8s) because it competes with background pipeline tasks (reflection scoring, reward backprop, skill crystallization) for two shared resources:

  1. Local ONNX embedding model (single-threaded CPU inference) — background captureRunner.runLite() embeds trace rows while the foreground retrieveTurnStart() needs to embed the query for vector search. These serialize on the ONNX runtime.

  2. Remote LLM API (mimo-v2.5 via openai_compatible) — background skill verification / reward scoring makes LLM calls that share the same API quota/concurrency as the foreground openEpisodeIfNeeded() topic classification.

Observed timing from bridge logs:

  • capture.reflect.scoring.startcapture.reflect.done: 1501ms
  • reward.done: 2564ms
  • skill.verify.fail (resonance-low): 12 seconds (LLM call)

During this 12-second skill verification window, any incoming turn.start RPC that needs embedding or LLM classification will exceed the host's 8-second prefetch timeout, causing the memory injection to be silently skipped.

Expected behavior: Foreground retrieval (turn.start) should not be starved by background pipeline work. The bridge should either:

  • Prioritize foreground RPC over background tasks (e.g., yield/pause background LLM/embedding calls when a foreground request arrives)
  • Run background pipeline on a separate worker/thread with its own embedding queue
  • Expose a concurrency semaphore so embedding inference is fair-queued

How to Reproduce

  1. Configure hermes-agent with memory.provider: memtensor and memos-plugin/config.yaml using local embedding (Xenova/all-MiniLM-L6-v2) + remote LLM (mimo-v2.5)
  2. Have an active conversation with multiple turns (so episodes accumulate)
  3. Trigger an episode boundary (topic change or session end) — this fires the full reflect → reward → skill pipeline
  4. Immediately send a new message (within the ~12s skill verification window)
  5. Observe: WARNING agent.memory_manager: Memory provider 'memtensor' prefetch timed out after 8.0s

Environment

  • Node.js: v20.x (bridge runtime)
  • Python: 3.12.3 (hermes-agent host)
  • Operating System: Ubuntu 24.04 (WSL2)
  • MemOS version: memos-local-plugin 2.0.7 (bridge.cjs)
  • Embedding: local Xenova/all-MiniLM-L6-v2 (ONNX, 384-dim)
  • LLM: mimo-v2.5 via openai_compatible endpoint

Additional Context

Relevant source locations (compiled dist):

  • dist/core/pipeline/orchestrator.js L976: onTurnStart — foreground retrieval path
  • dist/core/pipeline/orchestrator.js L1216: captureRunner.runLite() — background capture in onTurnEnd
  • dist/core/embedding/embedder.js L69: embedMany() — shared embedding facade (no priority queue)
  • dist/bridge/stdio.js: JSON-RPC dispatch (concurrent, but downstream resources are serialized)

The stdio transport itself handles requests concurrently (no serialization at the RPC layer). The bottleneck is purely in the shared embedding/LLM resource layer below.

Willingness to Implement

  • I'm willing to implement this myself
  • I would like someone else to implement this

Metadata

Metadata

Labels

area:pluginOpenClaw & Hermesstatus:needs-triageNeeds initial triage | 需要初步判断 & 问题复现

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions