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 |
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.
The Agent API surface supports both streaming and non-streaming 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.
# 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?"),
]
)
# 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
::: 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
::: 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.
- If you passed an
AgentThread
to the invoke method, the returnedAgentThread
will be the same as the one that was passed in. - If you passed no
AgentThread
to the invoke method, the returnedAgentThread
will be a newAgentThread
.
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.
- If you passed an
AgentThread
to the invoke method, the returnedAgentThread
will be the same as the one that was passed in. - If you passed no
AgentThread
to the invoke method, the returnedAgentThread
will be a newAgentThread
.
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
::: 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
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