From 09c17a37c61d5185f6304b1e37de062bd659ecae Mon Sep 17 00:00:00 2001 From: Jon Burchel Date: Wed, 21 Jan 2026 13:33:11 -0500 Subject: [PATCH 1/2] Fixes requirements.txt --- .../1-idea-to-prototype/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/requirements.txt b/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/requirements.txt index ece73277f..55aa9975a 100644 --- a/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/requirements.txt +++ b/samples/python/enterprise-agent-tutorial/1-idea-to-prototype/requirements.txt @@ -1,4 +1,4 @@ -azure-ai-projects>=2.0.0a20251015001 -azure-ai-agents>=2.0.0a20251015001 +azure-ai-projects==1.0.0 +azure-ai-agents==1.2.0b6 azure-identity python-dotenv \ No newline at end of file From da88093d9acdf977ed034b2adcff8b1af45fa29e Mon Sep 17 00:00:00 2001 From: Jon Burchel Date: Wed, 21 Jan 2026 15:33:53 -0500 Subject: [PATCH 2/2] Adds enterprise-agent-tutorial for csharp --- .../com/azure/ai/foundry/samples/README.md | 68 +++ .../ModernWorkplaceAssistant.csproj | 7 +- .../ModernWorkplaceAssistant/Program.cs | 499 +++++++++++++----- .../1-idea-to-prototype/README.md | 59 ++- 4 files changed, 479 insertions(+), 154 deletions(-) create mode 100644 samples-classic/java/quickstart/target/classes/com/azure/ai/foundry/samples/README.md diff --git a/samples-classic/java/quickstart/target/classes/com/azure/ai/foundry/samples/README.md b/samples-classic/java/quickstart/target/classes/com/azure/ai/foundry/samples/README.md new file mode 100644 index 000000000..b00109a64 --- /dev/null +++ b/samples-classic/java/quickstart/target/classes/com/azure/ai/foundry/samples/README.md @@ -0,0 +1,68 @@ +# Azure AI Foundry SDK Java Samples + +This directory contains Java sample code for Azure AI services using the Azure AI Inference SDK, Azure AI Agents Persistent SDK, Azure AI Projects SDK, and OpenAI Java SDK. + +## Key SDKs Used in These Samples + +### 1. Azure AI Agents Persistent SDK +- **Maven Dependency**: `com.azure:azure-ai-agents-persistent:1.0.0-beta.2` +- **Purpose**: Create, manage, and interact with persistent AI agents capable of maintaining state and performing complex tasks +- **Key Features**: + - Built-in conversation management and state tracking + - Document search and retrieval capabilities + - Agent evaluation and performance metrics + - Integration with Azure AI models and services + - Tool calling and function execution + +### 2. Azure AI Projects SDK +- **Maven Dependency**: `com.azure:azure-ai-projects:1.0.0-beta.2` +- **Purpose**: Manage and interact with Azure AI Projects and their deployments +- **Key Features**: + - List and manage project deployments + - Access deployment information (model type, configuration) + - Retrieve connection details for different AI resources + - Unified interface for Azure AI Studio projects + +### 3. Azure AI Inference SDK +- **Maven Dependency**: `com.azure:azure-ai-inference:1.0.0-beta.5` +- **Purpose**: Direct interaction with Azure-hosted AI models +- **Key Features**: + - Synchronous and streaming completions + - Support for multiple model providers + - Consistent API across different model types + +### 4. OpenAI Java SDK +- **Maven Dependency**: `com.openai:openai-java:2.7.0` +- **Purpose**: Direct integration with OpenAI platform models (not Azure-hosted) + +## Available Samples + +### Azure AI Inference SDK Samples +1. **ChatCompletionSample** - Shows how to use the Azure AI Inference SDK for synchronous chat completions with any Azure AI model +2. **ChatCompletionStreamingSample** - Demonstrates streaming chat completions using Azure AI Inference SDK for a more responsive user experience + +### OpenAI SDK Samples +3. **ChatCompletionSampleOpenAI** - Shows how to use the official OpenAI Java SDK for chat completions with OpenAI models +4. **ChatCompletionStreamingSampleOpenAI** - Demonstrates streaming chat completions using the OpenAI Java SDK + +### Azure AI Agents Persistent SDK Samples +5. **AgentSample** - Shows how to create and run a persistent agent using the Azure AI Agents SDK +6. **FileSearchAgentSample** - Demonstrates adding file search capabilities to an agent for document-based Q&A +7. **EvaluateAgentSample** - Shows how to evaluate agent performance with different metrics + +### Azure AI Projects SDK Samples +8. **CreateProject** - Demonstrates connecting to an Azure AI Project and listing available model deployments + +## Running the Samples + +See the main [README.md](../../README.md) file for instructions on how to set up and run these samples. + +For detailed testing procedures, including automated testing scripts, SDK features overview, and troubleshooting guidance for first-time users, refer to [TESTING.md](../../TESTING.md). + +### Testing Scripts + +We've provided automated testing scripts that can help you quickly validate your environment and run samples: +- **Windows**: Use `testing.bat [SampleClassName]` from the project root +- **Linux/macOS**: Use `./testing.sh [SampleClassName]` from the project root + +These scripts provide SDK version information, environment validation, and clearly formatted output. diff --git a/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/ModernWorkplaceAssistant.csproj b/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/ModernWorkplaceAssistant.csproj index 6077edd6e..6b8962598 100644 --- a/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/ModernWorkplaceAssistant.csproj +++ b/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/ModernWorkplaceAssistant.csproj @@ -8,13 +8,10 @@ - + + - - - - diff --git a/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/Program.cs b/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/Program.cs index 1a02b74fe..9380939d8 100644 --- a/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/Program.cs +++ b/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/ModernWorkplaceAssistant/Program.cs @@ -1,67 +1,71 @@ -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates - // using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; using System.Threading.Tasks; -using Azure; -using Azure.AI.Agents; -using Azure.Core; +using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Identity; using DotNetEnv; -using OpenAI; -using OpenAI.Responses; // /* - * Azure AI Foundry Agent Sample - Tutorial 1: Modern Workplace Assistant + * Azure AI Foundry Agent Sample - Tutorial 1: Modern Workplace Assistant (C#) * - * This sample demonstrates a complete business scenario using Azure AI Agents SDK v2: - * - Agent creation with the new SDK - * - Conversation and response management + * This sample demonstrates a complete business scenario using Azure AI Agents SDK: + * - Agent creation with SharePoint and MCP tools + * - Thread and message management + * - MCP tool approval handling * - Robust error handling and graceful degradation * * Educational Focus: - * - Enterprise AI patterns with Agent SDK v2 + * - Enterprise AI patterns with Azure AI Agents SDK * - Real-world business scenarios that enterprises face daily * - Production-ready error handling and diagnostics * - Foundation for governance, evaluation, and monitoring (Tutorials 2-3) * * Business Scenario: * An employee needs to implement Azure AD multi-factor authentication. They need: - * 1. Company security policy requirements - * 2. Technical implementation steps + * 1. Company security policy requirements (from SharePoint) + * 2. Technical implementation steps (from Microsoft Learn via MCP) * 3. Combined guidance showing how policy requirements map to technical implementation */ class Program { - private static AgentsClient? agentsClient; - private static OpenAIResponseClient? responseClient; - private static AgentConversation? conversation; + private static AIProjectClient? projectClient; + private static PersistentAgentsClient? agentsClient; + private static string? mcpServerLabel; static async Task Main(string[] args) { Console.WriteLine("๐Ÿš€ Azure AI Foundry - Modern Workplace Assistant"); - Console.WriteLine("Tutorial 1: Building Enterprise Agents with Agent SDK v2"); + Console.WriteLine("Tutorial 1: Building Enterprise Agents with SharePoint + MCP Tools"); Console.WriteLine("".PadRight(70, '=')); try { // Create the agent with full diagnostic output - string agentName = await CreateWorkplaceAssistantAsync(); + var agent = await CreateWorkplaceAssistantAsync(); // Demonstrate business scenarios - await DemonstrateBusinessScenariosAsync(agentName); + await DemonstrateBusinessScenariosAsync(agent); // Offer interactive testing Console.Write("\n๐ŸŽฏ Try interactive mode? (y/n): "); var response = Console.ReadLine(); if (response?.ToLower().StartsWith("y") == true) { - await InteractiveModeAsync(agentName); + await InteractiveModeAsync(agent); } + // Cleanup + Console.WriteLine("\n๐Ÿงน Cleaning up agent..."); + await agentsClient!.Administration.DeleteAgentAsync(agent.Id); + Console.WriteLine("โœ… Agent deleted"); + Console.WriteLine("\n๐ŸŽ‰ Sample completed successfully!"); Console.WriteLine("๐Ÿ“š This foundation supports Tutorial 2 (Governance) and Tutorial 3 (Production)"); Console.WriteLine("๐Ÿ”— Next: Add evaluation metrics, monitoring, and production deployment"); @@ -78,29 +82,39 @@ static async Task Main(string[] args) } /// - /// Create a Modern Workplace Assistant using Agent SDK v2. + /// Create a Modern Workplace Assistant with SharePoint and MCP tools. /// /// This demonstrates enterprise AI patterns: - /// 1. Agent creation with the new SDK - /// 2. Robust error handling with graceful degradation - /// 3. Clear diagnostic information for troubleshooting + /// 1. Agent creation with the SDK + /// 2. SharePoint integration for company documents + /// 3. MCP integration for Microsoft Learn documentation + /// 4. Robust error handling with graceful degradation + /// 5. Dynamic agent capabilities based on available resources /// /// Educational Value: /// - Shows real-world complexity of enterprise AI systems /// - Demonstrates how to handle partial system failures - /// - Provides patterns for agent creation with Agent SDK v2 - /// - /// Note: Tool integration (SharePoint, MCP) is being explored for SDK v2 beta. - /// This version demonstrates the core agent functionality. + /// - Provides patterns for agent creation with multiple tools /// - private static async Task CreateWorkplaceAssistantAsync() + private static async Task CreateWorkplaceAssistantAsync() { - // Load environment variables - Env.Load(".env"); + // Load environment variables from shared .env file + var envPath = Path.Combine(Directory.GetCurrentDirectory(), "..", "shared", ".env"); + if (File.Exists(envPath)) + { + Env.Load(envPath); + Console.WriteLine($"๐Ÿ“„ Loaded environment from: {envPath}"); + } + else + { + // Fallback to local .env + Env.Load(".env"); + } var projectEndpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT"); var modelDeploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME"); - var tenantId = Environment.GetEnvironmentVariable("AI_FOUNDRY_TENANT_ID"); + var sharePointResourceName = Environment.GetEnvironmentVariable("SHAREPOINT_RESOURCE_NAME"); + var mcpServerUrl = Environment.GetEnvironmentVariable("MCP_SERVER_URL"); if (string.IsNullOrEmpty(projectEndpoint)) throw new InvalidOperationException("PROJECT_ENDPOINT environment variable not set"); @@ -113,110 +127,251 @@ private static async Task CreateWorkplaceAssistantAsync() // AUTHENTICATION SETUP // ============================================================================ // - TokenCredential credential; - if (!string.IsNullOrEmpty(tenantId)) + var credential = new DefaultAzureCredential(); + + projectClient = new AIProjectClient(new Uri(projectEndpoint), credential); + agentsClient = projectClient.GetPersistentAgentsClient(); + Console.WriteLine($"โœ… Connected to Azure AI Foundry: {projectEndpoint}"); + // + + // ======================================================================== + // SHAREPOINT INTEGRATION SETUP + // ======================================================================== + // + SharepointToolDefinition? sharepointTool = null; + + // Support either connection name or full ARM ID + // Full ARM ID format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.MachineLearningServices/workspaces/{workspace}/connections/{name} + var sharePointConnectionId = Environment.GetEnvironmentVariable("SHAREPOINT_CONNECTION_ID"); + + if (!string.IsNullOrEmpty(sharePointResourceName) || !string.IsNullOrEmpty(sharePointConnectionId)) { - Console.WriteLine($"๐Ÿ” Using AI Foundry tenant: {tenantId}"); - credential = new AzureCliCredential(new AzureCliCredentialOptions { TenantId = tenantId }); + Console.WriteLine($"๐Ÿ“ Configuring SharePoint integration..."); + + try + { + string? connectionId = sharePointConnectionId; + + // If only a connection name is provided, user needs to provide the full ARM ID + if (string.IsNullOrEmpty(connectionId)) + { + Console.WriteLine($" Connection name: {sharePointResourceName}"); + Console.WriteLine($" โš ๏ธ Note: SharePoint tool requires the full ARM resource ID"); + Console.WriteLine($" ๐Ÿ’ก Set SHAREPOINT_CONNECTION_ID to the full ARM resource ID"); + Console.WriteLine($" ๐Ÿ“‹ Format: /subscriptions/{{sub}}/resourceGroups/{{rg}}/providers/Microsoft.MachineLearningServices/workspaces/{{workspace}}/connections/{{name}}"); + throw new InvalidOperationException($"Set SHAREPOINT_CONNECTION_ID to the full ARM resource ID for connection '{sharePointResourceName}'"); + } + + Console.WriteLine($" Using connection ID: {connectionId}"); + + // + // Create SharePoint tool with the full ARM resource ID + sharepointTool = new SharepointToolDefinition( + new SharepointGroundingToolParameters(connectionId) + ); + Console.WriteLine($"โœ… SharePoint tool configured successfully"); + // + } + catch (InvalidOperationException ex) + { + Console.WriteLine($"โš ๏ธ {ex.Message}"); + Console.WriteLine($" Available connections can be viewed in Azure AI Foundry portal"); + Console.WriteLine($" Agent will operate without SharePoint access"); + } + catch (Exception ex) + { + Console.WriteLine($"โš ๏ธ SharePoint connection unavailable: {ex.Message}"); + Console.WriteLine($" Possible causes:"); + Console.WriteLine($" - Connection '{sharePointResourceName}' doesn't exist in the project"); + Console.WriteLine($" - Insufficient permissions to access the connection"); + Console.WriteLine($" - Connection configuration is incomplete"); + Console.WriteLine($" Agent will operate without SharePoint access"); + } } else { - credential = new DefaultAzureCredential(); + Console.WriteLine($"๐Ÿ“ SharePoint integration skipped (SHAREPOINT_RESOURCE_NAME not set)"); } - - agentsClient = new AgentsClient(new Uri(projectEndpoint), credential); - Console.WriteLine($"โœ… Connected to Azure AI Foundry: {projectEndpoint}"); - // + // // ======================================================================== - // AGENT CREATION + // MICROSOFT LEARN MCP INTEGRATION SETUP // ======================================================================== - string instructions = @"You are a Technical Assistant specializing in Azure and Microsoft 365 guidance. + // + // MCP (Model Context Protocol) enables agents to access external data sources + // like Microsoft Learn documentation. The approval flow is handled in ChatWithAssistantAsync. + MCPToolDefinition? mcpTool = null; + mcpServerLabel = "Microsoft_Learn_Documentation"; -CAPABILITIES: -- Provide detailed Azure and Microsoft 365 technical guidance -- Explain implementation steps and best practices -- Help with Azure AD, Conditional Access, MFA, and security configurations + if (!string.IsNullOrEmpty(mcpServerUrl)) + { + Console.WriteLine($"๐Ÿ“š Configuring Microsoft Learn MCP integration..."); + Console.WriteLine($" Server URL: {mcpServerUrl}"); -RESPONSE STRATEGY: -- Provide comprehensive technical guidance -- Include step-by-step implementation instructions -- Reference best practices and security considerations -- For policy questions, explain common enterprise policies and how to implement them -- For technical questions, provide detailed Azure/M365 implementation steps + try + { + // Create MCP tool for Microsoft Learn documentation access + // server_label must match pattern: ^[a-zA-Z0-9_]+$ (alphanumeric and underscores only) + mcpTool = new MCPToolDefinition(mcpServerLabel, mcpServerUrl); + Console.WriteLine($"โœ… MCP tool configured successfully"); + } + catch (Exception ex) + { + Console.WriteLine($"โš ๏ธ MCP tool unavailable: {ex.Message}"); + Console.WriteLine($" Agent will operate without Microsoft Learn access"); + } + } + else + { + Console.WriteLine($"๐Ÿ“š MCP integration skipped (MCP_SERVER_URL not set)"); + } + // -EXAMPLE SCENARIOS: -- ""What is a typical enterprise MFA policy?"" โ†’ Explain common MFA policies and their implementation -- ""How do I configure Azure AD Conditional Access?"" โ†’ Provide detailed technical steps -- ""What are the best practices for remote work security?"" โ†’ Combine policy recommendations with implementation guidance"; + // ======================================================================== + // AGENT CREATION WITH DYNAMIC CAPABILITIES + // ======================================================================== + // Create agent instructions based on available data sources + string instructions = GetAgentInstructions(sharepointTool != null, mcpTool != null); - // + // + // Create the agent using the SDK with available tools Console.WriteLine($"๐Ÿ› ๏ธ Creating agent with model: {modelDeploymentName}"); - AgentDefinition agentDefinition = new PromptAgentDefinition(modelDeploymentName) + // Build tools list + var tools = new List(); + + if (sharepointTool != null) { - Instructions = instructions - }; + tools.Add(sharepointTool); + Console.WriteLine($" โœ“ SharePoint tool added"); + } + + if (mcpTool != null) + { + tools.Add(mcpTool); + Console.WriteLine($" โœ“ MCP tool added"); + } - AgentVersion agent = await agentsClient.CreateAgentVersionAsync( - "Modern_Workplace_Assistant", - agentDefinition + Console.WriteLine($" Total tools: {tools.Count}"); + + // Create agent with or without tools + PersistentAgent agent = await agentsClient.Administration.CreateAgentAsync( + model: modelDeploymentName, + name: "Modern_Workplace_Assistant", + instructions: instructions, + tools: tools.Count > 0 ? tools : null ); - Console.WriteLine("โœ… Agent created successfully"); - Console.WriteLine($" Agent Name: {agent.Name}"); - Console.WriteLine($" Agent Version: {agent.Version}"); + Console.WriteLine($"โœ… Agent created successfully: {agent.Id}"); + return agent; + // + } + + /// + /// Generate agent instructions based on available tools. + /// + private static string GetAgentInstructions(bool hasSharePoint, bool hasMcp) + { + if (hasSharePoint && hasMcp) + { + return @"You are a Modern Workplace Assistant for Contoso Corporation. - Console.WriteLine("\nโš ๏ธ Note: SDK v2 beta status:"); - Console.WriteLine(" - Core agent conversation functionality working"); - Console.WriteLine(" - Tool integration patterns being finalized"); - // +CAPABILITIES: +- Search SharePoint for company policies, procedures, and internal documentation +- Access Microsoft Learn for current Azure and Microsoft 365 technical guidance +- Provide comprehensive solutions combining internal requirements with external implementation + +RESPONSE STRATEGY: +- For policy questions: Search SharePoint for company-specific requirements and guidelines +- For technical questions: Use Microsoft Learn for current Azure/M365 documentation and best practices +- For implementation questions: Combine both sources to show how company policies map to technical implementation +- Always cite your sources and provide step-by-step guidance +- Explain how internal requirements connect to external implementation steps - // Initialize OpenAI client for conversations - OpenAIClient openAIClient = agentsClient.GetOpenAIClient(); - responseClient = openAIClient.GetOpenAIResponseClient(modelDeploymentName); +EXAMPLE SCENARIOS: +- ""What is our MFA policy?"" โ†’ Search SharePoint for security policies +- ""How do I configure Azure AD Conditional Access?"" โ†’ Use Microsoft Learn for technical steps +- ""Our policy requires MFA - how do I implement this?"" โ†’ Combine policy requirements with implementation guidance"; + } + else if (hasSharePoint) + { + return @"You are a Modern Workplace Assistant with access to Contoso Corporation's SharePoint. + +CAPABILITIES: +- Search SharePoint for company policies, procedures, and internal documentation +- Provide detailed technical guidance based on your knowledge +- Combine company policies with general best practices + +RESPONSE STRATEGY: +- Search SharePoint for company-specific requirements +- Provide technical guidance based on Azure and M365 best practices +- Explain how to align implementations with company policies"; + } + else if (hasMcp) + { + return @"You are a Technical Assistant with access to Microsoft Learn documentation. + +CAPABILITIES: +- Access Microsoft Learn for current Azure and Microsoft 365 technical guidance +- Provide detailed implementation steps and best practices +- Explain Azure services, features, and configuration options + +RESPONSE STRATEGY: +- Use Microsoft Learn for technical documentation +- Provide comprehensive implementation guidance +- Reference official documentation and best practices"; + } + else + { + return @"You are a Technical Assistant specializing in Azure and Microsoft 365 guidance. - // Create a conversation to maintain state - conversation = await agentsClient.GetConversationsClient().CreateConversationAsync(); +CAPABILITIES: +- Provide detailed Azure and Microsoft 365 technical guidance +- Explain implementation steps and best practices +- Help with Azure AD, Conditional Access, MFA, and security configurations - return agent.Name; +RESPONSE STRATEGY: +- Provide comprehensive technical guidance +- Include step-by-step implementation instructions +- Reference best practices and security considerations"; + } } /// - /// Demonstrate realistic business scenarios with Agent SDK v2. + /// Demonstrate realistic business scenarios. /// /// This function showcases the practical value of the Modern Workplace Assistant /// by walking through scenarios that enterprise employees face regularly. /// /// Educational Value: /// - Shows real business problems that AI agents can solve - /// - Demonstrates proper conversation and response management - /// - Illustrates Agent SDK v2 conversation patterns + /// - Demonstrates proper thread and message management + /// - Illustrates conversation patterns with tool usage /// - private static async Task DemonstrateBusinessScenariosAsync(string agentName) + private static async Task DemonstrateBusinessScenariosAsync(PersistentAgent agent) { var scenarios = new[] { new { - Title = "๐Ÿ“‹ Enterprise Policy Question", - Question = "What is a typical enterprise remote work policy for security?", - Context = "Employee needs to understand common enterprise remote work requirements", - LearningPoint = "Agent provides general guidance on enterprise policies" + Title = "๐Ÿ“‹ Company Policy Question (SharePoint Only)", + Question = "What is Contoso's remote work policy?", + Context = "Employee needs to understand company-specific remote work requirements", + LearningPoint = "SharePoint tool retrieves internal company policies" }, new { - Title = "๐Ÿ“š Technical Documentation Question", - Question = "What is the correct way to implement Azure AD Conditional Access policies?", - Context = "IT administrator needs technical implementation guidance", - LearningPoint = "Agent provides detailed Azure technical implementation steps" + Title = "๐Ÿ“š Technical Documentation Question (MCP Only)", + Question = "According to Microsoft Learn, what is the correct way to implement Azure AD Conditional Access policies? Please include reference links to the official documentation.", + Context = "IT administrator needs authoritative Microsoft technical guidance", + LearningPoint = "MCP tool accesses Microsoft Learn for official documentation with links" }, new { - Title = "๐Ÿ”„ Combined Implementation Question", - Question = "How should I configure my Azure environment for secure remote work with MFA?", - Context = "Need practical implementation combining security best practices", - LearningPoint = "Agent combines policy guidance with technical implementation" + Title = "๐Ÿ”„ Combined Implementation Question (SharePoint + MCP)", + Question = "Based on our company's remote work security policy, how should I configure my Azure environment to comply? Please include links to Microsoft documentation showing how to implement each requirement.", + Context = "Need to map company policy to technical implementation with official guidance", + LearningPoint = "Both tools work together: SharePoint for policy + MCP for implementation docs" } }; @@ -224,7 +379,7 @@ private static async Task DemonstrateBusinessScenariosAsync(string agentName) Console.WriteLine("๐Ÿข MODERN WORKPLACE ASSISTANT - BUSINESS SCENARIO DEMONSTRATION"); Console.WriteLine("".PadRight(70, '=')); Console.WriteLine("This demonstration shows how AI agents solve real business problems"); - Console.WriteLine("using the Azure AI Agents SDK v2."); + Console.WriteLine("using the Azure AI Agents SDK with SharePoint and MCP tools."); Console.WriteLine("".PadRight(70, '=')); for (int i = 0; i < scenarios.Length; i++) @@ -239,15 +394,15 @@ private static async Task DemonstrateBusinessScenariosAsync(string agentName) // Console.WriteLine("๐Ÿค– ASSISTANT RESPONSE:"); - var (response, status) = await ChatWithAssistantAsync(agentName, scenario.Question); + var (response, status) = await ChatWithAssistantAsync(agent, scenario.Question); // // Display response with analysis if (status == "completed" && !string.IsNullOrWhiteSpace(response) && response.Length > 10) { - var preview = response.Length > 300 ? response.Substring(0, 300) + "..." : response; + var preview = response.Length > 500 ? response.Substring(0, 500) + "..." : response; Console.WriteLine($"โœ… SUCCESS: {preview}"); - if (response.Length > 300) + if (response.Length > 500) { Console.WriteLine($" ๐Ÿ“ Full response: {response.Length} characters"); } @@ -266,43 +421,144 @@ private static async Task DemonstrateBusinessScenariosAsync(string agentName) Console.WriteLine("\nโœ… DEMONSTRATION COMPLETED!"); Console.WriteLine("๐ŸŽ“ Key Learning Outcomes:"); - Console.WriteLine(" โ€ข Agent SDK v2 usage for enterprise AI"); - Console.WriteLine(" โ€ข Proper conversation and response management"); + Console.WriteLine(" โ€ข Azure AI Agents SDK usage for enterprise AI"); + Console.WriteLine(" โ€ข Proper thread and message management"); + Console.WriteLine(" โ€ข SharePoint + MCP tool integration"); + Console.WriteLine(" โ€ข MCP tool approval handling"); Console.WriteLine(" โ€ข Real business value through AI assistance"); Console.WriteLine(" โ€ข Foundation for governance and monitoring (Tutorials 2-3)"); } /// - /// Execute a conversation with the workplace assistant using Agent SDK v2. + /// Execute a conversation with the workplace assistant. /// - /// This function demonstrates the conversation pattern for Azure AI Agents SDK v2. + /// This function demonstrates the conversation pattern including: + /// - Thread creation and message handling + /// - MCP tool approval handling (auto-approve pattern) + /// - Proper run status monitoring /// /// Educational Value: - /// - Shows proper conversation management with Agent SDK v2 - /// - Demonstrates conversation creation and message handling - /// - Includes error management patterns + /// - Shows proper conversation management + /// - Demonstrates MCP approval with SubmitToolApprovalAction + /// - Includes timeout and error management patterns /// - private static async Task<(string response, string status)> ChatWithAssistantAsync(string agentName, string message) + // + private static async Task<(string response, string status)> ChatWithAssistantAsync(PersistentAgent agent, string message) { try { - // - // Set up response creation options with agent and conversation references - ResponseCreationOptions responseCreationOptions = new(); - responseCreationOptions.SetAgentReference(agentName); - responseCreationOptions.SetConversationReference(conversation!); + // Create a thread for the conversation + PersistentAgentThread thread = await agentsClient!.Threads.CreateThreadAsync(); + + // Create a message in the thread + await agentsClient.Messages.CreateMessageAsync( + thread.Id, + MessageRole.User, + message + ); + + // Setup MCP tool resources if MCP is configured + ToolResources? toolResources = null; + if (!string.IsNullOrEmpty(mcpServerLabel)) + { + MCPToolResource mcpToolResource = new(mcpServerLabel); + toolResources = mcpToolResource.ToToolResources(); + } - // Create the user message item - List items = [ResponseItem.CreateUserMessageItem(message)]; + // Create and run the agent + ThreadRun run = await agentsClient.Runs.CreateRunAsync( + thread, + agent, + toolResources + ); + + // + // Handle run execution and MCP tool approvals + // This loop polls the run status and automatically approves MCP tool calls + int maxIterations = 60; // 30 second timeout + int iteration = 0; + + while ((run.Status == RunStatus.Queued || + run.Status == RunStatus.InProgress || + run.Status == RunStatus.RequiresAction) && + iteration < maxIterations) + { + await Task.Delay(500); + run = await agentsClient.Runs.GetRunAsync(thread.Id, run.Id); + iteration++; - // Create response from the agent - OpenAIResponse response = await responseClient!.CreateResponseAsync(items, responseCreationOptions); + // Handle MCP tool approval requests + if (run.Status == RunStatus.RequiresAction && + run.RequiredAction is SubmitToolApprovalAction toolApprovalAction) + { + var toolApprovals = new List(); + + foreach (var toolCall in toolApprovalAction.SubmitToolApproval.ToolCalls) + { + if (toolCall is RequiredMcpToolCall mcpToolCall) + { + Console.WriteLine($" ๐Ÿ”ง Approving MCP tool: {mcpToolCall.Name}"); + + // Auto-approve MCP tool calls + // In production, you might implement custom approval logic here: + // - RBAC checks (is user authorized for this tool?) + // - Cost controls (has budget limit been reached?) + // - Logging and auditing + // - Interactive approval prompts + toolApprovals.Add(new ToolApproval(mcpToolCall.Id, approve: true)); + } + } + + if (toolApprovals.Count > 0) + { + run = await agentsClient.Runs.SubmitToolOutputsToRunAsync( + thread.Id, + run.Id, + toolApprovals: toolApprovals + ); + } + } + } + // - // Extract the response text - string responseText = response.GetOutputText(); - // + // Retrieve messages if completed + if (run.Status == RunStatus.Completed) + { + var messages = agentsClient.Messages.GetMessages( + thread.Id, + order: ListSortOrder.Descending + ); + + // Get the assistant's response (most recent agent message) + foreach (PersistentThreadMessage threadMessage in messages) + { + if (threadMessage.Role == MessageRole.Agent) + { + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + // Cleanup thread + await agentsClient.Threads.DeleteThreadAsync(thread.Id); + return (textItem.Text, "completed"); + } + } + } + } - return (responseText, "completed"); + await agentsClient.Threads.DeleteThreadAsync(thread.Id); + return ("No response from assistant", "completed"); + } + else if (run.Status == RunStatus.Failed) + { + await agentsClient.Threads.DeleteThreadAsync(thread.Id); + return ($"Run failed: {run.LastError?.Message ?? "Unknown error"}", "failed"); + } + else + { + await agentsClient.Threads.DeleteThreadAsync(thread.Id); + return ($"Run ended with status: {run.Status}", run.Status.ToString().ToLower()); + } } catch (Exception ex) { @@ -314,6 +570,7 @@ private static async Task DemonstrateBusinessScenariosAsync(string agentName) return ($"Error in conversation: {ex.Message}", "failed"); } } + // /// /// Interactive mode for testing the workplace assistant. @@ -321,7 +578,7 @@ private static async Task DemonstrateBusinessScenariosAsync(string agentName) /// This provides a simple interface for users to test the agent with their own questions /// and see how it provides comprehensive technical guidance. /// - private static async Task InteractiveModeAsync(string agentName) + private static async Task InteractiveModeAsync(PersistentAgent agent) { Console.WriteLine("\n" + "".PadRight(60, '=')); Console.WriteLine("๐Ÿ’ฌ INTERACTIVE MODE - Test Your Workplace Assistant!"); @@ -352,7 +609,7 @@ private static async Task InteractiveModeAsync(string agentName) } Console.Write("\n๐Ÿค– Workplace Assistant: "); - var (response, status) = await ChatWithAssistantAsync(agentName, question); + var (response, status) = await ChatWithAssistantAsync(agent, question); Console.WriteLine(response); if (status != "completed") diff --git a/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/README.md b/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/README.md index 6adc88936..818541564 100644 --- a/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/README.md +++ b/samples/csharp/enterprise-agent-tutorial/1-idea-to-prototype/README.md @@ -1,11 +1,10 @@ # Enterprise Agent Tutorial - Stage 1: Idea to Prototype (C#) -> **SDK v2.0 Update:** This sample has been updated to use Azure AI Agents SDK version 2.0.0-alpha.20251016.2. Key changes: -> - Package: `Azure.AI.Agents.Persistent` โ†’ `Azure.AI.Agents` + `OpenAI` -> - Client: `PersistentAgentsClient` โ†’ `AgentsClient` -> - Agent creation: `CreateAgentAsync()` โ†’ `CreateAgentVersionAsync()` with `PromptAgentDefinition` -> - Conversation: Thread/Run pattern โ†’ OpenAI Client with `ResponseCreationOptions` -> - Agent references: Use `agent.Name` instead of `agent.Id` +> **Full Feature Parity with Python Sample:** This C# implementation now uses Azure.AI.Agents.Persistent SDK with complete support for SharePoint and MCP (Model Context Protocol) tools, matching the Python sample functionality. +> - Packages: `Azure.AI.Projects` (1.0.0-beta.9) + `Azure.AI.Agents.Persistent` (1.2.0-beta.8) +> - Client: `PersistentAgentsClient` from `AIProjectClient.GetPersistentAgentsClient()` +> - Tools: `SharepointToolDefinition` + `MCPToolDefinition` +> - MCP Approvals: `SubmitToolApprovalAction` + `ToolApproval` pattern This C# implementation demonstrates building and evaluating an enterprise agent with SharePoint and MCP integration using the Azure AI Foundry SDK. @@ -15,17 +14,12 @@ This C# implementation demonstrates building and evaluating an enterprise agent 1-idea-to-prototype/ โ”œโ”€โ”€ ModernWorkplaceAssistant/ # Main agent demonstration โ”‚ โ”œโ”€โ”€ Program.cs # Agent implementation with SharePoint + MCP -โ”‚ โ””โ”€โ”€ ModernWorkplaceAssistant.csproj +โ”‚ โ”œโ”€โ”€ ModernWorkplaceAssistant.csproj +โ”‚ โ””โ”€โ”€ .env # Your environment configuration (create this) โ”œโ”€โ”€ Evaluate/ # Evaluation project โ”‚ โ”œโ”€โ”€ Program.cs # Batch evaluation with keyword matching โ”‚ โ””โ”€โ”€ Evaluate.csproj -โ”œโ”€โ”€ shared/ # Shared configuration files -โ”‚ โ”œโ”€โ”€ .env # Environment variables (user-specific) -โ”‚ โ”œโ”€โ”€ .env.template # Environment variables template -โ”‚ โ”œโ”€โ”€ questions.jsonl # Evaluation questions -โ”‚ โ”œโ”€โ”€ README.md # Detailed setup instructions -โ”‚ โ”œโ”€โ”€ MCP_SERVERS.md # MCP server configuration guide -โ”‚ โ””โ”€โ”€ SAMPLE_SHAREPOINT_CONTENT.md # Sample SharePoint documents +โ”œโ”€โ”€ questions.jsonl # Evaluation questions โ””โ”€โ”€ README.md # This file ``` @@ -33,12 +27,19 @@ This C# implementation demonstrates building and evaluating an enterprise agent ### 1. Configure Environment -Copy the template and configure your Azure AI Foundry settings: +Create a `.env` file in the `ModernWorkplaceAssistant` directory with your Azure AI Foundry settings: -```bash -cd shared -cp .env.template .env -# Edit .env with your Azure AI Foundry project details +```dotenv +# Azure AI Foundry Configuration +PROJECT_ENDPOINT=https://your-project.services.ai.azure.com/api/projects/your-project +MODEL_DEPLOYMENT_NAME=gpt-4o-mini + +# SharePoint Integration (Optional - requires full ARM resource ID) +# Format: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.MachineLearningServices/workspaces/{workspace}/connections/{name} +SHAREPOINT_CONNECTION_ID=/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.MachineLearningServices/workspaces/xxx/connections/ContosoCorpPolicies + +# Microsoft Learn MCP Server (Optional) +MCP_SERVER_URL=https://learn.microsoft.com/api/mcp ``` ### 2. Run the Main Agent @@ -74,15 +75,19 @@ This runs batch evaluation against 4 test questions and generates `evaluation_re ## Environment Variables -The `.env` file in `shared/` requires: +Create a `.env` file with: - `PROJECT_ENDPOINT`: Your Azure AI Foundry project endpoint - `MODEL_DEPLOYMENT_NAME`: Your deployed model name (e.g., `gpt-4o-mini`) -- `AI_FOUNDRY_TENANT_ID`: Your Azure AI Foundry tenant ID -- `MCP_SERVER_URL`: Microsoft Learn MCP server URL -- `SHAREPOINT_CONNECTION_ID`: Full ARM resource path to SharePoint connection +- `SHAREPOINT_CONNECTION_ID`: *(Optional)* **Full ARM resource ID** for SharePoint connection + - Format: `/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.MachineLearningServices/workspaces/{workspace}/connections/{name}` + - Note: The C# SDK requires the full ARM ID (not just the connection name) +- `MCP_SERVER_URL`: *(Optional)* Microsoft Learn MCP server URL (e.g., `https://learn.microsoft.com/api/mcp`) -See `shared/.env.template` for details. +## Documentation + +- Python version: `samples/python/enterprise-agent-tutorial/` for reference +- For SharePoint setup, see the Azure AI Foundry documentation on connections ## Documentation @@ -94,11 +99,9 @@ For detailed setup instructions, SharePoint configuration, and MCP server setup, ## Troubleshooting -Both projects load environment variables from `../shared/.env`. If you encounter issues: - -1. Ensure `.env` exists in the `shared/` directory +1. Ensure `.env` exists in the `ModernWorkplaceAssistant/` directory 2. Verify all required environment variables are set -3. Check that SharePoint connection ID is the full ARM resource path +3. For SharePoint, ensure you have the **full ARM resource path** (not just the name) 4. Ensure you're authenticated with `az login` for the correct tenant ## Next Steps