Skip to content

Commit 8a5f845

Browse files
alliscodeBen Thomas
authored andcommitted
.Net: Removing KernelAgent.cs and moving its functionality into Agent.cs (microsoft#11244)
### Description Removing `KernelAgent` to decrease the number of layers in the Agent Framework. - Moved functionality of `KernelAgent` to `Agent` - Moved tests from `KernelAgentTests` to `AgentTests` - Removed `KernelAgent` and `KernelAgentTests` - Renamed `ChatHistoryKernelAgent` to `ChatHistoryAgent` ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄 --------- Co-authored-by: Ben Thomas <[email protected]>
1 parent 4cefe2a commit 8a5f845

31 files changed

+341
-283
lines changed

dotnet/samples/Concepts/Agents/ChatCompletion_ServiceSelection.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Agents;
77

88
/// <summary>
99
/// Demonstrate service selection for <see cref="ChatCompletionAgent"/> through setting service-id
10-
/// on <see cref="KernelAgent.Arguments"/> and also providing override <see cref="KernelArguments"/>
10+
/// on <see cref="Agent.Arguments"/> and also providing override <see cref="KernelArguments"/>
1111
/// when calling <see cref="ChatCompletionAgent.InvokeAsync(ChatHistory, KernelArguments?, Kernel?, CancellationToken)"/>
1212
/// </summary>
1313
public class ChatCompletion_ServiceSelection(ITestOutputHelper output) : BaseAgentsTest(output)

dotnet/samples/Concepts/Agents/OpenAIAssistant_Templating.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Always state the requested style of the poem.
3838
// Create the agent
3939
OpenAIAssistantAgent agent = new(assistant, this.AssistantClient)
4040
{
41-
Arguments =
41+
Arguments = new()
4242
{
4343
{"style", "haiku"}
4444
},
@@ -105,7 +105,7 @@ await this.AssistantClient.CreateAssistantFromTemplateAsync(
105105
// Create the agent
106106
OpenAIAssistantAgent agent = new(assistant, this.AssistantClient, plugins: null, templateFactory, templateFormat)
107107
{
108-
Arguments =
108+
Arguments = new()
109109
{
110110
{"style", "haiku"}
111111
},

dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step01_AzureAIAgent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task UseTemplateForAzureAgentAsync()
2626
templateFactory: new KernelPromptTemplateFactory(),
2727
templateFormat: PromptTemplateConfig.SemanticKernelTemplateFormat)
2828
{
29-
Arguments =
29+
Arguments = new()
3030
{
3131
{ "topic", "Dog" },
3232
{ "length", "3" }

dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step01_Assistant.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task UseTemplateForAssistantAgentAsync()
2626
templateFactory: new KernelPromptTemplateFactory(),
2727
templateFormat: PromptTemplateConfig.SemanticKernelTemplateFormat)
2828
{
29-
Arguments =
29+
Arguments = new()
3030
{
3131
{ "topic", "Dog" },
3232
{ "length", "3" }

dotnet/samples/GettingStartedWithAgents/Step01_Agent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public async Task UseTemplateForChatCompletionAgentAsync()
151151
new(templateConfig, templateFactory)
152152
{
153153
Kernel = this.CreateKernelWithChatCompletion(),
154-
Arguments =
154+
Arguments = new()
155155
{
156156
{ "topic", "Dog" },
157157
{ "length", "3" },

dotnet/samples/GettingStartedWithProcesses/Step04/KernelExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public static IChatHistoryProvider GetHistory(this Kernel kernel) =>
2121
/// <summary>
2222
/// Access an agent as a keyed service.
2323
/// </summary>
24-
public static TAgent GetAgent<TAgent>(this Kernel kernel, string key) where TAgent : KernelAgent =>
24+
public static TAgent GetAgent<TAgent>(this Kernel kernel, string key) where TAgent : Agent =>
2525
kernel.Services.GetRequiredKeyedService<TAgent>(key);
2626

2727
/// <summary>

dotnet/src/Agents/Abstractions/Agent.cs

+48
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77
using Microsoft.Extensions.Logging;
88
using Microsoft.Extensions.Logging.Abstractions;
9+
using Microsoft.SemanticKernel.Arguments.Extensions;
910
using Microsoft.SemanticKernel.ChatCompletion;
1011

1112
namespace Microsoft.SemanticKernel.Agents;
@@ -44,6 +45,32 @@ public abstract class Agent
4445
/// </summary>
4546
public ILoggerFactory? LoggerFactory { get; init; }
4647

48+
/// <summary>
49+
/// Gets the arguments for the agent instruction parameters (optional).
50+
/// </summary>
51+
/// <remarks>
52+
/// Also includes <see cref="PromptExecutionSettings"/>.
53+
/// </remarks>
54+
public KernelArguments? Arguments { get; init; }
55+
56+
/// <summary>
57+
/// Gets the instructions for the agent (optional).
58+
/// </summary>
59+
public string? Instructions { get; init; }
60+
61+
/// <summary>
62+
/// Gets the <see cref="Kernel"/> containing services, plugins, and filters for use throughout the agent lifetime.
63+
/// </summary>
64+
/// <value>
65+
/// The <see cref="Kernel"/> containing services, plugins, and filters for use throughout the agent lifetime. The default value is an empty Kernel, but that can be overridden.
66+
/// </value>
67+
public Kernel Kernel { get; init; } = new();
68+
69+
/// <summary>
70+
/// Gets or sets a prompt template based on the agent instructions.
71+
/// </summary>
72+
protected IPromptTemplate? Template { get; set; }
73+
4774
/// <summary>
4875
/// Invoke the agent with no message assuming that all required instructions are already provided to the agent or on the thread.
4976
/// </summary>
@@ -222,6 +249,27 @@ public abstract IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>>
222249
/// </summary>
223250
protected virtual ILoggerFactory ActiveLoggerFactory => this.LoggerFactory ?? NullLoggerFactory.Instance;
224251

252+
/// <summary>
253+
/// Formats the system instructions for the agent.
254+
/// </summary>
255+
/// <param name="kernel">The <see cref="Kernel"/> containing services, plugins, and other state for use by the agent.</param>
256+
/// <param name="arguments">Optional arguments to pass to the agents's invocation, including any <see cref="PromptExecutionSettings"/>.</param>
257+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
258+
/// <returns>The formatted system instructions for the agent.</returns>
259+
protected async Task<string?> RenderInstructionsAsync(Kernel kernel, KernelArguments? arguments, CancellationToken cancellationToken)
260+
{
261+
if (this.Template is null)
262+
{
263+
// Use the instructions as-is
264+
return this.Instructions;
265+
}
266+
267+
var mergedArguments = this.Arguments.Merge(arguments);
268+
269+
// Use the provided template as the instructions
270+
return await this.Template.RenderAsync(kernel, mergedArguments, cancellationToken).ConfigureAwait(false);
271+
}
272+
225273
/// <summary>
226274
/// Set of keys to establish channel affinity. Minimum expected key-set:
227275
/// <example>

dotnet/src/Agents/Abstractions/Agents.Abstractions.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<!-- THIS PROPERTY GROUP MUST COME FIRST -->
@@ -20,6 +20,7 @@
2020
<Compile Include="$(RepoRoot)/dotnet/src/InternalUtilities/src/Diagnostics/*" Link="%(RecursiveDir)Utilities/%(Filename)%(Extension)" />
2121
<Compile Include="$(RepoRoot)/dotnet/src/InternalUtilities/src/System/AppContextSwitchHelper.cs" Link="%(RecursiveDir)Utilities/%(Filename)%(Extension)" />
2222
<Compile Include="$(RepoRoot)/dotnet/src/InternalUtilities/agents/Extensions/AgentExtensions.cs" Link="%(RecursiveDir)Utilities/%(Filename)%(Extension)" />
23+
<Compile Include="$(RepoRoot)/dotnet/src/InternalUtilities/arguments/Extensions/KernelArgumentsExtensions.cs" Link="%(RecursiveDir)Utilities/%(Filename)%(Extension)" />
2324
</ItemGroup>
2425

2526
<ItemGroup>

dotnet/src/Agents/Abstractions/KernelAgent.cs

-100
This file was deleted.

dotnet/src/Agents/AzureAI/AzureAIAgent.ClientFactory.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI;
1010
/// <summary>
1111
/// Provides an <see cref="AIProjectClient"/> for use by <see cref="AzureAIAgent"/>.
1212
/// </summary>
13-
public sealed partial class AzureAIAgent : KernelAgent
13+
public sealed partial class AzureAIAgent : Agent
1414
{
1515
/// <summary>
1616
/// Produces a <see cref="AIProjectClient"/>.

dotnet/src/Agents/AzureAI/AzureAIAgent.cs

+5-9
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
namespace Microsoft.SemanticKernel.Agents.AzureAI;
1717

1818
/// <summary>
19-
/// Provides a specialized <see cref="KernelAgent"/> based on an Azure AI agent.
19+
/// Provides a specialized <see cref="Agent"/> based on an Azure AI agent.
2020
/// </summary>
21-
public sealed partial class AzureAIAgent : KernelAgent
21+
public sealed partial class AzureAIAgent : Agent
2222
{
2323
/// <summary>
2424
/// Provides tool definitions used when associating a file attachment to an input message:
@@ -200,7 +200,7 @@ async IAsyncEnumerable<ChatMessageContent> InternalInvokeAsync()
200200
options?.ToAzureAIInvocationOptions(),
201201
this.Logger,
202202
options?.Kernel ?? this.Kernel,
203-
this.MergeArguments(options?.KernelArguments),
203+
options?.KernelArguments,
204204
cancellationToken).ConfigureAwait(false))
205205
{
206206
// The thread and the caller should be notified of all messages regardless of visibility.
@@ -252,8 +252,6 @@ public IAsyncEnumerable<ChatMessageContent> InvokeAsync(
252252
async IAsyncEnumerable<ChatMessageContent> InternalInvokeAsync()
253253
{
254254
kernel ??= this.Kernel;
255-
arguments = this.MergeArguments(arguments);
256-
257255
await foreach ((bool isVisible, ChatMessageContent message) in AgentThreadActions.InvokeAsync(this, this.Client, threadId, options, this.Logger, kernel, arguments, cancellationToken).ConfigureAwait(false))
258256
{
259257
if (isVisible)
@@ -311,7 +309,7 @@ public async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> In
311309
var invokeResults = this.InvokeStreamingAsync(
312310
azureAIAgentThread.Id!,
313311
options?.ToAzureAIInvocationOptions(),
314-
this.MergeArguments(options?.KernelArguments),
312+
options?.KernelArguments,
315313
options?.Kernel ?? this.Kernel,
316314
newMessagesReceiver,
317315
cancellationToken);
@@ -388,8 +386,6 @@ public IAsyncEnumerable<StreamingChatMessageContent> InvokeStreamingAsync(
388386
IAsyncEnumerable<StreamingChatMessageContent> InternalInvokeStreamingAsync()
389387
{
390388
kernel ??= this.Kernel;
391-
arguments = this.MergeArguments(arguments);
392-
393389
return AgentThreadActions.InvokeStreamingAsync(this, this.Client, threadId, messages, options, this.Logger, kernel, arguments, cancellationToken);
394390
}
395391
}
@@ -425,7 +421,7 @@ protected override async Task<AgentChannel> CreateChannelAsync(CancellationToken
425421

426422
internal Task<string?> GetInstructionsAsync(Kernel kernel, KernelArguments? arguments, CancellationToken cancellationToken)
427423
{
428-
return this.FormatInstructionsAsync(kernel, arguments, cancellationToken);
424+
return this.RenderInstructionsAsync(kernel, arguments, cancellationToken);
429425
}
430426

431427
/// <inheritdoc/>

dotnet/src/Agents/Bedrock/BedrockAgent.cs

+6-12
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
namespace Microsoft.SemanticKernel.Agents.Bedrock;
1717

1818
/// <summary>
19-
/// Provides a specialized <see cref="KernelAgent"/> for the Bedrock Agent service.
19+
/// Provides a specialized <see cref="Agent"/> for the Bedrock Agent service.
2020
/// </summary>
21-
public sealed class BedrockAgent : KernelAgent
21+
public sealed class BedrockAgent : Agent
2222
{
2323
/// <summary>
2424
/// The client used to interact with the Bedrock Agent service.
@@ -136,8 +136,7 @@ public override async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> In
136136
});
137137

138138
// Invoke the agent
139-
var arguments = this.MergeArguments(options?.KernelArguments);
140-
var invokeResults = this.InvokeInternalAsync(invokeAgentRequest, arguments, cancellationToken);
139+
var invokeResults = this.InvokeInternalAsync(invokeAgentRequest, options?.KernelArguments, cancellationToken);
141140

142141
// Return the results to the caller in AgentResponseItems.
143142
await foreach (var result in invokeResults.ConfigureAwait(false))
@@ -180,8 +179,6 @@ public async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync
180179
AgentInvokeOptions? options = null,
181180
[EnumeratorCancellation] CancellationToken cancellationToken = default)
182181
{
183-
var arguments = this.MergeArguments(options?.KernelArguments);
184-
185182
// The provided thread is used to continue the conversation. If the thread is not provided and the session id is provided,
186183
// a new thread is created with the provided session id. If neither is provided, a new thread is created.
187184
if (thread is null && invokeAgentRequest.SessionId is not null)
@@ -200,7 +197,7 @@ public async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync
200197
invokeAgentRequest = this.ConfigureAgentRequest(options, () => invokeAgentRequest);
201198

202199
// Invoke the agent
203-
var invokeResults = this.InvokeInternalAsync(invokeAgentRequest, arguments, cancellationToken);
200+
var invokeResults = this.InvokeInternalAsync(invokeAgentRequest, options?.KernelArguments, cancellationToken);
204201

205202
// Return the results to the caller in AgentResponseItems.
206203
await foreach (var result in invokeResults.ConfigureAwait(false))
@@ -368,8 +365,7 @@ public override async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageCon
368365
});
369366

370367
// Invoke the agent
371-
var arguments = this.MergeArguments(options?.KernelArguments);
372-
var invokeResults = this.InvokeStreamingInternalAsync(invokeAgentRequest, bedrockThread, arguments, cancellationToken);
368+
var invokeResults = this.InvokeStreamingInternalAsync(invokeAgentRequest, bedrockThread, options?.KernelArguments, cancellationToken);
373369

374370
// Return the results to the caller in AgentResponseItems.
375371
await foreach (var result in invokeResults.ConfigureAwait(false))
@@ -413,8 +409,6 @@ public async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> In
413409
AgentInvokeOptions? options = null,
414410
[EnumeratorCancellation] CancellationToken cancellationToken = default)
415411
{
416-
var arguments = this.MergeArguments(options?.KernelArguments);
417-
418412
// The provided thread is used to continue the conversation. If the thread is not provided and the session id is provided,
419413
// a new thread is created with the provided session id. If neither is provided, a new thread is created.
420414
if (thread is null && invokeAgentRequest.SessionId is not null)
@@ -432,7 +426,7 @@ public async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> In
432426
invokeAgentRequest.SessionId = bedrockThread.Id;
433427
invokeAgentRequest = this.ConfigureAgentRequest(options, () => invokeAgentRequest);
434428

435-
var invokeResults = this.InvokeStreamingInternalAsync(invokeAgentRequest, bedrockThread, arguments, cancellationToken);
429+
var invokeResults = this.InvokeStreamingInternalAsync(invokeAgentRequest, bedrockThread, options?.KernelArguments, cancellationToken);
436430

437431
// The Bedrock agent service has the same API for both streaming and non-streaming responses.
438432
// We are invoking the same method as the non-streaming response with the streaming configuration set,

dotnet/src/Agents/Core/AgentGroupChat.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public sealed class AgentGroupChat : AgentChat
4444
/// <summary>
4545
/// Add an <see cref="Agent"/> to the chat.
4646
/// </summary>
47-
/// <param name="agent">The <see cref="KernelAgent"/> to add.</param>
47+
/// <param name="agent">The <see cref="Agent"/> to add.</param>
4848
public void AddAgent(Agent agent)
4949
{
5050
if (this._agentIds.Add(agent.Id))

0 commit comments

Comments
 (0)