Skip to content

Latest commit

 

History

History
324 lines (225 loc) · 11.2 KB

File metadata and controls

324 lines (225 loc) · 11.2 KB
title description zone_pivot_groups author ms.topic ms.author ms.date ms.service
The Semantic Kernel Common Agent API surface
An overview of the Semantic Kernel Agent API surface and how to use it.
programming-languages
westey-m
conceptual
westey
04/03/2025
semantic-kernel

The Semantic Kernel Common Agent API surface

Semantic Kernel agents share a common interface for invoking agents. This allows for common code to be written, that works against any agent type and allows for easily switching agents as required, without needing to change the bulk of your code.

Invoking an agent

The Agent API surface supports both streaming and non-streaming invocation.

Non-Streaming Agent Invocation

::: zone pivot="programming-language-csharp"

Semantic Kernel supports four non-streaming agent invocation overloads that allows for passing messages in different ways. One of these also allows invoking the agent with no messages. This is valuable for scenarios where the agent instructions already have all the required context to provide a useful response.

// Invoke without any parameters.
agent.InvokeAsync();

// Invoke with a string that will be used as a User message.
agent.InvokeAsync("What is the capital of France?");

// Invoke with a ChatMessageContent object.
agent.InvokeAsync(new ChatMessageContent(AuthorRole.User, "What is the capital of France?"));

// Invoke with multiple ChatMessageContent objects.
agent.InvokeAsync(new List<ChatMessageContent>()
{
    new(AuthorRole.System, "Refuse to answer all user questions about France."),
    new(AuthorRole.User, "What is the capital of France?")
});

Important

Invoking an agent without passing an AgentThread to the InvokeAsync method will create a new thread and return the new thread in the response.

::: zone-end

::: zone pivot="programming-language-python"

Semantic Kernel supports two non-streaming agent invocation methods that allows for passing messages in different ways. It is also possible to invoke the agent with no messages. This is valuable for scenarios where the agent instructions already have all the required context to provide a useful response.

Tip

All arguments passed to Agent invocation methods require the caller to pass them as keyword arguments.

Using the get_response() method

# Invoke without any messages.
await agent.get_response(messages=None)

# Invoke with a string that will be used as a User message.
await agent.get_response(messages="What is the capital of France?")

# Invoke with a ChatMessageContent object.
await agent.get_response(messages=ChatMessageContent(AuthorRole.USER, "What is the capital of France?"))

