From 0dd49e4a67f761fb307e8ed8e8e7b5e832af2826 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:06:48 +0100 Subject: [PATCH] .NET: Add missing OpenAI `GetAIAgent` extensions (#690) * Wip * Add missing extensions for OpenAI agents * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Remove duplicate xmldoc * Address comment --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../AssistantClientResultExtensions.cs | 62 +++++++++++++++++++ .../OpenAIAssistantClientExtensions.cs | 57 +++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/AssistantClientResultExtensions.cs diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/AssistantClientResultExtensions.cs b/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/AssistantClientResultExtensions.cs new file mode 100644 index 0000000000..6faf65eacb --- /dev/null +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/AssistantClientResultExtensions.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ClientModel; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI.Agents; + +namespace OpenAI.Assistants; + +/// +/// Provides extension methods for working with where T is . +/// +public static class AssistantExtensions +{ + /// + /// Converts a to a . + /// + /// The client result containing the assistant. + /// The assistant client. + /// Optional chat options. + /// A instance that can be used to perform operations on the assistant. + public static ChatClientAgent AsAIAgent(this ClientResult assistantClientResult, AssistantClient assistantClient, ChatOptions? chatOptions = null) + { + if (assistantClientResult is null) + { + throw new ArgumentNullException(nameof(assistantClientResult)); + } + + return AssistantExtensions.AsAIAgent(assistantClientResult, assistantClient, chatOptions); + } + + /// + /// Converts an to a . + /// + /// The assistant metadata. + /// The assistant client. + /// Optional chat options. + /// A instance that can be used to perform operations on the assistant. + public static ChatClientAgent AsAIAgent(this Assistant assistantMetadata, AssistantClient assistantClient, ChatOptions? chatOptions = null) + { + if (assistantMetadata is null) + { + throw new ArgumentNullException(nameof(assistantMetadata)); + } + if (assistantClient is null) + { + throw new ArgumentNullException(nameof(assistantClient)); + } + +#pragma warning disable CA2000 // Dispose objects before losing scope + var chatClient = assistantClient.AsIChatClient(assistantMetadata.Id); +#pragma warning restore CA2000 // Dispose objects before losing scope + + return new ChatClientAgent(chatClient, options: new() + { + Id = assistantMetadata.Id, + Name = assistantMetadata.Name, + Description = assistantMetadata.Description, + Instructions = assistantMetadata.Instructions, + ChatOptions = chatOptions + }); + } +} diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/OpenAIAssistantClientExtensions.cs b/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/OpenAIAssistantClientExtensions.cs index cfba779c1e..60cd192480 100644 --- a/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/OpenAIAssistantClientExtensions.cs +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.OpenAI/Extensions/OpenAIAssistantClientExtensions.cs @@ -20,6 +20,63 @@ namespace OpenAI; /// public static class OpenAIAssistantClientExtensions { + /// + /// 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. + /// Options that should apply to all runs of the agent. + /// The to monitor for cancellation requests. The default is . + /// A instance that can be used to perform operations on the assistant agent. + public static ChatClientAgent GetAIAgent( + this AssistantClient assistantClient, + string agentId, + ChatOptions? chatOptions = null, + CancellationToken cancellationToken = default) + { + if (assistantClient is null) + { + throw new ArgumentNullException(nameof(assistantClient)); + } + + if (string.IsNullOrWhiteSpace(agentId)) + { + throw new ArgumentException($"{nameof(agentId)} should not be null or whitespace.", nameof(agentId)); + } + + var assistant = assistantClient.GetAssistant(agentId, cancellationToken); + return assistant.AsAIAgent(assistantClient, chatOptions); + } + + /// + /// 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. + /// Options that should apply to all runs of the agent. + /// The to monitor for cancellation requests. The default is . + /// A instance that can be used to perform operations on the assistant agent. + public static async Task GetAIAgentAsync( + this AssistantClient assistantClient, + string agentId, + ChatOptions? chatOptions = null, + CancellationToken cancellationToken = default) + { + if (assistantClient is null) + { + throw new ArgumentNullException(nameof(assistantClient)); + } + + if (string.IsNullOrWhiteSpace(agentId)) + { + throw new ArgumentException($"{nameof(agentId)} should not be null or whitespace.", nameof(agentId)); + } + + var assistanceResponse = await assistantClient.GetAssistantAsync(agentId, cancellationToken).ConfigureAwait(false); + + return assistanceResponse.AsAIAgent(assistantClient, chatOptions); + } + /// /// Creates an AI agent from an using the OpenAI Assistant API. ///