From 62f905342c14f76263a7c55e496af45c9a260853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BA=91=E9=BE=99?= <76432572+nankingjing@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:57:34 +0800 Subject: [PATCH] fix(tool_search): remove MAX_RESULTS cap on select: exact-name lookups (#4086) The select: query form lets the model explicitly name the tools it wants to promote. Capping the result at MAX_RESULTS (5) silently drops valid selections when more than 5 deferred tools are requested at once. This removes the [:MAX_RESULTS] slice on the select: branch in DeferredToolCatalog.search() (exact-by-name lookups should return every matched tool) and the redundant re-cap in build_tool_search_tool() (search() already caps non-select query forms internally). Co-authored-by: Claude --- backend/tests/test_deferred_catalog.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/tests/test_deferred_catalog.py b/backend/tests/test_deferred_catalog.py index 131f3f492..b4032c050 100644 --- a/backend/tests/test_deferred_catalog.py +++ b/backend/tests/test_deferred_catalog.py @@ -1,4 +1,5 @@ import pytest +from langchain_core.tools import StructuredTool from langchain_core.tools import tool as as_tool from deerflow.tools.builtins.tool_search import MAX_RESULTS, DeferredToolCatalog @@ -123,3 +124,13 @@ def test_hash_changes_with_membership(): c1 = DeferredToolCatalog((alpha_search, beta_translate)) c2 = DeferredToolCatalog((alpha_search,)) assert c1.hash != c2.hash + + +def test_search_select_not_capped_at_max_results(): + """select: must return ALL requested tools, even when >MAX_RESULTS.""" + tools = tuple(StructuredTool.from_function(func=lambda q="": q, name=f"tool_{i:02d}", description=f"Tool {i}") for i in range(8)) + cat = DeferredToolCatalog(tools) + names_csv = ",".join(f"tool_{i:02d}" for i in range(8)) + got = cat.search(f"select:{names_csv}") + assert len(got) == 8 + assert [t.name for t in got] == [f"tool_{i:02d}" for i in range(8)]