Skip to content

Commit 9c5d041

Browse files
committed
Guard tool relevance filters by search mode
1 parent d52fb38 commit 9c5d041

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

agent-memory-client/agent_memory_client/client.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1265,12 +1265,23 @@ async def search_memory_tool(
12651265
"""
12661266
from .filters import Entities, MemoryType, Topics
12671267

1268+
normalized_search_mode = (
1269+
search_mode.value
1270+
if isinstance(search_mode, SearchModeEnum)
1271+
else search_mode
1272+
).lower()
1273+
12681274
# Convert simple parameters to filter objects
12691275
topics_filter = Topics(any=list(topics)) if topics else None
12701276
entities_filter = Entities(any=list(entities)) if entities else None
12711277
memory_type_filter = MemoryType(eq=memory_type) if memory_type else None
12721278
user_id_filter = UserId(eq=user_id) if user_id else None
12731279

1280+
if min_relevance is not None and normalized_search_mode != "semantic":
1281+
raise ValueError(
1282+
"min_relevance is only supported when search_mode='semantic'"
1283+
)
1284+
12741285
# Convert min_relevance to distance_threshold (assuming 0-1 relevance maps to 1-0 distance)
12751286
distance_threshold = (
12761287
(1.0 - min_relevance) if min_relevance is not None else None
@@ -1431,7 +1442,7 @@ async def handle_tool_calls(client, tool_calls):
14311442
"type": "number",
14321443
"minimum": 0.0,
14331444
"maximum": 1.0,
1434-
"description": "Optional minimum relevance score (0.0-1.0, higher = more relevant)",
1445+
"description": "Optional minimum relevance score (0.0-1.0, higher = more relevant). Supported only when `search_mode` is `semantic`.",
14351446
},
14361447
"user_id": {
14371448
"type": "string",

agent-memory-client/tests/test_client.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,21 @@ async def test_search_memory_tool_forwards_hybrid_parameters(
401401
assert kwargs["hybrid_alpha"] == 0.35
402402
assert kwargs["text_scorer"] == "TFIDF"
403403

404+
@pytest.mark.asyncio
405+
async def test_search_memory_tool_rejects_min_relevance_for_keyword_mode(
406+
self, enhanced_test_client
407+
):
408+
"""Test that non-semantic tool searches fail early on min_relevance."""
409+
with pytest.raises(
410+
ValueError,
411+
match="min_relevance is only supported when search_mode='semantic'",
412+
):
413+
await enhanced_test_client.search_memory_tool(
414+
query="alpha beta",
415+
search_mode=SearchModeEnum.KEYWORD,
416+
min_relevance=0.5,
417+
)
418+
404419
def test_memory_search_tool_schema_exposes_search_controls(self):
405420
"""Test that the LLM tool schema advertises keyword/hybrid controls."""
406421
schema = MemoryAPIClient.get_memory_search_tool_schema().to_dict()
@@ -414,6 +429,8 @@ def test_memory_search_tool_schema_exposes_search_controls(self):
414429
assert properties["search_mode"]["default"] == "semantic"
415430
assert properties["hybrid_alpha"]["default"] == 0.7
416431
assert properties["text_scorer"]["default"] == "BM25STD"
432+
assert "search_mode" in properties["min_relevance"]["description"]
433+
assert "semantic" in properties["min_relevance"]["description"]
417434

418435

419436
class TestClientSideValidation:

0 commit comments

Comments
 (0)