Skip to content

Commit d35d0c9

Browse files
authored
.Net: Add invoke overloads for string and no message. (#11219)
### Motivation and Context Most invocations take a user message as input, so supporting just passing the string is useful. Some agents support invoking the agent without any message, so adding explicit support for this is useful. ### Description Add invoke overloads for string and no message. ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] 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 - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
1 parent a72be1f commit d35d0c9

File tree

8 files changed

+327
-9
lines changed

8 files changed

+327
-9
lines changed

dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ApiService/Controllers/AgentCompletionsController.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ private async IAsyncEnumerable<ChatMessageContent> CompleteAsync(ChatHistory cha
7171
{
7272
var thread = new ChatHistoryAgentThread(chatHistory);
7373
IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> content =
74-
this._agent.InvokeAsync([], thread, options: new() { KernelArguments = arguments }, cancellationToken: cancellationToken);
74+
this._agent.InvokeAsync(thread, options: new() { KernelArguments = arguments }, cancellationToken: cancellationToken);
7575

7676
await foreach (ChatMessageContent item in content.ConfigureAwait(false))
7777
{
@@ -90,7 +90,7 @@ private async IAsyncEnumerable<StreamingChatMessageContent> CompleteSteamingAsyn
9090
{
9191
var thread = new ChatHistoryAgentThread(chatHistory);
9292
IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> content =
93-
this._agent.InvokeStreamingAsync([], thread, options: new() { KernelArguments = arguments }, cancellationToken: cancellationToken);
93+
this._agent.InvokeStreamingAsync(thread, options: new() { KernelArguments = arguments }, cancellationToken: cancellationToken);
9494

9595
await foreach (StreamingChatMessageContent item in content.ConfigureAwait(false))
9696
{

dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step01_AzureAIAgent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ await InvokeAgentAsync(
5858
// Local function to invoke agent and display the response.
5959
async Task InvokeAgentAsync(KernelArguments? arguments = null)
6060
{
61-
await foreach (ChatMessageContent response in agent.InvokeAsync([], thread, new() { KernelArguments = arguments }))
61+
await foreach (ChatMessageContent response in agent.InvokeAsync(thread, new() { KernelArguments = arguments }))
6262
{
6363
WriteAgentChatMessage(response);
6464
}

dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step01_Assistant.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ await InvokeAgentAsync(
5858
// Local function to invoke agent and display the response.
5959
async Task InvokeAgentAsync(KernelArguments? arguments = null)
6060
{
61-
await foreach (ChatMessageContent response in agent.InvokeAsync([], thread, options: new() { KernelArguments = arguments }))
61+
await foreach (ChatMessageContent response in agent.InvokeAsync(thread, options: new() { KernelArguments = arguments }))
6262
{
6363
WriteAgentChatMessage(response);
6464
}

dotnet/samples/GettingStartedWithAgents/Step01_Agent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ await InvokeAgentAsync(
173173
async Task InvokeAgentAsync(KernelArguments? arguments = null)
174174
{
175175
// Invoke the agent without any messages, since the agent has all that it needs via the template and arguments.
176-
await foreach (ChatMessageContent content in agent.InvokeAsync([], options: new() { KernelArguments = arguments }))
176+
await foreach (ChatMessageContent content in agent.InvokeAsync(options: new() { KernelArguments = arguments }))
177177
{
178178
WriteAgentChatMessage(content);
179179
}

dotnet/src/Agents/Abstractions/Agent.cs

+97-2
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.ChatCompletion;
910

1011
namespace Microsoft.SemanticKernel.Agents;
1112

@@ -43,6 +44,51 @@ public abstract class Agent
4344
/// </summary>
4445
public ILoggerFactory? LoggerFactory { get; init; }
4546

47+
/// <summary>
48+
/// Invoke the agent with no message assuming that all required instructions are already provided to the agent or on the thread.
49+
/// </summary>
50+
/// <param name="thread">The conversation thread to continue with this invocation. If not provided, creates a new thread.</param>
51+
/// <param name="options">Optional parameters for agent invocation.</param>
52+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
53+
/// <returns>An async list of response items that each contain a <see cref="ChatMessageContent"/> and an <see cref="AgentThread"/>.</returns>
54+
/// <remarks>
55+
/// To continue this thread in the future, use an <see cref="AgentThread"/> returned in one of the response items.
56+
/// </remarks>
57+
public virtual IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync(
58+
AgentThread? thread = null,
59+
AgentInvokeOptions? options = null,
60+
CancellationToken cancellationToken = default)
61+
{
62+
return this.InvokeAsync([], thread, options, cancellationToken);
63+
}
64+
65+
/// <summary>
66+
/// Invoke the agent with the provided message and arguments.
67+
/// </summary>
68+
/// <param name="message">The message to pass to the agent.</param>
69+
/// <param name="thread">The conversation thread to continue with this invocation. If not provided, creates a new thread.</param>
70+
/// <param name="options">Optional parameters for agent invocation.</param>
71+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
72+
/// <returns>An async list of response items that each contain a <see cref="ChatMessageContent"/> and an <see cref="AgentThread"/>.</returns>
73+
/// <remarks>
74+
/// <para>
75+
/// The provided message string will be treated as a user message.
76+
/// </para>
77+
/// <para>
78+
/// To continue this thread in the future, use an <see cref="AgentThread"/> returned in one of the response items.
79+
/// </para>
80+
/// </remarks>
81+
public virtual IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync(
82+
string message,
83+
AgentThread? thread = null,
84+
AgentInvokeOptions? options = null,
85+
CancellationToken cancellationToken = default)
86+
{
87+
Verify.NotNull(message);
88+
89+
return this.InvokeAsync(new ChatMessageContent(AuthorRole.User, message), thread, options, cancellationToken);
90+
}
91+
4692
/// <summary>
4793
/// Invoke the agent with the provided message and arguments.
4894
/// </summary>
@@ -60,7 +106,9 @@ public virtual IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsy
60106
AgentInvokeOptions? options = null,
61107
CancellationToken cancellationToken = default)
62108
{
63-
return this.InvokeAsync(new[] { message }, thread, options, cancellationToken);
109+
Verify.NotNull(message);
110+
111+
return this.InvokeAsync([message], thread, options, cancellationToken);
64112
}
65113

66114
/// <summary>
@@ -80,6 +128,51 @@ public abstract IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAs
80128
AgentInvokeOptions? options = null,
81129
CancellationToken cancellationToken = default);
82130

131+
/// <summary>
132+
/// Invoke the agent with no message assuming that all required instructions are already provided to the agent or on the thread.
133+
/// </summary>
134+
/// <param name="thread">The conversation thread to continue with this invocation. If not provided, creates a new thread.</param>
135+
/// <param name="options">Optional parameters for agent invocation.</param>
136+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
137+
/// <returns>An async list of response items that each contain a <see cref="ChatMessageContent"/> and an <see cref="AgentThread"/>.</returns>
138+
/// <remarks>
139+
/// To continue this thread in the future, use an <see cref="AgentThread"/> returned in one of the response items.
140+
/// </remarks>
141+
public virtual IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> InvokeStreamingAsync(
142+
AgentThread? thread = null,
143+
AgentInvokeOptions? options = null,
144+
CancellationToken cancellationToken = default)
145+
{
146+
return this.InvokeStreamingAsync([], thread, options, cancellationToken);
147+
}
148+
149+
/// <summary>
150+
/// Invoke the agent with the provided message and arguments.
151+
/// </summary>
152+
/// <param name="message">The message to pass to the agent.</param>
153+
/// <param name="thread">The conversation thread to continue with this invocation. If not provided, creates a new thread.</param>
154+
/// <param name="options">Optional parameters for agent invocation.</param>
155+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
156+
/// <returns>An async list of response items that each contain a <see cref="ChatMessageContent"/> and an <see cref="AgentThread"/>.</returns>
157+
/// <remarks>
158+
/// <para>
159+
/// The provided message string will be treated as a user message.
160+
/// </para>
161+
/// <para>
162+
/// To continue this thread in the future, use an <see cref="AgentThread"/> returned in one of the response items.
163+
/// </para>
164+
/// </remarks>
165+
public virtual IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> InvokeStreamingAsync(
166+
string message,
167+
AgentThread? thread = null,
168+
AgentInvokeOptions? options = null,
169+
CancellationToken cancellationToken = default)
170+
{
171+
Verify.NotNull(message);
172+
173+
return this.InvokeStreamingAsync(new ChatMessageContent(AuthorRole.User, message), thread, options, cancellationToken);
174+
}
175+
83176
/// <summary>
84177
/// Invoke the agent with the provided message and arguments.
85178
/// </summary>
@@ -97,7 +190,9 @@ public virtual IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>>
97190
AgentInvokeOptions? options = null,
98191
CancellationToken cancellationToken = default)
99192
{
100-
return this.InvokeStreamingAsync(new[] { message }, thread, options, cancellationToken);
193+
Verify.NotNull(message);
194+
195+
return this.InvokeStreamingAsync([message], thread, options, cancellationToken);
101196
}
102197

103198
/// <summary>

0 commit comments

Comments
 (0)