Skip to content

🐛 Bugfix: Guard memory_user_config against None in store/search memory tools#3359

Merged
WMC001 merged 3 commits into
developfrom
fix/active_memory_op_blocked_by_mem_share_option
Jul 2, 2026
Merged

🐛 Bugfix: Guard memory_user_config against None in store/search memory tools#3359
WMC001 merged 3 commits into
developfrom
fix/active_memory_op_blocked_by_mem_share_option

Conversation

@JasonW404

@JasonW404 JasonW404 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

This PR addresses multiple memory-related issues discovered during development and testing:

1. NoneType crash in memory tools

StoreMemoryTool and SearchMemoryTool crash with AttributeError: 'NoneType' object has no attribute 'agent_share_option' when memory_user_config is None.

This occurs in two scenarios:

  • Tool validation page (POST /api/tool/validate): _validate_local_tool instantiates StoreMemoryTool via the generic else branch with default memory_user_config=None
  • Actual agent conversations: memory_user_config can be None when metadata is not properly propagated to the tool instance

2. Duplicate tool names at runtime

store_memory and search_memory are system-managed tools that should be auto-injected when memory is enabled. They should not appear in the agent tool selection UI or be manually selectable by users. When present in both DB config and auto-injection, smolagents rejects with "Each tool or managed_agent should have a unique name".

3. Memory switch not persisting

The memory switch toggle in the UI would not persist after being enabled, because duplicate records in memory_user_config_t caused the aggregation logic to overwrite the latest value with stale data.

4. Hidden memory tabs in configuration page

The Tenant Shared and Agent Shared tabs in the memory configuration page were hidden due to a nested array syntax bug in tabItems. Additionally, the Tenant Shared tab should not be visible in speed mode (no tenant concept).

Fix

1. None guard for memory_user_config

Add None checks before accessing memory_user_config attributes in both tools. When config is unavailable, apply a conservative default equivalent to agent_share_option="never" — disabling agent-level memory sharing to protect user privacy.

Files changed:

  • sdk/nexent/core/tools/store_memory_tool.py
  • sdk/nexent/core/tools/search_memory_tool.py

Behavior when memory_user_config is None:

  • store_memory: Only writes to user_agent level (removes agent level)
  • search_memory: Searches ["tenant", "user", "user_agent"] (removes agent level)

2. System-managed tools hidden from UI

store_memory and search_memory are system-managed tools — they should not appear in the agent tool selection UI.

Files changed:

  • backend/consts/tool_labels.py — Added SYSTEM_MANAGED_TOOL_NAMES constant
  • backend/services/tool_configuration_service.py — Filter system-managed tools from list_all_tools response
  • backend/agents/create_agent_info.py — Remove any existing memory tools from DB config before injecting the active memory versions (safety net for legacy data)

Three-layer protection:

  1. UI layer: list_all_tools does not return store_memory/search_memory, preventing users from manually selecting them
  2. Runtime layer: create_agent_info.py removes any DB-configured memory tools before appending the platform-injected versions
  3. Existing data: Even if legacy agent configs contain memory tool instances in DB, they are safely replaced at runtime

3. Memory switch persistence fix

Clean up duplicate records in memory_user_config_t when updating single-type config entries. The _update_single_config function now detects and removes stale duplicates after updating the primary record.

File changed:

  • backend/services/memory_config_service.py

Root cause: Multiple records existed for the same (user_id, config_key) pair with different values. The _aggregate_records function processes records in insertion order, so a stale 'N' record inserted after the latest 'Y' record would overwrite the correct value.

4. Memory configuration page tab fix

Fix nested array syntax bug that hid Tenant Shared and Agent Shared tabs. Conditionally hide Tenant Shared tab in speed mode.

File changed:

  • frontend/app/[locale]/memory/page.tsx

Changes:

  • Fix [...] nested array → proper spread with ...(!isSpeedMode ? [...] : []) for Tenant Shared
  • Fix Agent Shared tab from nested array to proper object in tabItems
  • Speed mode: 4 tabs (Base Settings, Agent Shared, User Personal, User Agent)
  • Non-speed mode: 5 tabs (Base Settings, Tenant Shared, Agent Shared, User Personal, User Agent)

Testing

  • Verified via Playwright: agent successfully calls store_memory(content=...) in an actual conversation without AttributeError
  • Backend logs confirm "Memory stored successfully." with no NoneType errors
  • Memory switch toggle now persists correctly after navigating between pages
  • Agent tool selection UI no longer shows store_memory/search_memory options
  • Agent with legacy store_memory DB config runs without "duplicate name" errors
  • Memory configuration page shows all expected tabs (Tenant Shared hidden in speed mode)
image image image image ![Uploading image.png…]()

@JasonW404 JasonW404 requested review from Dallas98 and WMC001 as code owners July 2, 2026 08:55
Copilot AI review requested due to automatic review settings July 2, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a crash in the SDK’s active memory tools by guarding accesses to memory_user_config when it is None, and defaulting to a privacy-preserving “no agent-level sharing” behavior.

Changes:

  • Add None guards for memory_user_config in StoreMemoryTool to prevent AttributeError and default to removing the "agent" memory level.
  • Add the same None guards in SearchMemoryTool, defaulting to searching without the "agent" memory level.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
sdk/nexent/core/tools/store_memory_tool.py Avoids NoneType crashes by defaulting to no agent-level memory storage when user config is unavailable.
sdk/nexent/core/tools/search_memory_tool.py Avoids NoneType crashes by defaulting to no agent-level memory search when user config is unavailable.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread sdk/nexent/core/tools/store_memory_tool.py Outdated
Comment thread sdk/nexent/core/tools/search_memory_tool.py Outdated
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.22642% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
sdk/nexent/core/tools/search_memory_tool.py 90.47% 0 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@JasonW404 JasonW404 force-pushed the fix/active_memory_op_blocked_by_mem_share_option branch 2 times, most recently from 68a00ab to 90b9661 Compare July 2, 2026 09:17
…y tools

Add None checks before accessing memory_user_config attributes in
StoreMemoryTool and SearchMemoryTool. When config is unavailable,
apply conservative default (agent_share_option='never') to prevent
unintended cross-agent memory sharing.
@JasonW404 JasonW404 force-pushed the fix/active_memory_op_blocked_by_mem_share_option branch from 90b9661 to 06fa9ab Compare July 2, 2026 09:53
JasonW404 added 2 commits July 2, 2026 20:38
- Fix nested array syntax bug that hid Tenant Shared and Agent Shared tabs
- Conditionally hide Tenant Shared tab when isSpeedMode=true (no tenant concept)
- All 5 tabs now properly visible in non-speed mode
- 4 tabs visible in speed mode (Tenant Shared hidden)
…em tool filtering

- test_store_memory_tool: add None config, _run_coroutine tests
- test_search_memory_tool: add None config, _run_coroutine tests
- test_memory_config_service: add duplicate record cleanup tests
- test_tool_configuration_service: add SYSTEM_MANAGED_TOOL_NAMES filter test
@WMC001 WMC001 merged commit 8eae4ed into develop Jul 2, 2026
16 checks passed
@JasonW404 JasonW404 deleted the fix/active_memory_op_blocked_by_mem_share_option branch July 3, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants