.NET: AI Agent with plugin (#1009)

* add sample to demonstrate plugins for ai agent

* Update dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* remove lang version property

* address review comments

* rename functionInvocationServices to services

* restore the solution file corrupted during the merge with lates main

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
SergeyMenshykh
2025-09-30 15:10:03 +00:00
committed by GitHub
co-authored by Copilot
parent 38b6f68d70
commit bd167ee476
8 changed files with 181 additions and 16 deletions
@@ -30,6 +30,7 @@ public static class OpenAIChatClientExtensions
/// <param name="tools">Optional collection of AI tools that the agent can use during conversations.</param>
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
/// <param name="loggerFactory">Optional logger factory for enabling logging within the agent.</param>
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <returns>An <see cref="AIAgent"/> instance backed by the OpenAI Chat Completion service.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="client"/> is <see langword="null"/>.</exception>
public static AIAgent CreateAIAgent(
@@ -39,7 +40,8 @@ public static class OpenAIChatClientExtensions
string? description = null,
IList<AITool>? tools = null,
Func<IChatClient, IChatClient>? clientFactory = null,
ILoggerFactory? loggerFactory = null) =>
ILoggerFactory? loggerFactory = null,
IServiceProvider? services = null) =>
client.CreateAIAgent(
new ChatClientAgentOptions()
{
@@ -52,7 +54,8 @@ public static class OpenAIChatClientExtensions
}
},
clientFactory,
loggerFactory);
loggerFactory,
services);
/// <summary>
/// Creates an AI agent from an <see cref="ChatClient"/> using the OpenAI Chat Completion API.
@@ -61,13 +64,15 @@ public static class OpenAIChatClientExtensions
/// <param name="options">Full set of options to configure the agent.</param>
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
/// <param name="loggerFactory">Optional logger factory for enabling logging within the agent.</param>
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
/// <returns>An <see cref="AIAgent"/> instance backed by the OpenAI Chat Completion service.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="client"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
public static AIAgent CreateAIAgent(
this ChatClient client,
ChatClientAgentOptions options,
Func<IChatClient, IChatClient>? clientFactory = null,
ILoggerFactory? loggerFactory = null)
ILoggerFactory? loggerFactory = null,
IServiceProvider? services = null)
{
Throw.IfNull(client);
Throw.IfNull(options);
@@ -79,6 +84,6 @@ public static class OpenAIChatClientExtensions
chatClient = clientFactory(chatClient);
}
return new ChatClientAgent(chatClient, options, loggerFactory);
return new ChatClientAgent(chatClient, options, loggerFactory, services);
}
}
@@ -35,8 +35,8 @@ public sealed class ChatClientAgent : AIAgent
/// <param name="description">Optional description for the agent.</param>
/// <param name="tools">Optional list of tools that the agent can use during invocation.</param>
/// <param name="loggerFactory">Optional logger factory to use for logging.</param>
/// <param name="functionInvocationServices">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
public ChatClientAgent(IChatClient chatClient, string? instructions = null, string? name = null, string? description = null, IList<AITool>? tools = null, ILoggerFactory? loggerFactory = null, IServiceProvider? functionInvocationServices = null)
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
public ChatClientAgent(IChatClient chatClient, string? instructions = null, string? name = null, string? description = null, IList<AITool>? tools = null, ILoggerFactory? loggerFactory = null, IServiceProvider? services = null)
: this(
chatClient,
new ChatClientAgentOptions
@@ -50,7 +50,7 @@ public sealed class ChatClientAgent : AIAgent
}
},
loggerFactory,
functionInvocationServices)
services)
{
}
@@ -60,8 +60,8 @@ public sealed class ChatClientAgent : AIAgent
/// <param name="chatClient">The chat client to use for invoking the agent.</param>
/// <param name="options">Full set of options to configure the agent.</param>
/// <param name="loggerFactory">Optional logger factory to use for logging.</param>
/// <param name="functionInvocationServices">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
public ChatClientAgent(IChatClient chatClient, ChatClientAgentOptions? options, ILoggerFactory? loggerFactory = null, IServiceProvider? functionInvocationServices = null)
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
public ChatClientAgent(IChatClient chatClient, ChatClientAgentOptions? options, ILoggerFactory? loggerFactory = null, IServiceProvider? services = null)
{
_ = Throw.IfNull(chatClient);
@@ -74,7 +74,7 @@ public sealed class ChatClientAgent : AIAgent
this._chatClientType = chatClient.GetType();
// If the user has not opted out of using our default decorators, we wrap the chat client.
this.ChatClient = options?.UseProvidedChatClientAsIs is true ? chatClient : chatClient.WithDefaultAgentMiddleware(options, functionInvocationServices);
this.ChatClient = options?.UseProvidedChatClientAsIs is true ? chatClient : chatClient.WithDefaultAgentMiddleware(options, services);
this._logger = (loggerFactory ?? chatClient.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance).CreateLogger<ChatClientAgent>();
}
@@ -11,7 +11,7 @@ namespace Microsoft.Extensions.AI;
internal static class ChatClientExtensions
{
internal static IChatClient WithDefaultAgentMiddleware(this IChatClient chatClient, ChatClientAgentOptions? options, IServiceProvider? functionInvocationServices = null)
internal static IChatClient WithDefaultAgentMiddleware(this IChatClient chatClient, ChatClientAgentOptions? options, IServiceProvider? services = null)
{
var chatBuilder = chatClient.AsBuilder();
@@ -25,7 +25,7 @@ internal static class ChatClientExtensions
});
}
var agentChatClient = chatBuilder.Build(functionInvocationServices);
var agentChatClient = chatBuilder.Build(services);
if (options?.ChatOptions?.Tools is { Count: > 0 })
{