From 34a1eaf9eaa67478bb36b80125d861887d79094d Mon Sep 17 00:00:00 2001 From: suhasagg Date: Mon, 5 Oct 2026 13:38:52 +0530 Subject: [PATCH 1/3] fix(ollama): honor tool_choice="none" --- .../agent_framework_ollama/_chat_client.py | 5 +- .../ollama/tests/test_ollama_chat_client.py | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/python/packages/ollama/agent_framework_ollama/_chat_client.py b/python/packages/ollama/agent_framework_ollama/_chat_client.py index 7b27a4c660f..4475ba322b1 100644 --- a/python/packages/ollama/agent_framework_ollama/_chat_client.py +++ b/python/packages/ollama/agent_framework_ollama/_chat_client.py @@ -407,7 +407,7 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An messages = prepend_instructions_to_messages(list(messages), instructions, role="system") # Keys to exclude from processing - exclude_keys = {"instructions", "tool_choice"} + exclude_keys = {"instructions", "tool_choice", "tools"} # Build run_options and model_options separately run_options: dict[str, Any] = {} @@ -454,7 +454,8 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An # tools tools = options.get("tools") - if tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)): + tool_choice = options.get("tool_choice") + if tool_choice != "none" and tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)): run_options["tools"] = prepared_tools return run_options diff --git a/python/packages/ollama/tests/test_ollama_chat_client.py b/python/packages/ollama/tests/test_ollama_chat_client.py index 8c5e21172f2..7547c4d9622 100644 --- a/python/packages/ollama/tests/test_ollama_chat_client.py +++ b/python/packages/ollama/tests/test_ollama_chat_client.py @@ -907,3 +907,72 @@ def test_prepare_options_single_stop_string_becomes_list(ollama_unit_test_env: d request = client._prepare_options(messages, {"stop": "END"}) assert request["options"]["stop"] == ["END"] + + +def test_prepare_options_omits_tools_when_tool_choice_is_none( + ollama_unit_test_env: dict[str, str], +) -> None: + """Tools are omitted when tool_choice explicitly disables tool use.""" + client = OllamaChatClient() + messages = [Message(role="user", contents=[Content.from_text(text="hello")])] + tools = [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "Get weather for a city.", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string"}, + }, + "required": ["city"], + }, + }, + } + ] + + request = client._prepare_options( + messages, + { + "tools": tools, + "tool_choice": "none", + }, + ) + + assert "tools" not in request + + +def test_prepare_options_includes_tools_when_tool_choice_is_auto( + ollama_unit_test_env: dict[str, str], +) -> None: + """Tools remain available when automatic tool selection is enabled.""" + client = OllamaChatClient() + messages = [Message(role="user", contents=[Content.from_text(text="hello")])] + tools = [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "Get weather for a city.", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string"}, + }, + "required": ["city"], + }, + }, + } + ] + + request = client._prepare_options( + messages, + { + "tools": tools, + "tool_choice": "auto", + }, + ) + + assert "tools" in request + assert request["tools"] == tools From 294cae3de124172ad0f011b8054473d753bd21fa Mon Sep 17 00:00:00 2001 From: suhasagg Date: Mon, 5 Oct 2026 14:11:47 +0530 Subject: [PATCH 2/3] fix(ollama): handle ToolMode none --- .../agent_framework_ollama/_chat_client.py | 3 +- .../ollama/tests/test_ollama_chat_client.py | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/python/packages/ollama/agent_framework_ollama/_chat_client.py b/python/packages/ollama/agent_framework_ollama/_chat_client.py index 4475ba322b1..7d52570611d 100644 --- a/python/packages/ollama/agent_framework_ollama/_chat_client.py +++ b/python/packages/ollama/agent_framework_ollama/_chat_client.py @@ -455,7 +455,8 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An # tools tools = options.get("tools") tool_choice = options.get("tool_choice") - if tool_choice != "none" and tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)): + tool_mode = tool_choice.get("mode") if isinstance(tool_choice, Mapping) else tool_choice + if tool_mode != "none" and tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)): run_options["tools"] = prepared_tools return run_options diff --git a/python/packages/ollama/tests/test_ollama_chat_client.py b/python/packages/ollama/tests/test_ollama_chat_client.py index 7547c4d9622..eafd6cf53b2 100644 --- a/python/packages/ollama/tests/test_ollama_chat_client.py +++ b/python/packages/ollama/tests/test_ollama_chat_client.py @@ -943,6 +943,40 @@ def test_prepare_options_omits_tools_when_tool_choice_is_none( assert "tools" not in request +def test_prepare_options_omits_tools_when_tool_choice_mode_is_none( + ollama_unit_test_env: dict[str, str], +) -> None: + """Tools are omitted when ToolMode mapping explicitly disables tool use.""" + client = OllamaChatClient() + messages = [Message(role="user", contents=[Content.from_text(text="hello")])] + tools = [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "Get weather for a city.", + "parameters": { + "type": "object", + "properties": { + "city": {"type": "string"}, + }, + "required": ["city"], + }, + }, + } + ] + + request = client._prepare_options( + messages, + { + "tools": tools, + "tool_choice": {"mode": "none"}, + }, + ) + + assert "tools" not in request + + def test_prepare_options_includes_tools_when_tool_choice_is_auto( ollama_unit_test_env: dict[str, str], ) -> None: From ce0e4faee1d8bc59c714113a94aa9b7cb42414c5 Mon Sep 17 00:00:00 2001 From: suhasagg Date: Mon, 5 Oct 2026 20:02:20 +0530 Subject: [PATCH 3/3] fix(ollama): type ToolMode mapping --- .../packages/ollama/agent_framework_ollama/_chat_client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/packages/ollama/agent_framework_ollama/_chat_client.py b/python/packages/ollama/agent_framework_ollama/_chat_client.py index 7d52570611d..63ab08b5b74 100644 --- a/python/packages/ollama/agent_framework_ollama/_chat_client.py +++ b/python/packages/ollama/agent_framework_ollama/_chat_client.py @@ -15,7 +15,7 @@ Sequence, ) from itertools import chain -from typing import Any, ClassVar, Generic, TypedDict +from typing import Any, ClassVar, Generic, TypedDict, cast from agent_framework import ( BaseChatClient, @@ -31,6 +31,7 @@ FunctionTool, Message, ResponseStream, + ToolMode, UsageDetails, ) from agent_framework._settings import load_settings @@ -455,7 +456,7 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An # tools tools = options.get("tools") tool_choice = options.get("tool_choice") - tool_mode = tool_choice.get("mode") if isinstance(tool_choice, Mapping) else tool_choice + tool_mode = cast(ToolMode, tool_choice).get("mode") if isinstance(tool_choice, Mapping) else tool_choice if tool_mode != "none" and tools is not None and (prepared_tools := self._prepare_tools_for_ollama(tools)): run_options["tools"] = prepared_tools