Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions run_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7134,17 +7134,22 @@ def _build_api_kwargs(self, api_messages: list) -> dict:
options["num_ctx"] = self._ollama_num_ctx
extra_body["options"] = options

# Ollama / custom provider: pass think=false when reasoning is disabled.
# Ollama does not recognise the OpenRouter-style `reasoning` extra_body
# field, so we use its native `think` parameter instead.
# This prevents thinking-capable models (Qwen3, etc.) from generating
# <think> blocks and producing empty-response errors when the user has
# set reasoning_effort: none.
# Custom provider: opt out of thinking when reasoning is disabled.
# Different OpenAI-compat backends use different field names and
# ignore unknown fields, so send all the common ones:
# * Ollama: think: false
# * llama.cpp / vLLM (Qwen): chat_template_kwargs.enable_thinking: false
# Without this, thinking-capable models (Qwen3, etc.) emit <think>
# blocks and trigger llama.cpp's prefill-incompatibility 400 on the
# next turn (see llama.cpp tools/server/server-common.cpp).
if self.provider == "custom" and self.reasoning_config and isinstance(self.reasoning_config, dict):
_effort = (self.reasoning_config.get("effort") or "").strip().lower()
_enabled = self.reasoning_config.get("enabled", True)
if _effort == "none" or _enabled is False:
extra_body["think"] = False
_ctk = extra_body.setdefault("chat_template_kwargs", {})
if isinstance(_ctk, dict):
_ctk["enable_thinking"] = False

if self._is_qwen_portal():
extra_body["vl_high_resolution_images"] = True
Expand Down
38 changes: 38 additions & 0 deletions tests/run_agent/test_run_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,44 @@ def test_non_custom_provider_unaffected(self, agent):
kwargs = agent._build_api_kwargs(messages)
assert kwargs.get("extra_body", {}).get("think") is None

def test_custom_chat_template_kwargs_on_effort_none(self, agent):
"""Custom provider with effort=none should also inject
chat_template_kwargs.enable_thinking=false (llama.cpp / vLLM)."""
agent.provider = "custom"
agent.base_url = "http://localhost:11434/v1"
agent._base_url_lower = agent.base_url.lower()
agent.reasoning_config = {"effort": "none"}
messages = [{"role": "user", "content": "hi"}]
kwargs = agent._build_api_kwargs(messages)
extra = kwargs.get("extra_body", {})
assert extra.get("think") is False
assert extra.get("chat_template_kwargs", {}).get("enable_thinking") is False

def test_custom_chat_template_kwargs_on_enabled_false(self, agent):
"""Custom provider with enabled=false should also inject
chat_template_kwargs.enable_thinking=false."""
agent.provider = "custom"
agent.base_url = "http://localhost:11434/v1"
agent._base_url_lower = agent.base_url.lower()
agent.reasoning_config = {"enabled": False}
messages = [{"role": "user", "content": "hi"}]
kwargs = agent._build_api_kwargs(messages)
extra = kwargs.get("extra_body", {})
assert extra.get("think") is False
assert extra.get("chat_template_kwargs", {}).get("enable_thinking") is False

def test_custom_no_chat_template_kwargs_when_reasoning_enabled(self, agent):
"""Custom provider with reasoning enabled should NOT inject
chat_template_kwargs.enable_thinking=false."""
agent.provider = "custom"
agent.base_url = "http://localhost:11434/v1"
agent._base_url_lower = agent.base_url.lower()
agent.reasoning_config = {"enabled": True, "effort": "medium"}
messages = [{"role": "user", "content": "hi"}]
kwargs = agent._build_api_kwargs(messages)
extra = kwargs.get("extra_body", {})
assert extra.get("chat_template_kwargs") is None



class TestBuildAssistantMessage:
Expand Down