diff --git a/packages/openai-sdk-python/src/supermemory_openai/middleware.py b/packages/openai-sdk-python/src/supermemory_openai/middleware.py index db289cc89..4d8762e17 100644 --- a/packages/openai-sdk-python/src/supermemory_openai/middleware.py +++ b/packages/openai-sdk-python/src/supermemory_openai/middleware.py @@ -193,6 +193,9 @@ async def add_system_prompt( }, ) + if not memories: + return messages + if system_prompt_exists: logger.debug("Added memories to existing system prompt") return [ diff --git a/packages/openai-sdk-python/tests/test_middleware.py b/packages/openai-sdk-python/tests/test_middleware.py index b1dd80726..de4004ac4 100644 --- a/packages/openai-sdk-python/tests/test_middleware.py +++ b/packages/openai-sdk-python/tests/test_middleware.py @@ -318,6 +318,65 @@ async def test_existing_system_prompt_enhancement( assert "User prefers Python" in system_message["content"] + @pytest.mark.asyncio + async def test_empty_memories_do_not_modify_messages( + self, mock_async_openai_client, mock_openai_response + ): + """No system prompt should be injected when the memory lookup returns nothing. + + Previously, ``add_system_prompt`` would still modify messages even when + ``memories`` resolved to an empty string: it appended `` \\n `` (whitespace) to + any existing system prompt, or prepended a new ``{"role": "system", "content": ""}`` + message when none existed. Both outcomes pollute the conversation context with + meaningless tokens and can confuse the downstream model. + """ + original_create = AsyncMock(return_value=mock_openai_response) + mock_async_openai_client.chat.completions.create = original_create + + empty_response = { + "profile": {"static": [], "dynamic": []}, + "searchResults": {"results": []}, + } + + with patch.dict(os.environ, {"SUPERMEMORY_API_KEY": "test-key"}): + with patch("supermemory_openai.middleware.supermemory_profile_search") as mock_search: + mock_search.return_value = Mock() + mock_search.return_value.profile = empty_response["profile"] + mock_search.return_value.search_results = empty_response["searchResults"] + + wrapped_client = with_supermemory( + mock_async_openai_client, + OpenAIMiddlewareOptions( + container_tag="user-123", custom_id="test-conv", mode="full" + ), + ) + + # Case 1: no pre-existing system prompt — no system message should be prepended + user_only_messages = [{"role": "user", "content": "Hello"}] + await wrapped_client.chat.completions.create( + model="gpt-4", messages=user_only_messages + ) + sent_messages = original_create.call_args[1]["messages"] + assert sent_messages == user_only_messages, ( + "An empty-memory response must not prepend a blank system message" + ) + + original_create.reset_mock() + + # Case 2: existing system prompt — it must not be modified + with_system = [ + {"role": "system", "content": "You are helpful."}, + {"role": "user", "content": "Hello"}, + ] + await wrapped_client.chat.completions.create( + model="gpt-4", messages=with_system + ) + sent_messages = original_create.call_args[1]["messages"] + assert sent_messages[0]["content"] == "You are helpful.", ( + "An empty-memory response must not append whitespace to the existing system prompt" + ) + + class TestMemoryStorage: """Test memory storage functionality."""