Skip to content

Python: fix(mem0): do not forward unset user_id/agent_id as None to OSS client - #9911

Open
lisry-1 wants to merge 2 commits into
microsoft:mainfrom
lisry-1:fix/mem0-oss-omit-unset-identity-v2
Open

lisry-1 wants to merge 2 commits into
microsoft:mainfrom
lisry-1:fix/mem0-oss-omit-unset-identity-v2

Conversation

@lisry-1

@lisry-1 lisry-1 commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Mem0ContextProvider.after_run forwards user_id and agent_id to the OSS AsyncMemory client as unconditional direct kwargs, even though _validate_filters permits configuring only one of them. When a user configures only user_id (so agent_id is None), add() receives agent_id=None and the run crashes after the model has already produced a reply.

Problem

The two client paths are asymmetric for the same identity configuration:

  • Platform path (_build_filters) only includes non-empty fields:

    if self.user_id:   filters["user_id"] = self.user_id
    
    if self.agent_id:  filters["agent_id"] = self.agent_id
    
    if self.application_id: filters["app_id"] = self.application_id
  • OSS path writes both unconditionally:

    add_kwargs["user_id"] = self.user_id      # may be None
    
    add_kwargs["agent_id"] = self.agent_id    # may be None

_validate_filters explicitly allows a single identity field ("At least one of the filters: agent_id, user_id, or application_id"), so a user_id-only configuration is valid — yet it passes agent_id=None to the OSS SDK's required str parameter and fails after the reply was generated (after_run is awaited with no try/except upstream).

Changes

Make the OSS branch conditional, matching _build_filters: only include user_id / agent_id when non-empty.

Tests

Added test_oss_storage_omits_unset_identity_fields: with only user_id="u1" configured, add() receives user_id but no agent_id key and no filters dict.

…SS client

after_run unconditionally passed both user_id and agent_id as direct
kwargs to the OSS AsyncMemory client, even though _validate_filters
permits configuring only one of them. When a user configured only
user_id (agent_id=None), add() received agent_id=None and crashed the
run after the model had already produced a reply.

Match the Platform path (_build_filters), which only includes non-empty
identity fields.

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.

🟡 Changes recommended

The regression tests lack coverage for valid agent-only configurations, so restoring an unconditional user_id assignment could go undetected.

1 open issue
What changed in this PR

This PR updates the Python Mem0 integration to omit unset identity fields when storing memories through the OSS client, matching the Platform path’s filtering behavior.

Changes:

  • Forward user_id and agent_id only when non-empty.
  • Add a user-only regression test verifying that agent_id and filters are absent from OSS storage arguments.
File Description
python/​packages/​mem0/​tests/​test_mem0_context_provider.py Adds regression coverage for user-only OSS storage.
python/​packages/​mem0/​agent_framework_mem0/​_context_provider.py Conditionally forwards identity fields to the OSS client.

Review effort: Balanced

Comment on lines +692 to +714
async def test_oss_storage_omits_unset_identity_fields(self, mock_oss_mem0_client: AsyncMock) -> None:
"""OSS add must not forward unset identity fields as None kwargs.

_validate_filters permits configuring only one of user_id/agent_id, but
the OSS branch previously forwarded both unconditionally, passing
``agent_id=None`` (or ``user_id=None``) to AsyncMemory.add and crashing
the run after the model had already produced a reply.
"""
provider = Mem0ContextProvider(source_id="mem0", mem0_client=mock_oss_mem0_client, user_id="u1")
session = AgentSession(session_id="test-session")
ctx = SessionContext(input_messages=[Message(role="user", contents=["hi"])], session_id="s1")
ctx._response = AgentResponse(messages=[])

await provider.after_run(
agent=cast(Any, None),
session=session,
context=ctx,
state=session.state.setdefault(provider.source_id, {}),
) # type: ignore[arg-type]

call_kwargs = mock_oss_mem0_client.add.call_args.kwargs
assert call_kwargs["user_id"] == "u1"
assert "agent_id" not in call_kwargs
Parameterize the omit-unset-identity test to exercise both user-only and
agent-only configurations, asserting the configured identity is forwarded
and the other key is absent.
@lisry-1
lisry-1 temporarily deployed to github-app-auth November 1, 2026 12:30 — with GitHub Actions Inactive
@eavanvalkenburg

Copy link
Copy Markdown
Member

Thanks for the contribution, lisry-1. The code review is clean, but the PR body still needs the required Related Issue answer before approval. Please link an agreed issue with a closing keyword, or document why this is an undisputed trivial change or repository automation. Missing AI Assistance alone is not a blocker.

@lisry-1

lisry-1 commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks Eduard van Valkenburg (@eavanvalkenburg). I've opened #9976 to track this bug and linked it in the PR's Related Issue section (Fixes #9976). This makes the OSS path consistent with _build_filters by omitting unset identity fields. Please let me know if the issue needs a ready-for-implementation label or any further confirmation before you can approve. Happy to adjust.

This branch was previously deployed

1 inactive deployment
github-app-auth — 2a211ea7 Deployed Nov 2, 2026 by lisry-1 via add_label #26842
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants