Implementation:Microsoft Semantic kernel Agent InvokeAsync
Overview
agent.InvokeAsync(message, thread?, options?) is the primary invocation API for Semantic Kernel agents, returning an IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> that streams the agent's response along with the updated conversation thread. This method handles the complete lifecycle of a single agent interaction: history assembly, chat completion, tool calling, and thread state management.
Source file: dotnet/src/Agents/Core/ChatCompletionAgent.cs:L26-454
Principle page: Single Agent Invocation
Principle:Microsoft_Semantic_kernel_Single_Agent_Invocation
Code Reference
Method Signature
public IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync(
ChatMessageContent message,
AgentThread? thread = null,
AgentInvokeOptions? options = null,
CancellationToken cancellationToken = default);
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
message |
ChatMessageContent |
(required) | The user message to send to the agent. Typically created with AuthorRole.User and a string content.
|
thread |
AgentThread? |
null |
The conversation thread providing prior context. When null, a new ChatHistoryAgentThread is created automatically.
|
options |
AgentInvokeOptions? |
null |
Optional invocation settings that can override agent-level configuration for this specific call. |
cancellationToken |
CancellationToken |
default |
Token to cancel the asynchronous operation. |
Return Type
IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>
Each yielded item is an AgentResponseItem<ChatMessageContent> containing:
| Property | Type | Description |
|---|---|---|
Message |
ChatMessageContent |
The response message content, including the text, author role (Assistant), and any metadata.
|
Thread |
AgentThread |
The updated conversation thread after this response. Should be captured for subsequent invocations. |
I/O Contract
Input
agent.InvokeAsync(message, thread?, options?, cancellationToken)
├── message: ChatMessageContent
│ ├── Role: AuthorRole.User (typically)
│ └── Content: string (the user's message text)
├── thread: AgentThread? (null → auto-create)
│ └── ChatHistoryAgentThread with prior messages
├── options: AgentInvokeOptions? (null → use agent defaults)
└── cancellationToken: CancellationToken
Output
IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>
└── For each yielded item:
├── .Message: ChatMessageContent
│ ├── .Role: AuthorRole.Assistant
│ ├── .Content: string (response text)
│ └── .AuthorName: string (agent's Name, if set)
└── .Thread: AgentThread
└── Contains all messages up to and including this response
Internal Processing Flow
1. Resolve thread (use provided or create new ChatHistoryAgentThread)
2. Build chat history:
a. System message from agent.Instructions
b. All messages from thread.ChatHistory
c. The new user message
3. Retrieve IChatCompletionService from agent.Kernel
4. Call service with history + agent.Arguments
5. If tool calls in response:
a. Invoke corresponding KernelFunction from Kernel.Plugins
b. Append tool results to history
c. Call service again (loop until text response)
6. Yield AgentResponseItem with message + updated thread
7. Append user message and assistant response to thread
Usage Examples
Stateless One-Shot Invocation
ChatMessageContent message = new(AuthorRole.User, "Fortune favors the bold.");
await foreach (AgentResponseItem<ChatMessageContent> response in agent.InvokeAsync(message))
{
Console.WriteLine(response.Message.Content);
}
// Thread is created internally but not captured — stateless
Stateful Multi-Turn Conversation
AgentThread? thread = null;
// Turn 1
await foreach (var response in agent.InvokeAsync(
new ChatMessageContent(AuthorRole.User, "What is photosynthesis?"), thread))
{
thread = response.Thread; // Capture thread
Console.WriteLine(response.Message.Content);
}
// Turn 2 — agent has context from Turn 1
await foreach (var response in agent.InvokeAsync(
new ChatMessageContent(AuthorRole.User, "What are its inputs and outputs?"), thread))
{
thread = response.Thread; // Update thread
Console.WriteLine(response.Message.Content);
}
Invocation with Pre-Seeded Thread
AgentThread thread = new ChatHistoryAgentThread([
new ChatMessageContent(AuthorRole.User, "Tell me a joke."),
new ChatMessageContent(AuthorRole.Assistant, "Why did the chicken cross the road? To get to the other side!"),
]);
await foreach (var response in agent.InvokeAsync(
new ChatMessageContent(AuthorRole.User, "That was terrible. Try harder."), thread))
{
thread = response.Thread;
Console.WriteLine(response.Message.Content);
}
Conversation Loop Pattern
AgentThread? thread = null;
while (true)
{
Console.Write("You: ");
string? userInput = Console.ReadLine();
if (string.IsNullOrEmpty(userInput)) break;
ChatMessageContent message = new(AuthorRole.User, userInput);
await foreach (var response in agent.InvokeAsync(message, thread))
{
thread = response.Thread;
Console.WriteLine($"Agent: {response.Message.Content}");
}
}
Invocation with Cancellation
using CancellationTokenSource cts = new(TimeSpan.FromSeconds(30));
try
{
await foreach (var response in agent.InvokeAsync(message, thread, cancellationToken: cts.Token))
{
thread = response.Thread;
Console.WriteLine(response.Message.Content);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Agent invocation timed out.");
}
Related Pages
- Single Agent Invocation (Principle) -- The conceptual foundation for the invocation model.
- ChatCompletionAgent (Implementation) -- The agent class that implements
InvokeAsync. - ChatHistoryAgentThread (Implementation) -- The thread type created and used by
InvokeAsync. - Conversation Thread Management (Principle) -- How threads are managed across invocations.
- Agent Kernel Plugins Add (Implementation) -- Plugins that are invoked during the tool-calling phase.
- Orchestration Patterns (Implementation) -- How invocations are coordinated in multi-agent scenarios.