mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Add a CreateAIAgent extension method to IChatClient (#1223)
* Add a CreateAIAgent extension method to IChatClient * Fix unit tests * Add tests with null chat clients to ensure appropriate failure * Switch to similar constructor * Add ChatClientBuilder BuildAgent extensions * Address code review comments.
This commit is contained in:
committed by
GitHub
Unverified
parent
74905af778
commit
3dc14dac79
@@ -4,6 +4,7 @@
|
||||
// WARNING: ONNX doesn't support function calling, so any function tools passed to the agent will be ignored.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.ML.OnnxRuntimeGenAI;
|
||||
|
||||
// E.g. C:\repos\Phi-4-mini-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32-acc-level-4
|
||||
@@ -14,7 +15,7 @@ const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Get a chat client for ONNX and use it to construct an AIAgent.
|
||||
using OnnxRuntimeGenAIChatClient chatClient = new(modelPath);
|
||||
AIAgent agent = new ChatClientAgent(chatClient, JokerInstructions, JokerName);
|
||||
AIAgent agent = chatClient.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// This sample shows how to create and use a simple AI agent with Ollama as the backend.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OllamaSharp;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("OLLAMA_ENDPOINT") ?? throw new InvalidOperationException("OLLAMA_ENDPOINT is not set.");
|
||||
@@ -12,8 +13,8 @@ const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Get a chat client for Ollama and use it to construct an AIAgent.
|
||||
using OllamaApiClient chatClient = new(new Uri(endpoint), modelName);
|
||||
AIAgent agent = new ChatClientAgent(chatClient, JokerInstructions, JokerName);
|
||||
AIAgent agent = new OllamaApiClient(new Uri(endpoint), modelName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Text.RegularExpressions;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.ChatClient;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
// Get Azure AI Foundry configuration from environment variables
|
||||
@@ -28,25 +29,21 @@ static string GetWeather([Description("The location to get the weather for.")] s
|
||||
static string GetDateTime()
|
||||
=> DateTimeOffset.Now.ToString();
|
||||
|
||||
// Adding middleware to the chat client level
|
||||
var chatClient = azureOpenAIClient.AsIChatClient()
|
||||
// Adding middleware to the chat client level and building an agent on top of it
|
||||
var originalAgent = azureOpenAIClient.AsIChatClient()
|
||||
.AsBuilder()
|
||||
.Use(getResponseFunc: ChatClientMiddleware, getStreamingResponseFunc: null)
|
||||
.Build();
|
||||
|
||||
// For flexibility we create the agent without any middleware.
|
||||
var originalAgent = new ChatClientAgent(chatClient, new ChatClientAgentOptions(
|
||||
.Use(getResponseFunc: ChatClientMiddleware, getStreamingResponseFunc: null)
|
||||
.BuildAIAgent(
|
||||
instructions: "You are an AI assistant that helps people find information.",
|
||||
// Agent level tools
|
||||
tools: [AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime))]));
|
||||
tools: [AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime))]);
|
||||
|
||||
// Adding middleware to the agent level
|
||||
var middlewareEnabledAgent = originalAgent
|
||||
.AsBuilder()
|
||||
.Use(FunctionCallMiddleware)
|
||||
.Use(FunctionCallOverrideWeather)
|
||||
.Use(PIIMiddleware, null)
|
||||
.Use(GuardrailMiddleware, null)
|
||||
.Use(FunctionCallMiddleware)
|
||||
.Use(FunctionCallOverrideWeather)
|
||||
.Use(PIIMiddleware, null)
|
||||
.Use(GuardrailMiddleware, null)
|
||||
.Build();
|
||||
|
||||
var thread = middlewareEnabledAgent.GetNewThread();
|
||||
@@ -83,15 +80,15 @@ var optionsWithApproval = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
ChatClientFactory = (chatClient) => chatClient
|
||||
.AsBuilder()
|
||||
.Use(PerRequestChatClientMiddleware, null) // Using the non-streaming for handling streaming as well
|
||||
.Use(PerRequestChatClientMiddleware, null) // Using the non-streaming for handling streaming as well
|
||||
.Build()
|
||||
};
|
||||
|
||||
// var response = middlewareAgent // Using per-request middleware pipeline in addition to existing agent-level middleware
|
||||
var response = await originalAgent // Using per-request middleware pipeline without existing agent-level middleware
|
||||
.AsBuilder()
|
||||
.Use(PerRequestFunctionCallingMiddleware)
|
||||
.Use(ConsolePromptingApprovalMiddleware, null)
|
||||
.Use(PerRequestFunctionCallingMiddleware)
|
||||
.Use(ConsolePromptingApprovalMiddleware, null)
|
||||
.Build()
|
||||
.RunAsync("What's the current time and the weather in Seattle?", thread, optionsWithApproval);
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.ChatClient;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for building a <see cref="ChatClientAgent"/> from a <see cref="ChatClientBuilder"/>.
|
||||
/// </summary>
|
||||
public static class ChatClientBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Build a <see cref="ChatClientAgent"/> from the <see cref="IChatClient"/> pipeline described by this <see cref="ChatClientBuilder"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">A builder for creating pipelines of <see cref="IChatClient"/>.</param>
|
||||
/// <param name="instructions">
|
||||
/// Optional system instructions that guide the agent's behavior. These instructions are provided to the <see cref="IChatClient"/>
|
||||
/// with each invocation to establish the agent's role and behavior.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// Optional name for the agent. This name is used for identification and logging purposes.
|
||||
/// </param>
|
||||
/// <param name="description">
|
||||
/// Optional human-readable description of the agent's purpose and capabilities.
|
||||
/// This description can be useful for documentation and agent discovery scenarios.
|
||||
/// </param>
|
||||
/// <param name="tools">
|
||||
/// Optional collection of tools that the agent can invoke during conversations.
|
||||
/// These tools augment any tools that may be provided to the agent via <see cref="ChatOptions.Tools"/> when
|
||||
/// the agent is run.
|
||||
/// </param>
|
||||
/// <param name="loggerFactory">
|
||||
/// Optional logger factory for creating loggers used by the agent and its components.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional service provider for resolving dependencies required by AI functions and other agent components.
|
||||
/// This is particularly important when using custom tools that require dependency injection.
|
||||
/// </param>
|
||||
/// <returns>A new <see cref="ChatClientAgent"/> instance.</returns>
|
||||
public static ChatClientAgent BuildAIAgent(
|
||||
this ChatClientBuilder builder,
|
||||
string? instructions = null,
|
||||
string? name = null,
|
||||
string? description = null,
|
||||
IList<AITool>? tools = null,
|
||||
ILoggerFactory? loggerFactory = null,
|
||||
IServiceProvider? services = null) =>
|
||||
Throw.IfNull(builder).Build(services).CreateAIAgent(
|
||||
instructions: instructions,
|
||||
name: name,
|
||||
description: description,
|
||||
tools: tools,
|
||||
loggerFactory: loggerFactory,
|
||||
services: services);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ChatClientAgent"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="builder">A builder for creating pipelines of <see cref="IChatClient"/>.</param>
|
||||
/// <param name="options">
|
||||
/// Configuration options that control all aspects of the agent's behavior, including chat settings,
|
||||
/// message store factories, context provider factories, and other advanced configurations.
|
||||
/// </param>
|
||||
/// <param name="loggerFactory">
|
||||
/// Optional logger factory for creating loggers used by the agent and its components.
|
||||
/// </param>
|
||||
/// <param name="services">
|
||||
/// Optional service provider for resolving dependencies required by AI functions and other agent components.
|
||||
/// This is particularly important when using custom tools that require dependency injection.
|
||||
/// </param>
|
||||
/// <returns>A new <see cref="ChatClientAgent"/> instance.</returns>
|
||||
public static ChatClientAgent BuildAIAgent(
|
||||
this ChatClientBuilder builder,
|
||||
ChatClientAgentOptions? options,
|
||||
ILoggerFactory? loggerFactory = null,
|
||||
IServiceProvider? services = null) =>
|
||||
Throw.IfNull(builder).Build(services).CreateAIAgent(
|
||||
options: options,
|
||||
loggerFactory: loggerFactory,
|
||||
services: services);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -9,8 +10,45 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.Extensions.AI;
|
||||
|
||||
internal static class ChatClientExtensions
|
||||
/// <summary>
|
||||
/// Provides extension methods for Creating an <see cref="AIAgent"/> from an <see cref="IChatClient"/>.
|
||||
/// </summary>
|
||||
public static class ChatClientExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ChatClientAgent"/> instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="ChatClientAgent(IChatClient, string?, string?, string?, IList{AITool}?, ILoggerFactory?, IServiceProvider?)"/>
|
||||
/// <returns>A new <see cref="ChatClientAgent"/> instance.</returns>
|
||||
public static ChatClientAgent CreateAIAgent(
|
||||
this IChatClient chatClient,
|
||||
string? instructions = null,
|
||||
string? name = null,
|
||||
string? description = null,
|
||||
IList<AITool>? tools = null,
|
||||
ILoggerFactory? loggerFactory = null,
|
||||
IServiceProvider? services = null) =>
|
||||
new(
|
||||
chatClient,
|
||||
instructions: instructions,
|
||||
name: name,
|
||||
description: description,
|
||||
tools: tools,
|
||||
loggerFactory: loggerFactory,
|
||||
services: services);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ChatClientAgent"/> instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="ChatClientAgent(IChatClient, ChatClientAgentOptions?, ILoggerFactory?, IServiceProvider?)"/>
|
||||
/// <returns>A new <see cref="ChatClientAgent"/> instance.</returns>
|
||||
public static ChatClientAgent CreateAIAgent(
|
||||
this IChatClient chatClient,
|
||||
ChatClientAgentOptions? options,
|
||||
ILoggerFactory? loggerFactory = null,
|
||||
IServiceProvider? services = null) =>
|
||||
new(chatClient, options, loggerFactory, services);
|
||||
|
||||
internal static IChatClient WithDefaultAgentMiddleware(this IChatClient chatClient, ChatClientAgentOptions? options, IServiceProvider? services = null)
|
||||
{
|
||||
var chatBuilder = chatClient.AsBuilder();
|
||||
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.AI.ChatClient;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Contains unit tests for the <see cref="ChatClientBuilderExtensions"/> class.
|
||||
/// </summary>
|
||||
public sealed class ChatClientBuilderExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithBasicParameters_CreatesAgent()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(
|
||||
instructions: "Test instructions",
|
||||
name: "TestAgent",
|
||||
description: "Test description"
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("TestAgent", agent.Name);
|
||||
Assert.Equal("Test description", agent.Description);
|
||||
Assert.Equal("Test instructions", agent.Instructions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithTools_SetsToolsInOptions()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
var tools = new List<AITool> { new Mock<AITool>().Object };
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(tools: tools);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.NotNull(agent.ChatOptions);
|
||||
Assert.Equal(tools, agent.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithAllParameters_CreatesAgentCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
var tools = new List<AITool> { new Mock<AITool>().Object };
|
||||
var loggerFactoryMock = new Mock<ILoggerFactory>();
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(
|
||||
instructions: "Complex instructions",
|
||||
name: "ComplexAgent",
|
||||
description: "Complex description",
|
||||
tools: tools,
|
||||
loggerFactory: loggerFactoryMock.Object,
|
||||
services: serviceProviderMock.Object
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("ComplexAgent", agent.Name);
|
||||
Assert.Equal("Complex description", agent.Description);
|
||||
Assert.Equal("Complex instructions", agent.Instructions);
|
||||
Assert.NotNull(agent.ChatOptions);
|
||||
Assert.Equal(tools, agent.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithOptions_CreatesAgentWithOptions()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
var options = new ChatClientAgentOptions
|
||||
{
|
||||
Name = "AgentWithOptions",
|
||||
Description = "Desc",
|
||||
Instructions = "Instr",
|
||||
UseProvidedChatClientAsIs = true
|
||||
};
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(options);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("AgentWithOptions", agent.Name);
|
||||
Assert.Equal("Desc", agent.Description);
|
||||
Assert.Equal("Instr", agent.Instructions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithOptionsAndServices_CreatesAgentCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
var loggerFactoryMock = new Mock<ILoggerFactory>();
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
var options = new ChatClientAgentOptions
|
||||
{
|
||||
Name = "ServiceAgent",
|
||||
Instructions = "Service instructions"
|
||||
};
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(
|
||||
options: options,
|
||||
loggerFactory: loggerFactoryMock.Object,
|
||||
services: serviceProviderMock.Object
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("ServiceAgent", agent.Name);
|
||||
Assert.Equal("Service instructions", agent.Instructions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithNullBuilder_Throws()
|
||||
{
|
||||
// Arrange
|
||||
ChatClientBuilder builder = null!;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => builder.BuildAIAgent(instructions: "instructions"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithNullBuilderAndOptions_Throws()
|
||||
{
|
||||
// Arrange
|
||||
ChatClientBuilder builder = null!;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => builder.BuildAIAgent(options: new() { Instructions = "instructions" }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithMiddleware_BuildsCorrectPipeline()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var middlewareChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
|
||||
// Add middleware that returns our mock
|
||||
builder.Use((client, services) => middlewareChatClientMock.Object);
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(
|
||||
new ChatClientAgentOptions
|
||||
{
|
||||
Instructions = "Middleware test",
|
||||
UseProvidedChatClientAsIs = true
|
||||
}
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("Middleware test", agent.Instructions);
|
||||
// When UseProvidedChatClientAsIs is true, the agent should use the middleware chat client directly
|
||||
Assert.Same(middlewareChatClientMock.Object, agent.ChatClient);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithNullOptions_CreatesAgentWithDefaults()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent(options: null);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Null(agent.Name);
|
||||
Assert.Null(agent.Description);
|
||||
Assert.Null(agent.Instructions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAIAgent_WithEmptyParameters_CreatesMinimalAgent()
|
||||
{
|
||||
// Arrange
|
||||
var innerChatClientMock = new Mock<IChatClient>();
|
||||
var builder = new ChatClientBuilder(innerChatClientMock.Object);
|
||||
|
||||
// Act
|
||||
var agent = builder.BuildAIAgent();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Null(agent.Name);
|
||||
Assert.Null(agent.Description);
|
||||
Assert.Null(agent.Instructions);
|
||||
Assert.Null(agent.ChatOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Contains unit tests for the ChatClientExtensions class.
|
||||
/// </summary>
|
||||
public sealed class ChatClientExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void CreateAIAgent_WithBasicParameters_CreatesAgent()
|
||||
{
|
||||
// Arrange
|
||||
var chatClientMock = new Mock<IChatClient>();
|
||||
|
||||
// Act
|
||||
var agent = chatClientMock.Object.CreateAIAgent(
|
||||
instructions: "Test instructions",
|
||||
name: "TestAgent",
|
||||
description: "Test description"
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("TestAgent", agent.Name);
|
||||
Assert.Equal("Test description", agent.Description);
|
||||
Assert.Equal("Test instructions", agent.Instructions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateAIAgent_WithTools_SetsToolsInOptions()
|
||||
{
|
||||
// Arrange
|
||||
var chatClientMock = new Mock<IChatClient>();
|
||||
var tools = new List<AITool> { new Mock<AITool>().Object };
|
||||
|
||||
// Act
|
||||
var agent = chatClientMock.Object.CreateAIAgent(tools: tools);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.NotNull(agent.ChatOptions);
|
||||
Assert.Equal(tools, agent.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateAIAgent_WithOptions_CreatesAgentWithOptions()
|
||||
{
|
||||
// Arrange
|
||||
var chatClientMock = new Mock<IChatClient>();
|
||||
var options = new ChatClientAgentOptions
|
||||
{
|
||||
Name = "AgentWithOptions",
|
||||
Description = "Desc",
|
||||
Instructions = "Instr",
|
||||
UseProvidedChatClientAsIs = true
|
||||
};
|
||||
|
||||
// Act
|
||||
var agent = chatClientMock.Object.CreateAIAgent(options);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.Equal("AgentWithOptions", agent.Name);
|
||||
Assert.Equal("Desc", agent.Description);
|
||||
Assert.Equal("Instr", agent.Instructions);
|
||||
Assert.Same(chatClientMock.Object, agent.ChatClient);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateAIAgent_WithNullClient_Throws()
|
||||
{
|
||||
// Arrange
|
||||
IChatClient chatClient = null!;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => chatClient.CreateAIAgent(instructions: "instructions"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateAIAgent_WithNullClientAndOptions_Throws()
|
||||
{
|
||||
// Arrange
|
||||
IChatClient chatClient = null!;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => chatClient.CreateAIAgent(options: new() { Instructions = "instructions" }));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user