Python: [BREAKING] changed AIFunction to FunctionTool and @ai_function to @tool (#3413)

* changed AIFunction to FunctionTool and @ai_function to @tool

* test and mypy fixes

* mypy fix

* switch function tool to always_require

* fix noop

* fix github copilot imports

* test fixes

* fix ollama test

* fixes for tests

* fix tests

* reverted change to always_require and extended timeout

* fix test
This commit is contained in:
Eduard van Valkenburg
2026-01-28 15:53:53 +01:00
committed by GitHub
Unverified
parent 15b43f2abe
commit a7d924a7d2
255 changed files with 1202 additions and 1290 deletions
@@ -12,7 +12,7 @@ from agent_framework import (
HostedFileSearchTool,
HostedMCPTool,
HostedWebSearchTool,
ai_function,
tool,
)
from agent_framework.exceptions import ServiceInitializationError
from azure.ai.agents.models import (
@@ -222,7 +222,7 @@ async def test_create_agent_with_tools(
provider = AzureAIAgentsProvider(agents_client=mock_agents_client)
@ai_function
@tool(approval_mode="never_require")
def get_weather(city: str) -> str:
"""Get weather for a city."""
return f"Weather in {city}"
@@ -366,7 +366,7 @@ async def test_get_agent_with_provided_function_tools(
mock_agent.tools = [mock_function_tool]
mock_agents_client.get_agent = AsyncMock(return_value=mock_agent)
@ai_function
@tool(approval_mode="never_require")
def get_weather(city: str) -> str:
"""Get weather for a city."""
return f"Weather in {city}"
@@ -483,9 +483,9 @@ def test_to_azure_ai_agent_tools_empty() -> None:
def test_to_azure_ai_agent_tools_function() -> None:
"""Test converting AIFunction to Azure tool definition."""
"""Test converting FunctionTool to Azure tool definition."""
@ai_function
@tool(approval_mode="never_require")
def get_weather(city: str) -> str:
"""Get weather for a city."""
return f"Weather in {city}"
@@ -23,6 +23,7 @@ from agent_framework import (
HostedMCPTool,
HostedWebSearchTool,
Role,
tool,
)
from agent_framework._serialization import SerializationMixin
from agent_framework.exceptions import ServiceInitializationError
@@ -940,7 +941,7 @@ async def test_azure_ai_chat_client_service_url(mock_agents_client: MagicMock) -
assert result == "https://test-endpoint.com/"
async def test_azure_ai_chat_client_prepare_tool_outputs_for_azure_ai_function_result(
async def test_azure_ai_chat_client_prepare_tool_outputs_for_azure_tool_result(
mock_agents_client: MagicMock,
) -> None:
"""Test _prepare_tool_outputs_for_azure_ai with FunctionResultContent."""
@@ -1336,6 +1337,7 @@ def test_azure_ai_chat_client_extract_file_path_contents_empty_annotations(
assert len(file_contents) == 0
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -22,6 +22,7 @@ from agent_framework import (
HostedMCPTool,
HostedWebSearchTool,
Role,
tool,
)
from agent_framework.exceptions import ServiceInitializationError
from azure.ai.projects.aio import AIProjectClient
@@ -1025,6 +1026,7 @@ def test_from_azure_ai_tools() -> None:
# region Integration Tests
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
+13 -11
View File
@@ -4,16 +4,18 @@ import os
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from agent_framework import AIFunction, ChatAgent
from agent_framework import ChatAgent, FunctionTool
from agent_framework._mcp import MCPTool
from agent_framework.exceptions import ServiceInitializationError
from azure.ai.projects.aio import AIProjectClient
from azure.ai.projects.models import (
AgentReference,
AgentVersionDetails,
FunctionTool,
PromptAgentDefinition,
)
from azure.ai.projects.models import (
FunctionTool as AzureFunctionTool,
)
from azure.identity.aio import AzureCliCredential
from agent_framework_azure_ai import AzureAIProjectAgentProvider
@@ -373,7 +375,7 @@ async def test_provider_get_agent_missing_function_tools(mock_project_client: Ma
mock_agent_version.description = None
mock_agent_version.definition = MagicMock(spec=PromptAgentDefinition)
mock_agent_version.definition.tools = [
FunctionTool(name="test_tool", parameters=[], strict=True, description="Test tool")
AzureFunctionTool(name="test_tool", parameters=[], strict=True, description="Test tool")
]
mock_agent_object = MagicMock()
@@ -494,7 +496,7 @@ class MockMCPTool(MCPTool): # pyright: ignore[reportGeneralTypeIssues]
unit testing. We only need isinstance(obj, MCPTool) to return True.
"""
def __init__(self, functions: list[AIFunction] | None = None) -> None:
def __init__(self, functions: list[FunctionTool] | None = None) -> None:
self.name = "MockMCPTool"
self.description = "A mock MCP tool for testing"
self.is_connected = False
@@ -502,7 +504,7 @@ class MockMCPTool(MCPTool): # pyright: ignore[reportGeneralTypeIssues]
self._connect_called = False
@property
def functions(self) -> list[AIFunction]:
def functions(self) -> list[FunctionTool]:
return self._mock_functions
async def connect(self, *, reset: bool = False) -> None:
@@ -520,13 +522,13 @@ def mock_mcp_tool() -> MockMCPTool:
return MockMCPTool(functions=mock_functions)
def create_mock_ai_function(name: str, description: str = "A mock function") -> AIFunction:
"""Create a real AIFunction for testing."""
def create_mock_ai_function(name: str, description: str = "A mock function") -> FunctionTool:
"""Create a real FunctionTool for testing."""
def mock_func(arg: str) -> str:
return f"Result from {name}: {arg}"
return AIFunction(func=mock_func, name=name, description=description)
return FunctionTool(func=mock_func, name=name, description=description, approval_mode="never_require")
async def test_provider_create_agent_with_mcp_tool(
@@ -593,8 +595,8 @@ async def test_provider_create_agent_with_mcp_and_regular_tools(
azure_ai_unit_test_env: dict[str, str],
mock_mcp_tool: "MockMCPTool",
) -> None:
"""Test that create_agent handles both MCP tools and regular AIFunctions."""
# Create a regular AIFunction
"""Test that create_agent handles both MCP tools and regular FunctionTools."""
# Create a regular FunctionTool
regular_function = create_mock_ai_function("regular_function", "A regular function")
# Patch normalize_tools to return tools as-is in a list (avoids callable check)
@@ -637,7 +639,7 @@ async def test_provider_create_agent_with_mcp_and_regular_tools(
)
# Verify to_azure_ai_tools was called with:
# - The regular AIFunction (1)
# - The regular FunctionTool (1)
# - The 2 discovered MCP functions
mock_to_azure_tools.assert_called_once()
tools_passed = mock_to_azure_tools.call_args[0][0]