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
@@ -10,7 +10,7 @@ from agent_framework import (
FunctionApprovalResponseContent,
RequestInfoEvent,
WorkflowOutputEvent,
ai_function,
tool,
)
from agent_framework.openai import OpenAIChatClient
@@ -45,7 +45,8 @@ Prerequisites:
# 1. Define market data tools (no approval required)
@ai_function
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_stock_price(symbol: Annotated[str, "The stock ticker symbol"]) -> str:
"""Get the current stock price for a given symbol."""
# Mock data for demonstration
@@ -54,7 +55,7 @@ def get_stock_price(symbol: Annotated[str, "The stock ticker symbol"]) -> str:
return f"{symbol.upper()}: ${price:.2f}"
@ai_function
@tool(approval_mode="never_require")
def get_market_sentiment(symbol: Annotated[str, "The stock ticker symbol"]) -> str:
"""Get market sentiment analysis for a stock."""
# Mock sentiment data
@@ -68,7 +69,7 @@ def get_market_sentiment(symbol: Annotated[str, "The stock ticker symbol"]) -> s
# 2. Define trading tools (approval required)
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def execute_trade(
symbol: Annotated[str, "The stock ticker symbol"],
action: Annotated[str, "Either 'buy' or 'sell'"],
@@ -78,7 +79,7 @@ def execute_trade(
return f"Trade executed: {action.upper()} {quantity} shares of {symbol.upper()}"
@ai_function
@tool(approval_mode="never_require")
def get_portfolio_balance() -> str:
"""Get current portfolio balance and available funds."""
return "Portfolio: $50,000 invested, $10,000 cash available. Holdings: AAPL, GOOGL, MSFT."
@@ -10,7 +10,7 @@ from agent_framework import (
GroupChatRequestSentEvent,
GroupChatState,
RequestInfoEvent,
ai_function,
tool,
)
from agent_framework.openai import OpenAIChatClient
@@ -44,19 +44,20 @@ Prerequisites:
# 1. Define tools for different agents
@ai_function
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def run_tests(test_suite: Annotated[str, "Name of the test suite to run"]) -> str:
"""Run automated tests for the application."""
return f"Test suite '{test_suite}' completed: 47 passed, 0 failed, 0 skipped"
@ai_function
@tool(approval_mode="never_require")
def check_staging_status() -> str:
"""Check the current status of the staging environment."""
return "Staging environment: Healthy, Version 2.3.0 deployed, All services running"
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def deploy_to_production(
version: Annotated[str, "The version to deploy"],
components: Annotated[str, "Comma-separated list of components to deploy"],
@@ -65,7 +66,7 @@ def deploy_to_production(
return f"Production deployment complete: Version {version}, Components: {components}"
@ai_function
@tool(approval_mode="never_require")
def create_rollback_plan(version: Annotated[str, "The version being deployed"]) -> str:
"""Create a rollback plan for the deployment."""
return (
@@ -9,7 +9,7 @@ from agent_framework import (
RequestInfoEvent,
SequentialBuilder,
WorkflowOutputEvent,
ai_function,
tool,
)
from agent_framework.openai import OpenAIChatClient
@@ -17,7 +17,7 @@ from agent_framework.openai import OpenAIChatClient
Sample: Sequential Workflow with Tool Approval Requests
This sample demonstrates how to use SequentialBuilder with tools that require human
approval before execution. The approval flow uses the existing @ai_function decorator
approval before execution. The approval flow uses the existing @tool decorator
with approval_mode="always_require" to trigger human-in-the-loop interactions.
This sample works as follows:
@@ -33,7 +33,7 @@ Show how tool call approvals integrate seamlessly with SequentialBuilder without
requiring any additional builder configuration.
Demonstrate:
- Using @ai_function(approval_mode="always_require") for sensitive operations.
- Using @tool(approval_mode="always_require") for sensitive operations.
- Handling RequestInfoEvent with FunctionApprovalRequestContent in sequential workflows.
- Resuming workflow execution after approval via send_responses_streaming.
@@ -44,7 +44,7 @@ Prerequisites:
# 1. Define tools - one requiring approval, one that doesn't
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def execute_database_query(
query: Annotated[str, "The SQL query to execute against the production database"],
) -> str:
@@ -53,7 +53,8 @@ def execute_database_query(
return f"Query executed successfully. Results: 3 rows affected by '{query}'"
@ai_function
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/getting_started/tools/function_tool_with_approval.py and samples/getting_started/tools/function_tool_with_approval_and_threads.py.
@tool(approval_mode="never_require")
def get_database_schema() -> str:
"""Get the current database schema. Does not require approval."""
return """