diff --git a/plugins/model-providers/custom/__init__.py b/plugins/model-providers/custom/__init__.py index e893be95b279..573057e92c6b 100644 --- a/plugins/model-providers/custom/__init__.py +++ b/plugins/model-providers/custom/__init__.py @@ -30,12 +30,19 @@ def build_api_kwargs_extras( options["num_ctx"] = ollama_num_ctx extra_body["options"] = options - # Disable thinking when reasoning is turned off + # Reasoning / thinking support for custom providers (vLLM, Ollama, etc.) if reasoning_config and isinstance(reasoning_config, dict): _effort = (reasoning_config.get("effort") or "").strip().lower() _enabled = reasoning_config.get("enabled", True) if _effort == "none" or _enabled is False: extra_body["think"] = False + else: + # Pass through thinking enabled — vLLM/Ollama use this to + # enable chain-of-thought reasoning on compatible models. + extra_body["think"] = True + # Pass through effort level if specified + if _effort and _effort not in ("none", ""): + extra_body["reasoning_effort"] = _effort return extra_body, {} diff --git a/run_agent.py b/run_agent.py index bca815da3c69..0a1eaed46d22 100644 --- a/run_agent.py +++ b/run_agent.py @@ -4989,6 +4989,11 @@ def _supports_reasoning_extra_body(self) -> bool: opts = self._lmstudio_reasoning_options_cached() # "off-only" (or absent) means no real reasoning capability. return any(opt and opt != "off" for opt in opts) + # Custom/vLLM/Ollama providers: pass through reasoning if user + # explicitly configured it. The CustomProfile.build_api_kwargs_extras() + # handles the wire format (think=True/False + reasoning_effort). + if (self.provider or "").strip().lower() in ("custom", "ollama", "vllm", "local"): + return True if "openrouter" not in self._base_url_lower: return False if "api.mistral.ai" in self._base_url_lower: