Add extension methods to get an AF agent from a Foundry Client (#191)

* Add helpers to go from foundry client to agent more easily.

* Fix xml docs.
This commit is contained in:
westey
2025-07-16 15:45:31 +01:00
committed by GitHub
Unverified
parent 95a3264c8b
commit dd32a6d399
6 changed files with 140 additions and 11 deletions
+1
View File
@@ -113,6 +113,7 @@
<Folder Name="/src/">
<Project Path="src/Microsoft.Agents.Orchestration/Microsoft.Agents.Orchestration.csproj" />
<Project Path="src/Microsoft.Extensions.AI.Agents.Abstractions/Microsoft.Extensions.AI.Agents.Abstractions.csproj" />
<Project Path="src/Microsoft.Extensions.AI.Agents.AzureAI/Microsoft.Extensions.AI.Agents.AzureAI.csproj" />
<Project Path="src/Microsoft.Extensions.AI.Agents.CopilotStudio/Microsoft.Extensions.AI.Agents.CopilotStudio.csproj" />
<Project Path="src/Microsoft.Extensions.AI.Agents.Runtime.Abstractions/Microsoft.Extensions.AI.Agents.Runtime.Abstractions.csproj" />
<Project Path="src/Microsoft.Extensions.AI.Agents/Microsoft.Extensions.AI.Agents.csproj" />
@@ -29,6 +29,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Agents.Orchestration\Microsoft.Agents.Orchestration.csproj" />
<ProjectReference Include="..\..\src\Microsoft.Extensions.AI.Agents.AzureAI\Microsoft.Extensions.AI.Agents.AzureAI.csproj" />
<ProjectReference Include="..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
</ItemGroup>
@@ -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);
}
}
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugTargetFrameworks)</TargetFrameworks>
<VersionSuffix>alpha</VersionSuffix>
</PropertyGroup>
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
<ItemGroup>
<PackageReference Include="Azure.AI.Agents.Persistent" />
<PackageReference Include="Microsoft.Extensions.AI" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
</ItemGroup>
<PropertyGroup>
<!-- NuGet Package Settings -->
<Title>Microsoft.Extensions.AI.Agents.AzureAI</Title>
<Description>Implementation of generative AI abstractions for Azure AI Persistent Agents.</Description>
</PropertyGroup>
</Project>
@@ -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;
/// <summary>
/// Provides extension methods for <see cref="PersistentAgentsClient"/>.
/// </summary>
public static class PersistentAgentsClientExtensions
{
/// <summary>
/// Retrieves an existing server side agent, wrapped as a <see cref="ChatClientAgent"/> using the provided <see cref="PersistentAgentsClient"/>.
/// </summary>
/// <param name="persistentAgentsClient">The <see cref="PersistentAgentsClient"/> to create the <see cref="ChatClientAgent"/> with.</param>
/// <returns>A <see cref="ChatClientAgent"/> for the persistent agent.</returns>
/// <param name="agentId"> The ID of the server side agent to create a <see cref="ChatClientAgent"/> for.</param>
/// <param name="chatOptions">Options that should apply to all runs of the agent.</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 on the persistent agent.</returns>
public static async Task<ChatClientAgent> 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);
}
}
@@ -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;
/// <summary>
/// Provides extension methods for working with <see cref="Response{PersistentAgent}"/>.
/// </summary>
internal static class PersistentAgentResponseExtensions
{
/// <summary>
/// Converts a response containing persistent agent metadata into a runnable agent instance.
/// </summary>
/// <param name="persistentAgentResponse">The response containing the persistent agent to be converted. Cannot be <see langword="null"/>.</param>
/// <param name="persistentAgentsClient">The client used to interact with persistent agents. Cannot be <see langword="null"/>.</param>
/// <param name="chatOptions">The default <see cref="ChatOptions"/> to use when interacting with the agent.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the persistent agent.</returns>
public static ChatClientAgent AsRunnableAgent(this Response<PersistentAgent> persistentAgentResponse, PersistentAgentsClient persistentAgentsClient, ChatOptions? chatOptions = null)
{
if (persistentAgentResponse is null)
{
throw new ArgumentNullException(nameof(persistentAgentResponse));
}
return AsRunnableAgent(persistentAgentResponse.Value, persistentAgentsClient, chatOptions);
}
/// <summary>
/// Converts a <see cref="PersistentAgent"/> containing metadata about a persistent agent into a runnable agent instance.
/// </summary>
/// <param name="persistentAgentMetadata">The persistent agent metadata to be converted. Cannot be <see langword="null"/>.</param>
/// <param name="persistentAgentsClient">The client used to interact with persistent agents. Cannot be <see langword="null"/>.</param>
/// <param name="chatOptions">The default <see cref="ChatOptions"/> to use when interacting with the agent.</param>
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the persistent agent.</returns>
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
});
}
}