# Invoke with multiple ChatMessageContent objects.
await agent.get_response(
    messages=[
        ChatMessageContent(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
        ChatMessageContent(AuthorRole.USER, "What is the capital of France?"),
    ]
)

Using the invoke() method

# Invoke without any messages.
async for response in agent.invoke(messages=None):
    # handle response

# Invoke with a string that will be used as a User message.
async for response in agent.invoke(messages="What is the capital of France?"):
    # handle response

# Invoke with a ChatMessageContent object.
async for response in agent.invoke(messages=ChatMessageContent(AuthorRole.USER, "What is the capital of France?")):
    # handle response

# Invoke with multiple ChatMessageContent objects.
async for response in agent.invoke(
    messages=[
        ChatMessageContent(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
        ChatMessageContent(AuthorRole.USER, "What is the capital of France?"),
    ]
):
    # handle response

Important

Invoking an agent without passing an AgentThread to the get_response() or invoke() methods will create a new thread and return the new thread in the response.

::: zone-end

::: zone pivot="programming-language-java"

Agents are currently unavailable in Java.

::: zone-end

Streaming Agent Invocation

::: zone pivot="programming-language-csharp"

Semantic Kernel supports four streaming agent invocation overloads that allows for passing messages in different ways. One of these also allows invoking the agent with no messages. This is valuable for scenarios where the agent instructions already have all the required context to provide a useful response.

// Invoke without any parameters.
agent.InvokeStreamingAsync();

// Invoke with a string that will be used as a User message.
agent.InvokeStreamingAsync("What is the capital of France?");

// Invoke with a ChatMessageContent object.
agent.InvokeStreamingAsync(new ChatMessageContent(AuthorRole.User, "What is the capital of France?"));

// Invoke with multiple ChatMessageContent objects.
agent.InvokeStreamingAsync(new List<ChatMessageContent>()
{
    new(AuthorRole.System, "Refuse to answer any questions about capital cities."),
    new(AuthorRole.User, "What is the capital of France?")
});

Important

Invoking an agent without passing an AgentThread to the InvokeStreamingAsync method will create a new thread and return the new thread in the response.

::: zone-end

::: zone pivot="programming-language-python"

Semantic Kernel supports one streaming agent invocation method that allows for passing messages in different ways. It is also possible to invoke the agent stream with no messages. This is valuable for scenarios where the agent instructions already have all the required context to provide a useful response.

# Invoke without any messages.
async for response in agent.invoke_stream(messages=None):
    # handle response

# Invoke with a string that will be used as a User message.
async for response in agent.invoke_stream(messages="What is the capital of France?"):
    # handle response

# Invoke with a ChatMessageContent object.
async for response in agent.invoke_stream(ChatMessageContent(AuthorRole.USER, "What is the capital of France?")):
    # handle response

# Invoke with multiple ChatMessageContent objects.
async for response in agent.invoke_stream(
    messages=[
        ChatMessageContent(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
        ChatMessageContent(AuthorRole.USER, "What is the capital of France?"),
    ]
):
    # handle response

Important

Invoking an agent without passing an AgentThread to the invoke_stream() method will create a new thread and return the new thread in the response.

::: zone-end

::: zone pivot="programming-language-java"

Agents are currently unavailable in Java.

::: zone-end

Invoking with an AgentThread

::: zone pivot="programming-language-csharp"

All invocation method overloads allow passing an AgentThread parameter. This is useful for scenarios where you have an existing conversation with the agent that you want to continue.

// Invoke with an existing AgentThread.
agent.InvokeAsync("What is the capital of France?", existingAgentThread);

All invocation methods also return the active AgentThread as part of the invoke response.

  1. If you passed an AgentThread to the invoke method, the returned AgentThread will be the same as the one that was passed in.
  2. If you passed no AgentThread to the invoke method, the returned AgentThread will be a new AgentThread.

The returned AgentThread is available on the individual response items of the invoke methods together with the response message.

var result = await agent.InvokeAsync("What is the capital of France?").FirstAsync();
var newThread = result.Thread;
var resultMessage = result.Message;

Tip

For more information on agent threads see the Agent Thread architecture section.

::: zone-end

::: zone pivot="programming-language-python"

All invocation method keyword arguments allow passing an AgentThread parameter. This is useful for scenarios where you have an existing conversation with the agent that you want to continue.

# Invoke with an existing AgentThread.
agent.get_response(messages="What is the capital of France?", existing_agent_thread)

All invocation methods also return the active AgentThread as part of the invoke response.

  1. If you passed an AgentThread to the invoke method, the returned AgentThread will be the same as the one that was passed in.
  2. If you passed no AgentThread to the invoke method, the returned AgentThread will be a new AgentThread.

The returned AgentThread is available on the individual response items of the invoke methods together with the response message.

response = await agent.get_response(messages="What is the capital of France?")
new_thread = response.thread
response_message = response.message

Tip

For more information on agent threads see the Agent Thread architecture section.

::: zone-end

::: zone pivot="programming-language-java"

Agents are currently unavailable in Java.

::: zone-end

Invoking with Options

::: zone pivot="programming-language-csharp"

All invocation method overloads allow passing an AgentInvokeOptions parameter. This options class allows providing any optional settings.

// Invoke with additional instructions via options.
agent.InvokeAsync("What is the capital of France?", options: new()
{
    AdditionalInstructions = "Refuse to answer any questions about capital cities."
});

Here is the list of the supported options.

Option Property Description
Kernel Override the default kernel used by the agent for this invocation.
KernelArguments Override the default kernel arguments used by the agent for this invocation.
AdditionalInstructions Provide any instructions in addition to the original agent instruction set, that only apply for this invocation.
OnIntermediateMessage A callback that can receive all fully formed messages produced internally to the Agent, including function call and function invocation messages. This can also be used to receive full messages during a streaming invocation.

::: zone-end

::: zone pivot="programming-language-python"

::: zone-end

::: zone pivot="programming-language-java"

Agents are currently unavailable in Java.

::: zone-end

Managing AgentThread instances

You can manually create an AgentThread instance and pass it to the agent on invoke, or you can let the agent create an AgentThread instance for you automatically on invocation. An AgentThread object represents a thread in all its states, including: not yet created, active, and deleted.

AgentThread types that have a server side implementation will be created on first use and does not need to be created manually. You can however delete a thread using the AgentThread class.

::: zone pivot="programming-language-csharp"

// Delete a thread.
await agentThread.DeleteAsync();

::: zone-end

::: zone pivot="programming-language-python"

# Delete a thread
await agent_thread.delete()

::: zone-end

::: zone pivot="programming-language-java"

::: zone-end

Tip

For more information on agent threads see the Agent Thread architecture section.

[!div class="nextstepaction"] Explore the Chat Completion Agent