From ca4ad990b3fa6d4408b84748422207dac221c20f Mon Sep 17 00:00:00 2001 From: Franz Hiltscher Date: Sun, 9 Aug 2026 19:03:48 +0200 Subject: [PATCH 1/2] fix(mcp): pass the retain strategy to the worker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The async retain tool built the strategy into the content dict and then called submit_async_retain without it. That method only writes a strategy into the task payload when it is passed as the keyword argument, so the worker never saw one: apply_strategy() did not run and every strategy override — mission, entity labels, chunk size, free-form setting — fell back to the bank configuration, silently. Pass it the way sync_retain right below already does. The REST endpoint is unaffected; api_retain groups items by strategy and forwards it. --- hindsight-api-slim/hindsight_api/mcp_tools.py | 2 ++ hindsight-api-slim/tests/test_mcp_tools.py | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/hindsight-api-slim/hindsight_api/mcp_tools.py b/hindsight-api-slim/hindsight_api/mcp_tools.py index 24dfc7339a..036cd03609 100644 --- a/hindsight-api-slim/hindsight_api/mcp_tools.py +++ b/hindsight-api-slim/hindsight_api/mcp_tools.py @@ -644,6 +644,7 @@ async def retain( result = await memory.submit_async_retain( bank_id=target_bank, contents=[content_dict], + strategy=content_dict.pop("strategy", None), request_context=request_context, ) return { @@ -698,6 +699,7 @@ async def retain( result = await memory.submit_async_retain( bank_id=target_bank, contents=[content_dict], + strategy=content_dict.pop("strategy", None), request_context=request_context, ) return { diff --git a/hindsight-api-slim/tests/test_mcp_tools.py b/hindsight-api-slim/tests/test_mcp_tools.py index 17aa2bb0fb..351e756a7a 100644 --- a/hindsight-api-slim/tests/test_mcp_tools.py +++ b/hindsight-api-slim/tests/test_mcp_tools.py @@ -1062,6 +1062,19 @@ async def test_retain_with_document_id(self, mock_memory): contents = call_args.kwargs["contents"] assert contents[0]["document_id"] == "doc-1" + async def test_retain_passes_strategy_to_the_worker(self, mock_memory): + """The strategy must travel as the submit argument, not inside the content item. + + ``submit_async_retain`` only puts a strategy into the task payload when it + is passed as the keyword; a strategy left inside the content dict never + reaches the worker, so every strategy override silently falls back to the + bank configuration. + """ + mcp = _make_mcp_server(mock_memory, {"retain"}) + await _tools(mcp)["retain"].fn(content="test", strategy="documents") + call_args = mock_memory.submit_async_retain.call_args + assert call_args.kwargs["strategy"] == "documents" + async def test_retain_without_new_params_backward_compat(self, mock_memory): """Existing behavior preserved when new params not provided.""" mcp = _make_mcp_server(mock_memory, {"retain"}) From 1eb115751bdd6acbbc0354c392f7592adee4e456 Mon Sep 17 00:00:00 2001 From: Franz Hiltscher Date: Wed, 12 Aug 2026 09:19:42 +0200 Subject: [PATCH 2/2] test(mcp): pin the strategy pass-through on both retain registrations --- hindsight-api-slim/tests/test_mcp_tools.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hindsight-api-slim/tests/test_mcp_tools.py b/hindsight-api-slim/tests/test_mcp_tools.py index 351e756a7a..fa9b76d034 100644 --- a/hindsight-api-slim/tests/test_mcp_tools.py +++ b/hindsight-api-slim/tests/test_mcp_tools.py @@ -1070,7 +1070,13 @@ async def test_retain_passes_strategy_to_the_worker(self, mock_memory): reaches the worker, so every strategy override silently falls back to the bank configuration. """ - mcp = _make_mcp_server(mock_memory, {"retain"}) + mcp = _make_mcp_server(mock_memory, {"retain"}, include_bank_id=True) + await _tools(mcp)["retain"].fn(content="test", strategy="documents") + call_args = mock_memory.submit_async_retain.call_args + assert call_args.kwargs["strategy"] == "documents" + + async def test_retain_passes_strategy_single_bank(self, mock_memory): + mcp = _make_mcp_server(mock_memory, {"retain"}, include_bank_id=False) await _tools(mcp)["retain"].fn(content="test", strategy="documents") call_args = mock_memory.submit_async_retain.call_args assert call_args.kwargs["strategy"] == "documents"