fix: classify OpenRouter 'no endpoints found that support tool use' 404 as model_not_found with fallback - #58451
Closed
webtecnica wants to merge 2 commits into
Closed
Conversation
…llback 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.
webtecnica
force-pushed
the
fix/openrouter-tool-use-404-fallback
branch
from
July 4, 2026 22:33
9f92ab6 to
48590ca
Compare
Contributor
Author
Update: diff limpo + teste de regressãoRebaseei no
Todos os 180 testes do error_classifier passam. 👌 |
habarmc1223-sudo
pushed a commit
to habarmc1223-sudo/hermes-agent-fluxmem
that referenced
this pull request
Jul 8, 2026
- package-lock.json changes in NousResearch#58451 were unrelated peer-flag churn - CANONICAL_PROVIDERS 'poolside' entry from NousResearch#58374 has no ProviderConfig in hermes_cli/auth.py and no setup flow, so the picker entry would be dead; the wire-format coercions stand on their own
santhreal
pushed a commit
to santhreal/hermes-agent
that referenced
this pull request
Jul 13, 2026
- package-lock.json changes in NousResearch#58451 were unrelated peer-flag churn - CANONICAL_PROVIDERS 'poolside' entry from NousResearch#58374 has no ProviderConfig in hermes_cli/auth.py and no setup flow, so the picker entry would be dead; the wire-format coercions stand on their own
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
- package-lock.json changes in NousResearch#58451 were unrelated peer-flag churn - CANONICAL_PROVIDERS 'poolside' entry from NousResearch#58374 has no ProviderConfig in hermes_cli/auth.py and no setup flow, so the picker entry would be dead; the wire-format coercions stand on their own
leewenjie
pushed a commit
to leewenjie/hermes-agent
that referenced
this pull request
Aug 7, 2026
- package-lock.json changes in NousResearch#58451 were unrelated peer-flag churn - CANONICAL_PROVIDERS 'poolside' entry from NousResearch#58374 has no ProviderConfig in hermes_cli/auth.py and no setup flow, so the picker entry would be dead; the wire-format coercions stand on their own
webdevtodayjason
added a commit
to webdevtodayjason/hermes-agent
that referenced
this pull request
Aug 13, 2026
…n error quirks
Adds a plugin seam at the top of agent/error_classifier.classify_api_error()
(step 0, before the built-in pipeline) so model-provider plugins can classify
their provider's error quirks without patching core:
- New "classify_api_error" entry in VALID_HOOKS. Callbacks receive the parsed
error context (provider, model, status_code, error_type, error_code,
error_message, error_body, error, approx_tokens, context_length,
num_messages), self-scope on `provider`, and return None to pass or a dict
{"reason": "<FailoverReason name>", ...optional recovery-hint overrides}.
- get_plugin_error_classification() helper mirrors
get_pre_tool_call_block_message(): first valid result wins, invalid dicts
and unknown reasons are skipped, callback exceptions are isolated — a
broken plugin can never break classification. Zero behavior change when no
plugin claims the error (all 179 existing classifier tests pass untouched).
- Bundled reference plugin `openrouter-tool-use-404` (opt-in, like all
bundled standalone plugins) re-implements PR NousResearch#58451: OpenRouter's
"No endpoints found that support tool use" 404 carries no
_MODEL_NOT_FOUND_PATTERNS signal, so it classifies as unknown/retryable
and the retry loop burns 3-5 attempts on a deterministic rejection.
The plugin classifies it as model_not_found (retryable=False,
should_fallback=True) so the fast-fallback path fires immediately —
demonstrating a waiting core PR converted to a publishable plugin.
Motivation: ~10 open PRs are single-provider error-classification patches
(NousResearch#58451, NousResearch#58355, NousResearch#58502, NousResearch#58474, NousResearch#58366, ...). This hook turns that whole
class of contribution into plugin territory.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWMcB7RPSYUpsXDfBgwjzM
teknium1
pushed a commit
that referenced
this pull request
Aug 13, 2026
…n error quirks
Adds a plugin seam at the top of agent/error_classifier.classify_api_error()
(step 0, before the built-in pipeline) so model-provider plugins can classify
their provider's error quirks without patching core:
- New "classify_api_error" entry in VALID_HOOKS. Callbacks receive the parsed
error context (provider, model, status_code, error_type, error_code,
error_message, error_body, error, approx_tokens, context_length,
num_messages), self-scope on `provider`, and return None to pass or a dict
{"reason": "<FailoverReason name>", ...optional recovery-hint overrides}.
- get_plugin_error_classification() helper mirrors
get_pre_tool_call_block_message(): first valid result wins, invalid dicts
and unknown reasons are skipped, callback exceptions are isolated — a
broken plugin can never break classification. Zero behavior change when no
plugin claims the error (all 179 existing classifier tests pass untouched).
- Bundled reference plugin `openrouter-tool-use-404` (opt-in, like all
bundled standalone plugins) re-implements PR #58451: OpenRouter's
"No endpoints found that support tool use" 404 carries no
_MODEL_NOT_FOUND_PATTERNS signal, so it classifies as unknown/retryable
and the retry loop burns 3-5 attempts on a deterministic rejection.
The plugin classifies it as model_not_found (retryable=False,
should_fallback=True) so the fast-fallback path fires immediately —
demonstrating a waiting core PR converted to a publishable plugin.
Motivation: ~10 open PRs are single-provider error-classification patches
(#58451, #58355, #58502, #58474, #58366, ...). This hook turns that whole
class of contribution into plugin territory.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWMcB7RPSYUpsXDfBgwjzM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When OpenRouter routes to an endpoint that does not support tool/function calling, it returns HTTP 404:
The raw error body does not contain
"model not found"or any other_MODEL_NOT_FOUND_PATTERNSentry, so it falls through toFailoverReason.unknownwithretryable=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.Fix
Added the OpenRouter phrase
"no endpoints found that support tool use"to_MODEL_NOT_FOUND_PATTERNSinagent/error_classifier.py.This classifies the error as
model_not_found(retryable=False,should_fallback=True), which triggers the client-error fast-fallback path inconversation_loop.py: the agent switches to a configured fallback model/provider before the user ever sees the error.What doesn't change
conversation_loop.py(the"support tool use"hint at line ~2967) remains intact — it surfaces only if every fallback exhausts._PROVIDER_POLICY_BLOCKED_PATTERNSare unaffected — those are distinct OpenRouter errors about data/privacy guardrails where fallback would not help.Testing
model_not_found→retryable=False, should_fallback=Trueis_client_error→_try_activate_fallback()in the retry loopconversation_loop.py:2967still fires as a fallback safeguard