.NET: Update Foundry Agents to latest 2.0.0 alpha.20251107.3 (#2050)

* Update extensions for new CreateVersionOptions structure

* Update unit tests

* Addresss capitalized
This commit is contained in:
Roger Barreto
2025-11-10 15:40:37 +00:00
committed by GitHub
Unverified
parent fb1f4e2799
commit 68f79d8bea
17 changed files with 353 additions and 366 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
<PackageVersion Include="Aspire.Microsoft.Azure.Cosmos" Version="$(AspireAppHostSdkVersion)" />
<PackageVersion Include="CommunityToolkit.Aspire.OllamaSharp" Version="9.9.0" />
<!-- Azure.* -->
<PackageVersion Include="Azure.AI.Agents" Version="2.0.0-alpha.20251104.7" />
<PackageVersion Include="Azure.AI.Agents" Version="2.0.0-alpha.20251107.3" />
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.2.0-beta.7" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
<PackageVersion Include="Azure.Identity" Version="1.17.0" />
@@ -13,14 +13,13 @@ const string JokerInstructions = "You are good at telling jokes.";
const string JokerName = "JokerAgent";
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
var agentsClient = new AgentClient(new Uri(endpoint), new AzureCliCredential());
// Define the agent you want to create. (Prompt Agent in this case)
var agentDefinition = new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions };
var agentVersionCreationOptions = new AgentVersionCreationOptions(new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions });
// Azure.AI.Agents SDK creates and manages agent by name and versions.
// You can create a server side agent version with the Azure.AI.Agents SDK client below.
var agentVersion = agentsClient.CreateAgentVersion(agentName: JokerName, definition: agentDefinition);
var agentVersion = agentsClient.CreateAgentVersion(agentName: JokerName, options: agentVersionCreationOptions);
// Note:
// agentVersion.Id = "<agentName>:<versionNumber>",
@@ -46,39 +46,39 @@ internal sealed class Program
private static async Task CreateAgentsAsync(Uri foundryEndpoint, IConfiguration configuration)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "ResearchAgent",
agentDefinition: DefineResearchAgent(configuration),
agentDescription: "Planner agent for DeepResearch workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "PlannerAgent",
agentDefinition: DefinePlannerAgent(configuration),
agentDescription: "Planner agent for DeepResearch workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "ManagerAgent",
agentDefinition: DefineManagerAgent(configuration),
agentDescription: "Manager agent for DeepResearch workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "SummaryAgent",
agentDefinition: DefineSummaryAgent(configuration),
agentDescription: "Summary agent for DeepResearch workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "KnowledgeAgent",
agentDefinition: DefineKnowledgeAgent(configuration),
agentDescription: "Research agent for DeepResearch workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "CoderAgent",
agentDefinition: DefineCoderAgent(configuration),
agentDescription: "Coder agent for DeepResearch workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "WeatherAgent",
agentDefinition: DefineWeatherAgent(configuration),
agentDescription: "Weather agent for DeepResearch workflow");
@@ -55,9 +55,9 @@ internal sealed class Program
private static async Task CreateAgentAsync(Uri foundryEndpoint, IConfiguration configuration, AIFunction[] functions)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "MenuAgent",
agentDefinition: DefineMenuAgent(configuration, functions),
agentDescription: "Provides information about the restaurant menu");
@@ -45,19 +45,19 @@ internal sealed class Program
private static async Task CreateAgentsAsync(Uri foundryEndpoint, IConfiguration configuration)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "AnalystAgent",
agentDefinition: DefineAnalystAgent(configuration),
agentDescription: "Analyst agent for Marketing workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "WriterAgent",
agentDefinition: DefineWriterAgent(configuration),
agentDescription: "Writer agent for Marketing workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "EditorAgent",
agentDefinition: DefineEditorAgent(configuration),
agentDescription: "Editor agent for Marketing workflow");
@@ -45,14 +45,14 @@ internal sealed class Program
private static async Task CreateAgentsAsync(Uri foundryEndpoint, IConfiguration configuration)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "StudentAgent",
agentDefinition: DefineStudentAgent(configuration),
agentDescription: "Student agent for MathChat workflow");
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "TeacherAgent",
agentDefinition: DefineTeacherAgent(configuration),
agentDescription: "Teacher agent for MathChat workflow");
@@ -46,9 +46,9 @@ internal sealed class Program
private static async Task CreateAgentAsync(Uri foundryEndpoint, IConfiguration configuration)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "DocumentSearchAgent",
agentDefinition: DefineSearchAgent(configuration),
agentDescription: "Searches documents on Microsoft Learn");
@@ -13,14 +13,14 @@ using OpenAI.Responses;
namespace Azure.AI.Agents;
/// <summary>
/// Provides extension methods for <see cref="AgentsClient"/>.
/// Provides extension methods for <see cref="AgentClient"/>.
/// </summary>
public static class AgentsClientExtensions
public static class AgentClientExtensions
{
/// <summary>
/// Retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="AgentsClient"/>.
/// Retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="AgentClient"/>.
/// </summary>
/// <param name="agentsClient">The <see cref="AgentsClient"/> to create the <see cref="ChatClientAgent"/> with. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The <see cref="AgentClient"/> to create the <see cref="ChatClientAgent"/> with. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name of the server side agent to create a <see cref="ChatClientAgent"/> for. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
@@ -28,12 +28,12 @@ public static class AgentsClientExtensions
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the latest version of the named Azure AI Agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="name"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="name"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="name"/> is empty or whitespace, or when the agent with the specified name was not found.</exception>
/// <exception cref="InvalidOperationException">The agent with the specified name was not found.</exception>
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
public static ChatClientAgent GetAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
IList<AITool>? tools = null,
Func<IChatClient, IChatClient>? clientFactory = null,
@@ -41,14 +41,14 @@ public static class AgentsClientExtensions
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNullOrWhitespace(name);
var agentRecord = agentsClient.GetAgent(name, cancellationToken).Value
var agentRecord = AgentClient.GetAgent(name, cancellationToken).Value
?? throw new InvalidOperationException($"Agent with name '{name}' not found.");
return GetAIAgent(
agentsClient,
AgentClient,
agentRecord,
tools,
clientFactory,
@@ -58,9 +58,9 @@ public static class AgentsClientExtensions
}
/// <summary>
/// Asynchronously retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="AgentsClient"/>.
/// Asynchronously retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="AgentClient"/>.
/// </summary>
/// <param name="agentsClient">The <see cref="AgentsClient"/> to create the <see cref="ChatClientAgent"/> with. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The <see cref="AgentClient"/> to create the <see cref="ChatClientAgent"/> with. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name of the server side agent to create a <see cref="ChatClientAgent"/> for. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
@@ -68,12 +68,12 @@ public static class AgentsClientExtensions
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the latest version of the named Azure AI Agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="name"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="name"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="name"/> is empty or whitespace, or when the agent with the specified name was not found.</exception>
/// <exception cref="InvalidOperationException">The agent with the specified name was not found.</exception>
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
public static async Task<ChatClientAgent> GetAIAgentAsync(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
IList<AITool>? tools = null,
Func<IChatClient, IChatClient>? clientFactory = null,
@@ -81,14 +81,14 @@ public static class AgentsClientExtensions
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNullOrWhitespace(name);
var agentRecord = (await agentsClient.GetAgentAsync(name, cancellationToken).ConfigureAwait(false)).Value
var agentRecord = (await AgentClient.GetAgentAsync(name, cancellationToken).ConfigureAwait(false)).Value
?? throw new InvalidOperationException($"Agent with name '{name}' not found.");
return GetAIAgent(
agentsClient,
AgentClient,
agentRecord,
tools,
clientFactory,
@@ -100,7 +100,7 @@ public static class AgentsClientExtensions
/// <summary>
/// Gets a runnable agent instance from the provided agent record.
/// </summary>
/// <param name="agentsClient">The client used to interact with Azure AI Agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to interact with Azure AI Agents. Cannot be <see langword="null"/>.</param>
/// <param name="agentRecord">The agent record to be converted. The latest version will be used. Cannot be <see langword="null"/>.</param>
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
@@ -110,7 +110,7 @@ public static class AgentsClientExtensions
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the latest version of the Azure AI Agent.</returns>
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
public static ChatClientAgent GetAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
AgentRecord agentRecord,
IList<AITool>? tools = null,
Func<IChatClient, IChatClient>? clientFactory = null,
@@ -118,11 +118,11 @@ public static class AgentsClientExtensions
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNull(agentRecord);
return GetAIAgent(
agentsClient,
AgentClient,
agentRecord.Versions.Latest,
tools,
clientFactory,
@@ -134,7 +134,7 @@ public static class AgentsClientExtensions
/// <summary>
/// Gets a runnable agent instance from a <see cref="AgentVersion"/> containing metadata about an Azure AI Agent.
/// </summary>
/// <param name="agentsClient">The client used to interact with Azure AI Agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to interact with Azure AI Agents. Cannot be <see langword="null"/>.</param>
/// <param name="agentVersion">The agent version to be converted. Cannot be <see langword="null"/>.</param>
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
@@ -142,10 +142,10 @@ public static class AgentsClientExtensions
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the provided version of the Azure AI Agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="agentVersion"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="agentVersion"/> is <see langword="null"/>.</exception>
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
public static ChatClientAgent GetAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
AgentVersion agentVersion,
IList<AITool>? tools = null,
Func<IChatClient, IChatClient>? clientFactory = null,
@@ -153,13 +153,13 @@ public static class AgentsClientExtensions
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNull(agentVersion);
ValidateUsingToolsParameter(agentVersion, tools);
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
tools,
clientFactory,
@@ -169,25 +169,25 @@ public static class AgentsClientExtensions
}
/// <summary>
/// Creates a new Prompt AI Agent using the provided <see cref="AgentsClient"/> and options.
/// Creates a new Prompt AI Agent using the provided <see cref="AgentClient"/> and options.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
public static ChatClientAgent GetAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
ChatClientAgentOptions options,
Func<IChatClient, IChatClient>? clientFactory = null,
OpenAIClientOptions? openAIClientOptions = null,
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNull(options);
if (string.IsNullOrWhiteSpace(options.Name))
@@ -195,7 +195,7 @@ public static class AgentsClientExtensions
throw new ArgumentException("Agent name must be provided in the options.Name property", nameof(options));
}
var agentRecord = agentsClient.GetAgent(options.Name, cancellationToken).Value
var agentRecord = AgentClient.GetAgent(options.Name, cancellationToken).Value
?? throw new InvalidOperationException($"Agent with name '{options.Name}' not found.");
var agentVersion = agentRecord.Versions.Latest;
@@ -203,7 +203,7 @@ public static class AgentsClientExtensions
var agentOptions = CreateChatClientAgentOptions(agentVersion, options, requireInvocableTools: true);
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
agentOptions,
clientFactory,
@@ -213,25 +213,25 @@ public static class AgentsClientExtensions
}
/// <summary>
/// Creates a new Prompt AI Agent using the provided <see cref="AgentsClient"/> and options.
/// Creates a new Prompt AI Agent using the provided <see cref="AgentClient"/> and options.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
public static async Task<ChatClientAgent> GetAIAgentAsync(
this AgentsClient agentsClient,
this AgentClient AgentClient,
ChatClientAgentOptions options,
Func<IChatClient, IChatClient>? clientFactory = null,
OpenAIClientOptions? openAIClientOptions = null,
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNull(options);
if (string.IsNullOrWhiteSpace(options.Name))
@@ -239,7 +239,7 @@ public static class AgentsClientExtensions
throw new ArgumentException("Agent name must be provided in the options.Name property", nameof(options));
}
var agentRecord = (await agentsClient.GetAgentAsync(options.Name, cancellationToken).ConfigureAwait(false)).Value
var agentRecord = (await AgentClient.GetAgentAsync(options.Name, cancellationToken).ConfigureAwait(false)).Value
?? throw new InvalidOperationException($"Agent with name '{options.Name}' not found.");
var agentVersion = agentRecord.Versions.Latest;
@@ -247,7 +247,7 @@ public static class AgentsClientExtensions
var agentOptions = CreateChatClientAgentOptions(agentVersion, options, requireInvocableTools: true);
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
agentOptions,
clientFactory,
@@ -259,43 +259,42 @@ public static class AgentsClientExtensions
/// <summary>
/// Creates a new Prompt AI agent using the specified configuration parameters.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name for the agent.</param>
/// <param name="model">The name of the model to use for the agent. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="instructions">The instructions that guide the agent's behavior. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="description">The description for the agent.</param>
/// <param name="tools">The tools to use when interacting with the agent, this is required when using prompt agent definitions with tools.</param>
/// <param name="creationOptions">Settings that control the creation of the agent.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/>, <paramref name="model"/>, or <paramref name="instructions"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/>, <paramref name="model"/>, or <paramref name="instructions"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="model"/> or <paramref name="instructions"/> is empty or whitespace.</exception>
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
public static ChatClientAgent CreateAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
string model,
string instructions,
string? description = null,
IList<AITool>? tools = null,
AgentVersionCreationOptions? creationOptions = null,
Func<IChatClient, IChatClient>? clientFactory = null,
OpenAIClientOptions? openAIClientOptions = null,
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNullOrWhitespace(name);
Throw.IfNullOrWhitespace(model);
Throw.IfNullOrWhitespace(instructions);
return CreateAIAgent(
agentsClient,
AgentClient,
name,
tools,
new PromptAgentDefinition(model) { Instructions = instructions },
creationOptions,
new AgentVersionCreationOptions(new PromptAgentDefinition(model) { Instructions = instructions }) { Description = description },
clientFactory,
openAIClientOptions,
requireInvocableTools: true,
@@ -306,43 +305,42 @@ public static class AgentsClientExtensions
/// <summary>
/// Creates a new Prompt AI agent using the specified configuration parameters.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name for the agent.</param>
/// <param name="model">The name of the model to use for the agent. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="instructions">The instructions that guide the agent's behavior. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="description">The description for the agent.</param>
/// <param name="tools">The tools to use when interacting with the agent, this is required when using prompt agent definitions with tools.</param>
/// <param name="creationOptions">Settings that control the creation of the agent.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/>, <paramref name="model"/>, or <paramref name="instructions"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/>, <paramref name="model"/>, or <paramref name="instructions"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="model"/> or <paramref name="instructions"/> is empty or whitespace.</exception>
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
public static Task<ChatClientAgent> CreateAIAgentAsync(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
string model,
string instructions,
string? description = null,
IList<AITool>? tools = null,
AgentVersionCreationOptions? creationOptions = null,
Func<IChatClient, IChatClient>? clientFactory = null,
OpenAIClientOptions? openAIClientOptions = null,
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNullOrWhitespace(name);
Throw.IfNullOrWhitespace(model);
Throw.IfNullOrWhitespace(instructions);
return CreateAIAgentAsync(
agentsClient,
AgentClient,
name,
tools,
new PromptAgentDefinition(model) { Instructions = instructions },
creationOptions,
new AgentVersionCreationOptions(new PromptAgentDefinition(model) { Instructions = instructions }) { Description = description },
clientFactory,
openAIClientOptions,
requireInvocableTools: true,
@@ -351,9 +349,9 @@ public static class AgentsClientExtensions
}
/// <summary>
/// Creates a new Prompt AI Agent using the provided <see cref="AgentsClient"/> and options.
/// Creates a new Prompt AI Agent using the provided <see cref="AgentClient"/> and options.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="model">The name of the model to use for the agent. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
@@ -361,10 +359,10 @@ public static class AgentsClientExtensions
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="model"/> is empty or whitespace, or when the agent name is not provided in the options.</exception>
public static ChatClientAgent CreateAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string model,
ChatClientAgentOptions options,
Func<IChatClient, IChatClient>? clientFactory = null,
@@ -372,7 +370,7 @@ public static class AgentsClientExtensions
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNull(options);
Throw.IfNullOrWhitespace(model);
const bool RequireInvocableTools = true;
@@ -389,18 +387,18 @@ public static class AgentsClientExtensions
ApplyToolsToAgentDefinition(agentDefinition, options.ChatOptions?.Tools, RequireInvocableTools);
AgentVersionCreationOptions? versionCreationOptions = null;
AgentVersionCreationOptions? versionCreationOptions = new(agentDefinition);
if (!string.IsNullOrWhiteSpace(options.Description))
{
(versionCreationOptions ??= new()).Description = options.Description;
versionCreationOptions.Description = options.Description;
}
AgentVersion agentVersion = agentsClient.CreateAgentVersion(options.Name, agentDefinition, versionCreationOptions, cancellationToken).Value;
AgentVersion agentVersion = AgentClient.CreateAgentVersion(options.Name, versionCreationOptions, cancellationToken).Value;
var agentOptions = CreateChatClientAgentOptions(agentVersion, options, RequireInvocableTools);
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
agentOptions,
clientFactory,
@@ -410,9 +408,9 @@ public static class AgentsClientExtensions
}
/// <summary>
/// Creates a new Prompt AI Agent using the provided <see cref="AgentsClient"/> and options.
/// Creates a new Prompt AI Agent using the provided <see cref="AgentClient"/> and options.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="model">The name of the model to use for the agent. Cannot be <see langword="null"/> or whitespace.</param>
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
@@ -420,10 +418,10 @@ public static class AgentsClientExtensions
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="model"/> is empty or whitespace, or when the agent name is not provided in the options.</exception>
public static async Task<ChatClientAgent> CreateAIAgentAsync(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string model,
ChatClientAgentOptions options,
Func<IChatClient, IChatClient>? clientFactory = null,
@@ -431,7 +429,7 @@ public static class AgentsClientExtensions
IServiceProvider? services = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNull(options);
Throw.IfNullOrWhitespace(model);
const bool RequireInvocableTools = true;
@@ -448,18 +446,18 @@ public static class AgentsClientExtensions
ApplyToolsToAgentDefinition(agentDefinition, options.ChatOptions?.Tools, RequireInvocableTools);
AgentVersionCreationOptions? versionCreationOptions = null;
AgentVersionCreationOptions? versionCreationOptions = new(agentDefinition);
if (!string.IsNullOrWhiteSpace(options.Description))
{
(versionCreationOptions ??= new()).Description = options.Description;
versionCreationOptions.Description = options.Description;
}
AgentVersion agentVersion = await agentsClient.CreateAgentVersionAsync(options.Name, agentDefinition, versionCreationOptions, cancellationToken).ConfigureAwait(false);
AgentVersion agentVersion = await AgentClient.CreateAgentVersionAsync(options.Name, versionCreationOptions, cancellationToken).ConfigureAwait(false);
var agentOptions = CreateChatClientAgentOptions(agentVersion, options, RequireInvocableTools);
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
agentOptions,
clientFactory,
@@ -471,39 +469,36 @@ public static class AgentsClientExtensions
/// <summary>
/// Creates a new AI agent using the specified agent definition and optional configuration parameters.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name for the agent.</param>
/// <param name="agentDefinition">The definition that specifies the configuration and behavior of the agent to create. Cannot be <see langword="null"/>.</param>
/// <param name="creationOptions">Settings that control the creation of the agent.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="agentDefinition"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="creationOptions"/> is <see langword="null"/>.</exception>
/// <remarks>
/// When using this extension method with a <see cref="PromptAgentDefinition"/> the tools are only declarative and not invocable.
/// Invocation of any in-process tools will need to be handled manually.
/// </remarks>
public static ChatClientAgent CreateAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
AgentDefinition agentDefinition,
AgentVersionCreationOptions? creationOptions = null,
AgentVersionCreationOptions creationOptions,
Func<IChatClient, IChatClient>? clientFactory = null,
OpenAIClientOptions? openAIClientOptions = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNullOrWhitespace(name);
Throw.IfNull(agentDefinition);
Throw.IfNull(creationOptions);
var tools = (agentDefinition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
var tools = (creationOptions.Definition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
return CreateAIAgent(
agentsClient,
AgentClient,
name,
tools,
agentDefinition,
creationOptions,
clientFactory,
openAIClientOptions,
@@ -516,40 +511,37 @@ public static class AgentsClientExtensions
/// Asynchronously creates a new AI agent using the specified agent definition and optional configuration
/// parameters.
/// </summary>
/// <param name="agentsClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="AgentClient">The client used to manage and interact with AI agents. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name for the agent.</param>
/// <param name="agentDefinition">The definition that specifies the configuration and behavior of the agent to create. Cannot be <see langword="null"/>.</param>
/// <param name="agentVersionCreationOptions">Settings that control the creation of the agent.</param>
/// <param name="creationOptions">Settings that control the creation of the agent.</param>
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="agentDefinition"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="AgentClient"/> or <paramref name="creationOptions"/> is <see langword="null"/>.</exception>
/// <remarks>
/// When using this extension method with a <see cref="PromptAgentDefinition"/> the tools are only declarative and not invocable.
/// Invocation of any in-process tools will need to be handled manually.
/// </remarks>
public static Task<ChatClientAgent> CreateAIAgentAsync(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
AgentDefinition agentDefinition,
AgentVersionCreationOptions? agentVersionCreationOptions = null,
AgentVersionCreationOptions creationOptions,
Func<IChatClient, IChatClient>? clientFactory = null,
OpenAIClientOptions? openAIClientOptions = null,
CancellationToken cancellationToken = default)
{
Throw.IfNullOrWhitespace(name);
Throw.IfNull(agentsClient);
Throw.IfNull(agentDefinition);
Throw.IfNull(AgentClient);
Throw.IfNull(creationOptions);
var tools = (agentDefinition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
var tools = (creationOptions.Definition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
return CreateAIAgentAsync(
agentsClient,
AgentClient,
name,
tools,
agentDefinition,
agentVersionCreationOptions,
creationOptions,
clientFactory,
openAIClientOptions,
requireInvocableTools: false,
@@ -560,29 +552,28 @@ public static class AgentsClientExtensions
#region Private
private static ChatClientAgent CreateAIAgent(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
IList<AITool>? tools,
AgentDefinition agentDefinition,
AgentVersionCreationOptions? creationOptions,
AgentVersionCreationOptions creationOptions,
Func<IChatClient, IChatClient>? clientFactory,
OpenAIClientOptions? openAIClientOptions,
bool requireInvocableTools,
IServiceProvider? services,
CancellationToken cancellationToken)
{
Throw.IfNull(agentsClient);
Throw.IfNull(AgentClient);
Throw.IfNullOrWhitespace(name);
Throw.IfNull(agentDefinition);
Throw.IfNull(creationOptions);
tools ??= (agentDefinition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
tools ??= (creationOptions.Definition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
ApplyToolsToAgentDefinition(agentDefinition, tools, requireInvocableTools);
ApplyToolsToAgentDefinition(creationOptions.Definition, tools, requireInvocableTools);
AgentVersion agentVersion = agentsClient.CreateAgentVersion(name, agentDefinition, creationOptions, cancellationToken).Value;
AgentVersion agentVersion = AgentClient.CreateAgentVersion(name, creationOptions, cancellationToken).Value;
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
tools,
clientFactory,
@@ -592,11 +583,10 @@ public static class AgentsClientExtensions
}
private static async Task<ChatClientAgent> CreateAIAgentAsync(
this AgentsClient agentsClient,
this AgentClient AgentClient,
string name,
IList<AITool>? tools,
AgentDefinition agentDefinition,
AgentVersionCreationOptions? agentVersionCreationOptions,
AgentVersionCreationOptions creationOptions,
Func<IChatClient, IChatClient>? clientFactory,
OpenAIClientOptions? openAIClientOptions,
bool requireInvocableTools,
@@ -604,17 +594,17 @@ public static class AgentsClientExtensions
CancellationToken cancellationToken)
{
Throw.IfNullOrWhitespace(name);
Throw.IfNull(agentsClient);
Throw.IfNull(agentDefinition);
Throw.IfNull(AgentClient);
Throw.IfNull(creationOptions);
tools ??= (agentDefinition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
tools ??= (creationOptions.Definition as PromptAgentDefinition)?.Tools.Select(t => t.AsAITool()).ToList();
ApplyToolsToAgentDefinition(agentDefinition, tools, requireInvocableTools);
ApplyToolsToAgentDefinition(creationOptions.Definition, tools, requireInvocableTools);
AgentVersion agentVersion = await agentsClient.CreateAgentVersionAsync(name, agentDefinition, agentVersionCreationOptions, cancellationToken).ConfigureAwait(false);
AgentVersion agentVersion = await AgentClient.CreateAgentVersionAsync(name, creationOptions, cancellationToken).ConfigureAwait(false);
return CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
tools,
clientFactory,
@@ -625,7 +615,7 @@ public static class AgentsClientExtensions
/// <summary>This method creates an <see cref="ChatClientAgent"/> with the specified ChatClientAgentOptions.</summary>
private static ChatClientAgent CreateChatClientAgent(
AgentsClient agentsClient,
AgentClient AgentClient,
AgentVersion agentVersion,
ChatClientAgentOptions agentOptions,
Func<IChatClient, IChatClient>? clientFactory,
@@ -633,7 +623,7 @@ public static class AgentsClientExtensions
bool requireInvocableTools,
IServiceProvider? services)
{
IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, agentOptions.ChatOptions, openAIClientOptions);
IChatClient chatClient = new AzureAIAgentChatClient(AgentClient, agentVersion, agentOptions.ChatOptions, openAIClientOptions);
if (clientFactory is not null)
{
@@ -645,7 +635,7 @@ public static class AgentsClientExtensions
/// <summary>This method creates an <see cref="ChatClientAgent"/> with a auto-generated ChatClientAgentOptions from the specified configuration parameters.</summary>
private static ChatClientAgent CreateChatClientAgent(
AgentsClient agentsClient,
AgentClient AgentClient,
AgentVersion agentVersion,
IList<AITool>? tools,
Func<IChatClient, IChatClient>? clientFactory,
@@ -653,7 +643,7 @@ public static class AgentsClientExtensions
bool requireInvocableTools,
IServiceProvider? services)
=> CreateChatClientAgent(
agentsClient,
AgentClient,
agentVersion,
CreateChatClientAgentOptions(agentVersion, new ChatOptions() { Tools = tools }, requireInvocableTools),
clientFactory,
@@ -20,7 +20,7 @@ namespace Microsoft.Agents.AI.AzureAI;
internal sealed class AzureAIAgentChatClient : DelegatingChatClient
{
private readonly ChatClientMetadata? _metadata;
private readonly AgentsClient _agentsClient;
private readonly AgentClient _agentClient;
private readonly AgentVersion _agentVersion;
private readonly ChatOptions? _chatOptions;
@@ -33,25 +33,25 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
/// <summary>
/// Initializes a new instance of the <see cref="AzureAIAgentChatClient"/> class.
/// </summary>
/// <param name="agentsClient">An instance of <see cref="AgentsClient"/> to interact with Azure AI Agents services.</param>
/// <param name="agentClient">An instance of <see cref="AgentClient"/> to interact with Azure AI Agents services.</param>
/// <param name="agentRecord">An instance of <see cref="AgentRecord"/> representing the specific agent to use.</param>
/// <param name="chatOptions">An instance of <see cref="ChatOptions"/> representing the options on how the agent was predefined.</param>
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
/// <remarks>
/// The <see cref="IChatClient"/> provided should be decorated with a <see cref="AzureAIAgentChatClient"/> for proper functionality.
/// </remarks>
internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentRecord agentRecord, ChatOptions? chatOptions, OpenAIClientOptions? openAIClientOptions = null)
: this(agentsClient, Throw.IfNull(agentRecord).Versions.Latest, chatOptions, openAIClientOptions)
internal AzureAIAgentChatClient(AgentClient agentClient, AgentRecord agentRecord, ChatOptions? chatOptions, OpenAIClientOptions? openAIClientOptions = null)
: this(agentClient, Throw.IfNull(agentRecord).Versions.Latest, chatOptions, openAIClientOptions)
{
}
internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentVersion agentVersion, ChatOptions? chatOptions, OpenAIClientOptions? openAIClientOptions = null)
: base(agentsClient
internal AzureAIAgentChatClient(AgentClient agentClient, AgentVersion agentVersion, ChatOptions? chatOptions, OpenAIClientOptions? openAIClientOptions = null)
: base(agentClient
.GetOpenAIClient(openAIClientOptions)
.GetOpenAIResponseClient((agentVersion.Definition as PromptAgentDefinition)?.Model ?? NoOpModel)
.AsIChatClient())
{
this._agentsClient = Throw.IfNull(agentsClient);
this._agentClient = Throw.IfNull(agentClient);
this._agentVersion = Throw.IfNull(agentVersion);
this._metadata = new ChatClientMetadata("azure.ai.agents");
this._chatOptions = chatOptions;
@@ -62,8 +62,8 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
{
return (serviceKey is null && serviceType == typeof(ChatClientMetadata))
? this._metadata
: (serviceKey is null && serviceType == typeof(AgentsClient))
? this._agentsClient
: (serviceKey is null && serviceType == typeof(AgentClient))
? this._agentClient
: (serviceKey is null && serviceType == typeof(AgentVersion))
? this._agentVersion
: base.GetService(serviceType, serviceKey);
@@ -92,7 +92,7 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
private async Task<string> GetOrCreateConversationAsync(ChatOptions? options, CancellationToken cancellationToken)
=> string.IsNullOrWhiteSpace(options?.ConversationId)
? (await this._agentsClient.GetConversationClient().CreateConversationAsync(cancellationToken: cancellationToken).ConfigureAwait(false)).Value.Id
? (await this._agentClient.GetConversationClient().CreateConversationAsync(cancellationToken: cancellationToken).ConfigureAwait(false)).Value.Id
: options.ConversationId;
private ChatOptions GetConversationEnabledChatOptions(ChatOptions? chatOptions, string conversationId)
@@ -29,7 +29,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
private readonly Dictionary<string, AgentVersion> _versionCache = [];
private readonly Dictionary<string, AIAgent> _agentCache = [];
private AgentsClient? _agentsClient;
private AgentClient? _agentClient;
private ConversationClient? _conversationClient;
/// <inheritdoc/>
@@ -112,7 +112,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
return targetAgent;
}
AgentsClient client = this.GetAgentsClient();
AgentClient client = this.GetAgentClient();
if (string.IsNullOrEmpty(agentVersion))
{
@@ -137,17 +137,17 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
return targetAgent;
}
private async Task<AIAgent> GetAgentAsync(AgentVersion agentDefinition, CancellationToken cancellationToken = default)
private async Task<AIAgent> GetAgentAsync(AgentVersion agentVersion, CancellationToken cancellationToken = default)
{
if (this._agentCache.TryGetValue(agentDefinition.Id, out AIAgent? agent))
if (this._agentCache.TryGetValue(agentVersion.Id, out AIAgent? agent))
{
return agent;
}
AgentsClient client = this.GetAgentsClient();
AgentClient client = this.GetAgentClient();
IList<AITool>? tools = null;
if (agentDefinition.Definition is PromptAgentDefinition promptAgent)
if (agentVersion.Definition is PromptAgentDefinition promptAgent)
{
tools =
promptAgent.Tools
@@ -155,7 +155,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
.ToArray();
}
agent = client.GetAIAgent(agentDefinition, tools, clientFactory: null, openAIClientOptions: null, requireInvocableTools: false, cancellationToken);
agent = client.GetAIAgent(agentVersion, tools, clientFactory: null, openAIClientOptions: null, services: null, cancellationToken);
FunctionInvokingChatClient? functionInvokingClient = agent.GetService<FunctionInvokingChatClient>();
if (functionInvokingClient is not null)
@@ -178,7 +178,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
}
}
this._agentCache[agentDefinition.Id] = agent;
this._agentCache[agentVersion.Id] = agent;
return agent;
}
@@ -200,7 +200,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
bool newestFirst = false,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
AgentsListOrder order = newestFirst ? AgentsListOrder.Asc : AgentsListOrder.Desc;
AgentListOrder order = newestFirst ? AgentListOrder.Ascending : AgentListOrder.Descending;
await foreach (AgentResponseItem responseItem in this.GetConversationClient().GetConversationItemsAsync(conversationId, limit, order, after, before, itemType: null, cancellationToken).ConfigureAwait(false))
{
ResponseItem[] items = [responseItem.AsOpenAIResponseItem()];
@@ -211,30 +211,30 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
}
}
private AgentsClient GetAgentsClient()
private AgentClient GetAgentClient()
{
if (this._agentsClient is null)
if (this._agentClient is null)
{
AgentsClientOptions clientOptions = new();
AgentClientOptions clientOptions = new();
if (httpClient is not null)
{
clientOptions.Transport = new HttpClientPipelineTransport(httpClient);
}
AgentsClient newClient = new(projectEndpoint, projectCredentials, clientOptions);
AgentClient newClient = new(projectEndpoint, projectCredentials, clientOptions);
Interlocked.CompareExchange(ref this._agentsClient, newClient, null);
Interlocked.CompareExchange(ref this._agentClient, newClient, null);
}
return this._agentsClient;
return this._agentClient;
}
private ConversationClient GetConversationClient()
{
if (this._conversationClient is null)
{
ConversationClient conversationClient = this.GetAgentsClient().GetConversationClient();
ConversationClient conversationClient = this.GetAgentClient().GetConversationClient();
Interlocked.CompareExchange(ref this._conversationClient, conversationClient, null);
}
@@ -11,13 +11,13 @@ namespace Shared.Foundry;
internal static class AgentFactory
{
public static async ValueTask<AgentVersion> CreateAgentAsync(
this AgentsClient agentsClient,
this AgentClient agentClient,
string agentName,
PromptAgentDefinition agentDefinition,
string agentDescription)
{
AgentVersionCreationOptions options =
new()
new(agentDefinition)
{
Description = agentDescription,
Metadata =
@@ -27,7 +27,7 @@ internal static class AgentFactory
},
};
AgentVersion agentVersion = await agentsClient.CreateAgentVersionAsync(agentName, agentDefinition, options).ConfigureAwait(false);
AgentVersion agentVersion = await agentClient.CreateAgentVersionAsync(agentName, options).ConfigureAwait(false);
Console.ForegroundColor = ConsoleColor.Cyan;
try
File diff suppressed because it is too large Load Diff
@@ -23,10 +23,10 @@ internal sealed class FunctionToolAgentProvider(IConfiguration configuration) :
AIFunctionFactory.Create(menuPlugin.GetItemPrice),
];
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "MenuAgent",
agentDefinition: this.DefineMenuAgent(functions),
agentDescription: "Provides information about the restaurant menu");
@@ -13,22 +13,22 @@ internal sealed class MarketingAgentProvider(IConfiguration configuration) : Age
{
protected override async IAsyncEnumerable<AgentVersion> CreateAgentsAsync(Uri foundryEndpoint)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "AnalystAgent",
agentDefinition: this.DefineAnalystAgent(),
agentDescription: "Analyst agent for Marketing workflow");
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "WriterAgent",
agentDefinition: this.DefineWriterAgent(),
agentDescription: "Writer agent for Marketing workflow");
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "EditorAgent",
agentDefinition: this.DefineEditorAgent(),
agentDescription: "Editor agent for Marketing workflow");
@@ -13,16 +13,16 @@ internal sealed class MathChatAgentProvider(IConfiguration configuration) : Agen
{
protected override async IAsyncEnumerable<AgentVersion> CreateAgentsAsync(Uri foundryEndpoint)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "StudentAgent",
agentDefinition: this.DefineStudentAgent(),
agentDescription: "Student agent for MathChat workflow");
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "TeacherAgent",
agentDefinition: this.DefineTeacherAgent(),
agentDescription: "Teacher agent for MathChat workflow");
@@ -13,10 +13,10 @@ internal sealed class TestAgentProvider(IConfiguration configuration) : AgentPro
{
protected override async IAsyncEnumerable<AgentVersion> CreateAgentsAsync(Uri foundryEndpoint)
{
AgentsClient agentsClient = new(foundryEndpoint, new AzureCliCredential());
AgentClient agentClient = new(foundryEndpoint, new AzureCliCredential());
yield return
await agentsClient.CreateAgentAsync(
await agentClient.CreateAgentAsync(
agentName: "TestAgent",
agentDefinition: this.DefineMenuAgent(),
agentDescription: "Provides information about the restaurant menu");
@@ -42,7 +42,7 @@ public sealed class MediaInputTest(ITestOutputHelper output) : IntegrationTest(o
public async Task ValidateImageUploadAsync()
{
byte[] imageData = await DownloadFileAsync();
AgentsClient client = new(this.TestEndpoint, new AzureCliCredential());
AgentClient client = new(this.TestEndpoint, new AzureCliCredential());
using MemoryStream contentStream = new(imageData);
OpenAIFileClient fileClient = client.GetOpenAIClient().GetOpenAIFileClient();
OpenAIFile fileInfo = await fileClient.UploadFileAsync(contentStream, "basic-text.pdf", FileUploadPurpose.Assistants);