fix(memory): pass per-turn user_id through model tool calls + compat fallback - #45
fix(memory): pass per-turn user_id through model tool calls + compat fallback#45dizhaky wants to merge 1 commit into
Conversation
🔎 Lint report:
|
…fallback Addresses two remaining gaps flagged in Codex reviews on PRs #30 and #33. **P2 — model-facing tool calls used stale init-time user_id** `tool_executor.py` called `handle_tool_call` without `user_id`, so when the model invoked memgw_recall/retain/reflect or mem0_search/profile/conclude in a shared gateway session, both providers fell back to the user_id captured at `initialize()` time (i.e. the first user's id). In shared-thread sessions (`thread_sessions_per_user=False`) this meant one user's tool calls could read or write another user's memory scope. Fix: pass `user_id=agent._user_id` at the `tool_executor` call site (already refreshed per-turn by `gateway/run.py:16368`); thread it through `memory_manager.handle_tool_call` → provider, then use it in both `memgw.handle_tool_call` (via `_user_scope(call_user_id)`) and `mem0.handle_tool_call` (as per-call `read_filters` / `write_filters`). **P2 — external providers without user_id kwarg raised TypeError silently** Old third-party providers that override `sync_turn`/`prefetch`/`queue_prefetch` without the `user_id` keyword arg raised `TypeError`, which was caught by the broad `except Exception` and logged — causing silent sync/prefetch failures. Fix: add a specific `except TypeError` in `memory_manager.sync_all`, `prefetch_all`, and `queue_prefetch_all` that retries the call without the `user_id` kwarg, keeping old plugins functional while new ones get full per-user scoping. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QKeVgEJBrwJQSH2BSXA4oL
c2cb8b2 to
f24945a
Compare
Claude Code automated review — PR #45 (Codex usage-limit bypass)Codex hit its usage cap before reviewing this PR. Running a manual pass to cover the gap. Summary of changes
Detailed findings
Lint / type checkCI passed cleanly — 0 new ruff issues, 0 new VerdictThis is a narrow, targeted fix with a safe compat fallback. All Codex P1 findings from the PR #30–#33 chain are now closed by this PR. No concerns. Approve. Automated review by Claude Code — substituting for Codex (usage limit reached). Generated by Claude Code |
Summary
tool_executor.py,memgw,mem0): Model-invoked memory tools (memgw_recall,mem0_search, etc.) were called withoutuser_id, so in shared-thread gateway sessions the provider used the stale_user_idfrominitialize()(the first user in the session). This could leak one user's memories to another. Fix: passuser_id=agent._user_idat thetool_executordispatch site (already refreshed per-turn sincegateway/run.py:16368) and thread it through tomemgw.handle_tool_callandmem0.handle_tool_call.memory_manager.py): Old third-party providers that overridesync_turn/prefetch/queue_prefetchwithout theuser_idkwarg raisedTypeError, which was swallowed by the broadexcept Exception— silently breaking sync/prefetch. Fix: add an explicitexcept TypeErrorfallback that retries the call withoutuser_id, keeping old plugins functional.Closes remaining Codex P2 findings from PR #30 review and PR #33 review.
Test plan
memgw_recallandmem0_searchuse the current turn'suser_id, not the first user'suser_idkwarg still syncs/prefetches correctly (TypeError fallback)user_idfalls through toself._user_id)🤖 Generated with Claude Code
https://claude.ai/code/session_01QKeVgEJBrwJQSH2BSXA4oL
Generated by Claude Code
Note
Medium Risk
Touches memory isolation in multi-user gateway sessions (security-sensitive); changes are narrow and fall back to prior behavior when
user_idis empty or providers lack the kwarg.Overview
Fixes cross-user memory leakage in shared gateway sessions by passing the current turn’s
agent._user_idintoMemoryManager.handle_tool_callfrom the sequential tool executor, and honoring it in mem0 and memgw tool handlers (recall/search/reflect/retain/conclude) instead of only theinitialize()-time user.Adds
TypeErrorfallbacks inMemoryManagerforprefetch,queue_prefetch, andsync_turn: providers that don’t acceptuser_idare retried without it so older third-party plugins keep working instead of failing silently.Reviewed by Cursor Bugbot for commit c2cb8b248510f3f3cc3b7a41c9e43a73ffe735da. Configure here.