From b30af494ef5b3ad26efd4dd7892b360a813dc23d Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Tue, 1 Sep 2026 15:18:44 +0100 Subject: [PATCH 1/3] .NET: Update Azure AI Projects to 3.0.0 beta 1 Migrate Foundry consumers to the OpenAI 2.12 response and conversation types while preserving Azure.AI.OpenAI compatibility through scoped package overrides. Refs #7994 Copilot-Session: 57730879-50c2-46e6-82f6-ddf01a29ba0c --- dotnet/Directory.Packages.props | 6 +++--- .../Program.cs | 5 +++-- .../Agent_Step18_BingCustomSearch.csproj | 1 + .../Agent_Step19_SharePoint.csproj | 1 + .../Agent_Step20_MicrosoftFabric.csproj | 1 + .../Agent_Step22_MemorySearch.csproj | 1 + .../Agent_Step22_MemorySearch/Program.cs | 5 ++--- ...emory_Step06_MemoryUsingAgentMemory.csproj | 2 +- .../Declarative/HostedWorkflow/Program.cs | 4 ++-- .../Visualization/Visualization.csproj | 5 +++++ .../Hosted-Steering/HostedSteering.csproj | 3 ++- .../HostedWorkflowResilient.csproj | 3 ++- .../AgentWebChat.AgentHost.csproj | 3 ++- .../OpenAIResponsesAgentClient.cs | 3 +-- .../HostedAgentUserAgentPolicy.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../ClientHeadersExtensions.cs | 2 +- .../ClientHeadersPolicy.cs | 4 ++-- .../Microsoft.Agents.AI.Foundry.csproj | 5 +++-- .../ServedModelPolicy.cs | 2 +- .../Microsoft.Agents.AI.OpenAI.csproj | 4 +++- .../AzureAgentProvider.cs | 11 +++++----- .../Fixtures/HostedAgentFixture.cs | 4 ++-- .../Foundry.Hosting.IntegrationTests.csproj | 2 +- .../Foundry.IntegrationTests.csproj | 2 +- .../FoundryVersionedAgentFixture.cs | 6 ++---- .../ResponsesAgentExtensionCreateTests.cs | 3 ++- .../ResponsesAgentFixture.cs | 6 ++---- .../FoundryAIToolExtensionsTests.cs | 2 +- .../HostedOutboundUserAgentTests.cs | 4 ++-- .../AIProjectClientExtensionsTests.cs | 20 +++++++++---------- .../FoundryAgentTests.cs | 2 +- .../MeaiAutoUserAgentVerificationTests.cs | 5 ++--- ...crosoft.Agents.AI.Foundry.UnitTests.csproj | 2 +- ...HostingServiceCollectionExtensionsTests.cs | 3 +-- .../OpenAIResponsesIntegrationTests.cs | 3 +-- .../PolicyPipelineInvestigationTests.cs | 0 .../OpenTelemetryAgentTests.cs | 2 +- 38 files changed, 75 insertions(+), 66 deletions(-) rename dotnet/tests/{Microsoft.Agents.AI.Foundry.UnitTests => Microsoft.Agents.AI.OpenAI.UnitTests}/PolicyPipelineInvestigationTests.cs (100%) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 3e94a182dd2..7d8852c2659 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -27,7 +27,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -128,7 +128,7 @@ - + diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs index c41d9713f37..16bfe4d5602 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs @@ -8,6 +8,7 @@ using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; +using OpenAI.Conversations; string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set."); string deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-5.4-mini"; @@ -24,9 +25,9 @@ .GetProjectOpenAIClient() .GetProjectConversationsClient(); -ProjectConversation conversation = (await conversationsClient.CreateProjectConversationAsync().ConfigureAwait(false)).Value; +ConversationResource conversation = (await conversationsClient.CreateProjectConversationAsync().ConfigureAwait(false)).Value; -// CreateConversationSessionAsync creates a server-side ProjectConversation +// CreateConversationSessionAsync creates a server-side ConversationResource // that persists on the Foundry service and is visible in the Foundry Project UI. AgentSession session = await agent.CreateSessionAsync(conversation.Id); diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj index b00975905a4..351be63a94d 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj @@ -6,6 +6,7 @@ enable enable + $(NoWarn);AAIP001 diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj index b00975905a4..351be63a94d 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj @@ -6,6 +6,7 @@ enable enable + $(NoWarn);AAIP001 diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj index b00975905a4..351be63a94d 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj @@ -6,6 +6,7 @@ enable enable + $(NoWarn);AAIP001 diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj index feb74168cd2..b1ad80d32d9 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj @@ -6,6 +6,7 @@ enable enable + $(NoWarn);AAIP001 diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Program.cs b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Program.cs index 08531f6edd0..8db823e49c3 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Program.cs +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step22_MemorySearch/Program.cs @@ -6,7 +6,6 @@ using Azure.AI.Extensions.OpenAI; using Azure.AI.Projects; -using Azure.AI.Projects.Agents; using Azure.AI.Projects.Memory; using Azure.Identity; using Microsoft.Agents.AI; @@ -29,7 +28,7 @@ Use the memory search tool to recall relevant information from previous interact string userScope = $"user_{Environment.MachineName}"; -MemorySearchPreviewTool memorySearchTool = new(memoryStoreName, userScope) { UpdateDelayInSecs = 0 }; +MemorySearchPreviewTool memorySearchTool = new(memoryStoreName, userScope) { UpdateDelayInSeconds = 0 }; // WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production. // In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid // latency issues, unintended credential probing, and potential security risks from fallback mechanisms. @@ -66,7 +65,7 @@ Use the memory search tool to recall relevant information from previous interact Console.WriteLine($" - Memory ID: {memoryItem.MemoryId}"); Console.WriteLine($" Scope: {memoryItem.Scope}"); Console.WriteLine($" Content: {memoryItem.Content}"); - Console.WriteLine($" Updated: {memoryItem.UpdatedAt}"); + Console.WriteLine($" Updated: {memoryItem.UpdatedOn}"); } } } diff --git a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory.csproj b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory.csproj index 446f7f8bbe3..4224265ea15 100644 --- a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory.csproj +++ b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory.csproj @@ -42,7 +42,7 @@ - + + ships a stable 3.0.0. --> true true + $(NoWarn);AAIP001;OPENAI001;SCME0001 diff --git a/dotnet/src/Microsoft.Agents.AI.Foundry/ServedModelPolicy.cs b/dotnet/src/Microsoft.Agents.AI.Foundry/ServedModelPolicy.cs index 27e98b7b7df..5339a2bdabe 100644 --- a/dotnet/src/Microsoft.Agents.AI.Foundry/ServedModelPolicy.cs +++ b/dotnet/src/Microsoft.Agents.AI.Foundry/ServedModelPolicy.cs @@ -18,7 +18,7 @@ namespace Microsoft.Agents.AI.Foundry; /// can overwrite ChatResponse.ModelId with the true model name. /// /// -/// Registered once per OpenAIRequestPolicies instance via the MEAI 10.5.1 extension hook. +/// Registered once per OpenAIRequestPolicies instance via the MEAI 10.9.0 extension hook. /// When the header is absent (non-Azure endpoints), the scope is not set and the /// preserves the original model name. /// diff --git a/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj b/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj index e9a664f5758..1f4646475b2 100644 --- a/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj +++ b/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj @@ -15,7 +15,9 @@ - + + + diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Foundry/AzureAgentProvider.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Foundry/AzureAgentProvider.cs index ac5e7056ecc..a89f9b91550 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Foundry/AzureAgentProvider.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Foundry/AzureAgentProvider.cs @@ -15,6 +15,7 @@ using Azure.AI.Projects.Agents; using Azure.Core; using Microsoft.Extensions.AI; +using OpenAI.Conversations; using OpenAI.Responses; namespace Microsoft.Agents.AI.Workflows.Declarative; @@ -53,7 +54,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj /// public override async Task CreateConversationAsync(CancellationToken cancellationToken = default) { - ProjectConversation conversation = + ConversationResource conversation = await this.GetConversationClient() .CreateProjectConversationAsync(options: null, cancellationToken).ConfigureAwait(false); @@ -280,8 +281,8 @@ private async Task GetAgentAsync(ProjectsAgentVersion agentVersion, Can /// public override async Task GetMessageAsync(string conversationId, string messageId, CancellationToken cancellationToken = default) { - AgentResponseItem responseItem = await this.GetConversationClient().GetProjectConversationItemAsync(conversationId, messageId, include: null, cancellationToken).ConfigureAwait(false); - ResponseItem[] items = [responseItem.AsResponseResultItem()]; + ResponseItem responseItem = await this.GetConversationClient().GetProjectConversationItemAsync(conversationId, messageId, include: null, cancellationToken).ConfigureAwait(false); + ResponseItem[] items = [responseItem]; ChatMessage[] messages = [.. items.AsChatMessages()]; if (messages.Length != 1) { @@ -303,9 +304,9 @@ public override async IAsyncEnumerable GetMessagesAsync( { AgentListOrder order = newestFirst ? AgentListOrder.Ascending : AgentListOrder.Descending; - await foreach (AgentResponseItem responseItem in this.GetConversationClient().GetProjectConversationItemsAsync(conversationId, null, limit, order.ToString(), after, before, include: null, cancellationToken).ConfigureAwait(false)) + await foreach (ResponseItem responseItem in this.GetConversationClient().GetProjectConversationItemsAsync(conversationId, null, limit, order.ToString(), after, before, include: null, cancellationToken).ConfigureAwait(false)) { - ResponseItem[] items = [responseItem.AsResponseResultItem()]; + ResponseItem[] items = [responseItem]; foreach (ChatMessage message in items.AsChatMessages()) { yield return message; diff --git a/dotnet/tests/Foundry.Hosting.IntegrationTests/Fixtures/HostedAgentFixture.cs b/dotnet/tests/Foundry.Hosting.IntegrationTests/Fixtures/HostedAgentFixture.cs index c44f642830f..f5dfaa96a63 100644 --- a/dotnet/tests/Foundry.Hosting.IntegrationTests/Fixtures/HostedAgentFixture.cs +++ b/dotnet/tests/Foundry.Hosting.IntegrationTests/Fixtures/HostedAgentFixture.cs @@ -157,9 +157,9 @@ public async Task CountConversationItemsAsync(string conversationId) public async Task> ReadConversationMessagesAsync(string conversationId) { List<(string Role, string Text)> messages = []; - await foreach (AgentResponseItem item in this.AgentOpenAIClient.GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc").ConfigureAwait(false)) + await foreach (ResponseItem item in this.AgentOpenAIClient.GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc").ConfigureAwait(false)) { - if (item.AsResponseResultItem() is MessageResponseItem message) + if (item is MessageResponseItem message) { var text = string.Concat(message.Content .Where(c => c.Kind is ResponseContentPartKind.OutputText or ResponseContentPartKind.InputText) diff --git a/dotnet/tests/Foundry.Hosting.IntegrationTests/Foundry.Hosting.IntegrationTests.csproj b/dotnet/tests/Foundry.Hosting.IntegrationTests/Foundry.Hosting.IntegrationTests.csproj index 6f1236e7b47..c05108bf506 100644 --- a/dotnet/tests/Foundry.Hosting.IntegrationTests/Foundry.Hosting.IntegrationTests.csproj +++ b/dotnet/tests/Foundry.Hosting.IntegrationTests/Foundry.Hosting.IntegrationTests.csproj @@ -7,7 +7,7 @@ inherits the default tests TFM list (net10.0;net472). The intersection is net10.0. --> net10.0 - $(NoWarn);CS8793;NU1605;NU1903;AAIP001 + $(NoWarn);CS8793;NU1605;NU1903;AAIP001;SCME0001 false True True diff --git a/dotnet/tests/Foundry.IntegrationTests/Foundry.IntegrationTests.csproj b/dotnet/tests/Foundry.IntegrationTests/Foundry.IntegrationTests.csproj index dbff50104c9..5ff0a38a6db 100644 --- a/dotnet/tests/Foundry.IntegrationTests/Foundry.IntegrationTests.csproj +++ b/dotnet/tests/Foundry.IntegrationTests/Foundry.IntegrationTests.csproj @@ -1,7 +1,7 @@ - $(NoWarn);CS8793 + $(NoWarn);AAIP001;CS8793 True True diff --git a/dotnet/tests/Foundry.IntegrationTests/FoundryVersionedAgentFixture.cs b/dotnet/tests/Foundry.IntegrationTests/FoundryVersionedAgentFixture.cs index cceacfa40b5..f8d4d54be8a 100644 --- a/dotnet/tests/Foundry.IntegrationTests/FoundryVersionedAgentFixture.cs +++ b/dotnet/tests/Foundry.IntegrationTests/FoundryVersionedAgentFixture.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using AgentConformance.IntegrationTests; using AgentConformance.IntegrationTests.Support; -using Azure.AI.Extensions.OpenAI; using Azure.AI.Projects; using Azure.AI.Projects.Agents; using Microsoft.Agents.AI; @@ -97,10 +96,9 @@ private static ChatMessage ConvertToChatMessage(ResponseItem item) private async Task> GetChatHistoryFromConversationAsync(string conversationId) { List messages = []; - await foreach (AgentResponseItem item in this._client.GetProjectOpenAIClient().GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc")) + await foreach (ResponseItem item in this._client.GetProjectOpenAIClient().GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc")) { - var openAIItem = item.AsResponseResultItem(); - if (openAIItem is MessageResponseItem messageItem) + if (item is MessageResponseItem messageItem) { messages.Add(new ChatMessage { diff --git a/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentExtensionCreateTests.cs b/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentExtensionCreateTests.cs index af358a9e556..c65bc44bcd2 100644 --- a/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentExtensionCreateTests.cs +++ b/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentExtensionCreateTests.cs @@ -7,6 +7,7 @@ using Azure.AI.Projects; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; +using OpenAI.Conversations; using Shared.IntegrationTests; namespace Foundry.IntegrationTests; @@ -130,7 +131,7 @@ private static async Task DeleteResponseChainAsync(AIProjectClient client, strin } } - private static async Task CreateConversationAsync(AIProjectClient client) + private static async Task CreateConversationAsync(AIProjectClient client) { ProjectConversationsClient conversationsClient = client.GetProjectOpenAIClient().GetProjectConversationsClient(); return (await conversationsClient.CreateProjectConversationAsync()).Value!; diff --git a/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentFixture.cs b/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentFixture.cs index 7bd0da0d953..57af7b34c48 100644 --- a/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentFixture.cs +++ b/dotnet/tests/Foundry.IntegrationTests/ResponsesAgentFixture.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using AgentConformance.IntegrationTests; using AgentConformance.IntegrationTests.Support; -using Azure.AI.Extensions.OpenAI; using Azure.AI.Projects; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; @@ -88,10 +87,9 @@ private static ChatMessage ConvertToChatMessage(ResponseItem item) private async Task> GetChatHistoryFromConversationAsync(string conversationId) { List messages = []; - await foreach (AgentResponseItem item in this._client.GetProjectOpenAIClient().GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc")) + await foreach (ResponseItem item in this._client.GetProjectOpenAIClient().GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc")) { - var openAIItem = item.AsResponseResultItem(); - if (openAIItem is MessageResponseItem messageItem) + if (item is MessageResponseItem messageItem) { messages.Add(new ChatMessage { diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/FoundryAIToolExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/FoundryAIToolExtensionsTests.cs index 022fbf0bfe1..5cd3cb85fd1 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/FoundryAIToolExtensionsTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/FoundryAIToolExtensionsTests.cs @@ -54,7 +54,7 @@ public void CreateHostedMcpToolbox_FromToolboxVersion_UsesNameAndVersion() name: "hr-tools", version: "2025-09-01", description: "HR toolbox", - createdAt: DateTimeOffset.UtcNow, + createdOn: DateTimeOffset.UtcNow, tools: null, policies: null); diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/HostedOutboundUserAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/HostedOutboundUserAgentTests.cs index 6e9838ab120..1bd9f7e6152 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/HostedOutboundUserAgentTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/HostedOutboundUserAgentTests.cs @@ -322,7 +322,7 @@ public async Task HostedAgentUserAgentPolicy_ReplacesDifferentVersionCombinedSeg var pipeline = ClientPipeline.Create( new ClientPipelineOptions { Transport = new HttpClientPipelineTransport(httpClient) }, - perCallPolicies: [new SetUserAgentPolicy("foundry-hosting/agent-framework-dotnet/0.0.1 MEAI/10.5.1"), HostedAgentUserAgentPolicy.Instance], + perCallPolicies: [new SetUserAgentPolicy("foundry-hosting/agent-framework-dotnet/0.0.1 MEAI/10.9.0"), HostedAgentUserAgentPolicy.Instance], perTryPolicies: default, beforeTransportPolicies: default); @@ -342,7 +342,7 @@ public async Task HostedAgentUserAgentPolicy_ReplacesDifferentVersionCombinedSeg Assert.True(firstCombined >= 0); var secondCombined = handler.LastUserAgent.IndexOf("foundry-hosting/agent-framework-dotnet/", firstCombined + 1, StringComparison.Ordinal); Assert.Equal(-1, secondCombined); - Assert.Contains(" MEAI/10.5.1", handler.LastUserAgent, StringComparison.Ordinal); + Assert.Contains(" MEAI/10.9.0", handler.LastUserAgent, StringComparison.Ordinal); // And the version that survives must be the runtime supplement value's version, not 0.0.1. Assert.DoesNotContain("foundry-hosting/agent-framework-dotnet/0.0.1", handler.LastUserAgent, StringComparison.Ordinal); diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/AIProjectClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/AIProjectClientExtensionsTests.cs index f4da9e6b772..ef500251343 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/AIProjectClientExtensionsTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/AIProjectClientExtensionsTests.cs @@ -674,25 +674,25 @@ public async Task CreateAIAgentAsync_WithResponseToolsInDefinition_CreatesAgentS // Arrange var definition = new DeclarativeAgentDefinition("test-model") { Instructions = "Test instructions" }; - var fabricToolOptions = new FabricDataAgentToolOptions(); - fabricToolOptions.ProjectConnections.Add(new ToolProjectConnection("connection-id")); + var fabricToolOptions = new Azure.AI.Projects.Agents.FabricDataAgentToolOptions(); + fabricToolOptions.ProjectConnections.Add(new Azure.AI.Projects.Agents.ToolProjectConnection("connection-id")); - var sharepointOptions = new SharePointGroundingToolOptions(); - sharepointOptions.ProjectConnections.Add(new ToolProjectConnection("connection-id")); + var sharepointOptions = new Azure.AI.Projects.Agents.SharePointGroundingToolOptions(); + sharepointOptions.ProjectConnections.Add(new Azure.AI.Projects.Agents.ToolProjectConnection("connection-id")); - var structuredOutputs = new StructuredOutputDefinition("name", "description", new Dictionary { ["schema"] = BinaryData.FromString(AIJsonUtilities.CreateJsonSchema(new { id = "test" }.GetType()).ToString()) }, false); + var structuredOutputs = new Azure.AI.Projects.Agents.StructuredOutputDefinition("name", "description", new Dictionary { ["schema"] = BinaryData.FromString(AIJsonUtilities.CreateJsonSchema(new { id = "test" }.GetType()).ToString()) }, false); // Add tools to the definition definition.Tools.Add(ResponseTool.CreateFunctionTool("create_tool", BinaryData.FromString("{}"), strictModeEnabled: false)); - definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateBingCustomSearchTool(new BingCustomSearchToolOptions([new BingCustomSearchConfiguration("connection-id", "instance-name")]))); - definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateBrowserAutomationTool(new BrowserAutomationToolOptions(new BrowserAutomationToolConnectionParameters("id")))); + definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateBingCustomSearchTool(new Azure.AI.Projects.Agents.BingCustomSearchToolOptions([new BingCustomSearchConfiguration("connection-id", "instance-name")]))); + definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateBrowserAutomationTool(new Azure.AI.Projects.Agents.BrowserAutomationToolOptions(new BrowserAutomationToolConnectionParameters("id")))); definition.Tools.Add(ProjectsAgentTool.CreateA2ATool(new Uri("https://test-uri.microsoft.com"))); - definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateBingGroundingTool(new BingGroundingSearchToolOptions([new BingGroundingSearchConfiguration("connection-id")]))); + definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateBingGroundingTool(new Azure.AI.Projects.Agents.BingGroundingSearchToolOptions([new BingGroundingSearchConfiguration("connection-id")]))); definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateMicrosoftFabricTool(fabricToolOptions)); - definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateOpenApiTool(new OpenApiFunctionDefinition("name", BinaryData.FromString(OpenAPISpec), new OpenAPIAnonymousAuthenticationDetails()))); + definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateOpenApiTool(new Azure.AI.Projects.Agents.OpenApiFunctionDefinition("name", BinaryData.FromString(OpenAPISpec), new OpenAPIAnonymousAuthenticationDetails()))); definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateSharepointTool(sharepointOptions)); definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateStructuredOutputsTool(structuredOutputs)); - definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateAzureAISearchTool(new AzureAISearchToolOptions([new AzureAISearchToolIndex() { IndexName = "name" }]))); + definition.Tools.Add((ResponseTool)ProjectsAgentTool.CreateAzureAISearchTool(new Azure.AI.Projects.Agents.AzureAISearchToolOptions([new Azure.AI.Projects.Agents.AzureAISearchToolIndex() { IndexName = "name" }]))); // Generate agent definition response with the tools var definitionResponse = GeneratePromptDefinitionResponse(definition, definition.Tools.Select(t => t.AsAITool()).ToList()); diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/FoundryAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/FoundryAgentTests.cs index 72e9fa342c0..0d9a22cbac7 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/FoundryAgentTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/FoundryAgentTests.cs @@ -406,7 +406,7 @@ public async Task Constructor_AgentFrameworkUserAgentHeaderAddedToRequestsAsync( // FoundryAgent-built chat client carries the new agent-framework-dotnet/{version} // segment (stamped by AgentFrameworkUserAgentPolicy registered via the MEAI // OpenAIRequestPolicies hook). The local MEAI/{version} stamp was removed because - // MEAI 10.5.1 stamps that itself; this test only verifies the framework-wide segment + // MEAI 10.9.0 stamps that itself; this test only verifies the framework-wide segment // that the Foundry package now guarantees. bool agentFrameworkUserAgentFound = false; using HttpHandlerAssert httpHandler = new(request => diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/MeaiAutoUserAgentVerificationTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/MeaiAutoUserAgentVerificationTests.cs index 050dd43a223..f99b81dd51d 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/MeaiAutoUserAgentVerificationTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/MeaiAutoUserAgentVerificationTests.cs @@ -9,7 +9,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.AI; -using OpenAI; using OpenAI.Responses; #pragma warning disable OPENAI001 @@ -17,7 +16,7 @@ namespace Microsoft.Agents.AI.Foundry.UnitTests; /// -/// One-shot verification (kept in tree to detect regressions) that MEAI 10.5.1 stamps its own +/// One-shot verification (kept in tree to detect regressions) that MEAI 10.9.0 stamps its own /// MEAI/{version} User-Agent segment automatically when an /// is wrapped via AsIChatClient(). If this test starts failing, the FoundryChatClient /// implementation must re-register the MEAI policy explicitly via OpenAIRequestPolicies because @@ -36,7 +35,7 @@ public async Task MeaiOpenAIResponsesClient_StampsMeaiSegmentAutomatically_Witho using var httpClient = new HttpClient(handler); #pragma warning restore CA5399 - var options = new OpenAIClientOptions + var options = new ResponsesClientOptions { Transport = new HttpClientPipelineTransport(httpClient), Endpoint = new Uri("https://example.test/v1"), diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Microsoft.Agents.AI.Foundry.UnitTests.csproj b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Microsoft.Agents.AI.Foundry.UnitTests.csproj index 05b94b7b82f..89879a5a0c6 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Microsoft.Agents.AI.Foundry.UnitTests.csproj +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Microsoft.Agents.AI.Foundry.UnitTests.csproj @@ -2,7 +2,7 @@ false - $(NoWarn);NU1605;NU1903 + $(NoWarn);AAIP001;NU1605;NU1903 diff --git a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/AgentHostingServiceCollectionExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/AgentHostingServiceCollectionExtensionsTests.cs index 587af5ff339..67471218e7e 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/AgentHostingServiceCollectionExtensionsTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/AgentHostingServiceCollectionExtensionsTests.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; -using OpenAI; using OpenAI.Responses; namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests; @@ -28,7 +27,7 @@ public async Task HostedWebSearchTool_WithResponsesClient_UsesResponsesWireForma #pragma warning restore CA5399 using IChatClient chatClient = new ResponsesClient( new ApiKeyCredential("test-key"), - new OpenAIClientOptions + new ResponsesClientOptions { Endpoint = new Uri("https://example.test/v1"), Transport = new HttpClientPipelineTransport(httpClient) diff --git a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs index 9a89bee4838..4612ec35844 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs @@ -15,7 +15,6 @@ using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using OpenAI; using OpenAI.Responses; namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests; @@ -1321,7 +1320,7 @@ private ResponsesClient CreateResponseClient(string agentName) { return new ResponsesClient( credential: new ApiKeyCredential("test-api-key"), - options: new OpenAIClientOptions + options: new ResponsesClientOptions { Endpoint = new Uri(this._httpClient!.BaseAddress!, $"/{agentName}/v1/"), Transport = new HttpClientPipelineTransport(this._httpClient) diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/PolicyPipelineInvestigationTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/PolicyPipelineInvestigationTests.cs similarity index 100% rename from dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/PolicyPipelineInvestigationTests.cs rename to dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/PolicyPipelineInvestigationTests.cs diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs index 79e3418b862..a6b609e971e 100644 --- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/OpenTelemetryAgentTests.cs @@ -606,7 +606,7 @@ async static IAsyncEnumerable CallbackAsync( Assert.False(tags.ContainsKey("gen_ai.system_instructions")); // gen_ai.tool.definitions is always emitted regardless of EnableSensitiveData (ME.AI 10.4.0+). - // ME.AI 10.5.1 omits description/parameters for function tools when sensitive data is disabled. + // ME.AI 10.9.0 omits description/parameters for function tools when sensitive data is disabled. Assert.Equal(ReplaceWhitespace(""" [ { From af61a79b16a674366f0666c9d9c2e4f40d878d3b Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Wed, 2 Sep 2026 16:08:44 +0100 Subject: [PATCH 2/3] .NET: Align SDK upgrade with current main Remove obsolete compatibility overrides after Azure.AI.OpenAI removal and keep all projects on the OpenAI 2.12 dependency line. Refs #7994 Copilot-Session: 57730879-50c2-46e6-82f6-ddf01a29ba0c --- .../samples/03-workflows/Visualization/Visualization.csproj | 5 ----- .../Hosted-Workflow-Handoff/HostedWorkflowHandoff.csproj | 4 ++-- .../AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj | 3 +-- .../Microsoft.Agents.AI.OpenAI.csproj | 4 +--- .../PolicyPipelineInvestigationTests.cs | 2 +- 5 files changed, 5 insertions(+), 13 deletions(-) rename dotnet/tests/{Microsoft.Agents.AI.OpenAI.UnitTests => Microsoft.Agents.AI.Foundry.UnitTests}/PolicyPipelineInvestigationTests.cs (99%) diff --git a/dotnet/samples/03-workflows/Visualization/Visualization.csproj b/dotnet/samples/03-workflows/Visualization/Visualization.csproj index ed1d92eba46..7f9f03dff47 100644 --- a/dotnet/samples/03-workflows/Visualization/Visualization.csproj +++ b/dotnet/samples/03-workflows/Visualization/Visualization.csproj @@ -8,11 +8,6 @@ enable - - - - - diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Handoff/HostedWorkflowHandoff.csproj b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Handoff/HostedWorkflowHandoff.csproj index 9bdcf4161b6..43d63de1389 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Handoff/HostedWorkflowHandoff.csproj +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Handoff/HostedWorkflowHandoff.csproj @@ -25,9 +25,9 @@ - + - + diff --git a/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj b/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj index 78e6c97c874..e99de857c4c 100644 --- a/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj +++ b/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj @@ -26,8 +26,7 @@ - - + diff --git a/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj b/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj index 1f4646475b2..e9a664f5758 100644 --- a/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj +++ b/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj @@ -15,9 +15,7 @@ - - - + diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/PolicyPipelineInvestigationTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/PolicyPipelineInvestigationTests.cs similarity index 99% rename from dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/PolicyPipelineInvestigationTests.cs rename to dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/PolicyPipelineInvestigationTests.cs index 3c4fdd45cb2..1d6b21291bf 100644 --- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/PolicyPipelineInvestigationTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/PolicyPipelineInvestigationTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.Agents.AI.Foundry.UnitTests; /// -/// Executable probes documenting the System.ClientModel policy behavior Stage 1 can rely on. +/// Executable probes documenting the System.ClientModel policy behavior used by Foundry clients. /// public sealed class PolicyPipelineInvestigationTests { From da1ca14405eb6c4aa898a3ede200874cb8f1024b Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Wed, 2 Sep 2026 19:20:46 +0100 Subject: [PATCH 3/3] .NET: Use Projects 3 in hosted samples Use the public Azure.AI.Projects 3.0.0 beta 1 package in both local and source deployment modes. Refs #7994 Copilot-Session: 57730879-50c2-46e6-82f6-ddf01a29ba0c --- .../responses/Hosted-Steering/HostedSteering.csproj | 3 +-- .../Hosted-Workflow-Resilient/HostedWorkflowResilient.csproj | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Steering/HostedSteering.csproj b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Steering/HostedSteering.csproj index 0e80e2ccdb3..8a2adf0facc 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Steering/HostedSteering.csproj +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Steering/HostedSteering.csproj @@ -30,8 +30,7 @@ - - + diff --git a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Resilient/HostedWorkflowResilient.csproj b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Resilient/HostedWorkflowResilient.csproj index 79b8c35d5bf..035789a4e1b 100644 --- a/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Resilient/HostedWorkflowResilient.csproj +++ b/dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-Workflow-Resilient/HostedWorkflowResilient.csproj @@ -30,8 +30,7 @@ - - +