From d77d152a4494f1690e1f9e870f8961e30b841e6b Mon Sep 17 00:00:00 2001 From: webtecnica <75556242+webtecnica@users.noreply.github.com> Date: Sat, 4 Jul 2026 15:51:58 -0300 Subject: [PATCH 1/2] fix: classify OpenRouter 'no tool use' 404 as model_not_found with fallback When OpenRouter routes to an endpoint that does not support tool/function calling, it returns HTTP 404 with the message 'No endpoints found that support tool use. Try disabling "browser_back".' The raw error body does not contain 'model not found' or any other _MODEL_NOT_FOUND_PATTERNS entry, so it falls through to FailoverReason.unknown with retryable=True. The retry loop wastes 3-5 attempts on the same deterministic rejection, then surfaces a confusing generic error instead of automatically failing over to a fallback model or provider. Adding the OpenRouter phrase to _MODEL_NOT_FOUND_PATTERNS classifies it as model_not_found (retryable=False, should_fallback=True), which triggers the client-error fast-fallback path in conversation_loop.py: the agent switches to a configured fallback model/provider before the user sees the error. Existing buffered guidance in conversation_loop.py (the 'support tool use' hint at line ~2967) remains intact and surfaces only if every fallback exhausts. --- agent/error_classifier.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/agent/error_classifier.py b/agent/error_classifier.py index 3489c66c949b1..27311609de669 100644 --- a/agent/error_classifier.py +++ b/agent/error_classifier.py @@ -279,6 +279,15 @@ def is_auth(self) -> bool: "no such model", "unknown model", "unsupported model", + # OpenRouter returns 404 with this message when none of the candidate + # endpoints for the selected model support tool/function calling. + # Classifying this as model_not_found triggers fallback to a different + # model or provider that does support tools. Without this entry the + # pattern falls through to ``unknown`` with ``retryable=True``, the + # retry loop burns all attempts on the same deterministic rejection, + # and the error surfaces as a confusing "model not found" message + # instead of automatically failing over. See PR #58446. + "no endpoints found that support tool use", ] # Request-validation patterns — the request is malformed and will fail From 48590ca396e022b4826c5e34e3c415ee0b1f3c44 Mon Sep 17 00:00:00 2001 From: webtecnica <75556242+webtecnica@users.noreply.github.com> Date: Sat, 4 Jul 2026 19:33:07 -0300 Subject: [PATCH 2/2] test: add regression test for OpenRouter tool-use 404 classification --- tests/agent/test_error_classifier.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/agent/test_error_classifier.py b/tests/agent/test_error_classifier.py index 6c533089986ce..7c266a5ad633a 100644 --- a/tests/agent/test_error_classifier.py +++ b/tests/agent/test_error_classifier.py @@ -516,6 +516,21 @@ def test_404_model_not_found(self): assert result.should_fallback is True assert result.retryable is False + def test_404_openrouter_tool_use_not_supported(self): + # OpenRouter returns 404 with this message when none of the + # candidate endpoints for the selected model support tool/function + # calling. Classify as model_not_found so the agent fast-fallbacks + # to a model/provider that does support tools. + e = MockAPIError( + "No endpoints found that support tool use. " + "Try disabling \"browser_back\".", + status_code=404, + ) + result = classify_api_error(e) + assert result.reason == FailoverReason.model_not_found + assert result.should_fallback is True + assert result.retryable is False + def test_404_generic(self): # Generic 404 with no "model not found" signal — common for local # llama.cpp/Ollama/vLLM endpoints with slightly wrong paths. Treat