Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Microsoft Semantic kernel Agent InvokeAsync

From Leeroopedia

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

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment