diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index 9833c90209..ddbad00eb2 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -113,6 +113,7 @@ + diff --git a/dotnet/samples/GettingStarted/GettingStarted.csproj b/dotnet/samples/GettingStarted/GettingStarted.csproj index b34401f6d7..504524ea1b 100644 --- a/dotnet/samples/GettingStarted/GettingStarted.csproj +++ b/dotnet/samples/GettingStarted/GettingStarted.csproj @@ -29,6 +29,7 @@ + diff --git a/dotnet/samples/GettingStarted/Providers/ChatClientAgent_With_AzureAIAgentsPersistent.cs b/dotnet/samples/GettingStarted/Providers/ChatClientAgent_With_AzureAIAgentsPersistent.cs index 5c685c36eb..4b065eb614 100644 --- a/dotnet/samples/GettingStarted/Providers/ChatClientAgent_With_AzureAIAgentsPersistent.cs +++ b/dotnet/samples/GettingStarted/Providers/ChatClientAgent_With_AzureAIAgentsPersistent.cs @@ -2,7 +2,6 @@ using Azure.AI.Agents.Persistent; using Azure.Identity; -using Microsoft.Extensions.AI; using Microsoft.Extensions.AI.Agents; using Microsoft.Shared.Samples; @@ -25,19 +24,14 @@ public sealed class ChatClientAgent_With_AzureAIAgentsPersistent(ITestOutputHelp // Get a client to create server side agents with. var persistentAgentsClient = new PersistentAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential()); - // Create a server side agent to work with. - var persistentAgentResponse = await persistentAgentsClient.Administration.CreateAgentAsync( + // Create a server side persistent agent. + var createPersistentAgentResponse = await persistentAgentsClient.Administration.CreateAgentAsync( model: TestConfiguration.AzureAI.DeploymentName, name: JokerName, instructions: JokerInstructions); - var persistentAgent = persistentAgentResponse.Value; - - // Get the chat client to use for the agent. - using var chatClient = persistentAgentsClient.AsIChatClient(persistentAgent.Id); - - // Define the agent. - ChatClientAgent agent = new(chatClient); + // Get a local proxy for the agent to work with. + Agent agent = await persistentAgentsClient.GetRunnableAgentAsync(createPersistentAgentResponse.Value.Id); // Start a new thread for the agent conversation. AgentThread thread = agent.GetNewThread(); @@ -58,6 +52,6 @@ public sealed class ChatClientAgent_With_AzureAIAgentsPersistent(ITestOutputHelp // Cleanup await persistentAgentsClient.Threads.DeleteThreadAsync(thread.Id); - await persistentAgentsClient.Administration.DeleteAgentAsync(persistentAgent.Id); + await persistentAgentsClient.Administration.DeleteAgentAsync(createPersistentAgentResponse.Value.Id); } } diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/Microsoft.Extensions.AI.Agents.AzureAI.csproj b/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/Microsoft.Extensions.AI.Agents.AzureAI.csproj new file mode 100644 index 0000000000..93a39ef9a8 --- /dev/null +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/Microsoft.Extensions.AI.Agents.AzureAI.csproj @@ -0,0 +1,26 @@ + + + + $(ProjectsTargetFrameworks) + $(ProjectsDebugTargetFrameworks) + alpha + + + + + + + + + + + + + + + + Microsoft.Extensions.AI.Agents.AzureAI + Implementation of generative AI abstractions for Azure AI Persistent Agents. + + + \ No newline at end of file diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/PersistentAgentsClientExtensions.cs b/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/PersistentAgentsClientExtensions.cs new file mode 100644 index 0000000000..fb2a4ed57d --- /dev/null +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/PersistentAgentsClientExtensions.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI.Agents; + +namespace Azure.AI.Agents.Persistent; + +/// +/// Provides extension methods for . +/// +public static class PersistentAgentsClientExtensions +{ + /// + /// 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. + /// 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 GetRunnableAgentAsync( + this PersistentAgentsClient persistentAgentsClient, + string agentId, + ChatOptions? chatOptions = 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 persistentAgentResponse.AsRunnableAgent(persistentAgentsClient, chatOptions); + } +} diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/ResponseExtensions.cs b/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/ResponseExtensions.cs new file mode 100644 index 0000000000..bc9446f163 --- /dev/null +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.AzureAI/ResponseExtensions.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI.Agents; + +namespace Azure.AI.Agents.Persistent; + +/// +/// Provides extension methods for working with . +/// +internal static class PersistentAgentResponseExtensions +{ + /// + /// Converts a response containing persistent agent metadata into a runnable agent instance. + /// + /// The response containing the persistent agent to be converted. Cannot be . + /// The client used to interact with persistent agents. Cannot be . + /// The default to use when interacting with the agent. + /// A instance that can be used to perform operations on the persistent agent. + public static ChatClientAgent AsRunnableAgent(this Response persistentAgentResponse, PersistentAgentsClient persistentAgentsClient, ChatOptions? chatOptions = null) + { + if (persistentAgentResponse is null) + { + throw new ArgumentNullException(nameof(persistentAgentResponse)); + } + + return AsRunnableAgent(persistentAgentResponse.Value, persistentAgentsClient, chatOptions); + } + + /// + /// Converts a containing metadata about a persistent agent into a runnable agent instance. + /// + /// The persistent agent metadata to be converted. Cannot be . + /// The client used to interact with persistent agents. Cannot be . + /// The default to use when interacting with the agent. + /// A instance that can be used to perform operations on the persistent agent. + public static ChatClientAgent AsRunnableAgent(this PersistentAgent persistentAgentMetadata, PersistentAgentsClient persistentAgentsClient, ChatOptions? chatOptions = null) + { + if (persistentAgentMetadata is null) + { + throw new ArgumentNullException(nameof(persistentAgentMetadata)); + } + + if (persistentAgentsClient is null) + { + throw new ArgumentNullException(nameof(persistentAgentsClient)); + } + +#pragma warning disable CA2000 // Dispose objects before losing scope + var chatClient = persistentAgentsClient.AsIChatClient(persistentAgentMetadata.Id); +#pragma warning restore CA2000 // Dispose objects before losing scope + + return new ChatClientAgent(chatClient, options: new() + { + Id = persistentAgentMetadata.Id, + Name = persistentAgentMetadata.Name, + Description = persistentAgentMetadata.Description, + Instructions = persistentAgentMetadata.Instructions, + ChatOptions = chatOptions + }); + } +}