From e22cf4b5003e54b20bedbfd4daf34b51233af94a Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Thu, 17 Sep 2026 19:07:22 +0000 Subject: [PATCH] bound search attempts by research depth --- src/clean_agent_preview.py | 19 ++++++++++++++++--- src/turn_contract.py | 7 ++++++- tests/test_clean_agent_preview.py | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/clean_agent_preview.py b/src/clean_agent_preview.py index d9d087145..22a03b3f0 100644 --- a/src/clean_agent_preview.py +++ b/src/clean_agent_preview.py @@ -1934,7 +1934,7 @@ def dependent_write_prerequisite_error(turn_contract, name, successful_required_ return None -def bounded_research_tool_policy(offered, *, searches=0, retrievals=0): +def bounded_research_tool_policy(offered, *, searches=0, retrievals=0, search_limit=2): """Bound research loops after enough discovery evidence has been gathered. Two searches are enough to choose a source in the ordinary research flow. @@ -1943,7 +1943,7 @@ def bounded_research_tool_policy(offered, *, searches=0, retrievals=0): so unrelated calendar, email, document, and media turns are unchanged. """ schemas = list(offered or ()) - if searches < 2: + if searches < max(1, int(search_limit)): return schemas, None, False schemas = [ schema for schema in schemas @@ -3791,6 +3791,7 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac successful_duplicate_counts = {} empty_search_intents = {} successful_search_intents = [] + web_search_attempts = 0 empty_web_search_attempts = 0 successful_web_searches = 0 successful_web_retrievals = 0 @@ -3922,6 +3923,7 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac round_offered, searches=successful_web_searches, retrievals=successful_web_retrievals, + search_limit=(2 if broad_current_web_request(direct_user_text) else 1), ) round_max_tokens = ( min(request_max_tokens, 4096) @@ -4433,6 +4435,16 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac 'page evidence or a different navigation strategy.' ) if tool_type == 'web_search': + web_search_attempts += 1 + if web_search_attempts > 4: + suppressed_tool_until_round['web_search'] = round_limit + 1 + force_no_tools_next_round = True + calls += 1 + raise ValueError( + 'The bounded search-attempt budget is exhausted. Do not search ' + 'again; answer from usable evidence already gathered, or clearly ' + 'report what could not be verified and suggest a concrete next step.' + ) search_intent = normalized_search_intent(args.get('query')) if repeated_search_refinement( args.get('query'), successful_search_intents, @@ -4782,7 +4794,8 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac 'reason': 'web_fetch_boilerplate_fallback', }) if not failed and canonical(actual_tool) == 'web_search': - successful_web_searches += 1 + if result.get('evidence_status') != 'empty': + successful_web_searches += 1 successful_intent = normalized_search_intent(args.get('query')) if successful_intent and result.get('evidence_status') != 'empty': successful_search_intents.append(successful_intent) diff --git a/src/turn_contract.py b/src/turn_contract.py index ef21c2917..9cbc6b367 100644 --- a/src/turn_contract.py +++ b/src/turn_contract.py @@ -3961,6 +3961,8 @@ def broad_web_briefing_request(message: str) -> bool: return True if re.search(r"\b(?:news|headlines?|top\s+stories|news\s+roundup)\b", text, re.I): return True + if re.search(r"\b(?:research|investigate|deep[ -]?dive)\b", text, re.I): + return True if ( re.search(r"\b(?:latest|recent|current|today(?:'s)?|right\s+now)\b", text, re.I) and re.search( @@ -3985,7 +3987,10 @@ def requested_capabilities(message: str, history: Iterable = (), *, active_docum text = lead["request"].strip() history = tuple(history) concrete_urls = re.findall(r"\bhttps?://[^\s<>\"']+", raw_text, re.I) - if broad_web_briefing_request(text): + if ( + broad_web_briefing_request(text) + and not re.search(r"\b(?:research|investigate|deep[ -]?dive)\b", text, re.I) + ): return frozenset({"search_browser"}) if re.search(r"\b(?:web_search|web_fetch)\b", raw_text, re.I): # Explicit native-tool requests are stronger than incidental domain diff --git a/tests/test_clean_agent_preview.py b/tests/test_clean_agent_preview.py index e2c79aef6..8b4bba04b 100644 --- a/tests/test_clean_agent_preview.py +++ b/tests/test_clean_agent_preview.py @@ -1054,6 +1054,22 @@ def test_bounded_research_policy_forces_fetch_after_two_searches(): assert active is True +def test_narrow_lookup_policy_forces_retrieval_after_one_successful_search(): + schemas = [ + {'type': 'function', 'function': {'name': name, 'parameters': {}}} + for name in ('web_search', 'web_fetch', 'private_browser') + ] + offered, choice, active = bounded_research_tool_policy( + schemas, searches=1, retrievals=0, search_limit=1, + ) + + assert [schema['function']['name'] for schema in offered] == [ + 'web_fetch', 'private_browser', + ] + assert choice == {'type': 'function', 'function': {'name': 'web_fetch'}} + assert active is True + + def test_bounded_research_policy_reserves_synthesis_after_retrieval(): schemas = [ {'type': 'function', 'function': {'name': name, 'parameters': {}}}