diff --git a/dotnet/src/Microsoft.Agents.Abstractions/AgentRunOptions.cs b/dotnet/src/Microsoft.Agents.Abstractions/AgentRunOptions.cs
index d99974d2dc..7e0090f251 100644
--- a/dotnet/src/Microsoft.Agents.Abstractions/AgentRunOptions.cs
+++ b/dotnet/src/Microsoft.Agents.Abstractions/AgentRunOptions.cs
@@ -27,17 +27,9 @@ public class AgentRunOptions
public AgentRunOptions(AgentRunOptions options)
{
Throw.IfNull(options);
-
- this.AdditionalInstructions = options.AdditionalInstructions;
this.OnIntermediateMessages = options.OnIntermediateMessages;
}
- ///
- /// Gets or sets any instructions, in addition to those that were provided to the agent
- /// initially, that need to be added to the prompt for this invocation only.
- ///
- public string? AdditionalInstructions { get; set; } = null;
-
///
/// Gets or sets a function to be called when a complete new message is generated by the agent.
///
diff --git a/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgent.cs b/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgent.cs
index bb765626eb..81ef89490f 100644
--- a/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgent.cs
+++ b/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgent.cs
@@ -363,11 +363,6 @@ public sealed class ChatClientAgent : Agent
private void UpdateThreadMessagesWithAgentInstructions(List threadMessages, AgentRunOptions? options)
{
- if (!string.IsNullOrWhiteSpace(options?.AdditionalInstructions))
- {
- threadMessages.Insert(0, new(ChatRole.System, options?.AdditionalInstructions) { AuthorName = this.Name });
- }
-
if (!string.IsNullOrWhiteSpace(this.Instructions))
{
threadMessages.Insert(0, new(ChatRole.System, this.Instructions) { AuthorName = this.Name });
diff --git a/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgentRunOptions.cs b/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgentRunOptions.cs
index 6cd31e73e2..d38d209a21 100644
--- a/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgentRunOptions.cs
+++ b/dotnet/src/Microsoft.Agents/ChatCompletion/ChatClientAgentRunOptions.cs
@@ -17,7 +17,6 @@ internal sealed class ChatClientAgentRunOptions : AgentRunOptions
internal ChatClientAgentRunOptions(AgentRunOptions? source = null, ChatOptions? chatOptions = null)
{
this.OnIntermediateMessages = source?.OnIntermediateMessages;
- this.AdditionalInstructions = source?.AdditionalInstructions;
this.ChatOptions = chatOptions;
}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/AgentFixture.cs b/dotnet/tests/AgentConformance.IntegrationTests/AgentFixture.cs
deleted file mode 100644
index 92ec807c33..0000000000
--- a/dotnet/tests/AgentConformance.IntegrationTests/AgentFixture.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Microsoft.Agents;
-using Microsoft.Extensions.AI;
-
-namespace AgentConformanceTests;
-
-///
-/// Base class for setting up and tearing down agents, to be used in tests.
-/// Each agent type should have its own derived class.
-///
-public abstract class AgentFixture : IAsyncLifetime
-{
- public abstract Agent Agent { get; }
-
- public abstract Task> GetChatHistoryAsync(AgentThread thread);
-
- public abstract Task DeleteThreadAsync(AgentThread thread);
-
- public abstract Task DisposeAsync();
-
- public abstract Task InitializeAsync();
-}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/AgentTests.cs b/dotnet/tests/AgentConformance.IntegrationTests/AgentTests.cs
index 1d04b1a5c3..f6ceb9819c 100644
--- a/dotnet/tests/AgentConformance.IntegrationTests/AgentTests.cs
+++ b/dotnet/tests/AgentConformance.IntegrationTests/AgentTests.cs
@@ -2,7 +2,6 @@
using System;
using System.Threading.Tasks;
-using AgentConformanceTests;
namespace AgentConformance.IntegrationTests;
@@ -12,7 +11,7 @@ namespace AgentConformance.IntegrationTests;
/// The type of the agent fixture used in these tests.
/// Used to create a new fixture for this test suite.
public abstract class AgentTests(Func createAgentFixture) : IAsyncLifetime
- where TAgentFixture : AgentFixture
+ where TAgentFixture : IAgentFixture
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
protected TAgentFixture Fixture { get; private set; }
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/ChatClientAgentRunStreamingTests.cs b/dotnet/tests/AgentConformance.IntegrationTests/ChatClientAgentRunStreamingTests.cs
new file mode 100644
index 0000000000..98dbe28111
--- /dev/null
+++ b/dotnet/tests/AgentConformance.IntegrationTests/ChatClientAgentRunStreamingTests.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests.Support;
+using Microsoft.Agents;
+
+namespace AgentConformance.IntegrationTests;
+
+///
+/// Conformance tests that are specific to the in addition to those in .
+///
+/// The type of test fixture used by the concrete test implementation.
+/// Function to create the test fixture with.
+public abstract class ChatClientAgentRunStreamingTests(Func createAgentFixture) : AgentTests(createAgentFixture)
+ where TAgentFixture : IChatClientAgentFixture
+{
+ [RetryFact(Constants.RetryCount, Constants.RetryDelay)]
+ public virtual async Task RunWithInstructionsAndNoMessageReturnsExpectedResultAsync()
+ {
+ // Arrange
+ var agent = await this.Fixture.CreateAgentWithInstructionsAsync("Always respond with 'Computer says no', even if there was no user input.");
+ var thread = agent.GetNewThread();
+ await using var agentCleanup = new AgentCleanup(agent, this.Fixture);
+ await using var threadCleanup = new ThreadCleanup(thread, this.Fixture);
+
+ // Act
+ var chatResponses = await agent.RunStreamingAsync(thread).ToListAsync();
+
+ // Assert
+ var chatResponseText = string.Join("", chatResponses.Select(x => x.Text));
+ Assert.Contains("Computer says no", chatResponseText, StringComparison.OrdinalIgnoreCase);
+ }
+}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/ChatClientAgentRunTests.cs b/dotnet/tests/AgentConformance.IntegrationTests/ChatClientAgentRunTests.cs
new file mode 100644
index 0000000000..730497f995
--- /dev/null
+++ b/dotnet/tests/AgentConformance.IntegrationTests/ChatClientAgentRunTests.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests.Support;
+using Microsoft.Agents;
+
+namespace AgentConformance.IntegrationTests;
+
+///
+/// Conformance tests that are specific to the in addition to those in .
+///
+/// The type of test fixture used by the concrete test implementation.
+/// Function to create the test fixture with.
+public abstract class ChatClientAgentRunTests(Func createAgentFixture) : AgentTests(createAgentFixture)
+ where TAgentFixture : IChatClientAgentFixture
+{
+ [RetryFact(Constants.RetryCount, Constants.RetryDelay)]
+ public virtual async Task RunWithInstructionsAndNoMessageReturnsExpectedResultAsync()
+ {
+ // Arrange
+ var agent = await this.Fixture.CreateAgentWithInstructionsAsync("Always respond with 'Computer says no', even if there was no user input.");
+ var thread = agent.GetNewThread();
+ await using var agentCleanup = new AgentCleanup(agent, this.Fixture);
+ await using var threadCleanup = new ThreadCleanup(thread, this.Fixture);
+
+ // Act
+ var chatResponse = await agent.RunAsync(thread);
+
+ // Assert
+ Assert.NotNull(chatResponse);
+ Assert.Single(chatResponse.Messages);
+ Assert.Contains("Computer says no", chatResponse.Text, StringComparison.OrdinalIgnoreCase);
+ }
+}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/IAgentFixture.cs b/dotnet/tests/AgentConformance.IntegrationTests/IAgentFixture.cs
new file mode 100644
index 0000000000..d88247623f
--- /dev/null
+++ b/dotnet/tests/AgentConformance.IntegrationTests/IAgentFixture.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.Agents;
+using Microsoft.Extensions.AI;
+
+namespace AgentConformance.IntegrationTests;
+
+///
+/// Interface for setting up and tearing down agents, to be used in tests.
+/// Each agent type should have its own derived class.
+///
+public interface IAgentFixture : IAsyncLifetime
+{
+ Agent Agent { get; }
+
+ Task> GetChatHistoryAsync(AgentThread thread);
+
+ Task DeleteThreadAsync(AgentThread thread);
+}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/IChatClientAgentFixture.cs b/dotnet/tests/AgentConformance.IntegrationTests/IChatClientAgentFixture.cs
new file mode 100644
index 0000000000..6637e788cb
--- /dev/null
+++ b/dotnet/tests/AgentConformance.IntegrationTests/IChatClientAgentFixture.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Threading.Tasks;
+using Microsoft.Agents;
+using Microsoft.Extensions.AI;
+
+namespace AgentConformance.IntegrationTests;
+
+///
+/// Interface for setting up and tearing down based agents, to be used in tests.
+/// Each agent type should have its own derived class.
+///
+public interface IChatClientAgentFixture : IAgentFixture
+{
+ IChatClient ChatClient { get; }
+
+ Task CreateAgentWithInstructionsAsync(string instructions);
+
+ Task DeleteAgentAsync(ChatClientAgent agent);
+}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/RunStreamingAsyncTests.cs b/dotnet/tests/AgentConformance.IntegrationTests/RunStreamingTests.cs
similarity index 81%
rename from dotnet/tests/AgentConformance.IntegrationTests/RunStreamingAsyncTests.cs
rename to dotnet/tests/AgentConformance.IntegrationTests/RunStreamingTests.cs
index a169ca99a6..633d205366 100644
--- a/dotnet/tests/AgentConformance.IntegrationTests/RunStreamingAsyncTests.cs
+++ b/dotnet/tests/AgentConformance.IntegrationTests/RunStreamingTests.cs
@@ -4,7 +4,6 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using AgentConformance.IntegrationTests.Support;
-using AgentConformanceTests;
using Microsoft.Extensions.AI;
namespace AgentConformance.IntegrationTests;
@@ -14,8 +13,8 @@ namespace AgentConformance.IntegrationTests;
///
/// The type of test fixture used by the concrete test implementation.
/// Function to create the test fixture with.
-public abstract class RunStreamingAsyncTests(Func createAgentFixture) : AgentTests(createAgentFixture)
- where TAgentFixture : AgentFixture
+public abstract class RunStreamingTests(Func createAgentFixture) : AgentTests(createAgentFixture)
+ where TAgentFixture : IAgentFixture
{
[RetryFact(Constants.RetryCount, Constants.RetryDelay)]
public virtual async Task RunWithStringReturnsExpectedResultAsync()
@@ -70,22 +69,6 @@ public abstract class RunStreamingAsyncTests(Func
Assert.Contains("Paris", chatResponseText);
}
- [RetryFact(Constants.RetryCount, Constants.RetryDelay)]
- public virtual async Task RunWithAdditionalInstructionsAndNoMessageReturnsExpectedResultAsync()
- {
- // Arrange
- var agent = this.Fixture.Agent;
- var thread = agent.GetNewThread();
- await using var cleanup = new ThreadCleanup(thread, this.Fixture);
-
- // Act
- var chatResponses = await agent.RunStreamingAsync(thread, new() { AdditionalInstructions = "Always respond with `Computer says no`" }).ToListAsync();
-
- // Assert
- var chatResponseText = string.Join("", chatResponses.Select(x => x.Text));
- Assert.Contains("Computer says no", chatResponseText);
- }
-
[RetryFact(Constants.RetryCount, Constants.RetryDelay)]
public virtual async Task ThreadMaintainsHistoryAsync()
{
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/RunAsyncTests.cs b/dotnet/tests/AgentConformance.IntegrationTests/RunTests.cs
similarity index 79%
rename from dotnet/tests/AgentConformance.IntegrationTests/RunAsyncTests.cs
rename to dotnet/tests/AgentConformance.IntegrationTests/RunTests.cs
index 324e0972c5..81d6aec3ae 100644
--- a/dotnet/tests/AgentConformance.IntegrationTests/RunAsyncTests.cs
+++ b/dotnet/tests/AgentConformance.IntegrationTests/RunTests.cs
@@ -4,7 +4,6 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using AgentConformance.IntegrationTests.Support;
-using AgentConformanceTests;
using Microsoft.Extensions.AI;
namespace AgentConformance.IntegrationTests;
@@ -14,8 +13,8 @@ namespace AgentConformance.IntegrationTests;
///
/// The type of test fixture used by the concrete test implementation.
/// Function to create the test fixture with.
-public abstract class RunAsyncTests(Func createAgentFixture) : AgentTests(createAgentFixture)
- where TAgentFixture : AgentFixture
+public abstract class RunTests(Func createAgentFixture) : AgentTests(createAgentFixture)
+ where TAgentFixture : IAgentFixture
{
[RetryFact(Constants.RetryCount, Constants.RetryDelay)]
public virtual async Task RunWithStringReturnsExpectedResultAsync()
@@ -73,23 +72,6 @@ public abstract class RunAsyncTests(Func createAge
Assert.Contains("Paris", chatResponse.Text);
}
- [RetryFact(Constants.RetryCount, Constants.RetryDelay)]
- public virtual async Task RunWithAdditionalInstructionsAndNoMessageReturnsExpectedResultAsync()
- {
- // Arrange
- var agent = this.Fixture.Agent;
- var thread = agent.GetNewThread();
- await using var cleanup = new ThreadCleanup(thread, this.Fixture);
-
- // Act
- var chatResponse = await agent.RunAsync(thread, new() { AdditionalInstructions = "Always respond with `Computer says no`, even when the user provided on input." });
-
- // Assert
- Assert.NotNull(chatResponse);
- Assert.Single(chatResponse.Messages);
- Assert.Contains("Computer says no", chatResponse.Text);
- }
-
[RetryFact(Constants.RetryCount, Constants.RetryDelay)]
public virtual async Task ThreadMaintainsHistoryAsync()
{
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/Support/AgentCleanup.cs b/dotnet/tests/AgentConformance.IntegrationTests/Support/AgentCleanup.cs
new file mode 100644
index 0000000000..6a0ef7458f
--- /dev/null
+++ b/dotnet/tests/AgentConformance.IntegrationTests/Support/AgentCleanup.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Threading.Tasks;
+using Microsoft.Agents;
+
+namespace AgentConformance.IntegrationTests.Support;
+
+///
+/// Helper class to delete agents after tests.
+///
+/// The agent to delete.
+/// The fixture that provides agent specific capabilities.
+internal sealed class AgentCleanup(ChatClientAgent agent, IChatClientAgentFixture fixture) : IAsyncDisposable
+{
+ public async ValueTask DisposeAsync()
+ {
+ await fixture.DeleteAgentAsync(agent);
+ }
+}
diff --git a/dotnet/tests/AgentConformance.IntegrationTests/Support/ThreadCleanup.cs b/dotnet/tests/AgentConformance.IntegrationTests/Support/ThreadCleanup.cs
index 2ba4dee798..17d70b46a8 100644
--- a/dotnet/tests/AgentConformance.IntegrationTests/Support/ThreadCleanup.cs
+++ b/dotnet/tests/AgentConformance.IntegrationTests/Support/ThreadCleanup.cs
@@ -2,7 +2,6 @@
using System;
using System.Threading.Tasks;
-using AgentConformanceTests;
using Microsoft.Agents;
namespace AgentConformance.IntegrationTests.Support;
@@ -12,7 +11,7 @@ namespace AgentConformance.IntegrationTests.Support;
///
/// The thread to delete.
/// The fixture that provides agent specific capabilities.
-internal sealed class ThreadCleanup(AgentThread thread, AgentFixture fixture) : IAsyncDisposable
+internal sealed class ThreadCleanup(AgentThread thread, IAgentFixture fixture) : IAsyncDisposable
{
public async ValueTask DisposeAsync()
{
diff --git a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsChatClientAgentRunStreamingTests.cs b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsChatClientAgentRunStreamingTests.cs
new file mode 100644
index 0000000000..84e3d5d9f9
--- /dev/null
+++ b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsChatClientAgentRunStreamingTests.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace AzureAIAgentsPersistent.IntegrationTests;
+
+public class AzureAIAgentsChatClientAgentRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new())
+{
+}
diff --git a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentInvokeStreamingTests.cs b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsChatClientAgentRunTests.cs
similarity index 54%
rename from dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentInvokeStreamingTests.cs
rename to dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsChatClientAgentRunTests.cs
index c003bec1f0..b2f75c536e 100644
--- a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentInvokeStreamingTests.cs
+++ b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsChatClientAgentRunTests.cs
@@ -4,6 +4,6 @@ using AgentConformance.IntegrationTests;
namespace AzureAIAgentsPersistent.IntegrationTests;
-public class AzureAIAgentsPersistentInvokeStreamingTests() : RunStreamingAsyncTests(() => new())
+public class AzureAIAgentsChatClientAgentRunTests() : ChatClientAgentRunTests(() => new())
{
}
diff --git a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentFixture.cs b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentFixture.cs
index 2e170025e1..4dead1fa6e 100644
--- a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentFixture.cs
+++ b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentFixture.cs
@@ -3,8 +3,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
using AgentConformance.IntegrationTests.Support;
-using AgentConformanceTests;
using Azure;
using Azure.AI.Agents.Persistent;
using Azure.Identity;
@@ -15,17 +15,22 @@ using Shared.IntegrationTests;
namespace AzureAIAgentsPersistent.IntegrationTests;
-public class AzureAIAgentsPersistentFixture : AgentFixture
+public class AzureAIAgentsPersistentFixture : IChatClientAgentFixture
{
+ private static readonly AzureAIConfiguration s_config = TestConfiguration.LoadSection();
+
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private Agent _agent;
private PersistentAgentsClient _persistentAgentsClient;
+ private IChatClient _chatClient;
private PersistentAgent _persistentAgent;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
- public override Agent Agent => this._agent;
+ public IChatClient ChatClient => this._chatClient;
- public override async Task> GetChatHistoryAsync(AgentThread thread)
+ public Agent Agent => this._agent;
+
+ public async Task> GetChatHistoryAsync(AgentThread thread)
{
if (thread is not ChatClientAgentThread chatClientThread)
{
@@ -57,7 +62,26 @@ public class AzureAIAgentsPersistentFixture : AgentFixture
return messages;
}
- public override Task DeleteThreadAsync(AgentThread thread)
+ public async Task CreateAgentWithInstructionsAsync(string instructions)
+ {
+ var persistentAgentResponse = await this._persistentAgentsClient.Administration.CreateAgentAsync(
+ model: s_config.DeploymentName,
+ name: "HelpfulAssistant",
+ instructions: "You are a helpful assistant.");
+
+ var persistentAgent = persistentAgentResponse.Value;
+
+ var chatClient = this._persistentAgentsClient.AsIChatClient(persistentAgent.Id);
+
+ return new ChatClientAgent(chatClient, new() { Id = persistentAgent.Id });
+ }
+
+ public Task DeleteAgentAsync(ChatClientAgent agent)
+ {
+ return this._persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
+ }
+
+ public Task DeleteThreadAsync(AgentThread thread)
{
if (thread?.Id is not null)
{
@@ -67,7 +91,7 @@ public class AzureAIAgentsPersistentFixture : AgentFixture
return Task.CompletedTask;
}
- public override Task DisposeAsync()
+ public Task DisposeAsync()
{
if (this._persistentAgentsClient is not null && this._persistentAgent is not null)
{
@@ -77,21 +101,19 @@ public class AzureAIAgentsPersistentFixture : AgentFixture
return Task.CompletedTask;
}
- public override async Task InitializeAsync()
+ public async Task InitializeAsync()
{
- var config = TestConfiguration.LoadSection();
-
- this._persistentAgentsClient = new(config.Endpoint, new AzureCliCredential());
+ this._persistentAgentsClient = new(s_config.Endpoint, new AzureCliCredential());
var persistentAgentResponse = await this._persistentAgentsClient.Administration.CreateAgentAsync(
- model: config.DeploymentName,
+ model: s_config.DeploymentName,
name: "HelpfulAssistant",
instructions: "You are a helpful assistant.");
this._persistentAgent = persistentAgentResponse.Value;
- var chatClient = this._persistentAgentsClient.AsIChatClient(this._persistentAgent.Id);
+ this._chatClient = this._persistentAgentsClient.AsIChatClient(this._persistentAgent.Id);
- this._agent = new ChatClientAgent(chatClient);
+ this._agent = new ChatClientAgent(this._chatClient);
}
}
diff --git a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentRunStreamingTests.cs b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentRunStreamingTests.cs
new file mode 100644
index 0000000000..e18812aff4
--- /dev/null
+++ b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentRunStreamingTests.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace AzureAIAgentsPersistent.IntegrationTests;
+
+public class AzureAIAgentsPersistentRunStreamingTests() : RunStreamingTests(() => new())
+{
+}
diff --git a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentInvokeTests.cs b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentRunTests.cs
similarity index 57%
rename from dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentInvokeTests.cs
rename to dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentRunTests.cs
index 877076a842..3e6032401d 100644
--- a/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentInvokeTests.cs
+++ b/dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentRunTests.cs
@@ -4,6 +4,6 @@ using AgentConformance.IntegrationTests;
namespace AzureAIAgentsPersistent.IntegrationTests;
-public class AzureAIAgentsPersistentInvokeTests() : RunAsyncTests(() => new())
+public class AzureAIAgentsPersistentRunTests() : RunTests(() => new())
{
}
diff --git a/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentRunOptionsTests.cs b/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentRunOptionsTests.cs
index f4df284401..d370b53bf4 100644
--- a/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentRunOptionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.Abstractions.UnitTests/AgentRunOptionsTests.cs
@@ -16,7 +16,6 @@ public class AgentRunOptionsTests
// Arrange
var options = new AgentRunOptions
{
- AdditionalInstructions = "Test instructions",
OnIntermediateMessages = msg => Task.CompletedTask
};
@@ -24,7 +23,6 @@ public class AgentRunOptionsTests
var clone = new AgentRunOptions(options);
// Assert
- Assert.Equal(options.AdditionalInstructions, clone.AdditionalInstructions);
Assert.Equal(options.OnIntermediateMessages, clone.OnIntermediateMessages);
}
diff --git a/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentExtensionsTests.cs
index 9a1f7f249d..f1e4a3df77 100644
--- a/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentExtensionsTests.cs
@@ -95,10 +95,10 @@ public class ChatClientAgentExtensionsTests
}
///
- /// Verify that RunAsync extension method with messages passes AgentRunOptions correctly.
+ /// Verify that RunAsync extension method with messages passes Instructions correctly.
///
[Fact]
- public async Task RunAsyncWithMessagesPassesAgentRunOptionsCorrectlyAsync()
+ public async Task RunAsyncWithMessagesPassesInstructionsCorrectlyAsync()
{
// Arrange
Mock mockService = new();
@@ -118,14 +118,13 @@ public class ChatClientAgentExtensionsTests
ChatClientAgent agent = new(mockService.Object, new() { Instructions = "base instructions" });
var messages = new List { new(ChatRole.User, "test") };
- var runOptions = new AgentRunOptions { AdditionalInstructions = "additional instructions" };
+ var runOptions = new AgentRunOptions();
// Act
await ChatClientAgentExtensions.RunAsync(agent, messages, agentRunOptions: runOptions);
// Assert
Assert.Contains(capturedMessages, m => m.Text == "base instructions" && m.Role == ChatRole.System);
- Assert.Contains(capturedMessages, m => m.Text == "additional instructions" && m.Role == ChatRole.System);
Assert.Contains(capturedMessages, m => m.Text == "test" && m.Role == ChatRole.User);
Assert.All(capturedChatOptions, Assert.Null);
}
@@ -349,14 +348,13 @@ public class ChatClientAgentExtensionsTests
ChatClientAgent agent = new(mockService.Object, new() { Instructions = "base instructions" });
const string TestPrompt = "test prompt";
- var runOptions = new AgentRunOptions { AdditionalInstructions = "additional instructions" };
+ var runOptions = new AgentRunOptions();
// Act
await ChatClientAgentExtensions.RunAsync(agent, TestPrompt, agentRunOptions: runOptions);
// Assert
Assert.Contains(capturedMessages, m => m.Text == "base instructions" && m.Role == ChatRole.System);
- Assert.Contains(capturedMessages, m => m.Text == "additional instructions" && m.Role == ChatRole.System);
Assert.Contains(capturedMessages, m => m.Text == "test prompt" && m.Role == ChatRole.User);
}
diff --git a/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentRunOptionsTests.cs b/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentRunOptionsTests.cs
index 8821617865..24e712487b 100644
--- a/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentRunOptionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentRunOptionsTests.cs
@@ -18,7 +18,6 @@ public class ChatClientAgentRunOptionsTests
// Assert
Assert.Null(runOptions.OnIntermediateMessages);
- Assert.Null(runOptions.AdditionalInstructions);
Assert.Null(runOptions.ChatOptions);
}
@@ -36,7 +35,6 @@ public class ChatClientAgentRunOptionsTests
// Assert
Assert.Null(runOptions.OnIntermediateMessages);
- Assert.Null(runOptions.AdditionalInstructions);
Assert.Same(chatOptions, runOptions.ChatOptions);
}
@@ -49,7 +47,6 @@ public class ChatClientAgentRunOptionsTests
// Arrange
var sourceRunOptions = new AgentRunOptions
{
- AdditionalInstructions = "additional instructions",
OnIntermediateMessages = messages => Task.CompletedTask
};
var chatOptions = new ChatOptions { MaxOutputTokens = 200 };
@@ -59,7 +56,6 @@ public class ChatClientAgentRunOptionsTests
// Assert
Assert.Same(sourceRunOptions.OnIntermediateMessages, runOptions.OnIntermediateMessages);
- Assert.Equal("additional instructions", runOptions.AdditionalInstructions);
Assert.Same(chatOptions, runOptions.ChatOptions);
}
@@ -72,14 +68,14 @@ public class ChatClientAgentRunOptionsTests
// Arrange
var sourceRunOptions = new AgentRunOptions
{
- AdditionalInstructions = "test instructions"
+ OnIntermediateMessages = messages => Task.CompletedTask
};
// Act
var runOptions = new ChatClientAgentRunOptions(sourceRunOptions, null);
// Assert
- Assert.Equal("test instructions", runOptions.AdditionalInstructions);
+ Assert.Same(sourceRunOptions.OnIntermediateMessages, runOptions.OnIntermediateMessages);
Assert.Null(runOptions.ChatOptions);
}
diff --git a/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentTests.cs b/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentTests.cs
index 6e92514ab6..4895985b20 100644
--- a/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.UnitTests/ChatCompletion/ChatClientAgentTests.cs
@@ -156,10 +156,10 @@ public class ChatClientAgentTests
}
///
- /// Verify that RunAsync includes additional instructions when provided in options.
+ /// Verify that RunAsync includes base instructions in messages.
///
[Fact]
- public async Task RunAsyncIncludesAdditionalInstructionsWhenProvidedInOptionsAsync()
+ public async Task RunAsyncIncludesBaseInstructionsAsync()
{
// Arrange
Mock mockService = new();
@@ -174,14 +174,13 @@ public class ChatClientAgentTests
.ReturnsAsync(new ChatResponse([new(ChatRole.Assistant, "response")]));
ChatClientAgent agent = new(mockService.Object, new() { Instructions = "base instructions" });
- var runOptions = new AgentRunOptions { AdditionalInstructions = "additional instructions" };
+ var runOptions = new AgentRunOptions();
// Act
await agent.RunAsync([new(ChatRole.User, "test")], options: runOptions);
// Assert
Assert.Contains(capturedMessages, m => m.Text == "base instructions" && m.Role == ChatRole.System);
- Assert.Contains(capturedMessages, m => m.Text == "additional instructions" && m.Role == ChatRole.System);
Assert.Contains(capturedMessages, m => m.Text == "test" && m.Role == ChatRole.User);
}
@@ -759,18 +758,21 @@ public class ChatClientAgentTests
MaxOutputTokens = 100,
Temperature = 0.7f,
TopP = 0.9f,
- ModelId = "agent-model"
+ ModelId = "agent-model",
+ AdditionalProperties = new AdditionalPropertiesDictionary() { ["key"] = "agent-value" }
};
var requestChatOptions = new ChatOptions
{
MaxOutputTokens = 200,
- Temperature = 0.3f
+ Temperature = 0.3f,
+ AdditionalProperties = new AdditionalPropertiesDictionary() { ["key"] = "request-value" }
// TopP and ModelId not set, should use agent values
};
var expectedChatOptionsMerge = new ChatOptions
{
MaxOutputTokens = 200, // Request value takes priority
Temperature = 0.3f, // Request value takes priority
+ AdditionalProperties = new AdditionalPropertiesDictionary() { ["key"] = "request-value" }, // Request value takes priority
TopP = 0.9f, // Agent value used when request doesn't specify
ModelId = "agent-model" // Agent value used when request doesn't specify
};
@@ -801,6 +803,8 @@ public class ChatClientAgentTests
Assert.Equivalent(expectedChatOptionsMerge, capturedChatOptions); // Should be the same instance (modified in place)
Assert.Equal(200, capturedChatOptions.MaxOutputTokens); // Request value takes priority
Assert.Equal(0.3f, capturedChatOptions.Temperature); // Request value takes priority
+ Assert.NotNull(capturedChatOptions.AdditionalProperties);
+ Assert.Equal("request-value", capturedChatOptions.AdditionalProperties["key"]); // Request value takes priority
Assert.Equal(0.9f, capturedChatOptions.TopP); // Agent value used when request doesn't specify
Assert.Equal("agent-model", capturedChatOptions.ModelId); // Agent value used when request doesn't specify
}
diff --git a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantChatClientAgentRunStreamingTests.cs b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantChatClientAgentRunStreamingTests.cs
new file mode 100644
index 0000000000..78d985a6f3
--- /dev/null
+++ b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantChatClientAgentRunStreamingTests.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIAssistant.IntegrationTests;
+
+public class OpenAIAssistantChatClientAgentRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new())
+{
+}
diff --git a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantChatClientAgentRunTests.cs b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantChatClientAgentRunTests.cs
new file mode 100644
index 0000000000..641e656379
--- /dev/null
+++ b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantChatClientAgentRunTests.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIAssistant.IntegrationTests;
+
+public class OpenAIAssistantChatClientAgentRunTests() : ChatClientAgentRunTests(() => new())
+{
+}
diff --git a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantFixture.cs b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantFixture.cs
index fe6ad9817b..01f6dfdd48 100644
--- a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantFixture.cs
+++ b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantFixture.cs
@@ -3,8 +3,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
using AgentConformance.IntegrationTests.Support;
-using AgentConformanceTests;
using Microsoft.Agents;
using Microsoft.Extensions.AI;
using OpenAI;
@@ -15,8 +15,10 @@ namespace OpenAIAssistant.IntegrationTests;
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
-public class OpenAIAssistantFixture : AgentFixture
+public class OpenAIAssistantFixture : IChatClientAgentFixture
{
+ private static readonly OpenAIConfiguration s_config = TestConfiguration.LoadSection();
+
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private AssistantClient? _assistantClient;
private Assistant? _assistant;
@@ -24,9 +26,11 @@ public class OpenAIAssistantFixture : AgentFixture
private Agent _agent;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
- public override Agent Agent => this._agent;
+ public Agent Agent => this._agent;
- public override async Task> GetChatHistoryAsync(AgentThread thread)
+ public IChatClient ChatClient => this._chatClient;
+
+ public async Task> GetChatHistoryAsync(AgentThread thread)
{
if (thread is not ChatClientAgentThread chatClientThread)
{
@@ -49,7 +53,26 @@ public class OpenAIAssistantFixture : AgentFixture
return messages;
}
- public override Task DeleteThreadAsync(AgentThread thread)
+ public async Task CreateAgentWithInstructionsAsync(string instructions)
+ {
+ var assistant =
+ await this._assistantClient!.CreateAssistantAsync(
+ s_config.ChatModelId!,
+ new AssistantCreationOptions()
+ {
+ Name = "HelpfulAssistant",
+ Instructions = instructions
+ });
+
+ return new ChatClientAgent(this._assistantClient.AsIChatClient(assistant.Value.Id), new() { Id = assistant.Value.Id });
+ }
+
+ public Task DeleteAgentAsync(ChatClientAgent agent)
+ {
+ return this._assistantClient!.DeleteAssistantAsync(agent.Id);
+ }
+
+ public Task DeleteThreadAsync(AgentThread thread)
{
if (thread?.Id is not null)
{
@@ -59,16 +82,14 @@ public class OpenAIAssistantFixture : AgentFixture
return Task.CompletedTask;
}
- public override async Task InitializeAsync()
+ public async Task InitializeAsync()
{
- var config = TestConfiguration.LoadSection();
-
- var client = new OpenAIClient(config.ApiKey);
+ var client = new OpenAIClient(s_config.ApiKey);
this._assistantClient = client.GetAssistantClient();
this._assistant =
await this._assistantClient.CreateAssistantAsync(
- config.ChatModelId!,
+ s_config.ChatModelId!,
new AssistantCreationOptions()
{
Name = "HelpfulAssistant",
@@ -80,7 +101,7 @@ public class OpenAIAssistantFixture : AgentFixture
this._agent = new ChatClientAgent(this._chatClient);
}
- public override Task DisposeAsync()
+ public Task DisposeAsync()
{
if (this._assistantClient is not null && this._assistant is not null)
{
diff --git a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantInvokeTests.cs b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantIRunTests.cs
similarity index 60%
rename from dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantInvokeTests.cs
rename to dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantIRunTests.cs
index c863a5e6a2..736c9fe063 100644
--- a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantInvokeTests.cs
+++ b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantIRunTests.cs
@@ -4,6 +4,6 @@ using AgentConformance.IntegrationTests;
namespace OpenAIAssistant.IntegrationTests;
-public class OpenAIAssistantInvokeTests() : RunAsyncTests(() => new())
+public class OpenAIAssistantIRunTests() : RunTests(() => new())
{
}
diff --git a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantInvokeStreamingTests.cs b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantRunStreamingTests.cs
similarity index 56%
rename from dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantInvokeStreamingTests.cs
rename to dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantRunStreamingTests.cs
index 37be58090d..355fe8e549 100644
--- a/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantInvokeStreamingTests.cs
+++ b/dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantRunStreamingTests.cs
@@ -4,6 +4,6 @@ using AgentConformance.IntegrationTests;
namespace OpenAIAssistant.IntegrationTests;
-public class OpenAIAssistantInvokeStreamingTests() : RunStreamingAsyncTests(() => new())
+public class OpenAIAssistantRunStreamingTests() : RunStreamingTests(() => new())
{
}
diff --git a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionChatClientAgentRunStreamingTests.cs b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionChatClientAgentRunStreamingTests.cs
new file mode 100644
index 0000000000..bcb2824a5a
--- /dev/null
+++ b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionChatClientAgentRunStreamingTests.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIChatCompletion.IntegrationTests;
+
+public class OpenAIChatCompletionChatClientAgentRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new())
+{
+}
diff --git a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionChatClientAgentRunTests.cs b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionChatClientAgentRunTests.cs
new file mode 100644
index 0000000000..5602204af8
--- /dev/null
+++ b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionChatClientAgentRunTests.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIChatCompletion.IntegrationTests;
+
+public class OpenAIChatCompletionChatClientAgentRunTests() : ChatClientAgentRunTests(() => new())
+{
+}
diff --git a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionFixture.cs b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionFixture.cs
index cdfb7c6555..a51e03da13 100644
--- a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionFixture.cs
+++ b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionFixture.cs
@@ -4,8 +4,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
using AgentConformance.IntegrationTests.Support;
-using AgentConformanceTests;
using Microsoft.Agents;
using Microsoft.Extensions.AI;
using OpenAI;
@@ -13,16 +13,20 @@ using Shared.IntegrationTests;
namespace OpenAIChatCompletion.IntegrationTests;
-public class OpenAIChatCompletionFixture : AgentFixture
+public class OpenAIChatCompletionFixture : IChatClientAgentFixture
{
+ private static readonly OpenAIConfiguration s_config = TestConfiguration.LoadSection();
+
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private IChatClient _chatClient;
private Agent _agent;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
- public override Agent Agent => this._agent;
+ public Agent Agent => this._agent;
- public override async Task> GetChatHistoryAsync(AgentThread thread)
+ public IChatClient ChatClient => this._chatClient;
+
+ public async Task> GetChatHistoryAsync(AgentThread thread)
{
if (thread is not ChatClientAgentThread chatClientThread)
{
@@ -32,18 +36,35 @@ public class OpenAIChatCompletionFixture : AgentFixture
return await chatClientThread.GetMessagesAsync().ToListAsync();
}
- public override Task DeleteThreadAsync(AgentThread thread)
+ public Task CreateAgentWithInstructionsAsync(string instructions)
+ {
+ this._chatClient = new OpenAIClient(s_config.ApiKey)
+ .GetChatClient(s_config.ChatModelId)
+ .AsIChatClient();
+
+ return Task.FromResult(new ChatClientAgent(this._chatClient, new()
+ {
+ Name = "HelpfulAssistant",
+ Instructions = instructions,
+ }));
+ }
+
+ public Task DeleteAgentAsync(ChatClientAgent agent)
+ {
+ // Chat Completion does not require/support deleting agents, so this is a no-op.
+ return Task.CompletedTask;
+ }
+
+ public Task DeleteThreadAsync(AgentThread thread)
{
// Chat Completion does not require/support deleting threads, so this is a no-op.
return Task.CompletedTask;
}
- public override Task InitializeAsync()
+ public Task InitializeAsync()
{
- var config = TestConfiguration.LoadSection();
-
- this._chatClient = new OpenAIClient(config.ApiKey)
- .GetChatClient(config.ChatModelId)
+ this._chatClient = new OpenAIClient(s_config.ApiKey)
+ .GetChatClient(s_config.ChatModelId)
.AsIChatClient();
this._agent =
@@ -56,7 +77,7 @@ public class OpenAIChatCompletionFixture : AgentFixture
return Task.CompletedTask;
}
- public override Task DisposeAsync()
+ public Task DisposeAsync()
{
this._chatClient.Dispose();
return Task.CompletedTask;
diff --git a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionInvokeStreamingTests.cs b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionRunStreamingTests.cs
similarity index 54%
rename from dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionInvokeStreamingTests.cs
rename to dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionRunStreamingTests.cs
index ee7cac8327..dac192ba5d 100644
--- a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionInvokeStreamingTests.cs
+++ b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionRunStreamingTests.cs
@@ -4,6 +4,6 @@ using AgentConformance.IntegrationTests;
namespace OpenAIChatCompletion.IntegrationTests;
-public class OpenAIChatCompletionInvokeStreamingTests() : RunStreamingAsyncTests(() => new())
+public class OpenAIChatCompletionRunStreamingTests() : RunStreamingTests(() => new())
{
}
diff --git a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionInvokeTests.cs b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionRunTests.cs
similarity index 58%
rename from dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionInvokeTests.cs
rename to dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionRunTests.cs
index 45e7993350..3de2d9b90d 100644
--- a/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionInvokeTests.cs
+++ b/dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionRunTests.cs
@@ -4,6 +4,6 @@ using AgentConformance.IntegrationTests;
namespace OpenAIChatCompletion.IntegrationTests;
-public class OpenAIChatCompletionInvokeTests() : RunAsyncTests(() => new())
+public class OpenAIChatCompletionRunTests() : RunTests(() => new())
{
}
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseChatClientAgentRunStreamingTests.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseChatClientAgentRunStreamingTests.cs
new file mode 100644
index 0000000000..171eecfd47
--- /dev/null
+++ b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseChatClientAgentRunStreamingTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIResponse.IntegrationTests;
+
+public class OpenAIResponseStoreTrueChatClientAgentRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new(store: true))
+{
+}
+
+public class OpenAIResponseStoreFalseChatClientAgentRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new(store: false))
+{
+}
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseChatClientAgentRunTests.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseChatClientAgentRunTests.cs
new file mode 100644
index 0000000000..d146ac7dbe
--- /dev/null
+++ b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseChatClientAgentRunTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIResponse.IntegrationTests;
+
+public class OpenAIResponseStoreTrueChatClientAgentRunTests() : ChatClientAgentRunTests(() => new(store: true))
+{
+}
+
+public class OpenAIResponseStoreFalseChatClientAgentRunTests() : ChatClientAgentRunTests(() => new(store: false))
+{
+}
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs
index c1a7b9edbf..45b19ebeb9 100644
--- a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs
+++ b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseFixture.cs
@@ -4,8 +4,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
using AgentConformance.IntegrationTests.Support;
-using AgentConformanceTests;
using Microsoft.Agents;
using Microsoft.Extensions.AI;
using OpenAI;
@@ -14,17 +14,21 @@ using Shared.IntegrationTests;
namespace OpenAIResponse.IntegrationTests;
-public class OpenAIResponseFixture(bool store) : AgentFixture
+public class OpenAIResponseFixture(bool store) : IChatClientAgentFixture
{
+ private static readonly OpenAIConfiguration s_config = TestConfiguration.LoadSection();
+
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private OpenAIResponseClient _openAIResponseClient;
private IChatClient _chatClient;
private Agent _agent;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
- public override Agent Agent => this._agent;
+ public Agent Agent => this._agent;
- public override async Task> GetChatHistoryAsync(AgentThread thread)
+ public IChatClient ChatClient => this._chatClient;
+
+ public async Task> GetChatHistoryAsync(AgentThread thread)
{
if (thread is not ChatClientAgentThread chatClientThread)
{
@@ -68,18 +72,37 @@ public class OpenAIResponseFixture(bool store) : AgentFixture
throw new NotSupportedException("This test currently only supports text messages");
}
- public override Task DeleteThreadAsync(AgentThread thread)
+ public Task CreateAgentWithInstructionsAsync(string instructions)
+ {
+ var options = new ChatClientAgentOptions
+ {
+ Name = "HelpfulAssistant",
+ Instructions = instructions,
+ ChatOptions = new ChatOptions
+ {
+ RawRepresentationFactory = new Func((_) => new ResponseCreationOptions() { StoredOutputEnabled = store })
+ },
+ };
+
+ return Task.FromResult(new ChatClientAgent(this._chatClient, options));
+ }
+
+ public Task DeleteAgentAsync(ChatClientAgent agent)
+ {
+ // Chat Completion does not require/support deleting agents, so this is a no-op.
+ return Task.CompletedTask;
+ }
+
+ public Task DeleteThreadAsync(AgentThread thread)
{
// Chat Completion does not require/support deleting threads, so this is a no-op.
return Task.CompletedTask;
}
- public override Task InitializeAsync()
+ public Task InitializeAsync()
{
- var config = TestConfiguration.LoadSection();
-
- this._openAIResponseClient = new OpenAIClient(config.ApiKey)
- .GetOpenAIResponseClient(config.ChatModelId);
+ this._openAIResponseClient = new OpenAIClient(s_config.ApiKey)
+ .GetOpenAIResponseClient(s_config.ChatModelId);
this._chatClient = this._openAIResponseClient
.AsIChatClient();
@@ -99,7 +122,7 @@ public class OpenAIResponseFixture(bool store) : AgentFixture
return Task.CompletedTask;
}
- public override Task DisposeAsync()
+ public Task DisposeAsync()
{
this._chatClient.Dispose();
return Task.CompletedTask;
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseInvokeStreamingTests.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseInvokeStreamingTests.cs
deleted file mode 100644
index 49d13af615..0000000000
--- a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseInvokeStreamingTests.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using AgentConformance.IntegrationTests;
-
-namespace OpenAIResponse.IntegrationTests;
-
-public class OpenAIResponseStoreTrueInvokeStreamingTests() : RunStreamingAsyncTests(() => new(store: true))
-{
-}
-
-public class OpenAIResponseStoreFalseInvokeStreamingTests() : RunStreamingAsyncTests(() => new(store: false))
-{
-}
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseInvokeTests.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseInvokeTests.cs
deleted file mode 100644
index a0135b3551..0000000000
--- a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseInvokeTests.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using AgentConformance.IntegrationTests;
-
-namespace OpenAIResponse.IntegrationTests;
-
-public class OpenAIResponseStoreTrueInvokeTests() : RunAsyncTests(() => new(store: true))
-{
-}
-
-public class OpenAIResponseStoreFalseInvokeTests() : RunAsyncTests(() => new(store: false))
-{
-}
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseRunStreamingTests.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseRunStreamingTests.cs
new file mode 100644
index 0000000000..00f8a04a68
--- /dev/null
+++ b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseRunStreamingTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIResponse.IntegrationTests;
+
+public class OpenAIResponseStoreTrueRunStreamingTests() : RunStreamingTests(() => new(store: true))
+{
+}
+
+public class OpenAIResponseStoreFalseRunStreamingTests() : RunStreamingTests(() => new(store: false))
+{
+}
diff --git a/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseRunTests.cs b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseRunTests.cs
new file mode 100644
index 0000000000..1a8fbb3286
--- /dev/null
+++ b/dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseRunTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using AgentConformance.IntegrationTests;
+
+namespace OpenAIResponse.IntegrationTests;
+
+public class OpenAIResponseStoreTrueRunTests() : RunTests(() => new(store: true))
+{
+}
+
+public class OpenAIResponseStoreFalseRunTests() : RunTests(() => new(store: false))
+{
+}