#!/usr/bin/dotnet run #:package Microsoft.Extensions.AI@10.* #:package Microsoft.Agents.AI.OpenAI@1.*-* #:package Azure.AI.OpenAI@2.1.0 #:package Azure.Identity@1.13.1 using System.ComponentModel; using System.Text.Json; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; using Azure.AI.OpenAI; using Azure.Identity; // ============================================================================ // TOOL USE DESIGN PATTERN DEMONSTRATION // ============================================================================ // This sample demonstrates the key concepts from the Tool Use lesson: // 1. FUNCTION SCHEMAS: Clear descriptions and typed parameters // 2. MULTIPLE TOOLS: Agent selects the right tool for each task // 3. TOOL COMPOSITION: Tools can work together to solve complex requests // 4. PARAMETER HANDLING: Functions with different parameter types // ============================================================================ // ---------------------------------------------------------------------------- // TOOL 1: Random Destination Generator (No Parameters) // ---------------------------------------------------------------------------- // Demonstrates: Simple tool with no parameters [Description("Provides a random vacation destination when the user hasn't specified one.")] static string GetRandomDestination() { var destinations = new List { "Paris, France", "Tokyo, Japan", "New York City, USA", "Sydney, Australia", "Rome, Italy", "Barcelona, Spain", "Cape Town, South Africa", "Rio de Janeiro, Brazil", "Bangkok, Thailand", "Vancouver, Canada" }; var random = new Random(); int index = random.Next(destinations.Count); Console.WriteLine($"\n[Tool Called] GetRandomDestination() -> {destinations[index]}"); return destinations[index]; } // ---------------------------------------------------------------------------- // TOOL 2: Weather Lookup (Single Parameter) // ---------------------------------------------------------------------------- // Demonstrates: Tool with a required parameter - the LLM must extract // the location from the user's message and pass it to this function [Description("Gets the current weather conditions for a specified location. Use this when planning activities or packing suggestions.")] static string GetWeather( [Description("The city and country to get weather for, e.g., 'Paris, France'")] string location) { // Simulated weather data for demonstration var weatherConditions = new Dictionary { { "paris", ("Partly Cloudy", 18, 64) }, { "tokyo", ("Sunny", 24, 75) }, { "new york", ("Rainy", 15, 59) }, { "sydney", ("Sunny", 28, 82) }, { "rome", ("Clear", 22, 72) }, { "barcelona", ("Sunny", 26, 79) }, { "cape town", ("Windy", 19, 66) }, { "rio", ("Hot and Humid", 32, 90) }, { "bangkok", ("Tropical", 33, 91) }, { "vancouver", ("Overcast", 12, 54) } }; var locationLower = location.ToLower(); foreach (var (key, weather) in weatherConditions) { if (locationLower.Contains(key)) { var result = $"Weather in {location}: {weather.condition}, {weather.tempC}°C ({weather.tempF}°F)"; Console.WriteLine($"\n[Tool Called] GetWeather(\"{location}\") -> {result}"); return result; } } var defaultResult = $"Weather in {location}: Mild conditions, around 20°C (68°F)"; Console.WriteLine($"\n[Tool Called] GetWeather(\"{location}\") -> {defaultResult}"); return defaultResult; } // ---------------------------------------------------------------------------- // TOOL 3: Destination Information (Multiple Parameters) // ---------------------------------------------------------------------------- // Demonstrates: Tool with multiple parameters including an enum-like category [Description("Gets detailed information about a destination including attractions, cuisine, and travel tips. Use this after selecting a destination to provide rich details.")] static string GetDestinationInfo( [Description("The destination city to get information about")] string destination, [Description("The category of information: 'attractions', 'cuisine', 'tips', or 'all'")] string category = "all") { Console.WriteLine($"\n[Tool Called] GetDestinationInfo(\"{destination}\", \"{category}\")"); // Simulated destination data var info = new Dictionary> { { "paris", new() { { "attractions", "Eiffel Tower, Louvre Museum, Notre-Dame, Champs-Élysées" }, { "cuisine", "Croissants, French onion soup, Coq au vin, Macarons" }, { "tips", "Metro is efficient, book museums in advance, tip 10-15%" } }}, { "tokyo", new() { { "attractions", "Senso-ji Temple, Shibuya Crossing, Tokyo Tower, Akihabara" }, { "cuisine", "Sushi, Ramen, Tempura, Wagyu beef" }, { "tips", "Get a Suica card, bow when greeting, shoes off indoors" } }}, { "rome", new() { { "attractions", "Colosseum, Vatican, Trevi Fountain, Pantheon" }, { "cuisine", "Pasta Carbonara, Pizza al taglio, Gelato, Tiramisu" }, { "tips", "Book Vatican early, carry water bottle, siesta 1-4pm" } }} }; var destLower = destination.ToLower(); foreach (var (key, data) in info) { if (destLower.Contains(key)) { if (category.ToLower() == "all") { return JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true }); } if (data.TryGetValue(category.ToLower(), out var value)) { return $"{category} in {destination}: {value}"; } } } return $"Information about {destination}: A wonderful destination with rich culture and experiences."; } // ---------------------------------------------------------------------------- // TOOL 4: Trip Cost Estimator (Numeric Parameters) // ---------------------------------------------------------------------------- // Demonstrates: Tool with numeric parameters for calculations [Description("Estimates the total trip cost based on destination, duration, and budget level. Returns a cost breakdown.")] static string EstimateTripCost( [Description("The destination city")] string destination, [Description("Number of days for the trip")] int days, [Description("Budget level: 'budget', 'moderate', or 'luxury'")] string budgetLevel = "moderate") { Console.WriteLine($"\n[Tool Called] EstimateTripCost(\"{destination}\", {days}, \"{budgetLevel}\")"); var dailyRates = new Dictionary { { "budget", 100 }, { "moderate", 250 }, { "luxury", 500 } }; var rate = dailyRates.GetValueOrDefault(budgetLevel.ToLower(), 250); var accommodation = rate * days; var food = (rate / 2) * days; var activities = (rate / 3) * days; var total = accommodation + food + activities; return $""" Trip Cost Estimate for {destination} ({days} days, {budgetLevel}): - Accommodation: ${accommodation} - Food & Dining: ${food} - Activities: ${activities} - Estimated Total: ${total} """; } // Azure OpenAI with the Responses API (stable v1 endpoint). Sign in with `az login`. var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); var deployment = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini"; var azureClient = new AzureOpenAIClient(new Uri(azureEndpoint), new AzureCliCredential()); // Agent Identity var AGENT_NAME = "TravelAgent"; // ============================================================================ // AGENT INSTRUCTIONS - Tool Use Expert // ============================================================================ var AGENT_INSTRUCTIONS = """ You are a travel planning AI Agent with access to multiple specialized tools. ## Available Tools You have access to these tools - use them appropriately: 1. **GetRandomDestination**: Suggests a random destination (no parameters needed) 2. **GetWeather**: Gets weather for a location (requires: location) 3. **GetDestinationInfo**: Gets attraction/cuisine/tips (requires: destination, optional: category) 4. **EstimateTripCost**: Calculates costs (requires: destination, days; optional: budgetLevel) ## Tool Usage Guidelines - **Chain tools together** for comprehensive responses (e.g., destination → weather → info → cost) - **Extract parameters** from the user's message to pass to tools - **Choose the right tool** based on what the user is asking - When the user asks for a "complete trip plan", use multiple tools ## Response Format After using tools, synthesize the information into a helpful, well-organized response. Always mention which tools you used so users understand the agent's capabilities. """; // Create AI Agent with Multiple Tools // This demonstrates the Tool Use Design Pattern with a variety of tool types AIAgent agent = azureClient .GetOpenAIResponseClient(deployment) .CreateAIAgent( name: AGENT_NAME, instructions: AGENT_INSTRUCTIONS, tools: [ AIFunctionFactory.Create(GetRandomDestination), AIFunctionFactory.Create(GetWeather), AIFunctionFactory.Create(GetDestinationInfo), AIFunctionFactory.Create(EstimateTripCost) ] ); // Create Conversation Session AgentSession session = await agent.CreateSessionAsync(); // ============================================================================ // DEMONSTRATION 1: Tool Selection - Agent picks the right tool // ============================================================================ Console.WriteLine("=== Tool Use Design Pattern Demonstration ===\n"); Console.WriteLine("--- Demo 1: Tool Selection ---"); Console.WriteLine("User: What's the weather like in Tokyo?\n"); Console.WriteLine("Agent Response:"); await foreach (var update in agent.RunStreamingAsync("What's the weather like in Tokyo?", session)) { await Task.Delay(10); Console.Write(update); } Console.WriteLine("\n"); // ============================================================================ // DEMONSTRATION 2: Parameterized Tool Calling // ============================================================================ Console.WriteLine("--- Demo 2: Parameterized Tool with Multiple Parameters ---"); Console.WriteLine("User: How much would a 5-day luxury trip to Rome cost?\n"); Console.WriteLine("Agent Response:"); await foreach (var update in agent.RunStreamingAsync("How much would a 5-day luxury trip to Rome cost?", session)) { await Task.Delay(10); Console.Write(update); } Console.WriteLine("\n"); // ============================================================================ // DEMONSTRATION 3: Tool Composition - Multiple tools for complex requests // ============================================================================ Console.WriteLine("--- Demo 3: Tool Composition ---"); Console.WriteLine("User: Plan me a complete trip - suggest a destination and give me all the details including weather and costs for a 3-day moderate budget trip.\n"); Console.WriteLine("Agent Response:"); await foreach (var update in agent.RunStreamingAsync( "Plan me a complete trip - suggest a destination and give me all the details including weather and costs for a 3-day moderate budget trip.", session)) { await Task.Delay(10); Console.Write(update); }