diff --git a/.github/workflows/dotnet-format.yml b/.github/workflows/dotnet-format.yml
index a9fe090013..bb55dbde86 100644
--- a/.github/workflows/dotnet-format.yml
+++ b/.github/workflows/dotnet-format.yml
@@ -7,7 +7,7 @@ name: dotnet-format
on:
workflow_dispatch:
pull_request:
- branches: ["main", "feature*"]
+ branches: ["main"]
paths:
- dotnet/**
- '.github/workflows/dotnet-format.yml'
diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 8967bad109..ad7880001d 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -17,8 +17,8 @@
-
-
+
+
diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index cf1e367293..2bc4067e55 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -28,6 +28,7 @@
+
@@ -263,6 +264,7 @@
+
diff --git a/dotnet/nuget.config b/dotnet/nuget.config
index 62c87f185c..ae2bf13b3a 100644
--- a/dotnet/nuget.config
+++ b/dotnet/nuget.config
@@ -3,14 +3,14 @@
-
+
-
-
+
+
\ No newline at end of file
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Agent_With_AzureAIAgent.csproj b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Agent_With_AzureAIAgent.csproj
new file mode 100644
index 0000000000..2d475becd4
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Agent_With_AzureAIAgent.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net9.0
+
+ enable
+ enable
+ $(NoWarn);IDE0059
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Program.cs b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Program.cs
new file mode 100644
index 0000000000..d6eb139ebb
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Program.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample shows how to create and use a simple AI agent with Azure Foundry Agents as the backend.
+
+using Azure.AI.Agents;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+
+var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
+var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
+
+const string JokerInstructions = "You are good at telling jokes.";
+const string JokerName = "JokerAgent";
+
+// Get a client to create/retrieve server side agents with.
+var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
+
+// Define the agent you want to create.
+var agentDefinition = new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions };
+
+// You can create a server side agent with the Azure.AI.Agents SDK.
+var agentVersion = agentsClient.CreateAgentVersion(agentName: JokerName, definition: agentDefinition).Value;
+
+// You can retrieve an already created server side agent as an AIAgent.
+AIAgent existingAgent = await agentsClient.GetAIAgentAsync(deploymentName, agentVersion.Name);
+
+// You can also create a server side persistent agent and return it as an AIAgent directly.
+var createdAgent = agentsClient.CreateAIAgent(deploymentName, name: JokerName, instructions: JokerInstructions);
+
+// You can then invoke the agent like any other AIAgent.
+AgentThread thread = existingAgent.GetNewThread();
+Console.WriteLine(await existingAgent.RunAsync("Tell me a joke about a pirate.", thread));
+
+// Cleanup by agent name (removes both agent versions created by existingAgent + createdAgent).
+await agentsClient.DeleteAgentAsync(agentVersion.Name);
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/README.md b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/README.md
new file mode 100644
index 0000000000..df0854ba2f
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/README.md
@@ -0,0 +1,16 @@
+# Prerequisites
+
+Before you begin, ensure you have the following prerequisites:
+
+- .NET 8.0 SDK or later
+- Azure Foundry service endpoint and deployment configured
+- Azure CLI installed and authenticated (for Azure credential authentication)
+
+**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
+
+Set the following environment variables:
+
+```powershell
+$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
+$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
+```
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj b/dotnet/src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj
index 5300c98b14..6d1cc23a1c 100644
--- a/dotnet/src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj
@@ -1,4 +1,4 @@
-
+
$(ProjectsTargetFrameworks)
@@ -11,9 +11,7 @@
-
-
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/New/PersistentAgentsClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/New/PersistentAgentsClientExtensions.cs
deleted file mode 100644
index a08d5badce..0000000000
--- a/dotnet/src/Microsoft.Agents.AI.AzureAI/New/PersistentAgentsClientExtensions.cs
+++ /dev/null
@@ -1,665 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using Microsoft.Agents.AI;
-using Microsoft.Extensions.AI;
-using OpenAI.Responses;
-
-#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
-
-namespace Azure.AI.Agents.Persistent;
-
-///
-/// Provides extension methods for .
-///
-public static class AgentsClientExtensions
-{
- /*
- ///
- /// Gets a runnable agent instance from the provided response containing persistent agent metadata.
- ///
- /// The client used to interact with persistent agents. Cannot be .
- /// The response containing the persistent agent to be converted. Cannot be .
- /// The default to use when interacting with the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// A instance that can be used to perform operations on the persistent agent.
- public static ChatClientAgent GetAIAgent(this AgentsClient client, Response persistentAgentResponse, ChatOptions? chatOptions = null, Func? clientFactory = null)
- {
- if (persistentAgentResponse is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentResponse));
- }
-
- return GetAIAgent(client, persistentAgentResponse.Value, chatOptions, clientFactory);
- }
-
- ///
- /// Gets a runnable agent instance from a containing metadata about a persistent agent.
- ///
- /// The client used to interact with persistent agents. Cannot be .
- /// The persistent agent metadata to be converted. Cannot be .
- /// The default to use when interacting with the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// A instance that can be used to perform operations on the persistent agent.
- public static ChatClientAgent GetAIAgent(this PersistentAgentsClient persistentAgentsClient, PersistentAgent persistentAgentMetadata, ChatOptions? chatOptions = null, Func? clientFactory = null)
- {
- if (persistentAgentMetadata is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentMetadata));
- }
-
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- var chatClient = persistentAgentsClient.AsIChatClient(persistentAgentMetadata.Id);
-
- if (clientFactory is not null)
- {
- chatClient = clientFactory(chatClient);
- }
-
- return new ChatClientAgent(chatClient, options: new()
- {
- Id = persistentAgentMetadata.Id,
- Name = persistentAgentMetadata.Name,
- Description = persistentAgentMetadata.Description,
- Instructions = persistentAgentMetadata.Instructions,
- ChatOptions = chatOptions
- });
- }
-
- ///
- /// Retrieves an existing server side agent, wrapped as a using the provided .
- ///
- /// The to create the with.
- /// A for the persistent agent.
- /// The ID of the server side agent to create a for.
- /// Options that should apply to all runs of the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the persistent agent.
- public static ChatClientAgent GetAIAgent(
- this PersistentAgentsClient persistentAgentsClient,
- string agentId,
- ChatOptions? chatOptions = null,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (string.IsNullOrWhiteSpace(agentId))
- {
- throw new ArgumentException($"{nameof(agentId)} should not be null or whitespace.", nameof(agentId));
- }
-
- var persistentAgentResponse = persistentAgentsClient.Administration.GetAgent(agentId, cancellationToken);
- return persistentAgentsClient.GetAIAgent(persistentAgentResponse, chatOptions, clientFactory);
- }
-
- ///
- /// Retrieves an existing server side agent, wrapped as a using the provided .
- ///
- /// The to create the with.
- /// A for the persistent agent.
- /// The ID of the server side agent to create a for.
- /// Options that should apply to all runs of the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the persistent agent.
- public static async Task GetAIAgentAsync(
- this PersistentAgentsClient persistentAgentsClient,
- string agentId,
- ChatOptions? chatOptions = null,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (string.IsNullOrWhiteSpace(agentId))
- {
- throw new ArgumentException($"{nameof(agentId)} should not be null or whitespace.", nameof(agentId));
- }
-
- var persistentAgentResponse = await persistentAgentsClient.Administration.GetAgentAsync(agentId, cancellationToken).ConfigureAwait(false);
- return persistentAgentsClient.GetAIAgent(persistentAgentResponse, chatOptions, clientFactory);
- }
-
- ///
- /// Gets a runnable agent instance from the provided response containing persistent agent metadata.
- ///
- /// The client used to interact with persistent agents. Cannot be .
- /// The response containing the persistent agent to be converted. Cannot be .
- /// Full set of options to configure the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// A instance that can be used to perform operations on the persistent agent.
- /// Thrown when or is .
- public static ChatClientAgent GetAIAgent(this PersistentAgentsClient persistentAgentsClient, Response persistentAgentResponse, ChatClientAgentOptions options, Func? clientFactory = null)
- {
- if (persistentAgentResponse is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentResponse));
- }
-
- return GetAIAgent(persistentAgentsClient, persistentAgentResponse.Value, options, clientFactory);
- }
-
- ///
- /// Gets a runnable agent instance from a containing metadata about a persistent agent.
- ///
- /// The client used to interact with persistent agents. Cannot be .
- /// The persistent agent metadata to be converted. Cannot be .
- /// Full set of options to configure the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// A instance that can be used to perform operations on the persistent agent.
- /// Thrown when or is .
- public static ChatClientAgent GetAIAgent(this PersistentAgentsClient persistentAgentsClient, PersistentAgent persistentAgentMetadata, ChatClientAgentOptions options, Func? clientFactory = null)
- {
- if (persistentAgentMetadata is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentMetadata));
- }
-
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (options is null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- var chatClient = persistentAgentsClient.AsIChatClient(persistentAgentMetadata.Id);
-
- if (clientFactory is not null)
- {
- chatClient = clientFactory(chatClient);
- }
-
- var agentOptions = new ChatClientAgentOptions()
- {
- Id = persistentAgentMetadata.Id,
- Name = options.Name ?? persistentAgentMetadata.Name,
- Description = options.Description ?? persistentAgentMetadata.Description,
- Instructions = options.Instructions ?? persistentAgentMetadata.Instructions,
- ChatOptions = options.ChatOptions,
- AIContextProviderFactory = options.AIContextProviderFactory,
- ChatMessageStoreFactory = options.ChatMessageStoreFactory,
- UseProvidedChatClientAsIs = options.UseProvidedChatClientAsIs
- };
-
- return new ChatClientAgent(chatClient, agentOptions);
- }
-
- ///
- /// Retrieves an existing server side agent, wrapped as a using the provided .
- ///
- /// The to create the with.
- /// The ID of the server side agent to create a for.
- /// Full set of options to configure the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the persistent agent.
- /// Thrown when or is .
- /// Thrown when is empty or whitespace.
- public static ChatClientAgent GetAIAgent(
- this PersistentAgentsClient persistentAgentsClient,
- string agentId,
- ChatClientAgentOptions options,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (string.IsNullOrWhiteSpace(agentId))
- {
- throw new ArgumentException($"{nameof(agentId)} should not be null or whitespace.", nameof(agentId));
- }
-
- if (options is null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- var persistentAgentResponse = persistentAgentsClient.Administration.GetAgent(agentId, cancellationToken);
- return persistentAgentsClient.GetAIAgent(persistentAgentResponse, options, clientFactory);
- }
-
- ///
- /// Retrieves an existing server side agent, wrapped as a using the provided .
- ///
- /// The to create the with.
- /// The ID of the server side agent to create a for.
- /// Full set of options to configure the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the persistent agent.
- /// Thrown when or is .
- /// Thrown when is empty or whitespace.
- public static async Task GetAIAgentAsync(
- this PersistentAgentsClient persistentAgentsClient,
- string agentId,
- ChatClientAgentOptions options,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (string.IsNullOrWhiteSpace(agentId))
- {
- throw new ArgumentException($"{nameof(agentId)} should not be null or whitespace.", nameof(agentId));
- }
-
- if (options is null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- var persistentAgentResponse = await persistentAgentsClient.Administration.GetAgentAsync(agentId, cancellationToken).ConfigureAwait(false);
- return persistentAgentsClient.GetAIAgent(persistentAgentResponse, options, clientFactory);
- }*/
-
- ///
- /// Creates a new server side agent using the provided .
- ///
- /// The to create the agent with.
- /// The model to be used by the agent.
- /// The name of the agent.
- /// The instructions for the agent.
- /// The tools to be used by the agent.
- /// The temperature setting for the agent.
- /// The top-p setting for the agent.
- /// The responsible AI config
- /// The reasoning options for the agent.
- /// The text options for the agent.
- /// The structured inputs for the agent.
- /// The metadata for the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the newly created agent.
- public static async Task CreateAIAgentAsync(
- this AgentsClient client,
- string model,
- string? name = null,
- string? instructions = null,
- IEnumerable? tools = null,
- float? temperature = null,
- float? topP = null,
- RaiConfig? raiConfig = null,
- ResponseReasoningOptions? reasoningOptions = null,
- ResponseTextOptions? textOptions = null,
- IDictionary? structuredInputs = null,
- IReadOnlyDictionary? metadata = null,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (client is null)
- {
- throw new ArgumentNullException(nameof(client));
- }
-
- var openAIClient = client.GetOpenAIClient();
- var chatClient = openAIClient.GetOpenAIResponseClient(model).AsIChatClient();
-
- var promptAgentDefinition = new PromptAgentDefinition(model)
- {
- Instructions = instructions,
- Temperature = temperature,
- TopP = topP,
- RaiConfig = raiConfig,
- ReasoningOptions = reasoningOptions,
- TextOptions = textOptions,
- };
-
- var versionCreation = new AgentVersionCreationOptions();
- if (metadata is not null)
- {
- foreach (var kvp in metadata)
- {
- versionCreation.Metadata.Add(kvp.Key, kvp.Value);
- }
- }
-
- AgentVersion newAgentVersion = await client.CreateAgentVersionAsync(name, promptAgentDefinition, versionCreation, cancellationToken).ConfigureAwait(false);
-
- if (tools is not null)
- {
- if (promptAgentDefinition.Tools is List toolsList)
- {
- toolsList.AddRange(tools);
- }
- else
- {
- foreach (var tool in tools)
- {
- promptAgentDefinition.Tools.Add(tool);
- }
- }
- }
-
- if (structuredInputs is not null)
- {
- foreach (var kvp in structuredInputs)
- {
- promptAgentDefinition.StructuredInputs.Add(kvp.Key, kvp.Value);
- }
- }
-
- var agent = new ChatClientAgent(chatClient);
- agent.AsBuilder().Use(FoundryAgentMiddlewareAsync).Build();
-
- async Task FoundryAgentMiddlewareAsync(IEnumerable messages, AgentThread? thread, AgentRunOptions? options, Func, AgentThread?, AgentRunOptions?, CancellationToken, Task> sharedFunc, CancellationToken cancellationToken)
- {
- if (options is not ChatClientAgentRunOptions chatClientOptions)
- {
- throw new InvalidOperationException("The provided AgentRunOptions is not of type ChatClientAgentRunOptions.");
- }
-
- ChatClientAgentThread? chatClientThread = null;
- if (thread is not null)
- {
- if (thread is not ChatClientAgentThread asChatClientAgentThread)
- {
- throw new InvalidOperationException("The provided AgentThread is not of type ChatClientAgentThread.");
- }
-
- if (string.IsNullOrWhiteSpace(asChatClientAgentThread.ConversationId))
- {
- throw new InvalidOperationException("The ChatClientAgentThread does not have a valid ConversationId.");
- }
-
- chatClientThread = asChatClientAgentThread;
- }
-
- var conversation = (chatClientThread is not null)
- ? await client.GetConversationsClient().GetConversationAsync(chatClientThread.ConversationId, cancellationToken).ConfigureAwait(false)
- : await client.GetConversationsClient().CreateConversationAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
-
- chatClientOptions.ChatOptions ??= new();
- chatClientOptions.ChatOptions.RawRepresentationFactory = (client) =>
- {
- var rawRepresentationFactory = chatClientOptions.ChatOptions?.RawRepresentationFactory;
- ResponseCreationOptions? responseCreationOptions = null;
-
- if (rawRepresentationFactory is not null)
- {
- responseCreationOptions = rawRepresentationFactory.Invoke(chatClient) as ResponseCreationOptions;
-
- if (responseCreationOptions is null)
- {
- throw new InvalidOperationException("The RawRepresentationFactory did not return a valid ResponseCreationOptions instance.");
- }
- }
- else
- {
- responseCreationOptions = new ResponseCreationOptions();
- }
-
- responseCreationOptions.SetAgentReference(name);
- responseCreationOptions.SetConversationReference(conversation);
-
- return responseCreationOptions;
- };
-
- await sharedFunc(messages, thread, options, cancellationToken).ConfigureAwait(false);
- }
-
- return agent;
- }
-
- ///
- /// Creates a new server side agent using the provided .
- ///
- /// The to create the agent with.
- /// The model to be used by the agent.
- /// The name of the agent.
- /// The description of the agent.
- /// The instructions for the agent.
- /// The tools to be used by the agent.
- /// The resources for the tools.
- /// The temperature setting for the agent.
- /// The top-p setting for the agent.
- /// The response format for the agent.
- /// The metadata for the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the newly created agent.
- public static ChatClientAgent CreateAIAgent(
- this PersistentAgentsClient persistentAgentsClient,
- string model,
- string? name = null,
- string? description = null,
- string? instructions = null,
- IEnumerable? tools = null,
- ToolResources? toolResources = null,
- float? temperature = null,
- float? topP = null,
- BinaryData? responseFormat = null,
- IReadOnlyDictionary? metadata = null,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- var createPersistentAgentResponse = persistentAgentsClient.Administration.CreateAgent(
- model: model,
- name: name,
- description: description,
- instructions: instructions,
- tools: tools,
- toolResources: toolResources,
- temperature: temperature,
- topP: topP,
- responseFormat: responseFormat,
- metadata: metadata,
- cancellationToken: cancellationToken);
-
- // Get a local proxy for the agent to work with.
- return persistentAgentsClient.GetAIAgent(createPersistentAgentResponse.Value.Id, clientFactory: clientFactory, cancellationToken: cancellationToken);
- }
-
- ///
- /// Creates a new server side agent using the provided .
- ///
- /// The to create the agent with.
- /// The model to be used by the agent.
- /// Full set of options to configure the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the newly created agent.
- /// Thrown when or or is .
- /// Thrown when is empty or whitespace.
- public static ChatClientAgent CreateAIAgent(
- this PersistentAgentsClient persistentAgentsClient,
- string model,
- ChatClientAgentOptions options,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (string.IsNullOrWhiteSpace(model))
- {
- throw new ArgumentException($"{nameof(model)} should not be null or whitespace.", nameof(model));
- }
-
- if (options is null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- var toolDefinitionsAndResources = ConvertAIToolsToToolDefinitions(options.ChatOptions?.Tools);
-
- var createPersistentAgentResponse = persistentAgentsClient.Administration.CreateAgent(
- model: model,
- name: options.Name,
- description: options.Description,
- instructions: options.Instructions,
- tools: toolDefinitionsAndResources.ToolDefinitions,
- toolResources: toolDefinitionsAndResources.ToolResources,
- temperature: null,
- topP: null,
- responseFormat: null,
- metadata: null,
- cancellationToken: cancellationToken);
-
- if (options.ChatOptions?.Tools is { Count: > 0 } && (toolDefinitionsAndResources.FunctionToolsAndOtherTools is null || options.ChatOptions.Tools.Count != toolDefinitionsAndResources.FunctionToolsAndOtherTools.Count))
- {
- options = options.Clone();
- options.ChatOptions!.Tools = toolDefinitionsAndResources.FunctionToolsAndOtherTools;
- }
-
- // Get a local proxy for the agent to work with.
- return persistentAgentsClient.GetAIAgent(createPersistentAgentResponse.Value.Id, options, clientFactory: clientFactory, cancellationToken: cancellationToken);
- }
-
- ///
- /// Creates a new server side agent using the provided .
- ///
- /// The to create the agent with.
- /// The model to be used by the agent.
- /// Full set of options to configure the agent.
- /// Provides a way to customize the creation of the underlying used by the agent.
- /// The to monitor for cancellation requests. The default is .
- /// A instance that can be used to perform operations on the newly created agent.
- /// Thrown when or or is .
- /// Thrown when is empty or whitespace.
- public static async Task CreateAIAgentAsync(
- this PersistentAgentsClient persistentAgentsClient,
- string model,
- ChatClientAgentOptions options,
- Func? clientFactory = null,
- CancellationToken cancellationToken = default)
- {
- if (persistentAgentsClient is null)
- {
- throw new ArgumentNullException(nameof(persistentAgentsClient));
- }
-
- if (string.IsNullOrWhiteSpace(model))
- {
- throw new ArgumentException($"{nameof(model)} should not be null or whitespace.", nameof(model));
- }
-
- if (options is null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- var toolDefinitionsAndResources = ConvertAIToolsToToolDefinitions(options.ChatOptions?.Tools);
-
- var createPersistentAgentResponse = await persistentAgentsClient.Administration.CreateAgentAsync(
- model: model,
- name: options.Name,
- description: options.Description,
- instructions: options.Instructions,
- tools: toolDefinitionsAndResources.ToolDefinitions,
- toolResources: toolDefinitionsAndResources.ToolResources,
- temperature: null,
- topP: null,
- responseFormat: null,
- metadata: null,
- cancellationToken: cancellationToken).ConfigureAwait(false);
-
- if (options.ChatOptions?.Tools is { Count: > 0 } && (toolDefinitionsAndResources.FunctionToolsAndOtherTools is null || options.ChatOptions.Tools.Count != toolDefinitionsAndResources.FunctionToolsAndOtherTools.Count))
- {
- options = options.Clone();
- options.ChatOptions!.Tools = toolDefinitionsAndResources.FunctionToolsAndOtherTools;
- }
-
- // Get a local proxy for the agent to work with.
- return await persistentAgentsClient.GetAIAgentAsync(createPersistentAgentResponse.Value.Id, options, clientFactory: clientFactory, cancellationToken: cancellationToken).ConfigureAwait(false);
- }
-
- private static (List? ToolDefinitions, ToolResources? ToolResources, List? FunctionToolsAndOtherTools) ConvertAIToolsToToolDefinitions(IList? tools)
- {
- List? toolDefinitions = null;
- ToolResources? toolResources = null;
- List? functionToolsAndOtherTools = null;
-
- if (tools is not null)
- {
- foreach (AITool tool in tools)
- {
- switch (tool)
- {
- case HostedCodeInterpreterTool codeTool:
-
- toolDefinitions ??= new();
- toolDefinitions.Add(new CodeInterpreterToolDefinition());
-
- if (codeTool.Inputs is { Count: > 0 })
- {
- foreach (var input in codeTool.Inputs)
- {
- switch (input)
- {
- case HostedFileContent hostedFile:
- // If the input is a HostedFileContent, we can use its ID directly.
- toolResources ??= new();
- toolResources.CodeInterpreter ??= new();
- toolResources.CodeInterpreter.FileIds.Add(hostedFile.FileId);
- break;
- }
- }
- }
- break;
-
- case HostedFileSearchTool fileSearchTool:
- toolDefinitions ??= new();
- toolDefinitions.Add(new FileSearchToolDefinition
- {
- FileSearch = new() { MaxNumResults = fileSearchTool.MaximumResultCount }
- });
-
- if (fileSearchTool.Inputs is { Count: > 0 })
- {
- foreach (var input in fileSearchTool.Inputs)
- {
- switch (input)
- {
- case HostedVectorStoreContent hostedVectorStore:
- toolResources ??= new();
- toolResources.FileSearch ??= new();
- toolResources.FileSearch.VectorStoreIds.Add(hostedVectorStore.VectorStoreId);
- break;
- }
- }
- }
- break;
-
- case HostedWebSearchTool webSearch when webSearch.AdditionalProperties?.TryGetValue("connectionId", out object? connectionId) is true:
- toolDefinitions ??= new();
- toolDefinitions.Add(new BingGroundingToolDefinition(new BingGroundingSearchToolParameters([new BingGroundingSearchConfiguration(connectionId!.ToString())])));
- break;
-
- default:
- functionToolsAndOtherTools ??= new();
- functionToolsAndOtherTools.Add(tool);
- break;
- }
- }
- }
-
- return (toolDefinitions, toolResources, functionToolsAndOtherTools);
- }
-}
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AgentsClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AgentsClientExtensions.cs
new file mode 100644
index 0000000000..4795ff1403
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AgentsClientExtensions.cs
@@ -0,0 +1,893 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.AzureAIAgents;
+using Microsoft.Extensions.AI;
+using Microsoft.Shared.Diagnostics;
+using OpenAI;
+using OpenAI.Responses;
+
+#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+namespace Azure.AI.Agents;
+
+///
+/// Provides extension methods for .
+///
+public static class AgentsClientExtensions
+{
+ ///
+ /// Gets a runnable agent instance from the provided agent record.
+ ///
+ /// The client used to interact with Azure AI Agents. Cannot be .
+ /// The model to be used by the agent.
+ /// The agent record to be converted. The latest version will be used. Cannot be .
+ /// The default to use when interacting with the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the latest version of the Azure AI Agent.
+ public static ChatClientAgent GetAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ AgentRecord agentRecord,
+ ChatOptions? chatOptions = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNull(agentRecord);
+
+ return GetAIAgent(agentsClient, model, agentRecord.Versions.Latest, chatOptions, clientFactory, openAIClientOptions, cancellationToken);
+ }
+
+ ///
+ /// Gets a runnable agent instance from the provided agent record.
+ ///
+ /// The client used to interact with Azure AI Agents. Cannot be .
+ /// The model to be used by the agent. Cannot be .
+ /// The agent version to be converted. Cannot be .
+ /// The default to use when interacting with the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the specified version of the Azure AI Agent.
+ /// Thrown when , , or is .
+ public static ChatClientAgent GetAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ AgentVersion agentVersion,
+ ChatOptions? chatOptions = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNull(agentVersion);
+
+ return GetAIAgent(agentsClient, model, agentVersion, new ChatClientAgentOptions() { ChatOptions = chatOptions }, clientFactory, openAIClientOptions, cancellationToken);
+ }
+
+ ///
+ /// Retrieves an existing server side agent, wrapped as a using the provided .
+ ///
+ /// The to create the with. Cannot be .
+ /// The model to be used by the agent. Cannot be or whitespace.
+ /// The name of the server side agent to create a for. Cannot be or whitespace.
+ /// The default to use when interacting with the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the latest version of the named Azure AI Agent.
+ /// Thrown when , , or is .
+ /// Thrown when or is empty or whitespace, or when the agent with the specified name was not found.
+ /// The agent with the specified name was not found.
+ public static ChatClientAgent GetAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ string name,
+ ChatOptions? chatOptions = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNullOrWhitespace(name);
+
+ var agentRecord = agentsClient.GetAgent(name, cancellationToken)
+ ?? throw new InvalidOperationException($"Agent with name '{name}' not found.");
+
+ return GetAIAgent(agentsClient, model, agentRecord, chatOptions, clientFactory, openAIClientOptions, cancellationToken);
+ }
+
+ ///
+ /// Asynchronously retrieves an existing server side agent, wrapped as a using the provided .
+ ///
+ /// The to create the with. Cannot be .
+ /// The model to be used by the agent. Cannot be or whitespace.
+ /// The name of the server side agent to create a for. Cannot be or whitespace.
+ /// The default to use when interacting with the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the latest version of the named Azure AI Agent.
+ /// Thrown when , , or is .
+ /// Thrown when or is empty or whitespace, or when the agent with the specified name was not found.
+ /// The agent with the specified name was not found.
+ public static async Task GetAIAgentAsync(
+ this AgentsClient agentsClient,
+ string model,
+ string name,
+ ChatOptions? chatOptions = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNullOrWhitespace(name);
+
+ var agentRecord = await agentsClient.GetAgentAsync(name, cancellationToken).ConfigureAwait(false)
+ ?? throw new InvalidOperationException($"Agent with name '{name}' not found.");
+
+ return GetAIAgent(agentsClient, model, agentRecord, chatOptions, clientFactory, openAIClientOptions, cancellationToken);
+ }
+
+ ///
+ /// Gets a runnable agent instance from a containing metadata about an Azure AI Agent.
+ ///
+ /// The client used to interact with Azure AI Agents. Cannot be .
+ /// The model to be used by the agent.
+ /// The agent record to be converted. The latest version will be used. Cannot be .
+ /// Full set of options to configure the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the latest version of the Azure AI Agent record.
+ /// Thrown when , , or is .
+ public static ChatClientAgent GetAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ AgentRecord agentRecord,
+ ChatClientAgentOptions? options = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNull(agentRecord);
+
+ return GetAIAgent(
+ agentsClient,
+ model,
+ agentRecord.Versions.Latest,
+ options,
+ clientFactory,
+ openAIClientOptions,
+ cancellationToken);
+ }
+
+ ///
+ /// Gets a runnable agent instance from a containing metadata about an Azure AI Agent.
+ ///
+ /// The client used to interact with Azure AI Agents. Cannot be .
+ /// The model to be used by the agent.
+ /// The agent version to be converted. Cannot be .
+ /// Full set of options to configure the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the provided version of the Azure AI Agent.
+ /// Thrown when , , or is .
+ public static ChatClientAgent GetAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ AgentVersion agentVersion,
+ ChatClientAgentOptions? options = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNull(agentVersion);
+ IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, model, openAIClientOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ ChatClientAgentOptions? agentOptions;
+
+ // If options are null, populate from agentRecord definition
+ var version = agentVersion;
+
+ if (options is null)
+ {
+ agentOptions = new();
+ agentOptions.Id = GetAgentId(agentVersion);
+ agentOptions.Name = agentVersion.Name;
+
+ agentOptions.Description = version.Description;
+
+ if (version.Definition is PromptAgentDefinition promptDef && promptDef.Tools is { Count: > 0 })
+ {
+ agentOptions.ChatOptions = new ChatOptions();
+ agentOptions.ChatOptions.Tools = [];
+ agentOptions.Instructions = promptDef.Instructions;
+
+ foreach (var tool in promptDef.Tools)
+ {
+ agentOptions.ChatOptions.Tools.Add(tool);
+ }
+ }
+ }
+ else
+ {
+ // When agent options it is used when available otherwise fallback to the agent definition used for the agent record.
+ agentOptions = new ChatClientAgentOptions()
+ {
+ Id = options.Id ?? GetAgentId(agentVersion),
+ Name = options.Name ?? agentVersion.Name,
+ Description = options.Description ?? version.Description,
+ Instructions = options.Instructions ?? options.ChatOptions?.Instructions ?? (version.Definition as PromptAgentDefinition)?.Instructions,
+ ChatOptions = options.ChatOptions,
+ AIContextProviderFactory = options.AIContextProviderFactory,
+ ChatMessageStoreFactory = options.ChatMessageStoreFactory,
+ UseProvidedChatClientAsIs = options.UseProvidedChatClientAsIs
+ };
+
+ // If no tools were provided in options, but exist in the agent definition, use those.
+ if (agentOptions.ChatOptions?.Tools is null or { Count: 0 } && version.Definition is PromptAgentDefinition promptDef && promptDef.Tools is { Count: > 0 })
+ {
+ agentOptions.ChatOptions ??= new ChatOptions();
+ agentOptions.ChatOptions.Tools ??= [];
+
+ foreach (var tool in promptDef.Tools)
+ {
+ agentOptions.ChatOptions.Tools.Add(tool);
+ }
+ }
+ }
+
+ return new ChatClientAgent(chatClient, agentOptions);
+ }
+
+ ///
+ /// Retrieves an existing server side agent, wrapped as a using the provided .
+ ///
+ /// The to create the with.
+ /// The model to be used by the agent.
+ /// The ID of the server side agent to create a for.
+ /// Full set of options to configure the agent.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations based on the latest version of named the Azure AI Agent.
+ /// Thrown when or is .
+ /// Thrown when is empty or whitespace.
+ public static async Task GetAIAgentAsync(
+ this AgentsClient agentsClient,
+ string model,
+ string name,
+ ChatClientAgentOptions options,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(name);
+ Throw.IfNull(options);
+
+ var agentRecord = await agentsClient.GetAgentAsync(name, cancellationToken).ConfigureAwait(false)
+ ?? throw new InvalidOperationException($"Agent with name '{name}' not found.");
+
+ return GetAIAgent(agentsClient, model, agentRecord, options, clientFactory, openAIClientOptions, cancellationToken);
+ }
+
+ ///
+ /// Creates a new server side agent using the provided .
+ ///
+ /// The to create the agent with.
+ /// The model to be used by the agent.
+ /// The name of the agent.
+ /// The instructions for the agent.
+ /// The description for the agent.
+ /// The tools to be used by the agent.
+ /// The temperature setting for the agent.
+ /// The top-p setting for the agent.
+ /// The responsible AI configuration for the agent.
+ /// The reasoning options for the agent.
+ /// The text options for the agent.
+ /// The structured inputs for the agent.
+ /// The metadata for the agent.
+ /// A factory function to customize the creation of the chat client used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests. The default is .
+ /// A instance that can be used to perform operations on the newly created agent.
+ public static ChatClientAgent CreateAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ string name,
+ string? instructions = null,
+ string? description = null,
+ IList? tools = null,
+ float? temperature = null,
+ float? topP = null,
+ RaiConfig? raiConfig = null,
+ ResponseReasoningOptions? reasoningOptions = null,
+ ResponseTextOptions? textOptions = null,
+ IDictionary? structuredInputs = null,
+ IReadOnlyDictionary? metadata = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNullOrWhitespace(name);
+
+ var (promptAgentDefinition, versionCreationOptions, chatClientAgentOptions) = CreatePromptAgentDefinitionAndOptions(
+ name,
+ model,
+ instructions,
+ description,
+ temperature,
+ topP,
+ raiConfig,
+ reasoningOptions,
+ textOptions,
+ tools,
+ structuredInputs,
+ metadata);
+
+ AgentVersion agentVersion = agentsClient.CreateAgentVersion(name, promptAgentDefinition, versionCreationOptions, cancellationToken);
+ IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, model, openAIClientOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ return new ChatClientAgent(chatClient, chatClientAgentOptions);
+ }
+
+ ///
+ /// Creates a new AI agent using the specified agent definition and optional configuration parameters.
+ ///
+ /// The client used to manage and interact with AI agents. Cannot be .
+ /// The name for the agent.
+ /// The definition that specifies the configuration and behavior of the agent to create. Cannot be .
+ /// The name of the model to use for the agent. Model must be provided either directly or as part of a specialization property.
+ /// Settings that control the creation of the agent.
+ /// A factory function to customize the creation of the chat client used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// A token to monitor for cancellation requests.
+ /// A instance that can be used to perform operations on the newly created agent.
+ /// Thrown when or is .
+ /// Thrown if neither the 'model' parameter nor a model in the agent definition is provided.
+ public static ChatClientAgent CreateAIAgent(
+ this AgentsClient agentsClient,
+ string name,
+ AgentDefinition agentDefinition,
+ string? model = null,
+ AgentCreationOptions? creationOptions = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(name);
+ Throw.IfNull(agentDefinition);
+
+ model ??= (agentDefinition as PromptAgentDefinition)?.Model;
+ if (string.IsNullOrWhiteSpace(model))
+ {
+ throw new ArgumentException("Model must be provided either directly or as part of a PromptAgentDefinition specialization.", nameof(model));
+ }
+
+ AgentRecord agentRecord = agentsClient.CreateAgent(name, agentDefinition, creationOptions, cancellationToken);
+ IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentRecord, model, openAIClientOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ return new ChatClientAgent(chatClient);
+ }
+
+ ///
+ /// Creates a new Prompt AI Agent using the provided and options.
+ ///
+ /// The client used to manage and interact with AI agents. Cannot be .
+ /// The name of the model to use for the agent. Cannot be or whitespace.
+ /// The options for creating the agent. Cannot be .
+ /// A factory function to customize the creation of the chat client used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// A to cancel the operation if needed.
+ /// A instance that can be used to perform operations on the newly created agent.
+ /// Thrown when , , or is .
+ /// Thrown when is empty or whitespace, or when the agent name is not provided in the options.
+ public static ChatClientAgent CreateAIAgent(
+ this AgentsClient agentsClient,
+ string model,
+ ChatClientAgentOptions options,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNull(options);
+
+ if (string.IsNullOrWhiteSpace(options.Name))
+ {
+ throw new ArgumentException("Agent name must be provided in the options.Name property", nameof(options));
+ }
+
+ var (agentDefinition, versionCreationOptions, chatClientAgentOptions) = CreatePromptAgentDefinitionAndOptions(
+ options.Name,
+ model,
+ options.Instructions,
+ options.Description);
+
+ if (options.ChatOptions?.Tools is { Count: > 0 })
+ {
+ foreach (var tool in options.ChatOptions.Tools)
+ {
+ agentDefinition.Tools.Add(ToResponseTool(tool, options.ChatOptions));
+ }
+ }
+
+ AgentVersion agentVersion = agentsClient.CreateAgentVersion(options.Name, agentDefinition, versionCreationOptions, cancellationToken);
+ IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, model, openAIClientOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ chatClientAgentOptions.Id = GetAgentId(agentVersion);
+
+ return new ChatClientAgent(chatClient, chatClientAgentOptions);
+ }
+
+ ///
+ /// Asynchronously creates a new AI agent using the specified agent definition and optional configuration
+ /// parameters.
+ ///
+ /// The client used to manage and interact with AI agents. Cannot be .
+ /// The definition that specifies the configuration and behavior of the agent to create. Cannot be .
+ /// The name of the model to use for the agent. If not specified, the model must be provided as part of the agent definition.
+ /// The name for the agent.
+ /// Settings that control the creation of the agent.
+ /// A factory function to customize the creation of the chat client used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// A token to monitor for cancellation requests.
+ /// A instance that can be used to perform operations on the newly created agent.
+ /// Thrown when or is .
+ /// Thrown if neither the 'model' parameter nor a model in the agent definition is provided.
+ public static async Task CreateAIAgentAsync(
+ this AgentsClient agentsClient,
+ AgentDefinition agentDefinition,
+ string? model = null,
+ string? name = null,
+ AgentVersionCreationOptions? agentVersionCreationOptions = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNull(agentDefinition);
+
+ model ??= (agentDefinition as PromptAgentDefinition)?.Model;
+ if (string.IsNullOrWhiteSpace(model))
+ {
+ throw new ArgumentException("Model must be provided either directly or as part of a PromptAgentDefinition specialization.", nameof(model));
+ }
+
+ AgentVersion agentVersion = await agentsClient.CreateAgentVersionAsync(name, agentDefinition, agentVersionCreationOptions, cancellationToken).ConfigureAwait(false);
+ IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, model, openAIClientOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ List? aiTools = null;
+ if (agentDefinition is PromptAgentDefinition { Tools: { Count: > 0 } definitionTools })
+ {
+ aiTools = definitionTools.Select(rt => rt.AsAITool()).ToList();
+ }
+
+ return new ChatClientAgent(chatClient, new ChatClientAgentOptions()
+ {
+ Id = GetAgentId(agentVersion),
+ Name = name,
+ Description = agentVersionCreationOptions?.Description,
+ Instructions = (agentDefinition as PromptAgentDefinition)?.Instructions,
+ ChatOptions = new ChatOptions()
+ {
+ Tools = aiTools
+ }
+ });
+ }
+
+ ///
+ /// Creates a new server side prompt agent using the provided .
+ ///
+ /// The to create the agent with.
+ /// The model to be used by the agent.
+ /// The name of the agent.
+ /// The instructions for the agent.
+ /// The description for the agent.
+ /// The tools to be used by the agent.
+ /// The temperature setting for the agent.
+ /// The top-p setting for the agent.
+ /// The responsible AI configuration for the agent.
+ /// The reasoning options for the agent.
+ /// The text options for the agent.
+ /// The structured inputs for the agent.
+ /// The metadata for the agent.
+ /// A factory function to customize the creation of the underlying used by the agent.
+ /// An optional for configuring the underlying OpenAI client.
+ /// The to monitor for cancellation requests.
+ /// A instance that can be used to perform operations on the newly created agent.
+ public static async Task CreateAIAgentAsync(
+ this AgentsClient agentsClient,
+ string model,
+ string name,
+ string? instructions = null,
+ string? description = null,
+ IList? tools = null,
+ float? temperature = null,
+ float? topP = null,
+ RaiConfig? raiConfig = null,
+ ResponseReasoningOptions? reasoningOptions = null,
+ ResponseTextOptions? textOptions = null,
+ IDictionary? structuredInputs = null,
+ IReadOnlyDictionary? metadata = null,
+ Func? clientFactory = null,
+ OpenAIClientOptions? openAIClientOptions = null,
+ CancellationToken cancellationToken = default)
+ {
+ Throw.IfNull(agentsClient);
+ Throw.IfNullOrWhitespace(model);
+
+ var (promptAgentDefinition, versionCreationOptions, chatClientAgentOptions) = CreatePromptAgentDefinitionAndOptions(name, model, instructions, description, temperature, topP, raiConfig, reasoningOptions, textOptions, tools, structuredInputs, metadata);
+
+ AgentVersion agentVersion = await agentsClient.CreateAgentVersionAsync(name, promptAgentDefinition, versionCreationOptions, cancellationToken).ConfigureAwait(false);
+ IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, model, openAIClientOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ chatClientAgentOptions.Id = GetAgentId(agentVersion);
+
+ return new ChatClientAgent(chatClient, chatClientAgentOptions);
+ }
+
+ #region Private
+
+ private static (PromptAgentDefinition, AgentVersionCreationOptions?, ChatClientAgentOptions) CreatePromptAgentDefinitionAndOptions(
+ string name,
+ string model,
+ string? instructions,
+ string? description,
+ float? temperature = null,
+ float? topP = null,
+ RaiConfig? raiConfig = null,
+ ResponseReasoningOptions? reasoningOptions = null,
+ ResponseTextOptions? textOptions = null,
+ IList? tools = null,
+ IDictionary? structuredInputs = null,
+ IReadOnlyDictionary? metadata = null)
+ {
+ PromptAgentDefinition promptAgentDefinition = new(model)
+ {
+ Model = model,
+ Instructions = instructions,
+ Temperature = temperature,
+ TopP = topP,
+ RaiConfig = raiConfig,
+ ReasoningOptions = reasoningOptions,
+ TextOptions = textOptions,
+ };
+
+ var chatOptions = new ChatOptions()
+ {
+ TopP = topP,
+ Temperature = temperature,
+ Instructions = instructions,
+ };
+
+ AgentVersionCreationOptions? versionCreationOptions = null;
+ if (metadata is not null)
+ {
+ versionCreationOptions ??= new();
+ foreach (var kvp in metadata)
+ {
+ versionCreationOptions.Metadata.Add(kvp.Key, kvp.Value);
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(description))
+ {
+ (versionCreationOptions ??= new()).Description = description;
+ }
+
+ if (tools is { Count: > 0 })
+ {
+ chatOptions.Tools ??= [];
+
+ foreach (var tool in tools)
+ {
+ chatOptions.Tools.Add(tool);
+ promptAgentDefinition.Tools.Add(tool);
+ }
+ }
+
+ if (structuredInputs is not null)
+ {
+ foreach (var kvp in structuredInputs)
+ {
+ promptAgentDefinition.StructuredInputs.Add(kvp.Key, kvp.Value);
+ }
+ }
+
+ var chatClientAgentOptions = new ChatClientAgentOptions()
+ {
+ Name = name,
+ Instructions = instructions,
+ Description = description,
+ ChatOptions = chatOptions
+ };
+
+ return (promptAgentDefinition, versionCreationOptions, chatClientAgentOptions);
+ }
+
+ private static string GetAgentId(AgentVersion agentVersion)
+ => $"{agentVersion.Name}:{agentVersion.Id}";
+
+ #endregion
+
+ #region Polyfill from MEAI.OpenAI for AITool -> ResponseTool conversion
+
+ // This code will be removed and replaced by the utility tool made public in the PR below for Microsoft.Extensions.AI.OpenAI package
+ // PR https://github.com/dotnet/extensions/pull/6958
+
+ /// Key into AdditionalProperties used to store a strict option.
+ private const string StrictKey = "strictJsonSchema";
+
+ private static FunctionTool ToResponseFunctionTool(AIFunctionDeclaration aiFunction, ChatOptions? options = null)
+ {
+ bool? strict =
+ HasStrict(aiFunction.AdditionalProperties) ??
+ HasStrict(options?.AdditionalProperties);
+
+ return ResponseTool.CreateFunctionTool(
+ aiFunction.Name,
+ ToOpenAIFunctionParameters(aiFunction, strict),
+ strict,
+ aiFunction.Description);
+ }
+
+ /// Gets whether the properties specify that strict schema handling is desired.
+ private static bool? HasStrict(IReadOnlyDictionary? additionalProperties) =>
+ additionalProperties?.TryGetValue(StrictKey, out object? strictObj) is true &&
+ strictObj is bool strictValue ?
+ strictValue : null;
+
+ /// Extracts from an the parameters and strictness setting for use with OpenAI's APIs.
+ private static BinaryData ToOpenAIFunctionParameters(AIFunctionDeclaration aiFunction, bool? strict)
+ {
+ // Perform any desirable transformations on the function's JSON schema, if it'll be used in a strict setting.
+ JsonElement jsonSchema = strict is true ?
+ GetStrictSchemaTransformCache().GetOrCreateTransformedSchema(aiFunction) :
+ aiFunction.JsonSchema;
+
+ // Roundtrip the schema through the ToolJson model type to remove extra properties
+ // and force missing ones into existence, then return the serialized UTF8 bytes as BinaryData.
+ var tool = JsonSerializer.Deserialize(jsonSchema, AgentsClientJsonContext.Default.ToolJson)!;
+ return BinaryData.FromBytes(JsonSerializer.SerializeToUtf8Bytes(tool, AgentsClientJsonContext.Default.ToolJson));
+ }
+
+ ///
+ /// Gets the JSON schema transformer cache conforming to OpenAI strict / structured output restrictions per
+ /// https://platform.openai.com/docs/guides/structured-outputs?api-mode=responses#supported-schemas.
+ ///
+ private static AIJsonSchemaTransformCache GetStrictSchemaTransformCache() => new(new()
+ {
+ DisallowAdditionalProperties = true,
+ ConvertBooleanSchemas = true,
+ MoveDefaultKeywordToDescription = true,
+ RequireAllProperties = true,
+ TransformSchemaNode = (ctx, node) =>
+ {
+ // Move content from common but unsupported properties to description. In particular, we focus on properties that
+ // the AIJsonUtilities schema generator might produce and/or that are explicitly mentioned in the OpenAI documentation.
+
+ if (node is JsonObject schemaObj)
+ {
+ StringBuilder? additionalDescription = null;
+
+ ReadOnlySpan unsupportedProperties =
+ [
+ // Produced by AIJsonUtilities but not in allow list at https://platform.openai.com/docs/guides/structured-outputs#supported-properties:
+ "contentEncoding", "contentMediaType", "not",
+
+ // Explicitly mentioned at https://platform.openai.com/docs/guides/structured-outputs?api-mode=responses#key-ordering as being unsupported with some models:
+ "minLength", "maxLength", "pattern", "format",
+ "minimum", "maximum", "multipleOf",
+ "patternProperties",
+ "minItems", "maxItems",
+
+ // Explicitly mentioned at https://learn.microsoft.com/azure/ai-services/openai/how-to/structured-outputs?pivots=programming-language-csharp&tabs=python-secure%2Cdotnet-entra-id#unsupported-type-specific-keywords
+ // as being unsupported with Azure OpenAI:
+ "unevaluatedProperties", "propertyNames", "minProperties", "maxProperties",
+ "unevaluatedItems", "contains", "minContains", "maxContains", "uniqueItems",
+ ];
+
+ foreach (string propName in unsupportedProperties)
+ {
+ if (schemaObj[propName] is { } propNode)
+ {
+ _ = schemaObj.Remove(propName);
+ AppendLine(ref additionalDescription, propName, propNode);
+ }
+ }
+
+ if (additionalDescription is not null)
+ {
+ schemaObj["description"] = schemaObj["description"] is { } descriptionNode && descriptionNode.GetValueKind() == JsonValueKind.String ?
+ $"{descriptionNode.GetValue()}{Environment.NewLine}{additionalDescription}" :
+ additionalDescription.ToString();
+ }
+
+ return node;
+
+ static void AppendLine(ref StringBuilder? sb, string propName, JsonNode propNode)
+ {
+ sb ??= new();
+
+ if (sb.Length > 0)
+ {
+ _ = sb.AppendLine();
+ }
+
+ _ = sb.Append(propName).Append(": ").Append(propNode);
+ }
+ }
+
+ return node;
+ },
+ });
+
+ private static ResponseTool ToResponseTool(AITool tool, ChatOptions options)
+ {
+ switch (tool)
+ {
+ case AIFunctionDeclaration aiFunction:
+ return ToResponseFunctionTool(aiFunction, options);
+
+ case HostedWebSearchTool webSearchTool:
+ WebSearchToolLocation? location = null;
+ if (webSearchTool.AdditionalProperties.TryGetValue(nameof(WebSearchToolLocation), out object? objLocation))
+ {
+ location = objLocation as WebSearchToolLocation;
+ }
+
+ WebSearchToolContextSize? size = null;
+ if (webSearchTool.AdditionalProperties.TryGetValue(nameof(WebSearchToolContextSize), out object? objSize) &&
+ objSize is WebSearchToolContextSize)
+ {
+ size = (WebSearchToolContextSize)objSize;
+ }
+
+ return ResponseTool.CreateWebSearchTool(location, size);
+
+ case HostedFileSearchTool fileSearchTool:
+ return ResponseTool.CreateFileSearchTool(
+ fileSearchTool.Inputs?.OfType().Select(c => c.VectorStoreId) ?? [],
+ fileSearchTool.MaximumResultCount);
+
+ case HostedCodeInterpreterTool codeTool:
+ return ResponseTool.CreateCodeInterpreterTool(
+ new CodeInterpreterToolContainer(codeTool.Inputs?.OfType().Select(f => f.FileId).ToList() is { Count: > 0 } ids ?
+ CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration(ids) :
+ new()));
+
+ case HostedMcpServerTool mcpTool:
+ McpTool responsesMcpTool = Uri.TryCreate(mcpTool.ServerAddress, UriKind.Absolute, out Uri? url) ?
+ ResponseTool.CreateMcpTool(
+ mcpTool.ServerName,
+ url,
+ mcpTool.AuthorizationToken,
+ mcpTool.ServerDescription) :
+ ResponseTool.CreateMcpTool(
+ mcpTool.ServerName,
+ new McpToolConnectorId(mcpTool.ServerAddress),
+ mcpTool.AuthorizationToken,
+ mcpTool.ServerDescription);
+
+ if (mcpTool.AllowedTools is not null)
+ {
+ responsesMcpTool.AllowedTools = new();
+ AddAllMcpFilters(mcpTool.AllowedTools, responsesMcpTool.AllowedTools);
+ }
+
+ switch (mcpTool.ApprovalMode)
+ {
+ case HostedMcpServerToolAlwaysRequireApprovalMode:
+ responsesMcpTool.ToolCallApprovalPolicy = new McpToolCallApprovalPolicy(GlobalMcpToolCallApprovalPolicy.AlwaysRequireApproval);
+ break;
+
+ case HostedMcpServerToolNeverRequireApprovalMode:
+ responsesMcpTool.ToolCallApprovalPolicy = new McpToolCallApprovalPolicy(GlobalMcpToolCallApprovalPolicy.NeverRequireApproval);
+ break;
+
+ case HostedMcpServerToolRequireSpecificApprovalMode specificMode:
+ responsesMcpTool.ToolCallApprovalPolicy = new McpToolCallApprovalPolicy(new CustomMcpToolCallApprovalPolicy());
+
+ if (specificMode.AlwaysRequireApprovalToolNames is { Count: > 0 } alwaysRequireToolNames)
+ {
+ responsesMcpTool.ToolCallApprovalPolicy.CustomPolicy.ToolsAlwaysRequiringApproval = new();
+ AddAllMcpFilters(alwaysRequireToolNames, responsesMcpTool.ToolCallApprovalPolicy.CustomPolicy.ToolsAlwaysRequiringApproval);
+ }
+
+ if (specificMode.NeverRequireApprovalToolNames is { Count: > 0 } neverRequireToolNames)
+ {
+ responsesMcpTool.ToolCallApprovalPolicy.CustomPolicy.ToolsNeverRequiringApproval = new();
+ AddAllMcpFilters(neverRequireToolNames, responsesMcpTool.ToolCallApprovalPolicy.CustomPolicy.ToolsNeverRequiringApproval);
+ }
+
+ break;
+ }
+
+ return responsesMcpTool;
+
+ default:
+ throw new NotSupportedException($"Tool of type '{tool.GetType().FullName}' is not supported.");
+ }
+ }
+
+ private static void AddAllMcpFilters(IList toolNames, McpToolFilter filter)
+ {
+ foreach (var toolName in toolNames)
+ {
+ filter.ToolNames.Add(toolName);
+ }
+ }
+
+ /// Used to create the JSON payload for an OpenAI tool description.
+ internal sealed class ToolJson
+ {
+ [JsonPropertyName("type")]
+ public string Type { get; set; } = "object";
+
+ [JsonPropertyName("required")]
+ public HashSet Required { get; set; } = [];
+
+ [JsonPropertyName("properties")]
+ public Dictionary Properties { get; set; } = [];
+
+ [JsonPropertyName("additionalProperties")]
+ public bool AdditionalProperties { get; set; }
+ }
+
+ #endregion
+}
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AgentsClientJsonContext.cs b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AgentsClientJsonContext.cs
new file mode 100644
index 0000000000..d54bd5ff8a
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AgentsClientJsonContext.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+namespace Azure.AI.Agents;
+
+/// Source-generated JSON type information for use by all OpenAI implementations.
+[JsonSourceGenerationOptions(JsonSerializerDefaults.Web,
+ UseStringEnumConverter = true,
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
+ WriteIndented = true)]
+[JsonSerializable(typeof(AgentsClientExtensions.ToolJson))]
+internal sealed partial class AgentsClientJsonContext : JsonSerializerContext;
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AzureAIAgentChatClient.cs b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AzureAIAgentChatClient.cs
new file mode 100644
index 0000000000..9177a63e06
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/AzureAIAgentChatClient.cs
@@ -0,0 +1,110 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Runtime.CompilerServices;
+using Azure.AI.Agents;
+using Microsoft.Extensions.AI;
+using Microsoft.Shared.Diagnostics;
+using OpenAI;
+using OpenAI.Responses;
+
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+namespace Microsoft.Agents.AI.AzureAIAgents;
+
+///
+/// Provides a chat client implementation that integrates with Azure AI Agents, enabling chat interactions using
+/// Azure-specific agent capabilities.
+///
+internal sealed class AzureAIAgentChatClient : DelegatingChatClient
+{
+ private readonly ChatClientMetadata? _metadata;
+ private readonly AgentsClient _agentsClient;
+ private readonly AgentVersion _agentVersion;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of to interact with Azure AI Agents services.
+ /// An instance of representing the specific agent to use.
+ /// The AI model to use for the chat client.
+ /// An optional for configuring the underlying OpenAI client.
+ ///
+ /// The provided should be decorated with a for proper functionality.
+ ///
+ internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentRecord agentRecord, string model, OpenAIClientOptions? openAIClientOptions = null)
+ : this(agentsClient, Throw.IfNull(agentRecord).Versions.Latest, model, openAIClientOptions)
+ {
+ }
+
+ internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentVersion agentVersion, string model, OpenAIClientOptions? openAIClientOptions = null)
+ : base(agentsClient.GetOpenAIClient(openAIClientOptions).GetOpenAIResponseClient(model).AsIChatClient())
+ {
+ this._agentsClient = Throw.IfNull(agentsClient);
+ this._agentVersion = Throw.IfNull(agentVersion);
+ this._metadata = new ChatClientMetadata("azure.ai.agents");
+ }
+
+ ///
+ public override object? GetService(Type serviceType, object? serviceKey = null)
+ {
+ return (serviceKey is null && serviceType == typeof(ChatClientMetadata))
+ ? this._metadata
+ : (serviceKey is null && serviceType == typeof(AgentsClient))
+ ? this._agentsClient
+ : (serviceKey is null && serviceType == typeof(AgentVersion))
+ ? this._agentVersion
+ : base.GetService(serviceType, serviceKey);
+ }
+
+ ///
+ public override async Task GetResponseAsync(IEnumerable messages, ChatOptions? options = null, CancellationToken cancellationToken = default)
+ {
+ var conversation = await this.GetOrCreateConversationAsync(messages, options, cancellationToken).ConfigureAwait(false);
+ var conversationOptions = this.GetConversationEnabledChatOptions(options, conversation);
+
+ return await base.GetResponseAsync(messages, conversationOptions, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ public async override IAsyncEnumerable GetStreamingResponseAsync(IEnumerable messages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ var conversation = await this.GetOrCreateConversationAsync(messages, options, cancellationToken).ConfigureAwait(false);
+ var conversationOptions = this.GetConversationEnabledChatOptions(options, conversation);
+
+ await foreach (var chunk in base.GetStreamingResponseAsync(messages, conversationOptions, cancellationToken).ConfigureAwait(false))
+ {
+ yield return chunk;
+ }
+ }
+
+ private async Task GetOrCreateConversationAsync(IEnumerable messages, ChatOptions? options, CancellationToken cancellationToken)
+ => string.IsNullOrWhiteSpace(options?.ConversationId)
+ ? await this._agentsClient.GetConversationClient().CreateConversationAsync(cancellationToken: cancellationToken).ConfigureAwait(false)
+ : await this._agentsClient.GetConversationClient().GetConversationAsync(options.ConversationId, cancellationToken: cancellationToken).ConfigureAwait(false);
+
+ private ChatOptions GetConversationEnabledChatOptions(ChatOptions? chatOptions, AgentConversation agentConversation)
+ {
+ var conversationChatOptions = chatOptions is null ? new ChatOptions() : chatOptions.Clone();
+
+ var originalFactory = conversationChatOptions.RawRepresentationFactory;
+ conversationChatOptions.RawRepresentationFactory = (client) =>
+ {
+ if (originalFactory?.Invoke(this) is not ResponseCreationOptions responseCreationOptions)
+ {
+ responseCreationOptions = new ResponseCreationOptions();
+ }
+
+ responseCreationOptions.SetAgentReference(this._agentVersion.Name);
+ responseCreationOptions.SetConversationReference(agentConversation);
+
+ return responseCreationOptions;
+ };
+
+ // Clear out the conversation ID to prevent the inner client from attempting to use it as a PreviousResponseId
+ conversationChatOptions.ConversationId = null;
+ // Clear out any instructions to avoid conflicts with the agent's instructions
+ conversationChatOptions.Instructions = null;
+
+ return conversationChatOptions;
+ }
+}
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/Microsoft.Agents.AI.AzureAIAgents.csproj b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/Microsoft.Agents.AI.AzureAIAgents.csproj
new file mode 100644
index 0000000000..6f662416e2
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAIAgents/Microsoft.Agents.AI.AzureAIAgents.csproj
@@ -0,0 +1,29 @@
+
+
+
+ $(ProjectsTargetFrameworks)
+ $(ProjectsDebugTargetFrameworks)
+ alpha
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Microsoft Agent Framework Azure AI Agents
+ Provides Microsoft Agent Framework support for Azure AI Agents.
+
+
+
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs
index d223a65e28..fbb087a153 100644
--- a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs
+++ b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs
@@ -68,7 +68,7 @@ public async Task CreateChatClientAgentAsync(
string name = "HelpfulAssistant",
string instructions = "You are a helpful assistant.",
IList? aiTools = null) =>
- new ChatClientAgent(
+ new(
this._openAIResponseClient.AsIChatClient(),
options: new()
{