diff --git a/agent/image_routing.py b/agent/image_routing.py index c8b3f6640c6d..0ee25002e6cf 100644 --- a/agent/image_routing.py +++ b/agent/image_routing.py @@ -337,12 +337,17 @@ def decide_image_input_mode( return "text" # auto - if _explicit_aux_vision_override(cfg): - return "text" - + # Check if the main model supports vision first — if it does, use native + # mode even if auxiliary.vision is configured. The user's explicit + # auxiliary.vision config is only used as a fallback when the main model + # lacks vision support (#44299). supports = _lookup_supports_vision(provider, model, cfg) if supports is True: return "native" + + if _explicit_aux_vision_override(cfg): + return "text" + return "text" diff --git a/tests/agent/test_image_routing.py b/tests/agent/test_image_routing.py index b5a43f1ff0e3..40fdc457fde9 100644 --- a/tests/agent/test_image_routing.py +++ b/tests/agent/test_image_routing.py @@ -98,10 +98,10 @@ def test_auto_with_unknown_model(self): assert decide_image_input_mode("openrouter", "brand-new-slug", {}) == "text" def test_auto_respects_aux_vision_override_even_for_vision_model(self): - """If the user configured a dedicated vision backend, don't bypass it.""" + """If the main model supports vision, use native even with aux vision config (#44299).""" cfg = {"auxiliary": {"vision": {"provider": "openrouter", "model": "google/gemini-2.5-flash"}}} with patch("agent.image_routing._lookup_supports_vision", return_value=True): - assert decide_image_input_mode("anthropic", "claude-sonnet-4", cfg) == "text" + assert decide_image_input_mode("anthropic", "claude-sonnet-4", cfg) == "native" def test_none_config_is_auto(self): with patch("agent.image_routing._lookup_supports_vision", return_value=True): @@ -280,14 +280,13 @@ def test_auto_text_for_custom_with_no_override(self): assert decide_image_input_mode("custom", "unknown", {}) == "text" def test_explicit_aux_vision_override_still_wins(self): - # If the user has configured a dedicated vision aux backend, respect - # it even when supports_vision: true is also set. + # If the main model supports vision, use native even with aux vision config (#44299). cfg = { "model": {"supports_vision": True}, "auxiliary": {"vision": {"provider": "openrouter", "model": "gemini-2.5-pro"}}, } with patch("agent.models_dev.get_model_capabilities", return_value=None): - assert decide_image_input_mode("custom", "qwen3.6-35b", cfg) == "text" + assert decide_image_input_mode("custom", "qwen3.6-35b", cfg) == "native" # ─── build_native_content_parts ──────────────────────────────────────────────