Use this file to discover all available pages before exploring further.
Tools allow agents to extend their capabilities beyond text generation by calling functions, accessing databases, making API requests, or performing computations. The framework automatically handles function calling, parameter validation, and result formatting.
Use the @tool decorator to convert any function into a tool:
from agent_framework import toolfrom typing import Annotatedfrom pydantic import Field@tool(approval_mode="never_require") # Use "always_require" in production!def get_weather( location: Annotated[str, Field(description="The city name")], unit: Annotated[str, Field(description="Temperature unit")] = "celsius",) -> str: """Get the current weather for a location.""" # Simulate API call return f"The weather in {location} is sunny and 22°{unit[0].upper()}."
Key Points:
The docstring becomes the tool description shown to the model
Use Annotated[type, Field(description="...")] for parameter descriptions
Set approval_mode="always_require" in production to require user confirmation
Return type should be JSON-serializable or a string
Use attributes to define tool functions:
using System.ComponentModel;using Microsoft.Extensions.AI;[Description("Get the current weather for a location.")]static string GetWeather( [Description("The city name")] string location, [Description("Temperature unit (celsius/fahrenheit)")] string unit = "celsius"){ // Simulate API call return $"The weather in {location} is sunny and 22°{unit[0].ToString().ToUpper()}.";}// Register with agentvar agent = client.GetChatClient(deploymentName).AsAIAgent( name: "WeatherAgent", instructions: "You provide weather information.", tools: [AIFunctionFactory.Create(GetWeather)]);
Key Points:
The [Description] attribute documents the function and parameters
Use AIFunctionFactory.Create() to register functions as tools
Return type should be JSON-serializable or a string
from agent_framework.azure import AzureOpenAIResponsesClientagent = client.as_agent( name="WeatherAgent", instructions="You are a weather assistant. Use the get_weather tool to answer questions.", tools=get_weather, # Single tool)# Or multiple toolsagent = client.as_agent( name="Assistant", instructions="You are a helpful assistant.", tools=[get_weather, calculate_tip, search_web], # Multiple tools)# Use the agentresult = await agent.run("What's the weather in Seattle?")print(result.text)# Output: "The weather in Seattle is sunny and 22°C."
Register tools with the agent:
var agent = client.GetChatClient(deploymentName).AsAIAgent( name: "WeatherAgent", instructions: "You are a weather assistant.", tools: [ AIFunctionFactory.Create(GetWeather), AIFunctionFactory.Create(CalculateTip) ]);var result = await agent.RunAsync("What's the weather in Seattle?");Console.WriteLine(result.Messages.LastOrDefault()?.Text);
Require user approval before executing sensitive tools:
@tool(approval_mode="always_require")def send_email( to: Annotated[str, Field(description="Recipient email")], subject: Annotated[str, Field(description="Email subject")], body: Annotated[str, Field(description="Email body")],) -> str: """Send an email.""" # Send email return f"Email sent to {to}"agent = client.as_agent( name="EmailAgent", tools=send_email,)# When the model requests to call this tool, you'll get an approval requestasync for update in agent.run("Send an email to alice@example.com", stream=True): if update.approval_required: print(f"Tool call requires approval: {update.function_calls}") # Display to user and get approval approved = get_user_approval() if approved: # Continue with approved=True ...
Tool approval is managed through the function invocation flow:
// Mark tool as requiring approvalvar sendEmailTool = AIFunctionFactory.Create( SendEmail, name: "SendEmail", description: "Send an email (requires approval)");// Configure approval callbackvar options = new AgentRunOptions{ // Custom approval logic};
Create tools that agents can reason about without executing:
from agent_framework import FunctionTool# Tool declaration without implementationtime_tool = FunctionTool( name="get_current_time", description="Get the current time in ISO 8601 format.", func=None, # No implementation)# Agent can see and request the tool, but it won't execute# Useful for testing agent reasoning or client-side implementations
Declaration-only tools are less common in .NET but can be achieved by not providing an implementation:
// Typically, tools require implementations in .NET
import httpxfrom agent_framework import toolfrom agent_framework.azure import AzureOpenAIResponsesClientfrom typing import Annotatedfrom pydantic import Fieldimport os@tool(approval_mode="never_require")async def get_weather( location: Annotated[str, Field(description="City name")], unit: Annotated[str, Field(description="celsius or fahrenheit")] = "celsius",) -> str: """Get current weather for a location.""" api_key = os.environ["WEATHER_API_KEY"] async with httpx.AsyncClient() as client: response = await client.get( f"https://api.weather.com/current", params={"location": location, "unit": unit, "key": api_key}, ) data = response.json() return f"The weather in {location} is {data['condition']} with a temperature of {data['temp']}°{unit[0].upper()}."@tool(approval_mode="never_require")async def get_forecast( location: Annotated[str, Field(description="City name")], days: Annotated[int, Field(description="Number of days", ge=1, le=7)] = 3,) -> str: """Get weather forecast for a location.""" # Implementation ...async def main(): client = AzureOpenAIResponsesClient( project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], deployment_name=os.environ["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"], ) agent = client.as_agent( name="WeatherAgent", instructions="You are a weather assistant. Use the tools to provide accurate weather information.", tools=[get_weather, get_forecast], ) session = agent.create_session() # Multi-turn conversation questions = [ "What's the weather in Seattle?", "How about the 5-day forecast?", "Compare it to San Francisco", ] for question in questions: print(f"\nUser: {question}") result = await agent.run(question, session=session) print(f"Agent: {result.text}")
using System.ComponentModel;using Microsoft.Agents.AI;using Microsoft.Extensions.AI;[Description("Get current weather for a location.")]static async Task<string> GetWeather( [Description("City name")] string location, [Description("celsius or fahrenheit")] string unit = "celsius"){ var apiKey = Environment.GetEnvironmentVariable("WEATHER_API_KEY"); using var client = new HttpClient(); var response = await client.GetStringAsync( $"https://api.weather.com/current?location={location}&unit={unit}&key={apiKey}"); return response;}[Description("Get weather forecast for a location.")]static async Task<string> GetForecast( [Description("City name")] string location, [Description("Number of days (1-7)")] int days = 3){ // Implementation return "";}var agent = client.GetChatClient(deploymentName).AsAIAgent( name: "WeatherAgent", instructions: "You are a weather assistant.", tools: [ AIFunctionFactory.Create(GetWeather), AIFunctionFactory.Create(GetForecast) ]);var session = await agent.CreateSessionAsync();var questions = new[]{ "What's the weather in Seattle?", "How about the 5-day forecast?", "Compare it to San Francisco"};foreach (var question in questions){ Console.WriteLine($"\nUser: {question}"); var result = await agent.RunAsync(question, session); Console.WriteLine($"Agent: {result.Messages.LastOrDefault()?.Text}");}