diff --git a/python/packages/ollama/agent_framework_ollama/_chat_client.py b/python/packages/ollama/agent_framework_ollama/_chat_client.py index 7b27a4c660f..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 @@ -407,7 +408,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 +455,9 @@ 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") + 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 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..eafd6cf53b2 100644 --- a/python/packages/ollama/tests/test_ollama_chat_client.py +++ b/python/packages/ollama/tests/test_ollama_chat_client.py @@ -907,3 +907,106 @@ 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_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: + """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