diff --git a/dotnet/samples/Directory.Build.props b/dotnet/samples/Directory.Build.props index 15880d4a8e..57767cdd5a 100644 --- a/dotnet/samples/Directory.Build.props +++ b/dotnet/samples/Directory.Build.props @@ -7,6 +7,7 @@ false net10.0;net472 5ee045b0-aea3-4f08-8d31-32d1a6f8fed0 + $(NoWarn);MAAI001 diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs index 5dfcafbb6d..6aca7f24b8 100644 --- a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs +++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs @@ -5,6 +5,7 @@ using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; using OpenAI.Responses; var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); @@ -21,3 +22,16 @@ // Invoke the agent and output the text result. Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); + +// Create a responses based agent with "store"=false. +// This means that chat history is managed locally by Agent Framework +// instead of being stored in the service (default). +AIAgent agentStoreFalse = new AzureOpenAIClient( + new Uri(endpoint), + new DefaultAzureCredential()) + .GetResponsesClient(deploymentName) + .AsIChatClientWithStoredOutputDisabled() + .AsAIAgent(instructions: "You are good at telling jokes.", name: "Joker"); + +// Invoke the agent and output the text result. +Console.WriteLine(await agentStoreFalse.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs index 1bef6cab4d..98561704f2 100644 --- a/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs +++ b/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs @@ -92,4 +92,23 @@ public static ChatClientAgent AsAIAgent( return new ChatClientAgent(chatClient, options, loggerFactory, services); } + + /// + /// Gets an for use with this that does not store responses for later retrieval. + /// + /// + /// This corresponds to setting the "store" property in the JSON representation to false. + /// + /// The client. + /// An that can be used to converse via the that does not store responses for later retrieval. + /// is . + [Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)] + public static IChatClient AsIChatClientWithStoredOutputDisabled(this ResponsesClient responseClient) + { + return Throw.IfNull(responseClient) + .AsIChatClient() + .AsBuilder() + .ConfigureOptions(x => x.RawRepresentationFactory = _ => new CreateResponseOptions() { StoredOutputEnabled = false }) + .Build(); + } } diff --git a/dotnet/tests/Directory.Build.props b/dotnet/tests/Directory.Build.props index e6c285595e..e3bdd6745d 100644 --- a/dotnet/tests/Directory.Build.props +++ b/dotnet/tests/Directory.Build.props @@ -8,7 +8,7 @@ false net10.0;net472 b7762d10-e29b-4bb1-8b74-b6d69a667dd4 - $(NoWarn);Moq1410;xUnit2023 + $(NoWarn);Moq1410;xUnit2023;MAAI001 diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIResponseClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIResponseClientExtensionsTests.cs index 8723deeac9..19a39c1d35 100644 --- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIResponseClientExtensionsTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIResponseClientExtensionsTests.cs @@ -259,6 +259,38 @@ public void CreateAIAgent_WithClientFactoryAndServices_AppliesBothCorrectly() Assert.Same(serviceProvider, GetFunctionInvocationServices(functionInvokingClient)); } + /// + /// Verify that AsIChatClientWithStoredOutputDisabled throws ArgumentNullException when client is null. + /// + [Fact] + public void AsIChatClientWithStoredOutputDisabled_WithNullClient_ThrowsArgumentNullException() + { + // Act & Assert + var exception = Assert.Throws(() => + ((ResponsesClient)null!).AsIChatClientWithStoredOutputDisabled()); + + Assert.Equal("responseClient", exception.ParamName); + } + + /// + /// Verify that AsIChatClientWithStoredOutputDisabled wraps the original ResponsesClient, + /// which remains accessible via the service chain. + /// + [Fact] + public void AsIChatClientWithStoredOutputDisabled_InnerResponsesClientIsAccessible() + { + // Arrange + var responseClient = new TestOpenAIResponseClient(); + + // Act + var chatClient = responseClient.AsIChatClientWithStoredOutputDisabled(); + + // Assert - the inner ResponsesClient should be accessible via GetService + var innerClient = chatClient.GetService(); + Assert.NotNull(innerClient); + Assert.Same(responseClient, innerClient); + } + /// /// A simple test IServiceProvider implementation for testing. ///