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
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework.anthropic import AnthropicClient
from agent_framework import tool
"""
Anthropic Chat Agent Example
@@ -12,7 +13,8 @@ Anthropic Chat Agent Example
This sample demonstrates using Anthropic with an agent and a single custom tool.
"""
# 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_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent Basic Example
@@ -15,7 +16,8 @@ This sample demonstrates basic usage of AzureAIProjectAgentProvider.
Shows both streaming and non-streaming responses with function tools.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -10,6 +10,7 @@ from azure.ai.projects.aio import AIProjectClient
from azure.ai.projects.models import AgentReference, PromptAgentDefinition
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Project Agent Provider Methods Example
@@ -25,7 +26,8 @@ with different configurations, which is efficient for multi-agent scenarios.
Each method returns a ChatAgent that can be used for conversations.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent Latest Version Example
@@ -16,7 +17,8 @@ instead of creating a new agent version on each instantiation. The first call cr
while subsequent calls with `get_agent()` reuse the latest agent version.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -11,6 +11,7 @@ from agent_framework import (
HostedCodeInterpreterTool,
HostedFileContent,
TextContent,
tool,
)
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
@@ -5,6 +5,7 @@ import asyncio
from agent_framework import (
AgentResponseUpdate,
HostedCodeInterpreterTool,
tool,
)
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
@@ -8,6 +8,7 @@ from agent_framework.azure import AzureAIProjectAgentProvider
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent Existing Conversation Example
@@ -15,7 +16,8 @@ Azure AI Agent Existing Conversation Example
This sample demonstrates usage of AzureAIProjectAgentProvider with existing conversation created on service side.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent with Explicit Settings Example
@@ -16,7 +17,8 @@ This sample demonstrates creating Azure AI Agents with explicit configuration
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent with Thread Management Example
@@ -15,7 +16,8 @@ This sample demonstrates thread management with Azure AI Agent, showing
persistent conversation capabilities using service-managed threads as well as storing messages in-memory.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIAgentsProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent Basic Example
@@ -15,7 +16,8 @@ This sample demonstrates basic usage of AzureAIAgentsProvider to create agents w
lifecycle management. Shows both streaming and non-streaming responses with function tools.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -9,6 +9,7 @@ from agent_framework.azure import AzureAIAgentsProvider
from azure.ai.agents.aio import AgentsClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent Provider Methods Example
@@ -19,7 +20,8 @@ This sample demonstrates the methods available on the AzureAIAgentsProvider clas
- as_agent(): Wrap an SDK Agent object without making HTTP calls
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from agent_framework import (
AgentResponseUpdate,
HostedCodeInterpreterTool,
HostedFileContent,
tool,
)
from agent_framework.azure import AzureAIAgentsProvider
from azure.ai.agents.aio import AgentsClient
@@ -9,6 +9,7 @@ from agent_framework.azure import AzureAIAgentsProvider
from azure.ai.agents.aio import AgentsClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent with Existing Thread Example
@@ -17,7 +18,8 @@ This sample demonstrates working with pre-existing conversation threads
by providing thread IDs for thread reuse patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIAgentsProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent with Explicit Settings Example
@@ -16,7 +17,8 @@ This sample demonstrates creating Azure AI Agents with explicit configuration
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIAgentsProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Agent with Function Tools Example
@@ -16,7 +17,8 @@ This sample demonstrates function tool integration with Azure AI Agents,
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -24,7 +26,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -9,6 +9,7 @@ from agent_framework import (
AgentThread,
HostedMCPTool,
HostedWebSearchTool,
tool,
)
from agent_framework.azure import AzureAIAgentsProvider
from azure.identity.aio import AzureCliCredential
@@ -33,6 +34,8 @@ To set up Bing Grounding:
4. Copy the connection ID and set it as the BING_CONNECTION_ID environment variable
"""
# 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_time() -> str:
"""Get the current UTC time."""
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread
from agent_framework import tool
from agent_framework.azure import AzureAIAgentsProvider
from azure.identity.aio import AzureCliCredential
from pydantic import Field
@@ -16,7 +17,8 @@ This sample demonstrates thread management with Azure AI Agents, comparing
automatic thread creation with explicit thread management for persistent context.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure OpenAI Assistants Basic Example
@@ -15,7 +16,8 @@ This sample demonstrates basic usage of AzureOpenAIAssistantsClient with automat
assistant lifecycle management, showing both streaming and non-streaming responses.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential, get_bearer_token_provider
from openai import AsyncAzureOpenAI
@@ -18,7 +19,8 @@ This sample demonstrates working with pre-existing Azure OpenAI Assistants
using existing assistant IDs rather than creating new ones.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure OpenAI Assistants with Explicit Settings Example
@@ -16,7 +17,8 @@ This sample demonstrates creating Azure OpenAI Assistants with explicit configur
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential
from pydantic import Field
@@ -17,7 +18,8 @@ This sample demonstrates function tool integration with Azure OpenAI Assistants,
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -25,7 +27,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread, ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential
from pydantic import Field
@@ -16,7 +17,8 @@ This sample demonstrates thread management with Azure OpenAI Assistants, compari
automatic thread creation with explicit thread management for persistent context.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure OpenAI Chat Client Basic Example
@@ -15,7 +16,8 @@ This sample demonstrates basic usage of AzureOpenAIChatClient for direct chat-ba
interactions, showing both streaming and non-streaming responses.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure OpenAI Chat Client with Explicit Settings Example
@@ -16,7 +17,8 @@ This sample demonstrates creating Azure OpenAI Chat Client with explicit configu
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
from pydantic import Field
@@ -17,7 +18,8 @@ This sample demonstrates function tool integration with Azure OpenAI Chat Client
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -25,7 +27,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread, ChatAgent, ChatMessageStore
from agent_framework import tool
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
from pydantic import Field
@@ -16,7 +17,8 @@ This sample demonstrates thread management with Azure OpenAI Chat Client, compar
automatic thread creation with explicit thread management for persistent context.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure OpenAI Responses Client Basic Example
@@ -15,7 +16,8 @@ This sample demonstrates basic usage of AzureOpenAIResponsesClient for structure
response generation, showing both streaming and non-streaming responses.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure OpenAI Responses Client with Explicit Settings Example
@@ -16,7 +17,8 @@ This sample demonstrates creating Azure OpenAI Responses Client with explicit co
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from pydantic import Field
@@ -17,7 +18,8 @@ This sample demonstrates function tool integration with Azure OpenAI Responses C
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -25,7 +27,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread, ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from pydantic import Field
@@ -16,7 +17,8 @@ This sample demonstrates thread management with Azure OpenAI Responses Client, c
automatic thread creation with explicit thread management for persistent context.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -12,6 +12,7 @@ from agent_framework import (
ChatMessage,
Role,
TextContent,
tool,
)
"""
@@ -15,6 +15,7 @@ from agent_framework import (
TextContent,
use_chat_middleware,
use_function_invocation,
tool,
)
from agent_framework._clients import TOptions_co
@@ -19,8 +19,10 @@ from typing import Annotated
from agent_framework.github import GithubCopilotAgent, GithubCopilotOptions
from pydantic import Field
from agent_framework import tool
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -14,8 +14,10 @@ from typing import Annotated
from agent_framework.github import GithubCopilotAgent, GithubCopilotOptions
from pydantic import Field
from agent_framework import tool
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -4,6 +4,7 @@ import asyncio
from datetime import datetime
from agent_framework.ollama import OllamaChatClient
from agent_framework import tool
"""
Ollama Agent Basic Example
@@ -17,7 +18,8 @@ https://ollama.com/
"""
# 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_time(location: str) -> str:
"""Get the current time."""
return f"The current time in {location} is {datetime.now().strftime('%I:%M %p')}."
@@ -4,6 +4,7 @@ import asyncio
from datetime import datetime
from agent_framework.ollama import OllamaChatClient
from agent_framework import tool
"""
Ollama Chat Client Example
@@ -17,7 +18,8 @@ https://ollama.com/
"""
# 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_time():
"""Get the current time."""
return f"The current time is {datetime.now().strftime('%I:%M %p')}."
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework.openai import OpenAIChatClient
from agent_framework import tool
"""
Ollama with OpenAI Chat Client Example
@@ -19,7 +20,8 @@ Environment Variables:
- OLLAMA_MODEL: The model name to use (e.g., "mistral", "llama3.2", "phi3")
"""
# 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_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
from agent_framework import tool
"""
OpenAI Assistants Basic Example
@@ -16,7 +17,8 @@ This sample demonstrates basic usage of OpenAIAssistantProvider with automatic
assistant lifecycle management, showing both streaming and non-streaming responses.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
from agent_framework import tool
"""
OpenAI Assistant Provider Methods Example
@@ -18,7 +19,8 @@ This sample demonstrates the methods available on the OpenAIAssistantProvider cl
- as_agent(): Wrap an SDK Assistant object without making HTTP calls
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
from agent_framework import tool
"""
OpenAI Assistants with Existing Assistant Example
@@ -16,7 +17,8 @@ This sample demonstrates working with pre-existing OpenAI Assistants
using the provider's get_agent() and as_agent() methods.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
from agent_framework import tool
"""
OpenAI Assistants with Explicit Settings Example
@@ -16,7 +17,8 @@ This sample demonstrates creating OpenAI Assistants with explicit configuration
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -9,6 +9,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
from agent_framework import tool
"""
OpenAI Assistants with Function Tools Example
@@ -17,7 +18,8 @@ This sample demonstrates function tool integration with OpenAI Assistants,
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -25,7 +27,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread
from agent_framework import tool
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
@@ -17,7 +18,8 @@ This sample demonstrates thread management with OpenAI Assistants, showing
persistent conversation threads and context preservation across interactions.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework.openai import OpenAIChatClient
from agent_framework import tool
"""
OpenAI Chat Client Basic Example
@@ -13,7 +14,8 @@ This sample demonstrates basic usage of OpenAIChatClient for direct chat-based
interactions, showing both streaming and non-streaming responses.
"""
# 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_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIChatClient
from pydantic import Field
from agent_framework import tool
"""
OpenAI Chat Client with Explicit Settings Example
@@ -15,7 +16,8 @@ This sample demonstrates creating OpenAI Chat Client with explicit configuration
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.openai import OpenAIChatClient
from pydantic import Field
@@ -16,7 +17,8 @@ This sample demonstrates function tool integration with OpenAI Chat Client,
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -24,7 +26,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread, ChatAgent, ChatMessageStore
from agent_framework import tool
from agent_framework.openai import OpenAIChatClient
from pydantic import Field
@@ -15,7 +16,8 @@ This sample demonstrates thread management with OpenAI Chat Client, showing
conversation threads and message history preservation across interactions.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.openai import OpenAIResponsesClient
from pydantic import Field
@@ -15,7 +16,8 @@ This sample demonstrates basic usage of OpenAIResponsesClient for structured
response generation, showing both streaming and non-streaming responses.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from agent_framework import (
CodeInterpreterToolResultContent,
HostedCodeInterpreterTool,
TextContent,
tool,
)
from agent_framework.openai import OpenAIResponsesClient
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIResponsesClient
from pydantic import Field
from agent_framework import tool
"""
OpenAI Responses Client with Explicit Settings Example
@@ -15,7 +16,8 @@ This sample demonstrates creating OpenAI Responses Client with explicit configur
settings rather than relying on environment variable defaults.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.openai import OpenAIResponsesClient
from pydantic import Field
@@ -16,7 +17,8 @@ This sample demonstrates function tool integration with OpenAI Responses Client,
showing both agent-level and query-level tool configuration patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -24,7 +26,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time() -> str:
"""Get the current UTC time."""
current_time = datetime.now(timezone.utc)
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import AgentThread, ChatAgent
from agent_framework import tool
from agent_framework.openai import OpenAIResponsesClient
from pydantic import Field
@@ -15,7 +16,8 @@ This sample demonstrates thread management with OpenAI Responses Client, showing
persistent conversation context and simplified response handling.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -13,10 +13,12 @@ from typing import Any
from agent_framework.azure import AgentFunctionApp, AzureOpenAIChatClient
from azure.identity import AzureCliCredential
from agent_framework import tool
logger = logging.getLogger(__name__)
# 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_weather(location: str) -> dict[str, Any]:
"""Get current weather for a location."""
@@ -30,7 +32,7 @@ def get_weather(location: str) -> dict[str, Any]:
logger.info(f"✓ [TOOL RESULT] {result}")
return result
@tool(approval_mode="never_require")
def calculate_tip(bill_amount: float, tip_percentage: float = 15.0) -> dict[str, Any]:
"""Calculate tip amount and total bill."""
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure AI Chat Client Direct Usage Example
@@ -15,7 +16,8 @@ Demonstrates direct AzureAIChatClient usage for chat interactions with Azure AI
Shows function calling capabilities with custom business logic.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIAssistantsClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure Assistants Client Direct Usage Example
@@ -15,7 +16,8 @@ Demonstrates direct AzureAssistantsClient usage for chat interactions with Azure
Shows function calling capabilities and automatic assistant creation.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
from pydantic import Field
from agent_framework import tool
"""
Azure Chat Client Direct Usage Example
@@ -15,7 +16,8 @@ Demonstrates direct AzureChatClient usage for chat interactions with Azure OpenA
Shows function calling capabilities with custom business logic.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatResponse
from agent_framework import tool
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
from pydantic import BaseModel, Field
@@ -16,7 +17,8 @@ Demonstrates direct AzureResponsesClient usage for structured response generatio
Shows function calling capabilities with custom business logic.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIAssistantsClient
from pydantic import Field
from agent_framework import tool
"""
OpenAI Assistants Client Direct Usage Example
@@ -15,7 +16,8 @@ Shows function calling capabilities and automatic assistant creation.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIChatClient
from pydantic import Field
from agent_framework import tool
"""
OpenAI Chat Client Direct Usage Example
@@ -15,7 +16,8 @@ Shows function calling capabilities with custom business logic.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,6 +6,7 @@ from typing import Annotated
from agent_framework.openai import OpenAIResponsesClient
from pydantic import Field
from agent_framework import tool
"""
OpenAI Responses Client Direct Usage Example
@@ -15,7 +16,8 @@ Shows function calling capabilities with custom business logic.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,8 +6,10 @@ import uuid
from agent_framework.azure import AzureAIAgentClient
from agent_framework.mem0 import Mem0Provider
from azure.identity.aio import AzureCliCredential
from agent_framework import tool
# 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 retrieve_company_report(company_code: str, detailed: bool) -> str:
if company_code != "CNTS":
raise ValueError("Company code not found")
@@ -7,8 +7,10 @@ from agent_framework.azure import AzureAIAgentClient
from agent_framework.mem0 import Mem0Provider
from azure.identity.aio import AzureCliCredential
from mem0 import AsyncMemory
from agent_framework import tool
# 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 retrieve_company_report(company_code: str, detailed: bool) -> str:
if company_code != "CNTS":
raise ValueError("Company code not found")
@@ -6,8 +6,10 @@ import uuid
from agent_framework.azure import AzureAIAgentClient
from agent_framework.mem0 import Mem0Provider
from azure.identity.aio import AzureCliCredential
from agent_framework import tool
# 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_user_preferences(user_id: str) -> str:
"""Mock function to get user preferences."""
preferences = {
@@ -31,12 +31,14 @@ import asyncio
import os
from agent_framework import ChatMessage, Role
from agent_framework import tool
from agent_framework.openai import OpenAIChatClient
from agent_framework_redis._provider import RedisProvider
from redisvl.extensions.cache.embeddings import EmbeddingsCache
from redisvl.utils.vectorize import OpenAITextVectorizer
# 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 search_flights(origin_airport_code: str, destination_airport_code: str, detailed: bool = False) -> str:
"""Simulated flight-search tool to demonstrate tool memory.
@@ -21,7 +21,7 @@ import logging
import os
from typing import Annotated
from agent_framework import ChatAgent, ai_function
from agent_framework import ChatAgent, tool
from agent_framework.azure import AzureOpenAIResponsesClient
logger = logging.getLogger(__name__)
@@ -50,7 +50,8 @@ def analyze_content(
return f"Analyzing content for: {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 summarize_document(
length: Annotated[str, "Desired summary length: 'brief', 'medium', or 'detailed'"] = "medium",
) -> str:
@@ -58,7 +59,7 @@ def summarize_document(
return f"Generating {length} summary of the document..."
@ai_function
@tool(approval_mode="never_require")
def extract_key_points(
max_points: Annotated[int, "Maximum number of key points to extract"] = 5,
) -> str:
@@ -25,6 +25,7 @@ from agent_framework import (
WorkflowBuilder,
WorkflowContext,
handler,
tool,
)
from pydantic import BaseModel, Field
from typing_extensions import Never
@@ -9,11 +9,13 @@ import os
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -22,7 +24,7 @@ def get_weather(
temperature = 22
return f"The weather in {location} is {conditions[0]} with a high of {temperature}°C."
@tool(approval_mode="never_require")
def get_forecast(
location: Annotated[str, Field(description="The location to get the forecast for.")],
days: Annotated[int, Field(description="Number of days for forecast")] = 3,
@@ -11,12 +11,16 @@ import os
from typing import Annotated
from agent_framework import ChatAgent, Executor, WorkflowBuilder, WorkflowContext, handler
from agent_framework import tool
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.devui import serve
from typing_extensions import Never
# 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")
# Tool functions for the agent
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
@@ -25,7 +29,7 @@ def get_weather(
temperature = 53
return f"The weather in {location} is {conditions[0]} with a high of {temperature}°C."
@tool(approval_mode="never_require")
def get_time(
timezone: Annotated[str, "The timezone to get time for."] = "UTC",
) -> str:
@@ -27,6 +27,7 @@ from agent_framework import (
WorkflowContext,
handler,
response_handler,
tool,
)
from pydantic import BaseModel, Field
from typing_extensions import Never
@@ -15,7 +15,7 @@ from agent_framework import (
FunctionInvocationContext,
Role,
TextContent,
ai_function,
tool,
chat_middleware,
function_middleware,
)
@@ -98,6 +98,8 @@ async def atlantis_location_filter_middleware(
await next(context)
# 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_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
@@ -107,6 +109,7 @@ def get_weather(
return f"The weather in {location} is {conditions[0]} with a high of {temperature}°C."
@tool(approval_mode="never_require")
def get_forecast(
location: Annotated[str, "The location to get the forecast for."],
days: Annotated[int, "Number of days for forecast"] = 3,
@@ -123,7 +126,7 @@ def get_forecast(
return f"Weather forecast for {location}:\n" + "\n".join(forecast)
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def send_email(
recipient: Annotated[str, "The email address of the recipient."],
subject: Annotated[str, "The subject of the email."],
@@ -4,6 +4,7 @@ from typing import Annotated, Any
import anyio
from agent_framework.openai import OpenAIResponsesClient
from agent_framework import tool
"""
This sample demonstrates how to expose an Agent as an MCP server.
@@ -30,7 +31,8 @@ with the following configuration:
```
"""
# 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_specials() -> Annotated[str, "Returns the specials from the menu."]:
return """
Special Soup: Clam Chowder
@@ -38,7 +40,7 @@ def get_specials() -> Annotated[str, "Returns the specials from the menu."]:
Special Drink: Chai Tea
"""
@tool(approval_mode="never_require")
def get_item_price(
menu_item: Annotated[str, "The name of the menu item."],
) -> Annotated[str, "Returns the price of the menu item."]:
@@ -11,6 +11,7 @@ from agent_framework import (
AgentResponse,
AgentRunContext,
FunctionInvocationContext,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -33,6 +34,8 @@ The example shows:
Execution order: Agent middleware (outermost) -> Run middleware (innermost) -> Agent execution
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -12,6 +12,7 @@ from agent_framework import (
ChatResponse,
Role,
chat_middleware,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -35,6 +36,8 @@ The example covers:
- Middleware registration at run level (applies to specific run only)
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -14,6 +14,7 @@ from agent_framework import (
FunctionInvocationContext,
FunctionMiddleware,
Role,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -33,6 +34,8 @@ This approach is useful when you need stateful middleware or complex logic that
from object-oriented design patterns.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -6,6 +6,7 @@ import datetime
from agent_framework import (
agent_middleware,
function_middleware,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -40,6 +41,8 @@ Key benefits of decorator approach:
- Prevents type mismatches
"""
# 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_current_time() -> str:
"""Get the current time."""
@@ -5,6 +5,7 @@ from collections.abc import Awaitable, Callable
from typing import Annotated
from agent_framework import FunctionInvocationContext
from agent_framework import tool
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
from pydantic import Field
@@ -23,7 +24,8 @@ The middleware catches TimeoutError from an unstable data service and replaces i
a helpful message for the user, preventing raw exceptions from reaching the end user.
"""
# 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 unstable_data_service(
query: Annotated[str, Field(description="The data query to execute.")],
) -> str:
@@ -9,6 +9,7 @@ from typing import Annotated
from agent_framework import (
AgentRunContext,
FunctionInvocationContext,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -29,6 +30,8 @@ lightweight approach compared to class-based middleware. Both agent and function
can be implemented as async functions that accept context and next parameters.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -11,6 +11,7 @@ from agent_framework import (
AgentRunContext,
ChatMessage,
Role,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -28,6 +29,8 @@ The example includes:
This is useful for implementing security checks, rate limiting, or early exit conditions.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -12,6 +12,7 @@ from agent_framework import (
ChatMessage,
Role,
TextContent,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -34,6 +35,8 @@ then replaces its result with a custom "perfect weather" message. For streaming
it creates a custom async generator that yields the override message in chunks.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -4,7 +4,7 @@ import asyncio
from collections.abc import Awaitable, Callable
from typing import Annotated
from agent_framework import FunctionInvocationContext, ai_function, function_middleware
from agent_framework import FunctionInvocationContext, tool, function_middleware
from agent_framework.openai import OpenAIChatClient
from pydantic import Field
@@ -81,7 +81,8 @@ class SessionContextContainer:
runtime_context = SessionContextContainer()
@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")
async def send_email(
to: Annotated[str, Field(description="Recipient email address")],
subject: Annotated[str, Field(description="Email subject line")],
@@ -112,7 +113,7 @@ async def send_email(
return f"Email sent to {to} from user {user_id} (tenant: {tenant}). Subject: '{subject}'"
@ai_function
@tool(approval_mode="never_require")
async def send_notification(
message: Annotated[str, Field(description="Notification message to send")],
priority: Annotated[str, Field(description="Priority level: low, medium, high")] = "medium",
@@ -241,7 +242,7 @@ async def pattern_1_single_agent_with_closure() -> None:
# Create tools for sub-agents (these will use kwargs propagation)
@ai_function
@tool(approval_mode="never_require")
async def send_email_v2(
to: Annotated[str, Field(description="Recipient email")],
subject: Annotated[str, Field(description="Subject")],
@@ -253,7 +254,7 @@ async def send_email_v2(
return f"Email sent to {to} with subject '{subject}'"
@ai_function
@tool(approval_mode="never_require")
async def send_sms(
phone: Annotated[str, Field(description="Phone number")],
message: Annotated[str, Field(description="SMS message")],
@@ -377,7 +378,7 @@ class AuthContextMiddleware:
await next(context)
@ai_function
@tool(approval_mode="never_require")
async def protected_operation(operation: Annotated[str, Field(description="Operation to perform")]) -> str:
"""Protected operation that requires authentication."""
return f"Executed protected operation: {operation}"
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework import (
FunctionInvocationContext,
tool,
)
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
@@ -25,6 +26,8 @@ The example includes:
This approach shows how middleware can work together by sharing state within the same class instance.
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -33,6 +36,7 @@ def get_weather(
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
@tool(approval_mode="never_require")
def get_time(
timezone: Annotated[str, Field(description="The timezone to get the time for.")] = "UTC",
@@ -7,6 +7,7 @@ from typing import Annotated
from agent_framework import (
AgentRunContext,
ChatMessageStore,
tool,
)
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
@@ -30,6 +31,8 @@ Key behaviors demonstrated:
4. After next(): thread contains full conversation history (all previous + current messages)
"""
# 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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -5,8 +5,10 @@ from random import randint
from typing import Annotated
from agent_framework.openai import OpenAIChatClient
from agent_framework import tool
# 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_weather(
location: Annotated[str, "The location to get the weather for."],
) -> str:
@@ -19,6 +19,7 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExport
from opentelemetry.semconv._incubating.attributes.service_attributes import SERVICE_NAME
from opentelemetry.trace import set_tracer_provider
from pydantic import Field
from agent_framework import tool
"""
This sample shows how to manually configure to send traces, logs, and metrics to the console,
@@ -64,7 +65,8 @@ def setup_metrics():
# Sets the global default meter provider
set_meter_provider(meter_provider)
# 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -9,6 +9,7 @@ from agent_framework.openai import OpenAIResponsesClient
from opentelemetry.trace import SpanKind
from opentelemetry.trace.span import format_trace_id
from pydantic import Field
from agent_framework import tool
if TYPE_CHECKING:
from agent_framework import ChatClientProtocol
@@ -38,7 +39,8 @@ You can also set the environment variables instead of passing them as CLI argume
"""
# 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -5,6 +5,7 @@ from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.observability import configure_otel_providers, get_tracer
from agent_framework.openai import OpenAIChatClient
from opentelemetry.trace import SpanKind
@@ -16,7 +17,8 @@ This sample shows how you can observe an agent in Agent Framework by using the
same observability setup 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -8,6 +8,7 @@ from typing import Annotated
import dotenv
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.observability import create_resource, enable_instrumentation, get_tracer
from agent_framework.openai import OpenAIResponsesClient
from azure.ai.projects.aio import AIProjectClient
@@ -31,7 +32,8 @@ dotenv.load_dotenv()
logger = logging.getLogger(__name__)
# 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -7,6 +7,7 @@ from typing import Annotated
import dotenv
from agent_framework import ChatAgent
from agent_framework import tool
from agent_framework.azure import AzureAIClient
from agent_framework.observability import get_tracer
from azure.ai.projects.aio import AIProjectClient
@@ -28,7 +29,8 @@ for this sample to work.
# For loading the `AZURE_AI_PROJECT_ENDPOINT` environment variable
dotenv.load_dotenv()
# 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -6,7 +6,7 @@ from contextlib import suppress
from random import randint
from typing import TYPE_CHECKING, Annotated, Literal
from agent_framework import ai_function
from agent_framework import tool
from agent_framework.observability import configure_otel_providers, get_tracer
from agent_framework.openai import OpenAIResponsesClient
from opentelemetry import trace
@@ -28,9 +28,11 @@ output traces, logs, and metrics to the console.
"""
# Define the scenarios that can be run to show the telemetry data collected by the SDK
SCENARIOS = ["chat_client", "chat_client_stream", "ai_function", "all"]
SCENARIOS = ["chat_client", "chat_client_stream", "tool", "all"]
# 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -78,7 +80,7 @@ async def run_chat_client(client: "ChatClientProtocol", stream: bool = False) ->
print(f"Assistant: {response}")
async def run_ai_function() -> None:
async def run_tool() -> None:
"""Run a AI function.
This function runs a AI function and prints the output.
@@ -90,12 +92,12 @@ async def run_ai_function() -> None:
"""
with get_tracer().start_as_current_span("Scenario: AI Function", kind=trace.SpanKind.CLIENT):
print("Running scenario: AI Function")
func = ai_function(get_weather)
func = tool(get_weather)
weather = await func.invoke(location="Amsterdam")
print(f"Weather in Amsterdam:\n{weather}")
async def main(scenario: Literal["chat_client", "chat_client_stream", "ai_function", "all"] = "all"):
async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "all"] = "all"):
"""Run the selected scenario(s)."""
# This will enable tracing and create the necessary tracing, logging and metrics providers
@@ -108,9 +110,9 @@ async def main(scenario: Literal["chat_client", "chat_client_stream", "ai_functi
client = OpenAIResponsesClient()
# Scenarios where telemetry is collected in the SDK, from the most basic to the most complex.
if scenario == "ai_function" or scenario == "all":
if scenario == "tool" or scenario == "all":
with suppress(Exception):
await run_ai_function()
await run_tool()
if scenario == "chat_client_stream" or scenario == "all":
with suppress(Exception):
await run_chat_client(client, stream=True)
@@ -6,7 +6,7 @@ from contextlib import suppress
from random import randint
from typing import TYPE_CHECKING, Annotated, Literal
from agent_framework import ai_function, setup_logging
from agent_framework import tool, setup_logging
from agent_framework.observability import configure_otel_providers, get_tracer
from agent_framework.openai import OpenAIResponsesClient
from opentelemetry import trace
@@ -28,9 +28,11 @@ Use this approach when you need custom exporter configuration beyond what enviro
"""
# Define the scenarios that can be run to show the telemetry data collected by the SDK
SCENARIOS = ["chat_client", "chat_client_stream", "ai_function", "all"]
SCENARIOS = ["chat_client", "chat_client_stream", "tool", "all"]
# 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")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
@@ -78,7 +80,7 @@ async def run_chat_client(client: "ChatClientProtocol", stream: bool = False) ->
print(f"Assistant: {response}")
async def run_ai_function() -> None:
async def run_tool() -> None:
"""Run a AI function.
This function runs a AI function and prints the output.
@@ -90,12 +92,12 @@ async def run_ai_function() -> None:
"""
with get_tracer().start_as_current_span("Scenario: AI Function", kind=trace.SpanKind.CLIENT):
print("Running scenario: AI Function")
func = ai_function(get_weather)
func = tool(get_weather)
weather = await func.invoke(location="Amsterdam")
print(f"Weather in Amsterdam:\n{weather}")
async def main(scenario: Literal["chat_client", "chat_client_stream", "ai_function", "all"] = "all"):
async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "all"] = "all"):
"""Run the selected scenario(s)."""
# Setup the logging with the more complete format
@@ -137,9 +139,9 @@ async def main(scenario: Literal["chat_client", "chat_client_stream", "ai_functi
client = OpenAIResponsesClient()
# Scenarios where telemetry is collected in the SDK, from the most basic to the most complex.
if scenario == "ai_function" or scenario == "all":
if scenario == "tool" or scenario == "all":
with suppress(Exception):
await run_ai_function()
await run_tool()
if scenario == "chat_client_stream" or scenario == "all":
with suppress(Exception):
await run_chat_client(client, stream=True)
@@ -8,6 +8,7 @@ from agent_framework import (
WorkflowContext,
WorkflowOutputEvent,
handler,
tool,
)
from agent_framework.observability import configure_otel_providers, get_tracer
from opentelemetry.trace import SpanKind
+22 -18
View File
@@ -1,25 +1,29 @@
# Tools Examples
This folder contains examples demonstrating how to use AI functions (tools) with the Agent Framework. AI functions allow agents to interact with external systems, perform computations, and execute custom logic.
This folder contains examples demonstrating how to use local tools with the Agent Framework. Local tools allow agents to interact with external systems, perform computations, and execute custom logic.
Note: Several examples set `approval_mode="never_require"` to keep the samples concise. For production scenarios,
keep `approval_mode="always_require"` unless you are confident in the tool behavior and approval flow. See
`function_tool_with_approval.py` and `function_tool_with_approval_and_threads.py` for end-to-end approval handling.
## Examples
| File | Description |
|------|-------------|
| [`ai_function_declaration_only.py`](ai_function_declaration_only.py) | Demonstrates how to create function declarations without implementations. Useful for testing agent reasoning about tool usage or when tools are defined elsewhere. Shows how agents request tool calls even when the tool won't be executed. |
| [`ai_function_from_dict_with_dependency_injection.py`](ai_function_from_dict_with_dependency_injection.py) | Shows how to create AI functions from dictionary definitions using dependency injection. The function implementation is injected at runtime during deserialization, enabling dynamic tool creation and configuration. Note: This serialization/deserialization feature is in active development. |
| [`ai_function_recover_from_failures.py`](ai_function_recover_from_failures.py) | Demonstrates graceful error handling when tools raise exceptions. Shows how agents receive error information and can recover from failures, deciding whether to retry or respond differently based on the exception. |
| [`ai_function_with_approval.py`](ai_function_with_approval.py) | Shows how to implement user approval workflows for function calls without using threads. Demonstrates both streaming and non-streaming approval patterns where users can approve or reject function executions before they run. |
| [`ai_function_with_approval_and_threads.py`](ai_function_with_approval_and_threads.py) | Demonstrates tool approval workflows using threads for automatic conversation history management. Shows how threads simplify approval workflows by automatically storing and retrieving conversation context. Includes both approval and rejection examples. |
| [`ai_function_with_kwargs.py`](ai_function_with_kwargs.py) | Demonstrates how to inject custom arguments (context) into an AI function from the agent's run method. Useful for passing runtime information like access tokens or user IDs that the tool needs but the model shouldn't see. |
| [`ai_function_with_thread_injection.py`](ai_function_with_thread_injection.py) | Shows how to access the current `thread` object inside an AI function via `**kwargs`. |
| [`ai_function_with_max_exceptions.py`](ai_function_with_max_exceptions.py) | Shows how to limit the number of times a tool can fail with exceptions using `max_invocation_exceptions`. Useful for preventing expensive tools from being called repeatedly when they keep failing. |
| [`ai_function_with_max_invocations.py`](ai_function_with_max_invocations.py) | Demonstrates limiting the total number of times a tool can be invoked using `max_invocations`. Useful for rate-limiting expensive operations or ensuring tools are only called a specific number of times per conversation. |
| [`ai_functions_in_class.py`](ai_functions_in_class.py) | Shows how to use `ai_function` decorator with class methods to create stateful tools. Demonstrates how class state can control tool behavior dynamically, allowing you to adjust tool functionality at runtime by modifying class properties. |
| [`function_tool_declaration_only.py`](function_tool_declaration_only.py) | Demonstrates how to create function declarations without implementations. Useful for testing agent reasoning about tool usage or when tools are defined elsewhere. Shows how agents request tool calls even when the tool won't be executed. |
| [`function_tool_from_dict_with_dependency_injection.py`](function_tool_from_dict_with_dependency_injection.py) | Shows how to create local tools from dictionary definitions using dependency injection. The function implementation is injected at runtime during deserialization, enabling dynamic tool creation and configuration. Note: This serialization/deserialization feature is in active development. |
| [`function_tool_recover_from_failures.py`](function_tool_recover_from_failures.py) | Demonstrates graceful error handling when tools raise exceptions. Shows how agents receive error information and can recover from failures, deciding whether to retry or respond differently based on the exception. |
| [`function_tool_with_approval.py`](function_tool_with_approval.py) | Shows how to implement user approval workflows for function calls without using threads. Demonstrates both streaming and non-streaming approval patterns where users can approve or reject function executions before they run. |
| [`function_tool_with_approval_and_threads.py`](function_tool_with_approval_and_threads.py) | Demonstrates tool approval workflows using threads for automatic conversation history management. Shows how threads simplify approval workflows by automatically storing and retrieving conversation context. Includes both approval and rejection examples. |
| [`function_tool_with_kwargs.py`](function_tool_with_kwargs.py) | Demonstrates how to inject custom arguments (context) into a local tool from the agent's run method. Useful for passing runtime information like access tokens or user IDs that the tool needs but the model shouldn't see. |
| [`function_tool_with_thread_injection.py`](function_tool_with_thread_injection.py) | Shows how to access the current `thread` object inside a local tool via `**kwargs`. |
| [`function_tool_with_max_exceptions.py`](function_tool_with_max_exceptions.py) | Shows how to limit the number of times a tool can fail with exceptions using `max_invocation_exceptions`. Useful for preventing expensive tools from being called repeatedly when they keep failing. |
| [`function_tool_with_max_invocations.py`](function_tool_with_max_invocations.py) | Demonstrates limiting the total number of times a tool can be invoked using `max_invocations`. Useful for rate-limiting expensive operations or ensuring tools are only called a specific number of times per conversation. |
| [`tool_in_class.py`](tool_in_class.py) | Shows how to use the `tool` decorator with class methods to create stateful tools. Demonstrates how class state can control tool behavior dynamically, allowing you to adjust tool functionality at runtime by modifying class properties. |
## Key Concepts
### AI Function Features
### Local Tool Features
- **Function Declarations**: Define tool schemas without implementations for testing or external tools
- **Dependency Injection**: Create tools from configurations with runtime-injected implementations
@@ -33,10 +37,10 @@ This folder contains examples demonstrating how to use AI functions (tools) with
#### Basic Tool Definition
```python
from agent_framework import ai_function
from agent_framework import tool
from typing import Annotated
@ai_function
@tool(approval_mode="never_require")
def my_tool(param: Annotated[str, "Description"]) -> str:
"""Tool description for the AI."""
return f"Result: {param}"
@@ -45,7 +49,7 @@ def my_tool(param: Annotated[str, "Description"]) -> str:
#### Tool with Approval
```python
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def sensitive_operation(data: Annotated[str, "Data to process"]) -> str:
"""This requires user approval before execution."""
return f"Processed: {data}"
@@ -54,12 +58,12 @@ def sensitive_operation(data: Annotated[str, "Data to process"]) -> str:
#### Tool with Invocation Limits
```python
@ai_function(max_invocations=3)
@tool(max_invocations=3)
def limited_tool() -> str:
"""Can only be called 3 times total."""
return "Result"
@ai_function(max_invocation_exceptions=2)
@tool(max_invocation_exceptions=2)
def fragile_tool() -> str:
"""Can only fail 2 times before being disabled."""
return "Result"
@@ -115,7 +119,7 @@ Two approaches for handling approvals:
Each example is a standalone Python script that can be run directly:
```bash
uv run python ai_function_with_approval.py
uv run python function_tool_with_approval.py
```
Make sure you have the necessary environment variables configured (like `OPENAI_API_KEY` or Azure credentials) before running the examples.
@@ -4,15 +4,17 @@ import asyncio
from typing import Annotated
from agent_framework.openai import OpenAIResponsesClient
from agent_framework import tool
"""
This sample demonstrates how to configure function invocation settings
for an client and use a simple ai_function as a tool in an agent.
for an client and use a simple tool as a tool in an agent.
This behavior is the same for all chat client types.
"""
# 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 add(
x: Annotated[int, "First number"],
y: Annotated[int, "Second number"],
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft. All rights reserved.
from agent_framework import AIFunction
from agent_framework import FunctionTool
from agent_framework.openai import OpenAIResponsesClient
"""
@@ -8,13 +8,13 @@ Example of how to create a function that only consists of a declaration without
This is useful when you want the agent to use tools that are defined elsewhere or when you want
to test the agent's ability to reason about tool usage without executing them.
The only difference is that you provide an AIFunction without a function.
The only difference is that you provide a FunctionTool without a function.
If you need a input_model, you can still provide that as well.
"""
async def main():
function_declaration = AIFunction[None, None](
function_declaration = FunctionTool(
name="get_current_time",
description="Get the current time in ISO 8601 format.",
)
@@ -1,31 +1,31 @@
# Copyright (c) Microsoft. All rights reserved.
# type: ignore
"""
AIFunction Tool with Dependency Injection Example
Local Tool with Dependency Injection Example
This example demonstrates how to create an AIFunction tool using the agent framework's
This example demonstrates how to create a FunctionTool using the agent framework's
dependency injection system. Instead of providing the function at initialization time,
the actual callable function is injected during deserialization from a dictionary definition.
Note:
The serialization and deserialization feature used in this example is currently
in active development. The API may change in future versions as we continue
in active development. The API may change in future versions as we continue
to improve and extend its functionality. Please refer to the latest documentation
for any updates to the dependency injection patterns.
Usage:
Run this script to see how an AIFunction tool can be created from a dictionary
Run this script to see how a FunctionTool can be created from a dictionary
definition with the function injected at runtime. The agent will use this tool
to perform arithmetic operations.
"""
import asyncio
from agent_framework import AIFunction
from agent_framework import FunctionTool
from agent_framework.openai import OpenAIResponsesClient
definition = {
"type": "ai_function",
"type": "function_tool",
"name": "add_numbers",
"description": "Add two numbers together.",
"input_model": {
@@ -47,15 +47,15 @@ async def main() -> None:
"""Add two numbers together."""
return a + b
# Create the AIFunction tool using dependency injection
# Create the FunctionTool using dependency injection
# The 'definition' dictionary contains the serialized tool configuration,
# while the actual function implementation is provided via dependencies.
#
# Dependency structure: {"ai_function": {"name:add_numbers": {"func": func}}}
# - "ai_function": matches the tool type identifier
# Dependency structure: {"function_tool": {"name:add_numbers": {"func": func}}}
# - "function_tool": matches the tool type identifier
# - "name:add_numbers": instance-specific injection targeting tools with name="add_numbers"
# - "func": the parameter name that will receive the injected function
tool = AIFunction.from_dict(definition, dependencies={"ai_function": {"name:add_numbers": {"func": func}}})
tool = FunctionTool.from_dict(definition, dependencies={"function_tool": {"name:add_numbers": {"func": func}}})
agent = OpenAIResponsesClient().as_agent(
name="FunctionToolAgent", instructions="You are a helpful assistant.", tools=tool
@@ -4,6 +4,7 @@ import asyncio
from typing import Annotated
from agent_framework import FunctionCallContent, FunctionResultContent
from agent_framework import tool
from agent_framework.openai import OpenAIResponsesClient
"""
@@ -13,13 +14,16 @@ Shows how a tool that throws an exception creates gracefull recovery and can kee
The LLM decides whether to retry the call or to respond with something else, based on the exception.
"""
# 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 greet(name: Annotated[str, "Name to greet"]) -> str:
"""Greet someone."""
return f"Hello, {name}!"
@tool(approval_mode="never_require")
# we trick the AI into calling this function with 0 as denominator to trigger the exception
@tool(approval_mode="never_require")
def safe_divide(
a: Annotated[int, "Numerator"],
b: Annotated[int, "Denominator"],
@@ -4,7 +4,7 @@ import asyncio
from random import randrange
from typing import TYPE_CHECKING, Annotated, Any
from agent_framework import AgentResponse, ChatAgent, ChatMessage, ai_function
from agent_framework import AgentResponse, ChatAgent, ChatMessage, tool
from agent_framework.openai import OpenAIResponsesClient
if TYPE_CHECKING:
@@ -20,7 +20,8 @@ It shows how to handle function call approvals without using threads.
conditions = ["sunny", "cloudy", "raining", "snowing", "clear"]
@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_weather(location: Annotated[str, "The city and state, e.g. San Francisco, CA"]) -> str:
"""Get the current weather for a given location."""
# Simulate weather data
@@ -28,7 +29,7 @@ def get_weather(location: Annotated[str, "The city and state, e.g. San Francisco
# Define a simple weather tool that requires approval
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def get_weather_detail(location: Annotated[str, "The city and state, e.g. San Francisco, CA"]) -> str:
"""Get the current weather for a given location."""
# Simulate weather data
@@ -3,7 +3,7 @@
import asyncio
from typing import Annotated
from agent_framework import ChatAgent, ChatMessage, ai_function
from agent_framework import ChatAgent, ChatMessage, tool
from agent_framework.azure import AzureOpenAIChatClient
"""
@@ -15,7 +15,7 @@ the thread stores and retrieves them automatically.
"""
@ai_function(approval_mode="always_require")
@tool(approval_mode="always_require")
def add_to_calendar(
event_name: Annotated[str, "Name of the event"], date: Annotated[str, "Date of the event"]
) -> str:
@@ -3,7 +3,7 @@
import asyncio
from typing import Annotated, Any
from agent_framework import ai_function
from agent_framework import tool
from agent_framework.openai import OpenAIResponsesClient
from pydantic import Field
@@ -20,7 +20,8 @@ or provide.
# Define the function tool with **kwargs to accept injected arguments
@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_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
**kwargs: Any,
@@ -3,7 +3,7 @@
import asyncio
from typing import Annotated
from agent_framework import FunctionCallContent, FunctionResultContent, ai_function
from agent_framework import FunctionCallContent, FunctionResultContent, tool
from agent_framework.openai import OpenAIResponsesClient
"""
@@ -14,7 +14,7 @@ limited number of times.
# we trick the AI into calling this function with 0 as denominator to trigger the exception
@ai_function(max_invocation_exceptions=1)
@tool(max_invocation_exceptions=1)
def safe_divide(
a: Annotated[int, "Numerator"],
b: Annotated[int, "Denominator"],

Some files were not shown because too many files have changed in this diff Show More