diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 9dc8282e..ccd7fa2b 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -789,6 +789,41 @@ "source_path": "semantic-kernel/Frameworks/agent/personas.md", "redirect_url": "semantic-kernel/frameworks/agent", "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/assistant-agent.md", + "redirect_url": "semantic-kernel/frameworks/agent/agent-types/assistant-agent.md", + "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/chat-completion-agent.md", + "redirect_url": "semantic-kernel/frameworks/agent/agent-types/chat-completion-agent.md", + "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/azure-ai-agent.md", + "redirect_url": "semantic-kernel/frameworks/agent/agent-types/azure-ai-agent.md", + "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/copilot-studio-agent.md", + "redirect_url": "/semantic-kernel/frameworks/agent/agent-types/copilot-studio-agent.md", + "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/responses-agent.md", + "redirect_url": "/semantic-kernel/frameworks/agent/agent-types/responses-agent.md", + "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/agent-chat.md", + "redirect_url": "/semantic-kernel/support/archive/agent-chat.md", + "redirect_document_id": false + }, + { + "source_path": "semantic-kernel/Frameworks/agent/examples/example-agent-collaboration.md", + "redirect_url": "/semantic-kernel/support/archive/agent-chat-example.md", + "redirect_document_id": false } ] } diff --git a/semantic-kernel/Frameworks/agent/TOC.yml b/semantic-kernel/Frameworks/agent/TOC.yml index abd44f8a..b94e536f 100644 --- a/semantic-kernel/Frameworks/agent/TOC.yml +++ b/semantic-kernel/Frameworks/agent/TOC.yml @@ -4,23 +4,15 @@ href: agent-architecture.md - name: Common Agent Invocation API href: agent-api.md -- name: Chat Completion Agent - href: chat-completion-agent.md -- name: OpenAI Assistant Agent - href: assistant-agent.md -- name: Azure AI Agent - href: azure-ai-agent.md -- name: OpenAI Responses Agent - href: responses-agent.md -- name: Copilot Studio Agent - href: copilot-studio-agent.md -- name: Agent Collaboration - href: agent-chat.md -- name: Create an Agent from a Template - href: agent-templates.md - name: Configuring Agents with Plugins href: agent-functions.md +- name: Create an Agent from a Template + href: agent-templates.md - name: Streaming Agent Responses href: agent-streaming.md +- name: Supported Agent Types + href: agent-types/TOC.yml +- name: Agent Orchestration + href: agent-orchestration/TOC.yml - name: How-To with Agents href: examples/TOC.yml diff --git a/semantic-kernel/Frameworks/agent/agent-api.md b/semantic-kernel/Frameworks/agent/agent-api.md index 7e29ce54..25238d6e 100644 --- a/semantic-kernel/Frameworks/agent/agent-api.md +++ b/semantic-kernel/Frameworks/agent/agent-api.md @@ -9,10 +9,9 @@ ms.date: 04/03/2025 ms.service: semantic-kernel --- -# The Semantic Kernel Common Agent API surface +# 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. +Semantic Kernel agents implement a unified interface for invocation, enabling shared code that operates seamlessly across different agent types. This design allows you to switch agents as needed without modifying the majority of your application logic. ## Invoking an agent @@ -22,9 +21,7 @@ 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. +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. ```csharp // Invoke without any parameters. @@ -51,9 +48,7 @@ agent.InvokeAsync(new List() ::: 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. +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. @@ -111,9 +106,7 @@ async for response in agent.invoke( ::: zone pivot="programming-language-java" -Semantic Kernel supports three 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. +Semantic Kernel supports three 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. ```java // Invoke without any parameters. @@ -141,9 +134,7 @@ agent.invokeAsync(List.of( ::: 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. +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. ```csharp // Invoke without any parameters. @@ -170,9 +161,7 @@ agent.InvokeStreamingAsync(new List() ::: 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. +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. ```python # Invoke without any messages. @@ -200,7 +189,6 @@ async for response in agent.invoke_stream( > [!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" @@ -213,8 +201,7 @@ async for response in agent.invoke_stream( ::: 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. +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. ```csharp // Invoke with an existing AgentThread. @@ -241,12 +228,11 @@ var resultMessage = result.Message; ::: 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. +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. ```python # Invoke with an existing AgentThread. -agent.get_response(messages="What is the capital of France?", existing_agent_thread) +agent.get_response(messages="What is the capital of France?", thread=existing_agent_thread) ``` All invocation methods also return the active `AgentThread` as part of the invoke response. @@ -269,8 +255,7 @@ response_message = response.message ::: zone pivot="programming-language-java" -Two 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. +Two 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. ```java // Invoke with an existing AgentThread. @@ -295,10 +280,10 @@ var resultMessage = result.getMessage(); ::: zone-end -### Invoking with Options - ::: zone pivot="programming-language-csharp" +### Invoking with Options + All invocation method overloads allow passing an `AgentInvokeOptions` parameter. This options class allows providing any optional settings. @@ -312,12 +297,12 @@ agent.InvokeAsync("What is the capital of France?", options: new() 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.| +| 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 @@ -327,12 +312,14 @@ Here is the list of the supported options. ::: zone pivot="programming-language-java" +### Invoking with Options + One invocation method overloads allow passing an `AgentInvokeOptions` parameter. This options class allows providing any optional settings. ```java // Invoke with additional instructions via options. -agent.invokeAsync("What is the capital of France?", +agent.invokeAsync("What is the capital of France?", null, // null AgentThread AgentInvokeOptions.builder() .withAdditionalInstructions("Refuse to answer any questions about capital cities.") @@ -342,12 +329,12 @@ agent.invokeAsync("What is the capital of France?", 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.| -|InvocationContext|Override the default invocation context the agent uses for this invocation.| +| 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. | +| InvocationContext | Override the default invocation context the agent uses for this invocation. | ::: zone-end @@ -389,5 +376,10 @@ agentThread.deleteAsync().block(); > [!TIP] > For more information on agent threads see the [Agent Thread architecture section](./agent-architecture.md#agent-thread). +## Next steps + +> [!div class="nextstepaction"] +> [Configure agents with plugins](./agent-functions.md) + > [!div class="nextstepaction"] -> [Explore the Chat Completion Agent](./chat-completion-agent.md) \ No newline at end of file +> [Explore the Chat Completion Agent](./agent-types/chat-completion-agent.md) diff --git a/semantic-kernel/Frameworks/agent/agent-architecture.md b/semantic-kernel/Frameworks/agent/agent-architecture.md index 8c577b33..cf62fcc6 100644 --- a/semantic-kernel/Frameworks/agent/agent-architecture.md +++ b/semantic-kernel/Frameworks/agent/agent-architecture.md @@ -8,321 +8,132 @@ ms.author: crickman ms.date: 09/13/2024 ms.service: semantic-kernel --- -# An Overview of the Agent Architecture -> [!IMPORTANT] -> `AgentChat` patterns are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. +# An Overview of the Agent Architecture This article covers key concepts in the architecture of the Agent Framework, including foundational principles, design objectives, and strategic goals. - ## Goals The `Agent Framework` was developed with the following key priorities in mind: - The Semantic Kernel agent framework serves as the core foundation for implementing agent functionalities. -- Multiple agents can collaborate within a single conversation, while integrating human input. +- Multiple agents of different types can collaborate within a single conversation, each contributing their unique capabilities, while integrating human input. - An agent can engage in and manage multiple concurrent conversations simultaneously. -- Different types of agents can participate in the same conversation, each contributing their unique capabilities. - ## Agent -The abstract `Agent` class serves as the core abstraction for all types of agents, providing a foundational structure that can be extended to create more specialized agents. One key subclass is _Kernel Agent_, which establishes a direct association with a [`Kernel`](../../concepts/kernel.md) object. This relationship forms the basis for more specific agent implementations, such as the [`ChatCompletionAgent`](./chat-completion-agent.md), [`OpenAIAssistantAgent`](./assistant-agent.md), [`AzureAIAgent`](./azure-ai-agent.md), or [`OpenAIResponsesAgent`](./responses-agent.md), all of which leverage the Kernel's capabilities to execute their respective functions. +The abstract `Agent` class serves as the core abstraction for all types of agents, providing a foundational structure that can be extended to create more specialized agents. This base class forms the basis for more specific agent implementations, all of which leverage the Kernel's capabilities to execute their respective functions. See all the available agent types in the [Agent Types](#agent-types-in-semantic-kernel) section. ::: zone pivot="programming-language-csharp" -- [`Agent`](/dotnet/api/microsoft.semantickernel.agents.agent) -- [`KernelAgent`](/dotnet/api/microsoft.semantickernel.agents.kernelagent) +The underlying Semantic Kernel `Agent` abstraction can be found [here](/dotnet/api/microsoft.semantickernel.agents.agent). ::: zone-end ::: zone pivot="programming-language-python" -The underlying Semantic Kernel `Agent` abstraction can be found here: - -- [`Agent`](/python/api/semantic-kernel/semantic_kernel.agents.agent) - -::: zone-end - -::: zone pivot="programming-language-java" - -> Feature currently unavailable in Java. +The underlying Semantic Kernel `Agent` abstraction can be found [here](/python/api/semantic-kernel/semantic_kernel.agents.agent). ::: zone-end -Agents can either be invoked directly to perform tasks or orchestrated within an [`AgentChat`](./agent-chat.md), where multiple agents may collaborate or interact dynamically with user inputs. This flexible structure allows agents to adapt to various conversational or task-driven scenarios, providing developers with robust tools for building intelligent, multi-agent systems. - -#### Deep Dive: +Agents can either be invoked directly to perform tasks or be orchestrated by different patterns. This flexible structure allows agents to adapt to various conversational or task-driven scenarios, providing developers with robust tools for building intelligent, multi-agent systems. -- [`ChatCompletionAgent`](./chat-completion-agent.md) -- [`OpenAIAssistantAgent`](./assistant-agent.md) -- [`AzureAIAgent`](./azure-ai-agent.md) -- [`OpenAIResponsesAgent`](./responses-agent.md) +### Agent Types in Semantic Kernel - - +- [`ChatCompletionAgent`](./agent-types/chat-completion-agent.md) +- [`OpenAIAssistantAgent`](./agent-types/assistant-agent.md) +- [`AzureAIAgent`](./agent-types/azure-ai-agent.md) +- [`OpenAIResponsesAgent`](./agent-types/responses-agent.md) +- [`CopilotStudioAgent`](./agent-types/copilot-studio-agent.md) ## Agent Thread -The abstract `AgentThread` class serves as the core abstraction for threads or conversation state. -It abstracts away the different ways in which conversation state may be managed for different agents. - -Stateful agent services often store conversation state in the service, and you can interact with it via an id. -Other agents may require the entire chat history to be passed to the agent on each invocation, in which -case the conversation state is managed locally in the application. +The abstract `AgentThread` class serves as the core abstraction for threads or conversation state. It abstracts away the different ways in which conversation state may be managed for different agents. -Stateful agents typically only work with a matching `AgentThread` implementation, while other types of agents could work with more than one `AgentThread` type. -For example, `AzureAIAgent` requires a matching `AzureAIAgentThread`. -This is because the Azure AI Agent service stores conversations in the service, and requires specific service calls to create a thread and update it. -If a different agent thread type is used with the `AzureAIAgent`, we fail fast due to an unexpected thread type and raise an exception to alert the caller. +Stateful agent services often store conversation state in the service, and you can interact with it via an id. Other agents may require the entire chat history to be passed to the agent on each invocation, in which case the conversation state is managed locally in the application. -## Agent Chat +Stateful agents typically only work with a matching `AgentThread` implementation, while other types of agents could work with more than one `AgentThread` type. For example, `AzureAIAgent` requires a matching `AzureAIAgentThread`. This is because the Azure AI Agent service stores conversations in the service, and requires specific service calls to create a thread and update it. If a different agent thread type is used with the `AzureAIAgent`, we fail fast due to an unexpected thread type and raise an exception to alert the caller. -The [`AgentChat`](./agent-chat.md) class serves as the foundational component that enables agents of any type to engage in a specific conversation. This class provides the essential capabilities for managing agent interactions within a chat environment. Building on this, the [`AgentGroupChat`](./agent-chat.md#creating-an-agentgroupchat) class extends these capabilities by offering a strategy-based container, which allows multiple agents to collaborate across numerous interactions within the same conversation. +## Agent Orchestration > [!IMPORTANT] -> The current `OpenAIResponsesAgent` is not supported as part of Semantic Kernel's `AgentGroupChat` patterns. Stayed tuned for updates. - -This structure facilitates more complex, multi-agent scenarios where different agents can work together, share information, and dynamically respond to evolving conversations, making it an ideal solution for advanced use cases such as customer support, multi-faceted task management, or collaborative problem-solving environments. - -#### Deep Dive: -- [`AgentChat`](./agent-chat.md) +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. +> [!NOTE] +> If you have been using the [`AgentGroupChat`](../../support/archive/agent-chat.md) orchestration pattern, please note that it is no longer maintained. We recommend developers to use the new [`GroupChatOrchestration`](./agent-orchestration/group-chat.md) pattern. A migration guide is provided [here](../../support/migration/group-chat-orchestration-migration-guide.md). -## Agent Channel +The [Agent Orchestration](./agent-orchestration/index.md) framework in Semantic Kernel enables the coordination of multiple agents to solve complex tasks collaboratively. It provides a flexible structure for defining how agents interact, share information, and delegate responsibilities. The core components and concepts include: -The Agent Channel class enables agents of various types to participate in an [`AgentChat`](./agent-chat.md). This functionality is completely hidden from users of the `Agent Framework` and only needs to be considered by developers creating a custom [`Agent`](#agent). +- **Orchestration Patterns:** Pre-built patterns such as Concurrent, Sequential, Handoff, Group Chat, and Magentic allow developers to choose the most suitable collaboration model for their scenario. Each pattern defines a different way for agents to communicate and process tasks (see the [Orchestration patterns](./agent-orchestration/index.md#supported-orchestration-patterns) table for details). +- **Data Transform Logic:** Input and output transforms allow orchestration flows to adapt data between agents and external systems, supporting both simple and complex data types. +- **Human-in-the-loop:** Some patterns support human-in-the-loop, enabling human agents to participate in the orchestration process. This is particularly useful for scenarios where human judgment or expertise is required. -::: zone pivot="programming-language-csharp" - -- [`AgentChannel`](/dotnet/api/microsoft.semantickernel.agents.agentchannel) - -::: zone-end - -::: zone pivot="programming-language-python" - -- [`agent_channel`](/python/api/semantic-kernel/semantic_kernel.agents.channels.agent_channel) - -::: zone-end - -::: zone pivot="programming-language-java" - -> Feature currently unavailable in Java. - -::: zone-end +This architecture empowers developers to build intelligent, multi-agent systems that can tackle real-world problems through collaboration, specialization, and dynamic coordination. ## Agent Alignment with Semantic Kernel Features The `Agent Framework` is built on the foundational concepts and features that many developers have come to know within the Semantic Kernel ecosystem. These core principles serve as the building blocks for the Agent Framework’s design. By leveraging the familiar structure and capabilities of the Semantic Kernel, the Agent Framework extends its functionality to enable more advanced, autonomous agent behaviors, while maintaining consistency with the broader Semantic Kernel architecture. This ensures a smooth transition for developers, allowing them to apply their existing knowledge to create intelligent, adaptable agents within the framework. +### Plugins and Function Calling -### The `Kernel` - -::: zone pivot="programming-language-csharp" - -At the heart of the Semantic Kernel ecosystem is the [`Kernel`](../../concepts/kernel.md), which serves as the core object that drives AI operations and interactions. To create any agent within this framework, a Kernel instance is required as it provides the foundational context and capabilities for the agent’s functionality. The `Kernel` acts as the engine for processing instructions, managing state, and invoking the necessary AI services that power the agent's behavior. - -::: zone-end - -::: zone pivot="programming-language-python" - -At the core of the Semantic Kernel ecosystem is the [`Kernel`](../../concepts/kernel.md), the primary object responsible for managing AI operations and interactions. To simplify onboarding, the `Kernel` is optional—if none is supplied when constructing an agent, a new `Kernel` instance is automatically created for the caller. For more advanced scenarios, such as applying filters, the caller must configure the desired filters on a `Kernel` instance and explicitly pass it to the agent. - -::: zone-end - -::: zone pivot="programming-language-java" - -At the heart of the Semantic Kernel ecosystem is the [`Kernel`](../../concepts/kernel.md), which serves as the core object that drives AI operations and interactions. To create any agent within this framework, a Kernel instance is required as it provides the foundational context and capabilities for the agent’s functionality. The `Kernel` acts as the engine for processing instructions, managing state, and invoking the necessary AI services that power the agent's behavior. - -::: zone-end - -The [`AzureAIAgent`](./azure-ai-agent.md), [`ChatCompletionAgent`](./chat-completion-agent.md), [`OpenAIAssistantAgent`](./assistant-agent.md), and [`OpenAIResponsesAgent`](./responses-agent.md) articles provide specific details on how to create each type of agent. - -These resources offer step-by-step instructions and highlight the key configurations needed to tailor the agents to different conversational or task-based applications, demonstrating how the Kernel enables dynamic and intelligent agent behaviors across diverse use cases. - -#### Related API's: - -::: zone pivot="programming-language-csharp" - -- [`IKernelBuilder`](/dotnet/api/microsoft.semantickernel) -- [`Kernel`](/dotnet/api/microsoft.semantickernel.kernel) -- [`KernelBuilderExtensions`](/dotnet/api/microsoft.semantickernel.kernelbuilderextensions) -- [`KernelExtensions`](/dotnet/api/microsoft.semantickernel.kernelextensions) - -::: zone-end - -::: zone pivot="programming-language-python" - -- [`kernel`](/python/api/semantic-kernel/semantic_kernel.kernel.kernel) - -::: zone-end - -::: zone pivot="programming-language-java" - -- [`Kernel`](/java/api/com.microsoft.semantickernel.kernel) - -::: zone-end +[Plugins](./../../concepts/plugins/index.md) are a fundamental aspect of the Semantic Kernel, enabling developers to integrate custom functionalities and extend the capabilities of an AI application. These plugins offer a flexible way to incorporate specialized features or business-specific logic into the core AI workflows. Additionally, agent capabilities within the framework can be significantly enhanced by utilizing [Plugins](../../concepts/plugins/index.md) and leveraging [Function Calling](../../concepts/ai-services/chat-completion/function-calling/index.md). This allows agents to dynamically interact with external services or execute complex tasks, further expanding the scope and versatility of the AI system within diverse applications. +Learn how to configure agents to use plugins [here](./agent-functions.md). -### [Plugins and Function Calling](./agent-functions.md) - -Plugins are a fundamental aspect of the Semantic Kernel, enabling developers to integrate custom functionalities and extend the capabilities of an AI application. These plugins offer a flexible way to incorporate specialized features or business-specific logic into the core AI workflows. Additionally, agent capabilities within the framework can be significantly enhanced by utilizing [Plugins](../../concepts/plugins/index.md) and leveraging [Function Calling](../../concepts/ai-services/chat-completion/function-calling/index.md). This allows agents to dynamically interact with external services or execute complex tasks, further expanding the scope and versatility of the AI system within diverse applications. - -#### Example: - -- [How-To: `ChatCompletionAgent`](./examples/example-chat-agent.md) - -#### Related API's: - -::: zone pivot="programming-language-csharp" - -- [`KernelFunctionFactory`](/dotnet/api/microsoft.semantickernel.kernelfunctionfactory) -- [`KernelFunction`](/dotnet/api/microsoft.semantickernel.kernelfunction) -- [`KernelPluginFactory`](/dotnet/api/microsoft.semantickernel.kernelpluginfactory) -- [`KernelPlugin`](/dotnet/api/microsoft.semantickernel.kernelplugin) -- [`Kernel.Plugins`](/dotnet/api/microsoft.semantickernel.kernel.plugins) - -::: zone-end - -::: zone pivot="programming-language-python" - -- [`kernel_function`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_function) -- [`kernel_function_extension`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_function_extension) -- [`kernel_plugin`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_plugin) - -::: zone-end - -::: zone pivot="programming-language-java" - -- [`KernelFunction`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunction) -- [`KernelPlugin`](/java/api/com.microsoft.semantickernel.plugin.kernelplugin) -- [`KernelPluginFactory`](/java/api/com.microsoft.semantickernel.plugin.kernelpluginfactory) - -::: zone-end - - -### [Agent Messages](../../concepts/ai-services/chat-completion/chat-history.md) +### Agent Messages Agent messaging, including both input and response, is built upon the core content types of the Semantic Kernel, providing a unified structure for communication. This design choice simplifies the process of transitioning from traditional chat-completion patterns to more advanced agent-driven patterns in your application development. By leveraging familiar Semantic Kernel content types, developers can seamlessly integrate agent capabilities into their applications without needing to overhaul existing systems. This streamlining ensures that as you evolve from basic conversational AI to more autonomous, task-oriented agents, the underlying framework remains consistent, making development faster and more efficient. -> Note: The [`OpenAIAssistantAgent`](./assistant-agent.md) introduced content types specific to its usage for File References and Content Annotation: - -#### Related API's: - ::: zone pivot="programming-language-csharp" -- [`ChatHistory`](/dotnet/api/microsoft.semantickernel.chatcompletion.chathistory) -- [`ChatMessageContent`](/dotnet/api/microsoft.semantickernel.chatmessagecontent) -- [`KernelContent`](/dotnet/api/microsoft.semantickernel.kernelcontent) -- [`StreamingKernelContent`](/dotnet/api/microsoft.semantickernel.streamingkernelcontent) -- [`FileReferenceContent`](/dotnet/api/microsoft.semantickernel.filereferencecontent) -- [`AnnotationContent`](/dotnet/api/microsoft.semantickernel.agents.openai.annotationcontent) - +> [!TIP] +> API reference: +> +> - [`ChatHistory`](/dotnet/api/microsoft.semantickernel.chatcompletion.chathistory) +> - [`ChatMessageContent`](/dotnet/api/microsoft.semantickernel.chatmessagecontent) +> - [`KernelContent`](/dotnet/api/microsoft.semantickernel.kernelcontent) +> - [`StreamingKernelContent`](/dotnet/api/microsoft.semantickernel.streamingkernelcontent) +> - [`FileReferenceContent`](/dotnet/api/microsoft.semantickernel.filereferencecontent) +> - [`AnnotationContent`](/dotnet/api/microsoft.semantickernel.agents.openai.annotationcontent) ::: zone-end ::: zone pivot="programming-language-python" -- [`chat_history`](/python/api/semantic-kernel/semantic_kernel.contents.chat_history) -- [`chat_message_content`](/python/api/semantic-kernel/semantic_kernel.contents.chat_message_content) -- [`kernel_content`](/python/api/semantic-kernel/semantic_kernel.contents.kernel_content) -- [`streaming_chat_message_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_chat_message_content) -- [`file_reference_content`](/python/api/semantic-kernel/semantic_kernel.contents.file_reference_content) -- [`annotation_content`](/python/api/semantic-kernel/semantic_kernel.contents.annotation_content) +> [!TIP] +> API reference: +> +> - [`chat_history`](/python/api/semantic-kernel/semantic_kernel.contents.chat_history) +> - [`chat_message_content`](/python/api/semantic-kernel/semantic_kernel.contents.chat_message_content) +> - [`kernel_content`](/python/api/semantic-kernel/semantic_kernel.contents.kernel_content) +> - [`streaming_chat_message_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_chat_message_content) +> - [`file_reference_content`](/python/api/semantic-kernel/semantic_kernel.contents.file_reference_content) +> - [`annotation_content`](/python/api/semantic-kernel/semantic_kernel.contents.annotation_content) ::: zone-end ::: zone pivot="programming-language-java" -- [`ChatHistory`](/java/api/com.microsoft.semantickernel.services.chatcompletion.chathistory) -- [`ChatMessageContent`](/java/api/com.microsoft.semantickernel.services.chatcompletion.chatmessagecontent) -- [`KernelContent`](/java/api/com.microsoft.semantickernel.services.kernelcontent) -- [`StreamingKernelContent`](/java/api/com.microsoft.semantickernel.services.streamingkernelcontent) +> [!TIP] +> API reference: +> +> - [`ChatHistory`](/java/api/com.microsoft.semantickernel.services.chatcompletion.chathistory) +> - [`ChatMessageContent`](/java/api/com.microsoft.semantickernel.services.chatcompletion.chatmessagecontent) +> - [`KernelContent`](/java/api/com.microsoft.semantickernel.services.kernelcontent) +> - [`StreamingKernelContent`](/java/api/com.microsoft.semantickernel.services.streamingkernelcontent) ::: zone-end - -### [Templating](./agent-templates.md) +### Templating An agent's role is primarily shaped by the instructions it receives, which dictate its behavior and actions. Similar to invoking a `Kernel` [prompt](../../concepts/prompts/index.md), an agent's instructions can include templated parameters—both values and functions—that are dynamically substituted during execution. This enables flexible, context-aware responses, allowing the agent to adjust its output based on real-time input. Additionally, an agent can be configured directly using a Prompt Template Configuration, providing developers with a structured and reusable way to define its behavior. This approach offers a powerful tool for standardizing and customizing agent instructions, ensuring consistency across various use cases while still maintaining dynamic adaptability. -#### Example: - -- [How-To: `ChatCompletionAgent`](./examples/example-chat-agent.md) - -#### Related API's: - -::: zone pivot="programming-language-csharp" - -- [`PromptTemplateConfig`](/dotnet/api/microsoft.semantickernel.prompttemplateconfig) -- [`KernelFunctionYaml.FromPromptYaml`](/dotnet/api/microsoft.semantickernel.kernelfunctionyaml.frompromptyaml#microsoft-semantickernel-kernelfunctionyaml-frompromptyaml(system-string-microsoft-semantickernel-iprompttemplatefactory-microsoft-extensions-logging-iloggerfactory)) -- [`IPromptTemplateFactory`](/dotnet/api/microsoft.semantickernel.iprompttemplatefactory) -- [`KernelPromptTemplateFactory`](/dotnet/api/microsoft.semantickernel.kernelprompttemplatefactory) -- [`Handlebars`](/dotnet/api/microsoft.semantickernel.prompttemplates.handlebars) -- [`Prompty`](/dotnet/api/microsoft.semantickernel.prompty) -- [`Liquid`](/dotnet/api/microsoft.semantickernel.prompttemplates.liquid) - -::: zone-end - -::: zone pivot="programming-language-python" - -- [`prompt_template_config`](/python/api/semantic-kernel/semantic_kernel.prompt_template.prompt_template_config) -- [`kernel_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.kernel_prompt_template) -- [`jinja2_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.jinja2_prompt_template) -- [`handlebars_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.handlebars_prompt_template) - -::: zone-end - -::: zone pivot="programming-language-java" - -- [`PromptTemplateConfig`](/java/api/com.microsoft.semantickernel.semanticfunctions.prompttemplateconfig) -- [`KernelFunctionYaml.FromPromptYaml`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunctionyaml#com-microsoft-semantickernel-semanticfunctions-kernelfunctionyaml-(t)frompromptyaml(java-lang-string)) -- [`PromptTemplateFactory`](/java/api/com.microsoft.semantickernel.semanticfunctions.prompttemplatefactory) -- [`KernelPromptTemplateFactory`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelprompttemplatefactory) -- [`Handlebars`](/java/api/com.microsoft.semantickernel.templateengine.handlebars.handlebarsprompttemplate) - -::: zone-end - - -### [Chat Completion](./chat-completion-agent.md) - -The [`ChatCompletionAgent`](./chat-completion-agent.md) is designed around any Semantic Kernel [AI service](../../concepts/ai-services/chat-completion/index.md), offering a flexible and convenient persona encapsulation that can be seamlessly integrated into a wide range of applications. This agent allows developers to easily bring conversational AI capabilities into their systems without having to deal with complex implementation details. It mirrors the features and patterns found in the underlying [AI service](../../concepts/ai-services/chat-completion/index.md), ensuring that all functionalities—such as natural language processing, dialogue management, and contextual understanding—are fully supported within the [`ChatCompletionAgent`](./chat-completion-agent.md), making it a powerful tool for building conversational interfaces. - -#### Related API's: - -::: zone pivot="programming-language-csharp" - -- [`IChatCompletionService`](/dotnet/api/microsoft.semantickernel.chatcompletion.ichatcompletionservice) -- [`Microsoft.SemanticKernel.Connectors.AzureOpenAI`](/dotnet/api/microsoft.semantickernel.connectors.azureopenai) -- [`Microsoft.SemanticKernel.Connectors.OpenAI`](/dotnet/api/microsoft.semantickernel.connectors.openai) -- [`Microsoft.SemanticKernel.Connectors.Google`](/dotnet/api/microsoft.semantickernel.connectors.google) -- [`Microsoft.SemanticKernel.Connectors.HuggingFace`](/dotnet/api/microsoft.semantickernel.connectors.huggingface) -- [`Microsoft.SemanticKernel.Connectors.MistralAI`](/dotnet/api/microsoft.semantickernel.connectors.mistralai) -- [`Microsoft.SemanticKernel.Connectors.Onnx`](/dotnet/api/microsoft.semantickernel.connectors.onnx) - -::: zone-end - -::: zone pivot="programming-language-python" - -- [`azure_chat_completion`](/python/api/semantic-kernel/semantic_kernel.connectors.ai.open_ai.services.azure_chat_completion) -- [`open_ai_chat_completion`](/python/api/semantic-kernel/semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion) - -::: zone-end - -::: zone pivot="programming-language-java" - -- [`semantickernel.aiservices.openai`](/java/api/com.microsoft.semantickernel.services.openai) -- [`semantickernel.aiservices.google`](/java/api/com.microsoft.semantickernel.aiservices.google) -- [`semantickernel.aiservices.huggingface`](/java/api/com.microsoft.semantickernel.aiservices.huggingface) - -::: zone-end +Learn more about how to create an agent with Semantic Kernel template [here](./agent-templates.md). +## Next steps > [!div class="nextstepaction"] > [Explore the Common Agent Invocation API](./agent-api.md) - diff --git a/semantic-kernel/Frameworks/agent/agent-functions.md b/semantic-kernel/Frameworks/agent/agent-functions.md index 7742a6ee..c7f5087a 100644 --- a/semantic-kernel/Frameworks/agent/agent-functions.md +++ b/semantic-kernel/Frameworks/agent/agent-functions.md @@ -8,6 +8,7 @@ ms.author: crickman ms.date: 09/13/2024 ms.service: semantic-kernel --- + # Configuring Agents with Semantic Kernel Plugins > [!IMPORTANT] @@ -21,40 +22,50 @@ Once configured, an agent will choose when and how to call an available function ::: zone pivot="programming-language-csharp" -- [`KernelFunctionFactory`](/dotnet/api/microsoft.semantickernel.kernelfunctionfactory) -- [`KernelFunction`](/dotnet/api/microsoft.semantickernel.kernelfunction) -- [`KernelPluginFactory`](/dotnet/api/microsoft.semantickernel.kernelpluginfactory) -- [`KernelPlugin`](/dotnet/api/microsoft.semantickernel.kernelplugin) -- [`Kernel.Plugins`](/dotnet/api/microsoft.semantickernel.kernel.plugins) +> [!TIP] +> API reference: +> +> - [`KernelFunctionFactory`](/dotnet/api/microsoft.semantickernel.kernelfunctionfactory) +> - [`KernelFunction`](/dotnet/api/microsoft.semantickernel.kernelfunction) +> - [`KernelPluginFactory`](/dotnet/api/microsoft.semantickernel.kernelpluginfactory) +> - [`KernelPlugin`](/dotnet/api/microsoft.semantickernel.kernelplugin) +> - [`Kernel.Plugins`](/dotnet/api/microsoft.semantickernel.kernel.plugins) ::: zone-end ::: zone pivot="programming-language-python" -- [`kernel_function`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_function) -- [`kernel_function_extension`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_function_extension) -- [`kernel_plugin`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_plugin) +> [!TIP] +> API reference: +> +> - [`kernel_function`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_function) +> - [`kernel_function_extension`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_function_extension) +> - [`kernel_plugin`](/python/api/semantic-kernel/semantic_kernel.functions.kernel_plugin) ::: zone-end ::: zone pivot="programming-language-java" -- [`KernelFunction`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunction) -- [`KernelFunctionFromMethod`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunctionfrommethod) -- [`KernelFunctionFromPrompt`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunctionfromprompt) +> [!TIP] +> API reference: +> +> - [`KernelFunction`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunction) +> - [`KernelFunctionFromMethod`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunctionfrommethod) +> - [`KernelFunctionFromPrompt`](/java/api/com.microsoft.semantickernel.semanticfunctions.kernelfunctionfromprompt) ::: zone-end - ## Adding Plugins to an Agent Any [Plugin](../../concepts/plugins/index.md) available to an `Agent` is managed within its respective `Kernel` instance. This setup enables each `Agent` to access distinct functionalities based on its specific role. [Plugins](../../concepts/plugins/index.md) can be added to the `Kernel` either before or after the `Agent` is created. The process of initializing [Plugins](../../concepts/plugins/index.md) follows the same patterns used for any Semantic Kernel implementation, allowing for consistency and ease of use in managing AI capabilities. -> Note: For a [`ChatCompletionAgent`](./chat-completion-agent.md), the function calling mode must be explicitly enabled. [`OpenAIAssistant`](./assistant-agent.md) agent is always based on automatic function calling. - ::: zone pivot="programming-language-csharp" + +> [!NOTE] +> For a [`ChatCompletionAgent`](./agent-types/chat-completion-agent.md), the function calling mode must be explicitly enabled. [`OpenAIAssistant`](./agent-types/assistant-agent.md) agent is always based on automatic function calling. + ```csharp // Factory method to product an agent with a specific role. // Could be incorporated into DI initialization. @@ -70,27 +81,28 @@ ChatCompletionAgent CreateSpecificAgent(Kernel kernel, string credentials) agentKernel.ImportPluginFromObject(new StatefulPlugin(credentials)); // Create the agent - return + return new ChatCompletionAgent() { Name = "", Instructions = "", Kernel = agentKernel, Arguments = new KernelArguments( - new OpenAIPromptExecutionSettings() - { - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() + new OpenAIPromptExecutionSettings() + { + FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }) }; } ``` + ::: zone-end ::: zone pivot="programming-language-python" There are two ways to create a `ChatCompletionAgent` with plugins. -#### Method 1: Specify Plugins via the Constructor +### Method 1: Specify Plugins via the Constructor You can directly pass a list of plugins to the constructor: @@ -108,7 +120,7 @@ agent = ChatCompletionAgent( > [!TIP] > By default, auto-function calling is enabled. To disable it, set the `function_choice_behavior` argument to `function_choice_behavior=FunctionChoiceBehavior.Auto(auto_invoke=False)` in the constructor. With this setting, plugins are broadcast to the model, but they are not automatically invoked. If execution settings specify the same `service_id` or `ai_model_id` as the AI service configuration, the function calling behavior defined in the execution settings (via `KernelArguments`) will take precedence over the function choice behavior set in the constructor. -#### Method 2: Configure the Kernel Manually +### Method 2: Configure the Kernel Manually If no kernel is provided via the constructor, one is automatically created during model validation. Any plugins passed in take precedence and are added to the kernel. For more fine-grained control over the kernel's state, follow these steps: @@ -136,9 +148,9 @@ kernel.add_plugin(SamplePlugin(), plugin_name="") # Create the agent agent = ChatCompletionAgent( - kernel=kernel, - name=, - instructions=, + kernel=kernel, + name=, + instructions=, arguments=KernelArguments(settings=settings), ) ``` @@ -171,15 +183,14 @@ var agent = ChatCompletionAgent.builder() .build(); ``` - ::: zone-end - ## Adding Functions to an Agent A [Plugin](../../concepts/plugins/index.md) is the most common approach for configuring [Function Calling](../../concepts/ai-services/chat-completion/function-calling/index.md). However, individual functions can also be supplied independently including prompt functions. ::: zone pivot="programming-language-csharp" + ```csharp // Factory method to product an agent with a specific role. // Could be incorporated into DI initialization. @@ -198,23 +209,25 @@ ChatCompletionAgent CreateSpecificAgent(Kernel kernel) agentKernel.ImportPluginFromFunctions("my_plugin", [functionFromMethod, functionFromPrompt]); // Create the agent - return + return new ChatCompletionAgent() { Name = "", Instructions = "", Kernel = agentKernel, Arguments = new KernelArguments( - new OpenAIPromptExecutionSettings() - { - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() + new OpenAIPromptExecutionSettings() + { + FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }) }; } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.connectors.ai import FunctionChoiceBehavior @@ -245,12 +258,13 @@ kernel.add_function( # Create the agent agent = ChatCompletionAgent( - kernel=kernel, - name=, - instructions=, + kernel=kernel, + name=, + instructions=, arguments=KernelArguments(settings=settings), ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -289,14 +303,11 @@ var agent = ChatCompletionAgent.builder() .build(); ``` - ::: zone-end - ## Limitations for Agent Function Calling -When directly invoking a[`ChatCompletionAgent`](./chat-completion-agent.md), all Function Choice Behaviors are supported. However, when using an [`OpenAIAssistant`](./assistant-agent.md) or [`AgentChat`](./agent-chat.md), only Automatic [Function Calling](../../concepts/ai-services/chat-completion/function-calling/index.md) is currently available. - +When directly invoking a[`ChatCompletionAgent`](./agent-types/chat-completion-agent.md), all Function Choice Behaviors are supported. However, when using an [`OpenAIAssistant`](./agent-types/assistant-agent.md), only Automatic [Function Calling](../../concepts/ai-services/chat-completion/function-calling/index.md) is currently available. ## How-To @@ -304,7 +315,7 @@ For an end-to-end example for using function calling, see: - [How-To: `ChatCompletionAgent`](./examples/example-chat-agent.md) +## Next steps > [!div class="nextstepaction"] > [How to Stream Agent Responses](./agent-streaming.md) - diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/TOC.yml b/semantic-kernel/Frameworks/agent/agent-orchestration/TOC.yml new file mode 100644 index 00000000..4aa3bb81 --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/TOC.yml @@ -0,0 +1,14 @@ +- name: Overview + href: index.md +- name: Concurrent + href: concurrent.md +- name: Sequential + href: sequential.md +- name: Group Chat + href: group-chat.md +- name: Handoff + href: handoff.md +- name: Magentic + href: magentic.md +- name: Advanced Topics + href: advanced-topics.md \ No newline at end of file diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/advanced-topics.md b/semantic-kernel/Frameworks/agent/agent-orchestration/advanced-topics.md new file mode 100644 index 00000000..17bd7ab2 --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/advanced-topics.md @@ -0,0 +1,438 @@ +--- +title: Semantic Kernel Agent Orchestration Advanced Topics +description: Advanced topics for agent orchestration +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Semantic Kernel Agent Orchestration Advanced Topics + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +## Runtime + +The runtime is the foundational component that manages the lifecycle, communication, and execution of agents and orchestrations. It acts as the message bus and execution environment for all actors (agents and orchestration-specific actors) in the system. + +### Role of the Runtime + +- **Message Routing:** The runtime is responsible for delivering messages between agents and orchestration actors, using a pub-sub or direct messaging model depending on the orchestration pattern. +- **Actor Lifecycle Management:** It creates, registers, and manages the lifecycle of all actors involved in an orchestration, ensuring isolation and proper resource management. +- **Execution Context:** The runtime provides the execution context for orchestrations, allowing multiple orchestrations (and their invocations) to run independently and concurrently. + +### Relationship Between Runtime and Orchestrations + +Think of an orchestration as a graph that defines how agents interact with each other. The runtime is the engine that executes this graph, managing the flow of messages and the lifecycle of agents. Developers can execute this graph multiple times with different inputs on the same runtime instance, and the runtime will ensure that each execution is isolated and independent. + +## Timeouts + +When an orchestration is invoked, the orchestration returns immediately with a handler that can be used to get the result later. This asynchronous pattern allows a more flexible and responsive design, especially in scenarios where the orchestration may take a long time to complete. + +> [!IMPORTANT] +> If a timeout occurs, the invocation of the orchestration will not be cancelled. The orchestration will continue to run in the background until it completes. Developers can still retrieve the result later. + +::: zone pivot="programming-language-csharp" + +Developers can get the result of the an orchestration invocation later by calling the `GetValueAsync` method on the result object. When the application is ready to process the result, the invocation may or may not have completed. Therefore, developers can optionally specify a timeout for the `GetValueAsync` method. If the orchestration does not complete within the specified timeout, a timeout exception will be thrown. + +```csharp +string output = await result.GetValueAsync(TimeSpan.FromSeconds(60)); +``` + +If the orchestration does not complete within the specified timeout, a timeout exception will be thrown. + +::: zone-end + +::: zone pivot="programming-language-python" + +Developers can get the result of the an orchestration invocation later by calling the `get` method on the result object. When the application is ready to process the result, the invocation may or may not have completed. Therefore, developers can optionally specify a timeout for the `get` method. If the orchestration does not complete within the specified timeout, a timeout exception will be thrown. + +```python +value = await orchestration_result.get(timeout=60) +``` + +If the orchestration does not complete within the specified timeout, a timeout exception will be raised. + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Human-in-the-loop + +### Agent Response Callback + +::: zone pivot="programming-language-csharp" + +To see agent responses inside an invocation, developers can provide a `ResponseCallback` to the orchestration. This allows developers to observe the responses from each agent during the orchestration process. Developers can use this callback for UI updates, logging, or other purposes. + +```csharp +public ValueTask ResponseCallback(ChatMessageContent response) +{ + Console.WriteLine($"# {response.AuthorName}\n{response.Content}"); + return ValueTask.CompletedTask; +} + +SequentialOrchestration orchestration = new SequentialOrchestration( + analystAgent, writerAgent, editorAgent) +{ + ResponseCallback = ResponseCallback, +}; +``` + +::: zone-end + +::: zone pivot="programming-language-python" + +To see agent responses inside an invocation, developers can provide an `agent_response_callback` to the orchestration. This allows developers to observe the responses from each agent during the orchestration process. Developers can use this callback for UI updates, logging, or other purposes. + +```python +def agent_response_callback(message: ChatMessageContent) -> None: + print(f"# {message.name}\n{message.content}") + +sequential_orchestration = SequentialOrchestration( + members=agents, + agent_response_callback=agent_response_callback, +) +``` + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +### Human Response Function + +::: zone pivot="programming-language-csharp" + +For orchestrations that supports user input (e.g., handoff and group chat), provide an `InteractiveCallback` that returns a `ChatMessageContent` from the user. By using this callback, developers can implement custom logic to gather user input, such as displaying a UI prompt or integrating with other systems. + +```csharp +HandoffOrchestration orchestration = new(...) +{ + InteractiveCallback = () => + { + Console.Write("User: "); + string input = Console.ReadLine(); + return new ChatMessageContent(AuthorRole.User, input); + } +}; +``` + +::: zone-end + +::: zone pivot="programming-language-python" + +For orchestrations that supports user input (e.g., handoff and group chat), provide an `human_response_function` that returns a `ChatMessageContent` from the user. By using this callback, developers can implement custom logic to gather user input, such as displaying a UI prompt or integrating with other systems. + +```python +def human_response_function() -> ChatMessageContent: + user_input = input("User: ") + return ChatMessageContent(role=AuthorRole.USER, content=user_input) + +handoff_orchestration = HandoffOrchestration( + ..., + agent_response_callback=agent_response_callback, +) +``` + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Structured Data + +We believe that structured data is a key part in building agentic workflows. By using structured data, developers can create more reuseable orchestrations and the development experience is improved. The Semantic Kernel SDK provides a way to pass structured data as input to orchestrations and return structured data as output. + +> [!IMPORTANT] +> Internally, the orchestrations still process data as `ChatMessageContent`. + +### Structured Inputs + +::: zone pivot="programming-language-csharp" + +Developers can pass structured data as input to orchestrations by using a strongly-typed input class and specifying it as the generic parameter for the orchestration. This enables type safety and more flexibility for orchestrations to handle complex data structures. For example, to triage GitHub issues, define a class for the structured input: + +```csharp +public sealed class GithubIssue +{ + public string Id { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public string Body { get; set; } = string.Empty; + public string[] Labels { get; set; } = []; +} +``` + +Developers can then use this type as the input to an orchestration by providing it as the generic parameter: + +```csharp +HandoffOrchestration orchestration = + new(...); + +GithubIssue input = new GithubIssue { ... }; +var result = await orchestration.InvokeAsync(input, runtime); +``` + +#### Custom Input Transforms + +By default, the orchestration will use the built-in input transform, which serializes the object to JSON and wraps it in a `ChatMessageContent`. If you want to customize how your structured input is converted to the underlying message type, you can provide your own input transform function via the `InputTransform` property: + +```csharp +HandoffOrchestration orchestration = + new(...) + { + InputTransform = (issue, cancellationToken) => + { + // For example, create a chat message with a custom format + var message = new ChatMessageContent(AuthorRole.User, $"[{issue.Id}] {issue.Title}\n{issue.Body}"); + return ValueTask.FromResult>([message]); + }, + }; +``` + +This allows you to control exactly how your typed input is presented to the agents, enabling advanced scenarios such as custom formatting, field selection, or multi-message input. + +> [!TIP] +> See the full sample in [Step04a_HandoffWithStructuredInput.cs](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step04a_HandoffWithStructuredInput.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +Developers can pass structured data as input to orchestrations by specifying a Pydantic model (or any custom class) as the generic parameter for the orchestration. This enables type safety and lets the orchestrations handle complex data structures. + +For example, to triage GitHub issues, define a Pydantic model for the structured input: + +```python +from pydantic import BaseModel + +class GithubIssue(BaseModel): + id: str + title: str + body: str + labels: list[str] = [] +``` + +You can then use this type as the input to your orchestration by providing it as the generic parameter: + +```python +from semantic_kernel.agents import HandoffOrchestration + +def custom_input_transform(input_message: GithubIssue) -> ChatMessageContent: + return ChatMessageContent(role=AuthorRole.USER, content=f"[{input_message.id}] {input_message.title}\n{input_message.body}") + + +handoff_orchestration = HandoffOrchestration[GithubIssue, ChatMessageContent]( + ..., + input_transform=custom_input_transform, +) + +GithubIssueSample = GithubIssue( + id="12345", + title="Bug: ...", + body="Describe the bug...", + labels=[], +) + +orchestration_result = await handoff_orchestration.invoke( + task=GithubIssueSample, + runtime=runtime, +) +``` + +> [!TIP] +> See the full sample in [step4a_handoff_structured_inputs.py](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step4a_handoff_structured_inputs.py) + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +### Structured Outputs + +::: zone pivot="programming-language-csharp" + +Agents and orchestrations can return structured outputs by specifying a strongly-typed output class as the generic parameter for the orchestration. This enables you to work with rich, structured results in your application, rather than just plain text. + +For example, suppose you want to analyze an article and extract themes, sentiments, and entities. Define a class for the structured output: + +```csharp +public sealed class Analysis +{ + public IList Themes { get; set; } = []; + public IList Sentiments { get; set; } = []; + public IList Entities { get; set; } = []; +} +``` + +You can then use this type as the output for your orchestration by providing it as the generic parameter: + +```csharp +ConcurrentOrchestration orchestration = + new(agent1, agent2, agent3) + { + ResultTransform = outputTransform.TransformAsync, // see below + }; + +// ... +OrchestrationResult result = await orchestration.InvokeAsync(input, runtime); +Analysis output = await result.GetValueAsync(TimeSpan.FromSeconds(60)); +``` + +#### Custom Output Transforms + +By default, the orchestration will use the built-in output transform, which attempts to deserialize the agent's response content to your output type. For more advanced scenarios, you can provide a custom output transform (for example, with structured output by some models). + +```csharp +StructuredOutputTransform outputTransform = + new(chatCompletionService, new OpenAIPromptExecutionSettings { ResponseFormat = typeof(Analysis) }); + +ConcurrentOrchestration orchestration = + new(agent1, agent2, agent3) + { + ResultTransform = outputTransform.TransformAsync, + }; +``` + +This approach allows you to receive and process structured data directly from the orchestration, making it easier to build advanced workflows and integrations. + +> [!TIP] +> See the full sample in [Step01a_ConcurrentWithStructuredOutput.cs](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step01a_ConcurrentWithStructuredOutput.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +Agents and orchestrations can return structured outputs by specifying a Pydantic model (or any custom class) as the generic output type for the orchestration. This enables you to work with rich, structured results in your application, rather than just plain text. + +For example, suppose you want to analyze an article and extract themes, sentiments, and entities. Define a Pydantic model for the structured output: + +```python +from pydantic import BaseModel + +class ArticleAnalysis(BaseModel): + themes: list[str] + sentiments: list[str] + entities: list[str] +``` + +You can then use this type as the output for your orchestration by providing it as the generic parameter and specifying an output transform: + +```python +from semantic_kernel.agents import ConcurrentOrchestration +from semantic_kernel.agents.orchestration.tools import structured_outputs_transform +from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion + +# `structured_outputs_transform` is a built-in transform that uses the structured output + +concurrent_orchestration = ConcurrentOrchestration[str, ArticleAnalysis]( + members=agents, + output_transform=structured_outputs_transform(ArticleAnalysis, AzureChatCompletion()), +) + +... + +orchestration_result = await concurrent_orchestration.invoke( + task="article text", + runtime=runtime, +) + +value = await orchestration_result.get(timeout=20) + +# `value` is now an instance of ArticleAnalysis +``` + +This approach allows you to receive and process structured data directly from the orchestration, making it easier to build advanced workflows and integrations. + +> [!TIP] +> See the full sample in [step1a_concurrent_structured_outputs.py](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step1a_concurrent_structured_outputs.py) + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Cancellation + +> [!IMPORTANT] +> Cancellation will stop the agents from processing any further messages, but it will not stop agents that are already processing messages. + +> [!IMPORTANT] +> Cancellation will not stop the runtime. + +::: zone pivot="programming-language-csharp" + +You can cancel an orchestration by calling the `Cancel` method on the result handler. This will stop the orchestration by propagating the signal to all agents, and they will stop processing any further messages. + +```csharp +var resultTask = orchestration.InvokeAsync(input, runtime); +resultTask.Cancel(); +``` + +::: zone-end + +::: zone pivot="programming-language-python" + +Developers can cancel an orchestration by calling the `cancel` method on the result handler. This will stop the orchestration by propagating the signal to all agents, and they will stop processing any further messages. + +```python +orchestration_result = await orchestration.invoke(task=task, runtime=runtime) +orchestration_result.cancel() +``` + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Next steps + +::: zone pivot="programming-language-csharp" + +> [!div class="nextstepaction"] +> [More Code Samples](https://github.com/microsoft/semantic-kernel/tree/main/dotnet/samples/GettingStartedWithAgents/Orchestration) + +::: zone-end + +::: zone pivot="programming-language-python" + +> [!div class="nextstepaction"] +> [More Code Samples](https://github.com/microsoft/semantic-kernel/tree/main/python/samples/getting_started_with_agents/multi_agent_orchestration) + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/concurrent.md b/semantic-kernel/Frameworks/agent/agent-orchestration/concurrent.md new file mode 100644 index 00000000..948de1b1 --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/concurrent.md @@ -0,0 +1,220 @@ +--- +title: Concurrent Agent Orchestration +description: An overview of the concurrent orchestration +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Concurrent Orchestration + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +The concurrent pattern enables multiple agents to work on the same task in parallel. Each agent processes the input independently, and their results are collected and aggregated. This approach is well-suited for scenarios where diverse perspectives or solutions are valuable, such as brainstorming, ensemble reasoning, or voting systems. + +## Common Use Cases + +Multiple agents generate different solutions to a problem, and their responses are collected for further analysis or selection: + +![diagram](../../../media/multi-agent-concurrent.png) + +## What You'll Learn + +- How to define multiple agents with different expertise +- How to orchestrate these agents to work concurrently on a single task +- How to collect and process the results + +::: zone pivot="programming-language-csharp" + +### Define Your Agents + +Agents are specialized entities that can process tasks. Here, we define two agents: a physics expert and a chemistry expert. + +> [!TIP] +> The [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) is used here, but you can use any [agent type](../agent-architecture.md#agent-types-in-semantic-kernel). + +```csharp +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Agents; +using Microsoft.SemanticKernel.Agents.Orchestration; +using Microsoft.SemanticKernel.Agents.Orchestration.Concurrent; +using Microsoft.SemanticKernel.Agents.Runtime.InProcess; + +// Create a kernel with an AI service +Kernel kernel = ...; + +ChatCompletionAgent physicist = new ChatCompletionAgent{ + Name = "PhysicsExpert", + Instructions = "You are an expert in physics. You answer questions from a physics perspective." + Kernel = kernel, +}; + +ChatCompletionAgent chemist = new ChatCompletionAgent{ + Name = "ChemistryExpert", + Instructions = "You are an expert in chemistry. You answer questions from a chemistry perspective." + Kernel = kernel, +}; +``` + +### Set Up the Concurrent Orchestration + +The `ConcurrentOrchestration` class allows you to run multiple agents in parallel. You pass the list of agents as members. + +```csharp +ConcurrentOrchestration orchestration = new (physicist, chemist); +``` + +### Start the Runtime + +A runtime is required to manage the execution of agents. Here, we use `InProcessRuntime` and start it before invoking the orchestration. + +```csharp +InProcessRuntime runtime = new InProcessRuntime(); +await runtime.StartAsync(); +``` + +### Invoke the Orchestration + +You can now invoke the orchestration with a specific task. The orchestration will run all agents concurrently on the given task. + +```csharp +var result = await orchestration.InvokeAsync("What is temperature?", runtime); +``` + +### Collect Results + +The results from all agents can be collected asynchronously. Note that the order of results is not guaranteed. + +```csharp +string[] output = await result.GetValueAsync(TimeSpan.FromSeconds(20)); +Console.WriteLine($"# RESULT:\n{string.Join("\n\n", output.Select(text => $"{text}"))}"); +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```csharp +await runtime.RunUntilIdleAsync(); +``` + +### Sample Output + +```plaintext +# RESULT: +Temperature is a fundamental physical quantity that measures the average kinetic energy ... + +Temperature is a measure of the average kinetic energy of the particles ... +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step01_Concurrent.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +### Define Your Agents + +Agents are specialized entities that can process tasks. Here, we define two agents: a physics expert and a chemistry expert. + +> [!TIP] +> The [`ChatCompletionAgent`](./../agent-types/chat-completion-agent.md) is used here with Azure OpenAI, however, you can use any [agent type](./../agent-architecture.md#agent-types-in-semantic-kernel) or [model service](../../../concepts/ai-services/chat-completion/index.md). + +```python +from semantic_kernel.agents import Agent, ChatCompletionAgent +from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion + +def get_agents() -> list[Agent]: + physics_agent = ChatCompletionAgent( + name="PhysicsExpert", + instructions="You are an expert in physics. You answer questions from a physics perspective.", + service=AzureChatCompletion(), + ) + chemistry_agent = ChatCompletionAgent( + name="ChemistryExpert", + instructions="You are an expert in chemistry. You answer questions from a chemistry perspective.", + service=AzureChatCompletion(), + ) + return [physics_agent, chemistry_agent] +``` + +### Set Up the Concurrent Orchestration + +The `ConcurrentOrchestration` class allows you to run multiple agents in parallel. You pass the list of agents as members. + +```python +from semantic_kernel.agents import ConcurrentOrchestration + +agents = get_agents() +concurrent_orchestration = ConcurrentOrchestration(members=agents) +``` + +### Start the Runtime + +A runtime is required to manage the execution of agents. Here, we use `InProcessRuntime` and start it before invoking the orchestration. + +```python +from semantic_kernel.agents.runtime import InProcessRuntime + +runtime = InProcessRuntime() +runtime.start() +``` + +### Invoke the Orchestration + +You can now invoke the orchestration with a specific task. The orchestration will run all agents concurrently on the given task. + +```python +orchestration_result = await concurrent_orchestration.invoke( + task="What is temperature?", + runtime=runtime, +) +``` + +### Collect Results + +The results from all agents can be collected asynchronously. Note that the order of results is not guaranteed. + +```python +value = await orchestration_result.get(timeout=20) +# For the concurrent orchestration, the result is a list of chat messages +for item in value: + print(f"# {item.name}: {item.content}") +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```python +await runtime.stop_when_idle() +``` + +### Sample Output + +```plaintext +# PhysicsExpert: Temperature is a physical quantity that represents the average kinetic energy of the particles in a substance... +# ChemistryExpert: Temperature is a fundamental concept in chemistry and physics, representing a measure of the average kinetic energy... +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step1_concurrent.py). + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Next steps + +> [!div class="nextstepaction"] +> [Sequential Orchestration](./sequential.md) diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/group-chat.md b/semantic-kernel/Frameworks/agent/agent-orchestration/group-chat.md new file mode 100644 index 00000000..2ce8366a --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/group-chat.md @@ -0,0 +1,424 @@ +--- +title: Group Chat Agent Orchestration +description: An overview of the group chat orchestration +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Group Chat Orchestration + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +Group chat orchestration models a collaborative conversation among agents, optionally including a human participant. A group chat manager coordinates the flow, determining which agent should respond next and when to request human input. This pattern is powerful for simulating meetings, debates, or collaborative problem-solving sessions. + +## Common Use Cases + +Agents representing different departments discuss a business proposal, with a manager agent moderating the conversation and involving a human when needed: + +![diagram](../../../media/multi-agent-group-chat.png) + +## What You'll Learn + +- How to define agents with different roles for a group chat +- How to use a group chat manager to control the flow of conversation +- How to involve a human participant in the conversation +- How to observe the conversation and collect the final result + +::: zone pivot="programming-language-csharp" + +### Define Your Agents + +Each agent in the group chat has a specific role. In this example, we define a copywriter and a reviewer. + +> [!TIP] +> The [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) is used here, but you can use any [agent type](../agent-architecture.md#agent-types-in-semantic-kernel). + +```csharp +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Agents; +using Microsoft.SemanticKernel.Agents.Orchestration; +using Microsoft.SemanticKernel.Agents.Orchestration.GroupChat; +using Microsoft.SemanticKernel.Agents.Runtime.InProcess; + +// Create a kernel with an AI service +Kernel kernel = ...; + +ChatCompletionAgent writer = new ChatCompletionAgent { + Name = "CopyWriter", + Description = "A copy writer", + Instructions = "You are a copywriter with ten years of experience and are known for brevity and a dry humor. The goal is to refine and decide on the single best copy as an expert in the field. Only provide a single proposal per response. You're laser focused on the goal at hand. Don't waste time with chit chat. Consider suggestions when refining an idea.", + Kernel = kernel, +}; + +ChatCompletionAgent editor = new ChatCompletionAgent { + Name = "Reviewer", + Description = "An editor.", + Instructions = "You are an art director who has opinions about copywriting born of a love for David Ogilvy. The goal is to determine if the given copy is acceptable to print. If so, state that it is approved. If not, provide insight on how to refine suggested copy without example.", + Kernel = kernel, +}; +``` + +### Optional: Observe Agent Responses + +You can create a callback to capture agent responses as the sequence progresses via the `ResponseCallback` property. + +```csharp +ChatHistory history = []; + +ValueTask responseCallback(ChatMessageContent response) +{ + history.Add(response); + return ValueTask.CompletedTask; +} +``` + +### Set Up the Group Chat Orchestration + +Create a `GroupChatOrchestration` object, passing in the agents, a group chat manager (here, a `RoundRobinGroupChatManager`), and the response callback. The manager controls the flow—here, it alternates turns in a round-robin fashion for a set number of rounds. + +```csharp +GroupChatOrchestration orchestration = new GroupChatOrchestration( + new RoundRobinGroupChatManager { MaximumInvocationCount = 5 }, + writer, + editor) +{ + ResponseCallback = responseCallback, +}; +``` + +### Start the Runtime + +A runtime is required to manage the execution of agents. Here, we use `InProcessRuntime` and start it before invoking the orchestration. + +```csharp +InProcessRuntime runtime = new InProcessRuntime(); +await runtime.StartAsync(); +``` + +### Invoke the Orchestration + +Invoke the orchestration with your initial task (e.g., "Create a slogan for a new electric SUV..."). The agents will take turns responding, refining the result. + +```csharp +var result = await orchestration.InvokeAsync( + "Create a slogan for a new electric SUV that is affordable and fun to drive.", + runtime); +``` + +### Collect Results + +Wait for the orchestration to complete and retrieve the final output. + +```csharp +string output = await result.GetValueAsync(TimeSpan.FromSeconds(60)); +Console.WriteLine($"\n# RESULT: {text}"); +Console.WriteLine("\n\nORCHESTRATION HISTORY"); +foreach (ChatMessageContent message in history) +{ + this.WriteAgentChatMessage(message); +} +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```csharp +await runtime.RunUntilIdleAsync(); +``` + +### Sample Output + +```plaintext +# RESULT: “Affordable Adventure: Drive Electric, Drive Fun.” + + +ORCHESTRATION HISTORY + +# Assistant - CopyWriter: “Charge Ahead: Affordable Thrills, Zero Emissions.” + +# Assistant - Reviewer: The slogan is catchy but it could be refined to better ... + +# Assistant - CopyWriter: “Electrify Your Drive: Fun Meets Affordability.” + +# Assistant - Reviewer: The slogan captures the essence of electric driving and ... + +# Assistant - CopyWriter: “Affordable Adventure: Drive Electric, Drive Fun.” +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step03_GroupChat.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +### Define Your Agents + +Each agent in the group chat has a specific role. In this example: + +- Writer: Creates and edits content based on feedback. +- Reviewer: Reviews content and provides feedback for improvement. + +> [!TIP] +> The [`ChatCompletionAgent`](./../agent-types/chat-completion-agent.md) is used here with Azure OpenAI, however, you can use any [agent type](./../agent-architecture.md#agent-types-in-semantic-kernel) or [model service](../../../concepts/ai-services/chat-completion/index.md). + +```python +from semantic_kernel.agents import Agent, ChatCompletionAgent +from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion + +def get_agents() -> list[Agent]: + writer = ChatCompletionAgent( + name="Writer", + description="A content writer.", + instructions=( + "You are an excellent content writer. You create new content and edit contents based on the feedback." + ), + service=AzureChatCompletion(), + ) + reviewer = ChatCompletionAgent( + name="Reviewer", + description="A content reviewer.", + instructions=( + "You are an excellent content reviewer. You review the content and provide feedback to the writer." + ), + service=AzureChatCompletion(), + ) + return [writer, reviewer] +``` + +### Observe Agent Responses + +You can define a callback to print each agent's message as the conversation progresses. + +```python +from semantic_kernel.contents import ChatMessageContent + +def agent_response_callback(message: ChatMessageContent) -> None: + print(f"**{message.name}**\n{message.content}") +``` + +### Set Up the Group Chat Orchestration + +Create a `GroupChatOrchestration` object, passing in the agents, a group chat manager (in this case a `RoundRobinGroupChatManager`), and the response callback. The manager controls the flow—here, it alternates turns in a round-robin fashion for a set number of rounds. + +```python +from semantic_kernel.agents import GroupChatOrchestration, RoundRobinGroupChatManager + +agents = get_agents() +group_chat_orchestration = GroupChatOrchestration( + members=agents, + manager=RoundRobinGroupChatManager(max_rounds=5), # Odd number so writer gets the last word + agent_response_callback=agent_response_callback, +) +``` + +### Start the Runtime + +Start the runtime to manage agent execution. + +```python +from semantic_kernel.agents.runtime import InProcessRuntime + +runtime = InProcessRuntime() +runtime.start() +``` + +### Invoke the Orchestration + +Invoke the orchestration with your initial task (e.g., "Create a slogan for a new electric SUV..."). The agents will take turns responding, refining the result. + +```python +orchestration_result = await group_chat_orchestration.invoke( + task="Create a slogan for a new electric SUV that is affordable and fun to drive.", + runtime=runtime, +) +``` + +### Collect Results + +Wait for the orchestration to complete. + +```python +value = await orchestration_result.get() +print(f"***** Final Result *****\n{value}") +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```python +await runtime.stop_when_idle() +``` + +### Sample Output + +```plaintext +**Writer** +"Drive Tomorrow: Affordable Adventure Starts Today!" +**Reviewer** +This slogan, "Drive Tomorrow: Affordable Adventure Starts Today!", effectively communicates the core attributes... +**Writer** +"Embrace the Future: Your Affordable Electric Adventure Awaits!" +**Reviewer** +This revised slogan, "Embrace the Future: Your Affordable Electric Adventure Awaits!", further enhances the message... +**Writer** +"Feel the Charge: Adventure Meets Affordability in Your New Electric SUV!" +***** Result ***** +"Feel the Charge: Adventure Meets Affordability in Your New Electric SUV!" +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step3_group_chat.py). + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +### Customize the Group Chat Manager + +::: zone pivot="programming-language-csharp" + +You can customize the group chat flow by implementing your own `GroupChatManager`. This allows you to control how results are filtered, how the next agent is selected, and when to request user input or terminate the chat. + +For example, you can create a custom manager by inheriting from `GroupChatManager` and overriding its abstract methods: + +```csharp +using Microsoft.SemanticKernel.Agents.Orchestration.GroupChat; +using Microsoft.SemanticKernel.ChatCompletion; +using System.Threading; +using System.Threading.Tasks; + +public class CustomGroupChatManager : GroupChatManager +{ + public override ValueTask> FilterResults(ChatHistory history, CancellationToken cancellationToken = default) + { + // Custom logic to filter or summarize chat results + return ValueTask.FromResult(new GroupChatManagerResult("Summary") { Reason = "Custom summary logic." }); + } + + public override ValueTask> SelectNextAgent(ChatHistory history, GroupChatTeam team, CancellationToken cancellationToken = default) + { + // Randomly select an agent from the team + var random = new Random(); + int index = random.Next(team.Members.Count); + string nextAgent = team.Members[index].Id; + return ValueTask.FromResult(new GroupChatManagerResult(nextAgent) { Reason = "Custom selection logic." }); + } + + public override ValueTask> ShouldRequestUserInput(ChatHistory history, CancellationToken cancellationToken = default) + { + // Custom logic to decide if user input is needed + return ValueTask.FromResult(new GroupChatManagerResult(false) { Reason = "No user input required." }); + } + + public override ValueTask> ShouldTerminate(ChatHistory history, CancellationToken cancellationToken = default) + { + // Optionally call the base implementation to check for default termination logic + var baseResult = base.ShouldTerminate(history, cancellationToken).Result; + if (baseResult.Value) + { + // If the base logic says to terminate, respect it + return ValueTask.FromResult(baseResult); + } + + // Custom logic to determine if the chat should terminate + bool shouldEnd = history.Count > 10; // Example: end after 10 messages + return ValueTask.FromResult(new GroupChatManagerResult(shouldEnd) { Reason = "Custom termination logic." }); + } +} +``` + +You can then use your custom manager in the orchestration: + +```csharp +GroupChatOrchestration orchestration = new (new CustomGroupChatManager { MaximumInvocationCount = 5 }, ...); +``` + +> [!TIP] +> A complete example of a custom group chat manager is available [here](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step03b_GroupChatWithAIManager.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +You can customize the group chat flow by implementing your own `GroupChatManager`. This allows you to control how results are filtered, how the next agent is selected, and when to request user input or terminate the chat. + +For example, you can create a custom manager by inheriting from `GroupChatManager` and overriding its abstract methods: + +```python +from semantic_kernel.agents import GroupChatManager, BooleanResult, StringResult, MessageResult +from semantic_kernel.contents import ChatMessageContent, ChatHistory + +class CustomGroupChatManager(GroupChatManager): + async def filter_results(self, chat_history: ChatHistory) -> MessageResult: + # Custom logic to filter or summarize chat results + summary = "Summary of the discussion." + return MessageResult(result=ChatMessageContent(role="assistant", content=summary), reason="Custom summary logic.") + + async def select_next_agent(self, chat_history: ChatHistory, participant_descriptions: dict[str, str]) -> StringResult: + # Randomly select an agent from the participants + import random + next_agent = random.choice(list(participant_descriptions.keys())) + return StringResult(result=next_agent, reason="Custom selection logic.") + + async def should_request_user_input(self, chat_history: ChatHistory) -> BooleanResult: + # Custom logic to decide if user input is needed + return BooleanResult(result=False, reason="No user input required.") + + async def should_terminate(self, chat_history: ChatHistory) -> BooleanResult: + # Optionally call the base implementation to check for default termination logic + base_result = await super().should_terminate(chat_history) + if base_result.result: + return base_result + # Custom logic to determine if the chat should terminate + should_end = len(chat_history.messages) > 10 # Example: end after 10 messages + return BooleanResult(result=should_end, reason="Custom termination logic.") +``` + +You can then use your custom manager in the orchestration: + +```python +from semantic_kernel.agents import GroupChatOrchestration + +group_chat_orchestration = GroupChatOrchestration(manager=CustomGroupChatManager(max_rounds=5), ...) +``` + +> [!TIP] +> A complete example of a custom group chat manager is available [here](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step3b_group_chat_with_chat_completion_manager.py) + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +### Order of Group Chat Manager Function Calls + +When orchestrating a group chat, the group chat manager's methods are called in a specific order for each round of the conversation: + +1. **ShouldRequestUserInput**: Checks if user (human) input is required before the next agent speaks. If true, the orchestration pauses for user input. The user input is then added to the chat history of the manager and sent to all agents. +2. **ShouldTerminate**: Determines if the group chat should end (for example, if a maximum number of rounds is reached or a custom condition is met). If true, the orchestration proceeds to result filtering. +3. **FilterResults**: Called only if the chat is terminating, to summarize or process the final results of the conversation. +4. **SelectNextAgent**: If the chat is not terminating, selects the next agent to respond in the conversation. + +This order ensures that user input and termination conditions are checked before advancing the conversation, and that results are filtered only at the end. You can customize the logic for each step by overriding the corresponding methods in your custom group chat manager. + +## Next steps + +> [!div class="nextstepaction"] +> [Handoff Orchestration](./handoff.md) diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/handoff.md b/semantic-kernel/Frameworks/agent/agent-orchestration/handoff.md new file mode 100644 index 00000000..20e3c581 --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/handoff.md @@ -0,0 +1,469 @@ +--- +title: Handoff Agent Orchestration +description: An overview of the Handoff orchestration +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Handoff Orchestration + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +Handoff orchestration allows agents to transfer control to one another based on the context or user request. Each agent can “handoff” the conversation to another agent with the appropriate expertise, ensuring that the right agent handles each part of the task. This is particularly useful in customer support, expert systems, or any scenario requiring dynamic delegation. + +## Common Use Cases + +A customer support agent handles a general inquiry, then hands off to a technical expert agent for troubleshooting, or to a billing agent if needed: + +![diagram](../../../media/multi-agent-handoff.png) + +## What You'll Learn + +- How to define agents and their handoff relationships +- How to set up a handoff orchestration for dynamic agent routing +- How to involve a human in the conversation loop + +::: zone pivot="programming-language-csharp" + +### Define Specialized Agents + +Each agent is responsible for a specific area. In this example, we define a triage agent, a refund agent, an order status agent, and an order return agent. Some agents use plugins to handle specific tasks. + +> [!TIP] +> The [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) is used here, but you can use any [agent type](../agent-architecture.md#agent-types-in-semantic-kernel). + +```csharp +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Agents; +using Microsoft.SemanticKernel.Agents.Orchestration; +using Microsoft.SemanticKernel.Agents.Orchestration.Handoff; +using Microsoft.SemanticKernel.Agents.Runtime.InProcess; +using Microsoft.SemanticKernel.ChatCompletion; + +// Plugin implementations +public sealed class OrderStatusPlugin { + [KernelFunction] + public string CheckOrderStatus(string orderId) => $"Order {orderId} is shipped and will arrive in 2-3 days."; +} +public sealed class OrderReturnPlugin { + [KernelFunction] + public string ProcessReturn(string orderId, string reason) => $"Return for order {orderId} has been processed successfully."; +} +public sealed class OrderRefundPlugin { + [KernelFunction] + public string ProcessReturn(string orderId, string reason) => $"Refund for order {orderId} has been processed successfully."; +} + +// Helper function to create a kernel with chat completion +public static Kernel CreateKernelWithChatCompletion(...) +{ + ... +} + +ChatCompletionAgent triageAgent = new ChatCompletionAgent { + Name = "TriageAgent", + Description = "Handle customer requests.", + Instructions = "A customer support agent that triages issues.", + Kernel = CreateKernelWithChatCompletion(...), +}; + +ChatCompletionAgent statusAgent = new ChatCompletionAgent { + Name = "OrderStatusAgent", + Description = "A customer support agent that checks order status.", + Instructions = "Handle order status requests.", + Kernel = CreateKernelWithChatCompletion(...), +}; +statusAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderStatusPlugin())); + +ChatCompletionAgent returnAgent = new ChatCompletionAgent { + Name = "OrderReturnAgent", + Description = "A customer support agent that handles order returns.", + Instructions = "Handle order return requests.", + Kernel = CreateKernelWithChatCompletion(...), +}; +returnAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderReturnPlugin())); + +ChatCompletionAgent refundAgent = new ChatCompletionAgent { + Name = "OrderRefundAgent", + Description = "A customer support agent that handles order refund.", + Instructions = "Handle order refund requests.", + Kernel = CreateKernelWithChatCompletion(...), +}; +refundAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderRefundPlugin())); +``` + +### Set Up Handoff Relationships + +Use `OrchestrationHandoffs` to specify which agent can hand off to which, and under what circumstances. + +```csharp +var handoffs = OrchestrationHandoffs + .StartWith(triageAgent) + .Add(triageAgent, statusAgent, returnAgent, refundAgent) + .Add(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related") + .Add(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related") + .Add(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related"); +``` + +### Observe Agent Responses + +You can create a callback to capture agent responses as the conversation progresses via the `ResponseCallback` property. + +```csharp +ChatHistory history = []; + +ValueTask responseCallback(ChatMessageContent response) +{ + history.Add(response); + return ValueTask.CompletedTask; +} +``` + +### Human in the Loop + +A key feature of handoff orchestration is the ability for a human to participate in the conversation. This is achieved by providing an `InteractiveCallback`, which is called whenever an agent needs input from the user. In a real application, this would prompt the user for input; in a sample, you can use a queue of responses. + +```csharp +// Simulate user input with a queue +Queue responses = new(); +responses.Enqueue("I'd like to track the status of my order"); +responses.Enqueue("My order ID is 123"); +responses.Enqueue("I want to return another order of mine"); +responses.Enqueue("Order ID 321"); +responses.Enqueue("Broken item"); +responses.Enqueue("No, bye"); + +ValueTask interactiveCallback() +{ + string input = responses.Dequeue(); + Console.WriteLine($"\n# INPUT: {input}\n"); + return ValueTask.FromResult(new ChatMessageContent(AuthorRole.User, input)); +} +``` + +### Set Up the Handoff Orchestration + +Create a `HandoffOrchestration` object, passing in the agents, handoff relationships, and the callbacks. + +```csharp +HandoffOrchestration orchestration = new HandoffOrchestration( + handoffs, + triageAgent, + statusAgent, + returnAgent, + refundAgent) +{ + InteractiveCallback = interactiveCallback, + ResponseCallback = responseCallback, +}; +``` + +### Start the Runtime + +A runtime is required to manage the execution of agents. Here, we use `InProcessRuntime` and start it before invoking the orchestration. + +```csharp +InProcessRuntime runtime = new InProcessRuntime(); +await runtime.StartAsync(); +``` + +### Invoke the Orchestration + +Invoke the orchestration with your initial task (e.g., "I am a customer that needs help with my orders"). The agents will route the conversation as needed, involving the human when required. + +```csharp +string task = "I am a customer that needs help with my orders"; +var result = await orchestration.InvokeAsync(task, runtime); +``` + +### Collect Results + +Wait for the orchestration to complete and retrieve the final output. + +```csharp +string output = await result.GetValueAsync(TimeSpan.FromSeconds(300)); +Console.WriteLine($"\n# RESULT: {output}"); +Console.WriteLine("\n\nORCHESTRATION HISTORY"); +foreach (ChatMessageContent message in history) +{ + // Print each message + Console.WriteLine($"# {message.Role} - {message.AuthorName}: {message.Content}"); +} +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```csharp +await runtime.RunUntilIdleAsync(); +``` + +### Sample Output + +```plaintext +# RESULT: Handled order return for order ID 321 due to a broken item, and successfully processed the return. + +ORCHESTRATION HISTORY + +# Assistant - TriageAgent: Could you please specify what kind of help you need with your orders? Are you looking to check the order status, return an item, or request a refund? + +# Assistant - OrderStatusAgent: Could you please tell me your order ID? + +# Assistant - OrderStatusAgent: Your order with ID 123 has been shipped and will arrive in 2-3 days. Anything else I can assist you with? + +# Assistant - OrderReturnAgent: I can help you with that. Could you please provide the order ID and the reason you'd like to return it? + +# Assistant - OrderReturnAgent: Please provide the reason for returning the order with ID 321. + +# Assistant - OrderReturnAgent: The return for your order with ID 321 has been successfully processed due to the broken item. Anything else I can assist you with? +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step04_Handoff.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +### Define Specialized Agents + +Each agent is responsible for a specific area. For example: + +- TriageAgent: Handles initial customer requests and decides which specialist to involve. +- RefundAgent: Handles refund requests. +- OrderStatusAgent: Checks order status. +- OrderReturnAgent: Handles order returns. + +#### Plugins + +First we need to define the plugins that will be used in the agents. These plugins will contain the logic for handling specific tasks. + +```python +from semantic_kernel.functions import kernel_function + +class OrderStatusPlugin: + @kernel_function + def check_order_status(self, order_id: str) -> str: + """Check the status of an order.""" + # Simulate checking the order status + return f"Order {order_id} is shipped and will arrive in 2-3 days." + + +class OrderRefundPlugin: + @kernel_function + def process_refund(self, order_id: str, reason: str) -> str: + """Process a refund for an order.""" + # Simulate processing a refund + print(f"Processing refund for order {order_id} due to: {reason}") + return f"Refund for order {order_id} has been processed successfully." + + +class OrderReturnPlugin: + @kernel_function + def process_return(self, order_id: str, reason: str) -> str: + """Process a return for an order.""" + # Simulate processing a return + print(f"Processing return for order {order_id} due to: {reason}") + return f"Return for order {order_id} has been processed successfully." +``` + +#### Agents + +Next, we define the agents that will use these plugins. + +> [!TIP] +> The [`ChatCompletionAgent`](./../agent-types/chat-completion-agent.md) is used here with Azure OpenAI, however, you can use any [agent type](./../agent-architecture.md#agent-types-in-semantic-kernel) or [model service](../../../concepts/ai-services/chat-completion/index.md). + +```python +from semantic_kernel.agents import ChatCompletionAgent +from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion + +support_agent = ChatCompletionAgent( + name="TriageAgent", + description="A customer support agent that triages issues.", + instructions="Handle customer requests.", + service=OpenAIChatCompletion(), +) + +refund_agent = ChatCompletionAgent( + name="RefundAgent", + description="A customer support agent that handles refunds.", + instructions="Handle refund requests.", + service=OpenAIChatCompletion(), + plugins=[OrderRefundPlugin()], +) + +order_status_agent = ChatCompletionAgent( + name="OrderStatusAgent", + description="A customer support agent that checks order status.", + instructions="Handle order status requests.", + service=OpenAIChatCompletion(), + plugins=[OrderStatusPlugin()], +) + +order_return_agent = ChatCompletionAgent( + name="OrderReturnAgent", + description="A customer support agent that handles order returns.", + instructions="Handle order return requests.", + service=OpenAIChatCompletion(), + plugins=[OrderReturnPlugin()], +) +``` + +### Define Handoff Relationships + +Use `OrchestrationHandoffs` to specify which agent can hand off to which, and under what circumstances. + +```python +from semantic_kernel.agents import OrchestrationHandoffs + +handoffs = ( + OrchestrationHandoffs() + .add_many( # Use add_many to add multiple handoffs to the same source agent at once + source_agent=support_agent.name, + target_agents={ + refund_agent.name: "Transfer to this agent if the issue is refund related", + order_status_agent.name: "Transfer to this agent if the issue is order status related", + order_return_agent.name: "Transfer to this agent if the issue is order return related", + }, + ) + .add( # Use add to add a single handoff + source_agent=refund_agent.name, + target_agent=support_agent.name, + description="Transfer to this agent if the issue is not refund related", + ) + .add( + source_agent=order_status_agent.name, + target_agent=support_agent.name, + description="Transfer to this agent if the issue is not order status related", + ) + .add( + source_agent=order_return_agent.name, + target_agent=support_agent.name, + description="Transfer to this agent if the issue is not order return related", + ) +) +``` + +### Observe Agent Responses + +You can define a callback to print each agent's message as the conversation progresses. + +```python +from semantic_kernel.contents import ChatMessageContent + +def agent_response_callback(message: ChatMessageContent) -> None: + print(f"{message.name}: {message.content}") +``` + +### Human in the Loop + +A key feature of handoff orchestration is the ability for a human to participate in the conversation. This is achieved by providing a `human_response_function` callback, which is called whenever an agent needs input from the user. + +```python +from semantic_kernel.contents import AuthorRole, ChatMessageContent + +def human_response_function() -> ChatMessageContent: + user_input = input("User: ") + return ChatMessageContent(role=AuthorRole.USER, content=user_input) +``` + +### Set Up the Handoff Orchestration + +Create a `HandoffOrchestration` object, passing in the agents, handoff relationships, and the callbacks. + +```python +from semantic_kernel.agents import HandoffOrchestration + +handoff_orchestration = HandoffOrchestration( + members=[ + support_agent, + refund_agent, + order_status_agent, + order_return_agent, + ], + handoffs=handoffs, + agent_response_callback=agent_response_callback, + human_response_function=human_response_function, +) +``` + +### Start the Runtime + +Start the runtime to manage agent execution. + +```python +from semantic_kernel.agents.runtime import InProcessRuntime + +runtime = InProcessRuntime() +runtime.start() +``` + +### Invoke the Orchestration + +Invoke the orchestration with your initial task (e.g., "A customer is on the line."). The agents will route the conversation as needed, involving the human when required. + +```python +orchestration_result = await handoff_orchestration.invoke( + task="A customer is on the line.", + runtime=runtime, +) +``` + +### Collect Results + +Wait for the orchestration to complete. + +```python +value = await orchestration_result.get() +print(value) +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```python +await runtime.stop_when_idle() +``` + +### Sample Output + +```plaintext +TriageAgent: Hello! Thank you for reaching out. How can I assist you today? +User: I'd like to track the status of my order +OrderStatusAgent: Sure, I can help you with that. Could you please provide me with your order ID? +User: My order ID is 123 +OrderStatusAgent: Your order with ID 123 has been shipped and is expected to arrive in 2-3 days. Is there anything else I can assist you with? +User: I want to return another order of mine +OrderReturnAgent: I can help you with returning your order. Could you please provide the order ID for the return and the reason you'd like to return it? +User: Order ID 321 +OrderReturnAgent: Please provide the reason for returning the order with ID 321. +User: Broken item +OrderReturnAgent: The return for your order with ID 321 has been successfully processed due to the broken item. Is there anything else I can assist you with? +User: No, bye +Task is completed with summary: Handled order return for order ID 321 due to a broken item, and successfully processed the return. +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step4_handoff.py). + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Next steps + +> [!div class="nextstepaction"] +> [Magentic Orchestration](./magentic.md) diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/index.md b/semantic-kernel/Frameworks/agent/agent-orchestration/index.md new file mode 100644 index 00000000..3d32d15b --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/index.md @@ -0,0 +1,103 @@ +--- +title: Semantic Kernel Agent Orchestration +description: An overview on orchestrating agents in Semantic Kernel +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Semantic Kernel Agent Orchestration + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +Semantic Kernel’s Agent Orchestration framework enables developers to build, manage, and scale complex agent workflows with ease. + +## Why Multi-agent Orchestration? + +Traditional single-agent systems are limited in their ability to handle complex, multi-faceted tasks. By orchestrating multiple agents, each with specialized skills or roles, we can create systems that are more robust, adaptive, and capable of solving real-world problems collaboratively. Multi-agent orchestration in Semantic Kernel provides a flexible foundation for building such systems, supporting a variety of coordination patterns. + +## Orchestration Patterns + +Semantic Kernel supports several orchestration patterns, each designed for different collaboration scenarios. These patterns are available as part of the framework and can be easily extended or customized. + +## Supported Orchestration Patterns + +| Pattern | Description | Typical Use Case | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| [Concurrent](./concurrent.md) | Broadcasts a task to all agents, collects results independently. | Parallel analysis, independent subtasks, ensemble decision making. | +| [Sequential](./sequential.md) | Passes the result from one agent to the next in a defined order. | Step-by-step workflows, pipelines, multi-stage processing. | +| [Handoff](./handoff.md) | Dynamically passes control between agents based on context or rules. | Dynamic workflows, escalation, fallback, or expert handoff scenarios. | +| [Group Chat](./group-chat.md) | All agents participate in a group conversation, coordinated by a group manager. | Brainstorming, collaborative problem solving, consensus building. | +| [Magentic](./magentic.md) | Group chat-like orchestration inspired by [MagenticOne](https://www.microsoft.com/en-us/research/articles/magentic-one-a-generalist-multi-agent-system-for-solving-complex-tasks/). | Complex, generalist multi-agent collaboration. | + +## Simplicity and Developer-friendly + +All orchestration patterns share a unified interface for construction and invocation. No matter which orchestration you choose, you: + +- Define your agents and their capabilities, see Semantic Kernel Agents. +- Create an orchestration by passing the agents (and, if needed, a manager). +- Optionally provide callbacks or transforms for custom input/output handling. +- Start a runtime and invoke the orchestration with a task. +- Await the result in a consistent, asynchronous manner. + +This unified approach means you can easily switch between orchestration patterns, without learning new APIs or rewriting your agent logic. The framework abstracts away the complexity of agent communication, coordination, and result aggregation, letting you focus on your application’s goals. + +::: zone pivot="programming-language-csharp" + +```csharp +// Choose an orchestration pattern with your agents +SequentialOrchestration orchestration = new(agentA, agentB) +{ + LoggerFactory = this.LoggerFactory +}; // or ConcurrentOrchestration, GroupChatOrchestration, HandoffOrchestration, MagenticOrchestration, ... + +// Start the runtime +InProcessRuntime runtime = new(); +await runtime.StartAsync(); + +// Invoke the orchestration and get the result +OrchestrationResult result = await orchestration.InvokeAsync(task, runtime); +string text = await result.GetValueAsync(); + +await runtime.RunUntilIdleAsync(); +``` + +::: zone-end + +::: zone pivot="programming-language-python" + +```python +# Choose an orchestration pattern with your agents +orchestration = SequentialOrchestration(members=[agent_a, agent_b]) +# or ConcurrentOrchestration, GroupChatOrchestration, HandoffOrchestration, MagenticOrchestration, ... + +# Start the runtime +runtime = InProcessRuntime() +runtime.start() + +# Invoke the orchestration +result = await orchestration.invoke(task="Your task here", runtime=runtime) + +# Get the result +final_output = await result.get() + +await runtime.stop_when_idle() +``` + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Next steps + +> [!div class="nextstepaction"] +> [Concurrent Orchestration](./concurrent.md) diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/magentic.md b/semantic-kernel/Frameworks/agent/agent-orchestration/magentic.md new file mode 100644 index 00000000..451dd11f --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/magentic.md @@ -0,0 +1,355 @@ +--- +title: Magentic Agent Orchestration +description: An overview of the Magentic orchestration +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Magentic Orchestration + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +Magentic orchestration is designed based on the [Magentic-One](https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/magentic-one.html) system invented by AutoGen. It is a flexible, general-purpose multi-agent pattern designed for complex, open-ended tasks that require dynamic collaboration. In this pattern, a dedicated Magentic manager coordinates a team of specialized agents, selecting which agent should act next based on the evolving context, task progress, and agent capabilities. + +The Magentic manager maintains a shared context, tracks progress, and adapts the workflow in real time. This enables the system to break down complex problems, delegate subtasks, and iteratively refine solutions through agent collaboration. The orchestration is especially well-suited for scenarios where the solution path is not known in advance and may require multiple rounds of reasoning, research, and computation. + +> [!TIP] +> Read more about the Magentic-One [here](https://www.microsoft.com/research/articles/magentic-one-a-generalist-multi-agent-system-for-solving-complex-tasks/). + +> [!TIP] +> The name "Magentic" comes from "Magentic-One". "Magentic-One" is a multi-agent system that includes a set of agents, such as the `WebSurfer` and `FileSurfer`. The Semantic Kernel Magentic orchestration is inspired by the Magentic-One system where the `Magentic` manager coordinates a team of specialized agents to solve complex tasks. However, it is not a direct implementation of the Magentic-One system and does not feature the agents from the Magentic-One system. + +## Common Use Cases + +A user requests a comprehensive report comparing the energy efficiency and CO₂ emissions of different machine learning models. The Magentic manager first assigns a research agent to gather relevant data, then delegates analysis and computation to a coder agent. The manager coordinates multiple rounds of research and computation, aggregates the findings, and produces a detailed, structured report as the final output. + +![diagram](../../../media/multi-agent-magentic.png) + +## What You'll Learn + +- How to define and configure agents for Magentic orchestration +- How to set up a Magentic manager to coordinate agent collaboration +- How the orchestration process works, including planning, progress tracking, and final answer synthesis + +::: zone pivot="programming-language-csharp" + +### Define Your Agents + +Each agent in the Magentic pattern has a specialized role. In this example: + +- ResearchAgent: Finds and summarizes information (e.g., via web search). Here the sample is using the `ChatCompletionAgent` with the `gpt-4o-search-preview` model for its web search capability. +- CoderAgent: Writes and executes code to analyze or process data. Here the sample is using the `AzureAIAgent` since it has advanced tools like the code interpreter. + +> [!TIP] +> The [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) and [`AzureAIAgent`](../agent-types/azure-ai-agent.md) are used here, but you can use any [agent type](./../agent-architecture.md#agent-types-in-semantic-kernel). + +```csharp +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Agents; +using Microsoft.SemanticKernel.Agents.AzureAI; +using Microsoft.SemanticKernel.Agents.Magentic; +using Microsoft.SemanticKernel.Agents.Orchestration; +using Microsoft.SemanticKernel.Agents.Runtime.InProcess; +using Microsoft.SemanticKernel.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.OpenAI; +using Azure.AI.Agents.Persistent; +using Azure.Identity; + +// Helper function to create a kernel with chat completion +public static Kernel CreateKernelWithChatCompletion(...) +{ + ... +} + +// Create a kernel with OpenAI chat completion for the research agent +Kernel researchKernel = CreateKernelWithChatCompletion("gpt-4o-search-preview"); +ChatCompletionAgent researchAgent = new ChatCompletionAgent { + Name = "ResearchAgent", + Description = "A helpful assistant with access to web search. Ask it to perform web searches.", + Instructions = "You are a Researcher. You find information without additional computation or quantitative analysis.", + Kernel = researchKernel, +}; + +// Create a persistent Azure AI agent for code execution +PersistentAgentsClient agentsClient = AzureAIAgent.CreateAgentsClient(endpoint, new AzureCliCredential()); +PersistentAgent definition = await agentsClient.Administration.CreateAgentAsync( + modelId, + name: "CoderAgent", + description: "Write and executes code to process and analyze data.", + instructions: "You solve questions using code. Please provide detailed analysis and computation process.", + tools: [new CodeInterpreterToolDefinition()]); +AzureAIAgent coderAgent = new AzureAIAgent(definition, agentsClient); +``` + +### Set Up the Magentic Manager + +The Magentic manager coordinates the agents, plans the workflow, tracks progress, and synthesizes the final answer. The standard manager (`StandardMagenticManager`) uses a chat completion model that supports structured output. + +```csharp +Kernel managerKernel = CreateKernelWithChatCompletion("o3-mini"); +StandardMagenticManager manager = new StandardMagenticManager( + managerKernel.GetRequiredService(), + new OpenAIPromptExecutionSettings()) +{ + MaximumInvocationCount = 5, +}; +``` + +### Optional: Observe Agent Responses + +You can create a callback to capture agent responses as the orchestration progresses via the `ResponseCallback` property. + +```csharp +ChatHistory history = []; + +ValueTask responseCallback(ChatMessageContent response) +{ + history.Add(response); + return ValueTask.CompletedTask; +} +``` + +### Create the Magentic Orchestration + +Combine your agents and manager into a `MagenticOrchestration` object. + +```csharp +MagenticOrchestration orchestration = new MagenticOrchestration( + manager, + researchAgent, + coderAgent) +{ + ResponseCallback = responseCallback, +}; +``` + +### Start the Runtime + +A runtime is required to manage the execution of agents. Here, we use `InProcessRuntime` and start it before invoking the orchestration. + +```csharp +InProcessRuntime runtime = new InProcessRuntime(); +await runtime.StartAsync(); +``` + +### Invoke the Orchestration + +Invoke the orchestration with your complex task. The manager will plan, delegate, and coordinate the agents to solve the problem. + +```csharp +string input = @"I am preparing a report on the energy efficiency of different machine learning model architectures.\nCompare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 on standard datasets (e.g., ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 VM for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model per task type (image classification, text classification, and text generation)."; +var result = await orchestration.InvokeAsync(input, runtime); +``` + +### Collect Results + +Wait for the orchestration to complete and retrieve the final output. + +```csharp +string output = await result.GetValueAsync(TimeSpan.FromSeconds(300)); +Console.WriteLine($"\n# RESULT: {output}"); +Console.WriteLine("\n\nORCHESTRATION HISTORY"); +foreach (ChatMessageContent message in history) +{ + // Print each message + Console.WriteLine($"# {message.Role} - {message.AuthorName}: {message.Content}"); +} +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```csharp +await runtime.RunUntilIdleAsync(); +``` + +### Sample Output + +````plaintext +# RESULT: ```markdown +# Report: Energy Efficiency of Machine Learning Model Architectures + +This report assesses the energy consumption and related CO₂ emissions for three popular ... + +ORCHESTRATION HISTORY + +# Assistant - ResearchAgent: Comparing the energy efficiency of different machine learning ... + +# assistant - CoderAgent: Below are tables summarizing the approximate energy consumption and ... + +# assistant - CoderAgent: The estimates provided in our tables align with a general understanding ... + +# assistant - CoderAgent: Here's the updated structure for the report integrating both the ... +```` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step05_Magentic.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +### Define Your Agents + +Each agent in the Magentic pattern has a specialized role. In this example: + +- ResearchAgent: Finds and summarizes information (e.g., via web search). Here the sample is using the `ChatCompletionAgent` with the `gpt-4o-search-preview` model for its web search capability. +- CoderAgent: Writes and executes code to analyze or process data. Here the sample is using the `OpenAIAssistantAgent` since it has advanced tools like the code interpreter. + +> [!TIP] +> The [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) and [`OpenAIAssistantAgent`](../agent-types/assistant-agent.md) are used here, but you can use any [agent type](./../agent-architecture.md#agent-types-in-semantic-kernel). + +```python +from semantic_kernel.agents import ChatCompletionAgent, OpenAIAssistantAgent +from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion + +research_agent = ChatCompletionAgent( + name="ResearchAgent", + description="A helpful assistant with access to web search. Ask it to perform web searches.", + instructions="You are a Researcher. You find information without additional computation or quantitative analysis.", + service=OpenAIChatCompletion(ai_model_id="gpt-4o-search-preview"), +) + +# Create an OpenAI Assistant agent with code interpreter capability +client, model = OpenAIAssistantAgent.setup_resources() +code_interpreter_tool, code_interpreter_tool_resources = OpenAIAssistantAgent.configure_code_interpreter_tool() +definition = await client.beta.assistants.create( + model=model, + name="CoderAgent", + description="A helpful assistant that writes and executes code to process and analyze data.", + instructions="You solve questions using code. Please provide detailed analysis and computation process.", + tools=code_interpreter_tool, + tool_resources=code_interpreter_tool_resources, +) +coder_agent = OpenAIAssistantAgent( + client=client, + definition=definition, +) +``` + +### Set Up the Magentic Manager + +The Magentic manager coordinates the agents, plans the workflow, tracks progress, and synthesizes the final answer. The standard manager (`StandardMagenticManager`) uses carefully designed prompts and requires a chat completion model that supports structured output. + +```python +from semantic_kernel.agents import StandardMagenticManager +from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion + +manager = StandardMagenticManager(chat_completion_service=OpenAIChatCompletion()) +``` + +### Optional: Observe Agent Responses + +You can define a callback to print each agent's message as the orchestration progresses. + +```python +from semantic_kernel.contents import ChatMessageContent + +def agent_response_callback(message: ChatMessageContent) -> None: + print(f"**{message.name}**\n{message.content}") +``` + +### Create the Magentic Orchestration + +Combine your agents and manager into a `MagenticOrchestration` object. + +```python +from semantic_kernel.agents import MagenticOrchestration + +magentic_orchestration = MagenticOrchestration( + members=[research_agent, coder_agent], + manager=manager, + agent_response_callback=agent_response_callback, +) +``` + +### Start the Runtime + +Start the runtime to manage agent execution. + +```python +from semantic_kernel.agents.runtime import InProcessRuntime + +runtime = InProcessRuntime() +runtime.start() +``` + +### Invoke the Orchestration + +Invoke the orchestration with your complex task. The manager will plan, delegate, and coordinate the agents to solve the problem. + +```python +orchestration_result = await magentic_orchestration.invoke( + task=( + "I am preparing a report on the energy efficiency of different machine learning model architectures. " + "Compare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 " + "on standard datasets (e.g., ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). " + "Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 VM " + "for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model " + "per task type (image classification, text classification, and text generation)." + ), + runtime=runtime, +) +``` + +### Collect Results + +Wait for the orchestration to complete and print the final result. + +```python +value = await orchestration_result.get() +print(f"\nFinal result:\n{value}") +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```python +await runtime.stop_when_idle() +``` + +### Sample Output + +```plaintext +**ResearchAgent** +Estimating the energy consumption and associated CO₂ emissions for training and inference of ResNet-50, BERT-base... + +**CoderAgent** +Here is the comparison of energy consumption and CO₂ emissions for each model (ResNet-50, BERT-base, and GPT-2) +over a 24-hour period: + +| Model | Training Energy (kWh) | Inference Energy (kWh) | Total Energy (kWh) | CO₂ Emissions (kg) | +|-----------|------------------------|------------------------|---------------------|---------------------| +| ResNet-50 | 21.11 | 0.08232 | 21.19232 | 19.50 | +| BERT-base | 0.048 | 0.23736 | 0.28536 | 0.26 | +| GPT-2 | 42.22 | 0.35604 | 42.57604 | 39.17 | + +... + +Final result: +Here is the comprehensive report on energy efficiency and CO₂ emissions for ResNet-50, BERT-base, and GPT-2 models... +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step5_magentic.py). + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Next steps + +> [!div class="nextstepaction"] +> [Advanced Topics in Agent Orchestration](./advanced-topics.md) diff --git a/semantic-kernel/Frameworks/agent/agent-orchestration/sequential.md b/semantic-kernel/Frameworks/agent/agent-orchestration/sequential.md new file mode 100644 index 00000000..90d8d232 --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-orchestration/sequential.md @@ -0,0 +1,304 @@ +--- +title: Sequential Agent Orchestration +description: An overview of the sequential orchestration +zone_pivot_groups: programming-languages +author: TaoChenOSU +ms.topic: tutorial +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Sequential Orchestration + +> [!IMPORTANT] +> Agent Orchestrations are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. + +In the sequential pattern, agents are organized in a pipeline. Each agent processes the task in turn, passing its output to the next agent in the sequence. This is ideal for workflows where each step builds upon the previous one, such as document review, data processing pipelines, or multi-stage reasoning. + +## Common Use Cases + +A document passes through a summarization agent, then a translation agent, and finally a quality assurance agent, each building on the previous output: + +![diagram](../../../media/multi-agent-sequential.png) + +## What You'll Learn + +- How to define a sequence of agents, each with a specialized role +- How to orchestrate these agents so that each processes the output of the previous one +- How to observe intermediate outputs and collect the final result + +::: zone pivot="programming-language-csharp" + +### Define Your Agents + +Agents are specialized entities that process tasks in sequence. Here, we define three agents: an analyst, a copywriter, and an editor. + +> [!TIP] +> The [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) is used here, but you can use any [agent type](../agent-architecture.md#agent-types-in-semantic-kernel). + +```csharp +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Agents; +using Microsoft.SemanticKernel.Agents.Orchestration; +using Microsoft.SemanticKernel.Agents.Orchestration.Sequential; +using Microsoft.SemanticKernel.Agents.Runtime.InProcess; + +// Create a kernel with an AI service +Kernel kernel = ...; + +ChatCompletionAgent analystAgent = new ChatCompletionAgent { + Name = "Analyst", + Instructions = "You are a marketing analyst. Given a product description, identify:\n- Key features\n- Target audience\n- Unique selling points", + Kernel = kernel, +}; + +ChatCompletionAgent writerAgent = new ChatCompletionAgent { + Name = "Copywriter", + Instructions = "You are a marketing copywriter. Given a block of text describing features, audience, and USPs, compose a compelling marketing copy (like a newsletter section) that highlights these points. Output should be short (around 150 words), output just the copy as a single text block.", + Kernel = kernel, +}; + +ChatCompletionAgent editorAgent = new ChatCompletionAgent { + Name = "Editor", + Instructions = "You are an editor. Given the draft copy, correct grammar, improve clarity, ensure consistent tone, give format and make it polished. Output the final improved copy as a single text block.", + Kernel = kernel, +}; +``` + +### Optional: Observe Agent Responses + +You can create a callback to capture agent responses as the sequence progresses via the `ResponseCallback` property. + +```csharp +ChatHistory history = []; + +ValueTask responseCallback(ChatMessageContent response) +{ + history.Add(response); + return ValueTask.CompletedTask; +} +``` + +### Set Up the Sequential Orchestration + +Create a `SequentialOrchestration` object, passing in the agents and the optional response callback. + +```csharp +SequentialOrchestration orchestration = new(analystAgent, writerAgent, editorAgent) +{ + ResponseCallback = responseCallback, +}; +``` + +### Start the Runtime + +A runtime is required to manage the execution of agents. Here, we use `InProcessRuntime` and start it before invoking the orchestration. + +```csharp +InProcessRuntime runtime = new InProcessRuntime(); +await runtime.StartAsync(); +``` + +### Invoke the Orchestration + +Invoke the orchestration with your initial task (e.g., a product description). The output will flow through each agent in sequence. + +```csharp +var result = await orchestration.InvokeAsync( + "An eco-friendly stainless steel water bottle that keeps drinks cold for 24 hours", + runtime); +``` + +### Collect Results + +Wait for the orchestration to complete and retrieve the final output. + +```csharp +string output = await result.GetValueAsync(TimeSpan.FromSeconds(20)); +Console.WriteLine($"\n# RESULT: {text}"); +Console.WriteLine("\n\nORCHESTRATION HISTORY"); +foreach (ChatMessageContent message in history) +{ + this.WriteAgentChatMessage(message); +} +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```csharp +await runtime.RunUntilIdleAsync(); +``` + +### Sample Output + +```plaintext +# RESULT: Introducing our Eco-Friendly Stainless Steel Water Bottles – the perfect companion for those who care about the planet while staying hydrated! Our bottles ... + + +ORCHESTRATION HISTORY + +# Assistant - Analyst: **Key Features:** +- Made from eco-friendly stainless steel +- Insulation technology that maintains cold temperatures for up to 24 hours +- Reusable and sustainable design +- Various sizes and colors available (assumed based on typical offerings) +- Leak-proof cap +- BPA-free ... + +# Assistant - copywriter: Introducing our Eco-Friendly Stainless ... + +# Assistant - editor: Introducing our Eco-Friendly Stainless Steel Water Bottles – the perfect companion for those who care about the planet while staying hydrated! Our bottles ... +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Orchestration/Step02_Sequential.cs) + +::: zone-end + +::: zone pivot="programming-language-python" + +### Define Your Agents + +Each agent in the sequence has a specific responsibility. In this example, we have: + +- ConceptExtractorAgent: Extracts key features, target audience, and unique selling points from a product description. +- WriterAgent: Composes a marketing copy based on the extracted information. +- FormatProofAgent: Edits and polishes the draft copy for clarity and consistency. + +> [!TIP] +> The [`ChatCompletionAgent`](./../agent-types/chat-completion-agent.md) is used here with Azure OpenAI, however, you can use any [agent type](./../agent-architecture.md#agent-types-in-semantic-kernel) or [model service](../../../concepts/ai-services/chat-completion/index.md). + +```python +from semantic_kernel.agents import Agent, ChatCompletionAgent +from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion + +def get_agents() -> list[Agent]: + concept_extractor_agent = ChatCompletionAgent( + name="ConceptExtractorAgent", + instructions=( + "You are a marketing analyst. Given a product description, identify:\n" + "- Key features\n" + "- Target audience\n" + "- Unique selling points\n\n" + ), + service=AzureChatCompletion(), + ) + writer_agent = ChatCompletionAgent( + name="WriterAgent", + instructions=( + "You are a marketing copywriter. Given a block of text describing features, audience, and USPs, " + "compose a compelling marketing copy (like a newsletter section) that highlights these points. " + "Output should be short (around 150 words), output just the copy as a single text block." + ), + service=AzureChatCompletion(), + ) + format_proof_agent = ChatCompletionAgent( + name="FormatProofAgent", + instructions=( + "You are an editor. Given the draft copy, correct grammar, improve clarity, ensure consistent tone, " + "give format and make it polished. Output the final improved copy as a single text block." + ), + service=AzureChatCompletion(), + ) + return [concept_extractor_agent, writer_agent, format_proof_agent] +``` + +### Optional: Observe Agent Responses + +You can define a callback to observe and print the output from each agent as the sequence progresses. + +```python +from semantic_kernel.contents import ChatMessageContent + +def agent_response_callback(message: ChatMessageContent) -> None: + print(f"# {message.name}\n{message.content}") +``` + +### Set Up the Sequential Orchestration + +SequentialOrchestration object, passing in the agents and the optional response callback. + +```python +from semantic_kernel.agents import SequentialOrchestration + +agents = get_agents() +sequential_orchestration = SequentialOrchestration( + members=agents, + agent_response_callback=agent_response_callback, +) +``` + +### Start the Runtime + +Start the runtime to manage agent execution. + +```python +from semantic_kernel.agents.runtime import InProcessRuntime + +runtime = InProcessRuntime() +runtime.start() +``` + +### Invoke the Orchestration + +Invoke the orchestration with your initial task (e.g., a product description). The output will flow through each agent in sequence. + +```python +orchestration_result = await sequential_orchestration.invoke( + task="An eco-friendly stainless steel water bottle that keeps drinks cold for 24 hours", + runtime=runtime, +) +``` + +### Collect Results + +Wait for the orchestration to complete. + +```python +value = await orchestration_result.get(timeout=20) +print(f"***** Final Result *****\n{value}") +``` + +### Optional: Stop the Runtime + +After processing is complete, stop the runtime to clean up resources. + +```python +await runtime.stop_when_idle() +``` + +### Sample Output + +```plaintext +# ConceptExtractorAgent +- Key Features: +- Made of eco-friendly stainless steel +- Keeps drinks cold for 24 hours +... +# WriterAgent +Keep your beverages refreshingly chilled all day long with our eco-friendly stainless steel bottles... +# FormatProofAgent +Keep your beverages refreshingly chilled all day long with our eco-friendly stainless steel bottles... +***** Final Result ***** +Keep your beverages refreshingly chilled all day long with our eco-friendly stainless steel bottles... +``` + +> [!TIP] +> The full sample code is available [here](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/multi_agent_orchestration/step2_sequential.py). + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end + +## Next steps + +> [!div class="nextstepaction"] +> [Group Chat Orchestration](./group-chat.md) diff --git a/semantic-kernel/Frameworks/agent/agent-streaming.md b/semantic-kernel/Frameworks/agent/agent-streaming.md index 39f7adf5..48041d75 100644 --- a/semantic-kernel/Frameworks/agent/agent-streaming.md +++ b/semantic-kernel/Frameworks/agent/agent-streaming.md @@ -8,37 +8,45 @@ ms.author: crickman ms.date: 09/13/2024 ms.service: semantic-kernel --- + # How to Stream Agent Responses ## What is a Streamed Response? A streamed response delivers the message content in small, incremental chunks. This approach enhances the user experience by allowing them to view and engage with the message as it unfolds, rather than waiting for the entire response to load. Users can begin processing information immediately, improving the sense of responsiveness and interactivity. As a result, it minimizes delays and keeps users more engaged throughout the communication process. -#### Streaming References: +### Streaming References - [OpenAI Streaming Guide](https://platform.openai.com/docs/api-reference/streaming) - [OpenAI Chat Completion Streaming](https://platform.openai.com/docs/api-reference/chat/create#chat-create-stream) - [OpenAI Assistant Streaming](https://platform.openai.com/docs/api-reference/assistants-streaming) - [Azure OpenAI Service REST API](/azure/ai-services/openai/reference) - ## Streaming in Semantic Kernel [AI Services](../../concepts/ai-services/index.md) that support streaming in Semantic Kernel use different content types compared to those used for fully-formed messages. These content types are specifically designed to handle the incremental nature of streaming data. The same content types are also utilized within the Agent Framework for similar purposes. This ensures consistency and efficiency across both systems when dealing with streaming information. ::: zone pivot="programming-language-csharp" -- [`StreamingChatMessageContent`](/dotnet/api/microsoft.semantickernel.streamingchatmessagecontent) -- [`StreamingTextContent`](/dotnet/api/microsoft.semantickernel.streamingtextcontent) -- [`StreamingFileReferenceContent`](/dotnet/api/microsoft.semantickernel.streamingfilereferencecontent) -- [`StreamingAnnotationContent`](/dotnet/api/microsoft.semantickernel.agents.openai.streamingannotationcontent) + +> [!TIP] +> API reference: +> +> - [`StreamingChatMessageContent`](/dotnet/api/microsoft.semantickernel.streamingchatmessagecontent) +> - [`StreamingTextContent`](/dotnet/api/microsoft.semantickernel.streamingtextcontent) +> - [`StreamingFileReferenceContent`](/dotnet/api/microsoft.semantickernel.streamingfilereferencecontent) +> - [`StreamingAnnotationContent`](/dotnet/api/microsoft.semantickernel.agents.openai.streamingannotationcontent) ::: zone-end ::: zone pivot="programming-language-python" -- [`streaming_chat_message_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_chat_message_content) -- [`streaming_text_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_text_content) -- [`streaming_file_reference_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_file_reference_content) -- [`streaming_annotation_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_annotation_content) + +> [!TIP] +> API reference: +> +> - [`streaming_chat_message_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_chat_message_content) +> - [`streaming_text_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_text_content) +> - [`streaming_file_reference_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_file_reference_content) +> - [`streaming_annotation_content`](/python/api/semantic-kernel/semantic_kernel.contents.streaming_annotation_content) ::: zone-end @@ -48,16 +56,12 @@ A streamed response delivers the message content in small, incremental chunks. T ::: zone-end - -## Streaming Agent Invocation - -The `Agent Framework` supports streamed responses when using [`AgentChat`](./agent-chat.md) or when directly invoking a [`ChatCompletionAgent`](./chat-completion-agent.md) or [`OpenAIAssistantAgent`](./assistant-agent.md). In either mode, the framework delivers responses asynchronously as they are streamed. Alongside the streamed response, a consistent, non-streamed history is maintained to track the conversation. This ensures both real-time interaction and a reliable record of the conversation's flow. - ### Streamed response from `ChatCompletionAgent` -When invoking a streamed response from a [`ChatCompletionAgent`](./chat-completion-agent.md), the `ChatHistory` in the `AgentThread` is updated after the full response is received. Although the response is streamed incrementally, the history records only the complete message. This ensures that the `ChatHistory` reflects fully formed responses for consistency. +When invoking a streamed response from a [`ChatCompletionAgent`](./agent-types/chat-completion-agent.md), the `ChatHistory` in the `AgentThread` is updated after the full response is received. Although the response is streamed incrementally, the history records only the complete message. This ensures that the `ChatHistory` reflects fully formed responses for consistency. ::: zone pivot="programming-language-csharp" + ```csharp // Define agent ChatCompletionAgent agent = ...; @@ -79,9 +83,11 @@ await foreach (ChatMessageContent response in agentThread.GetMessagesAsync()) // Process messages... } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread @@ -100,6 +106,7 @@ async for response in agent.invoke_stream(messages="user input", thread=thread) thread = response.thread } ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -110,9 +117,10 @@ async for response in agent.invoke_stream(messages="user input", thread=thread) ### Streamed response from `OpenAIAssistantAgent` -When invoking a streamed response from an [`OpenAIAssistantAgent`](./assistant-agent.md), the assistant maintains the conversation state as a remote thread. It is possible to read the messages from the remote thread if required. +When invoking a streamed response from an [`OpenAIAssistantAgent`](./agent-types/assistant-agent.md), the assistant maintains the conversation state as a remote thread. It is possible to read the messages from the remote thread if required. ::: zone pivot="programming-language-csharp" + ```csharp // Define agent OpenAIAssistantAgent agent = ...; @@ -166,9 +174,11 @@ await foreach (ChatMessageContent response in agentThread.GetMessagesAsync()) // Delete the thread when it is no longer needed await agentThread.DeleteAsync(); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent, OpenAIAssistantAgent @@ -228,7 +238,9 @@ await thread.delete() The nature of streaming responses allows LLM models to return incremental chunks of text, enabling quicker rendering in a UI or console without waiting for the entire response to complete. Additionally, a caller might want to handle intermediate content, such as results from function calls. This can be achieved by supplying a callback function when invoking the streaming response. The callback function receives complete messages encapsulated within `ChatMessageContent`. ::: zone pivot="programming-language-csharp" + > Callback documentation for the `AzureAIAgent` is coming soon. + ::: zone-end ::: zone pivot="programming-language-python" @@ -240,6 +252,7 @@ import asyncio from typing import Annotated from semantic_kernel.agents import AzureResponsesAgent +from semantic_kernel.contents import ChatMessageContent, FunctionCallContent, FunctionResultContent from semantic_kernel.functions import kernel_function @@ -261,6 +274,18 @@ class MenuPlugin: ) -> Annotated[str, "Returns the price of the menu item."]: return "$9.99" +# This callback function will be called for each intermediate message, +# which will allow one to handle FunctionCallContent and FunctionResultContent. +# If the callback is not provided, the agent will return the final response +# with no intermediate tool call steps. +async def handle_streaming_intermediate_steps(message: ChatMessageContent) -> None: + for item in message.items or []: + if isinstance(item, FunctionResultContent): + print(f"Function Result:> {item.result} for function: {item.name}") + elif isinstance(item, FunctionCallContent): + print(f"Function Call:> {item.name} with arguments: {item.arguments}") + else: + print(f"{item}") # Simulate a conversation with the agent USER_INPUTS = [ @@ -290,31 +315,24 @@ async def main(): # created and returned with the initial response thread = None - for user_input in USER_INPUTS: - print(f"# User: '{user_input}'") - first_chunk = True - # 4. Invoke the agent for the current message and print the response - async for response in agent.invoke_stream(messages=user_input, thread=thread): - thread = response.thread - if first_chunk: - print(f"# {response.name}: ", end="", flush=True) - first_chunk = False - print(response.content, end="", flush=True) - print() - - # Print the intermediate steps - print("\nIntermediate Steps:") - for msg in intermediate_steps: - if any(isinstance(item, FunctionResultContent) for item in msg.items): - for fr in msg.items: - if isinstance(fr, FunctionResultContent): - print(f"Function Result:> {fr.result} for function: {fr.name}") - elif any(isinstance(item, FunctionCallContent) for item in msg.items): - for fcc in msg.items: - if isinstance(fcc, FunctionCallContent): - print(f"Function Call:> {fcc.name} with arguments: {fcc.arguments}") - else: - print(f"{msg.role}: {msg.content}") + try: + for user_input in user_inputs: + print(f"# {AuthorRole.USER}: '{user_input}'") + + first_chunk = True + async for response in agent.invoke_stream( + messages=user_input, + thread=thread, + on_intermediate_message=handle_streaming_intermediate_steps, + ): + thread = response.thread + if first_chunk: + print(f"# {response.name}: ", end="", flush=True) + first_chunk = False + print(response.content, end="", flush=True) + print() + finally: + await thread.delete() if thread else None if __name__ == "__main__": asyncio.run(main()) @@ -326,34 +344,23 @@ The following demonstrates sample output from the agent invocation process: Sample Output: # AuthorRole.USER: 'Hello' -# Host: Hi there! How can I assist you with the menu today? +# Host: Hello! How can I assist you with the menu today? # AuthorRole.USER: 'What is the special soup?' -# Host: The special soup is Clam Chowder. -# AuthorRole.USER: 'What is the special drink?' -# Host: The special drink is Chai Tea. -# AuthorRole.USER: 'How much is that?' -# Host: Could you please specify the menu item you are asking about? -# AuthorRole.USER: 'Thank you' -# Host: You're welcome! If you have any questions about the menu or need assistance, feel free to ask. - -Intermediate Steps: -AuthorRole.ASSISTANT: Hi there! How can I assist you with the menu today? -AuthorRole.ASSISTANT: -Function Result:> - Special Soup: Clam Chowder - Special Salad: Cobb Salad - Special Drink: Chai Tea - for function: MenuPlugin-get_specials -AuthorRole.ASSISTANT: The special soup is Clam Chowder. -AuthorRole.ASSISTANT: -Function Result:> +Function Call:> MenuPlugin-get_specials with arguments: {} +Function Result:> Special Soup: Clam Chowder Special Salad: Cobb Salad Special Drink: Chai Tea for function: MenuPlugin-get_specials -AuthorRole.ASSISTANT: The special drink is Chai Tea. -AuthorRole.ASSISTANT: Could you please specify the menu item you are asking about? -AuthorRole.ASSISTANT: You're welcome! If you have any questions about the menu or need assistance, feel free to ask. +# Host: The special soup today is Clam Chowder. Would you like to know more about it or hear about other specials? +# AuthorRole.USER: 'What is the special drink?' +# Host: The special drink today is Chai Tea. Would you like more details or are you interested in ordering it? +# AuthorRole.USER: 'How much is that?' +Function Call:> MenuPlugin-get_item_price with arguments: {"menu_item":"Chai Tea"} +Function Result:> $9.99 for function: MenuPlugin-get_item_price +# Host: The special drink, Chai Tea, is $9.99. Would you like to order one or need information on something else? +# AuthorRole.USER: 'Thank you' +# Host: You're welcome! If you have any more questions or need help with the menu, just let me know. Enjoy your day! ``` ::: zone-end @@ -364,70 +371,10 @@ AuthorRole.ASSISTANT: You're welcome! If you have any questions about the menu o ::: zone-end +## Next Steps -## Streaming with `AgentChat` +> [!div class="nextstepaction"] +> [Using templates with agents](./agent-templates.md) -When using [`AgentChat`](./agent-chat.md), the full conversation history is always preserved and can be accessed directly through the [`AgentChat`](./agent-chat.md) instance. Therefore, the key difference between streamed and non-streamed invocations lies in the delivery method and the resulting content type. In both cases, users can still access the complete history, but streamed responses provide real-time updates as the conversation progresses. This allows for greater flexibility in handling interactions, depending on the application's needs. - -::: zone pivot="programming-language-csharp" -```csharp -// Define agents -ChatCompletionAgent agent1 = ...; -OpenAIAssistantAgent agent2 = ...; - -// Create chat with participating agents. -AgentGroupChat chat = - new(agent1, agent2) - { - // Override default execution settings - ExecutionSettings = - { - TerminationStrategy = { MaximumIterations = 10 } - } - }; - -// Invoke agents -string lastAgent = string.Empty; -await foreach (StreamingChatMessageContent response in chat.InvokeStreamingAsync()) -{ - if (!lastAgent.Equals(response.AuthorName, StringComparison.Ordinal)) - { - // Process beginning of agent response - lastAgent = response.AuthorName; - } - - // Process streamed content... -} -``` -::: zone-end - -::: zone pivot="programming-language-python" -```python -# Define agents -agent1 = ChatCompletionAgent(...) -agent2 = OpenAIAssistantAgent(...) - -# Create chat with participating agents -chat = AgentGroupChat( - agents=[agent1, agent2], - termination_strategy=DefaultTerminationStrategy(maximum_iterations=10), -) - -await chat.add_chat_message("") - -# Invoke agents -last_agent = None -async for response in chat.invoke_stream(): - if message.content is not None: - if last_agent != response.name: - # Process beginning of agent response - last_agent = message.name - # Process streamed content -``` -::: zone-end - -::: zone pivot="programming-language-java" - -> Feature currently unavailable in Java. - -::: zone-end +> [!div class="nextstepaction"] +> [Agent orchestration](./agent-orchestration/index.md) diff --git a/semantic-kernel/Frameworks/agent/agent-templates.md b/semantic-kernel/Frameworks/agent/agent-templates.md index f08df49d..65a1395b 100644 --- a/semantic-kernel/Frameworks/agent/agent-templates.md +++ b/semantic-kernel/Frameworks/agent/agent-templates.md @@ -8,6 +8,7 @@ ms.author: crickman ms.date: 09/13/2024 ms.service: semantic-kernel --- + # Create an Agent from a Semantic Kernel Template ## Prompt Templates in Semantic Kernel @@ -16,26 +17,30 @@ An agent's role is primarily shaped by the instructions it receives, which dicta Additionally, an agent can be configured directly using a Prompt Template Configuration, providing developers with a structured and reusable way to define its behavior. This approach offers a powerful tool for standardizing and customizing agent instructions, ensuring consistency across various use cases while still maintaining dynamic adaptability. -#### Related API's: - ::: zone pivot="programming-language-csharp" -- [`PromptTemplateConfig`](/dotnet/api/microsoft.semantickernel.prompttemplateconfig) -- [`KernelFunctionYaml.FromPromptYaml`](/dotnet/api/microsoft.semantickernel.kernelfunctionyaml.frompromptyaml#microsoft-semantickernel-kernelfunctionyaml-frompromptyaml(system-string-microsoft-semantickernel-iprompttemplatefactory-microsoft-extensions-logging-iloggerfactory)) -- [`IPromptTemplateFactory`](/dotnet/api/microsoft.semantickernel.iprompttemplatefactory) -- [`KernelPromptTemplateFactory`](/dotnet/api/microsoft.semantickernel.kernelprompttemplatefactory) -- [_Handlebars_](/dotnet/api/microsoft.semantickernel.prompttemplates.handlebars) -- [_Prompty_](/dotnet/api/microsoft.semantickernel.prompty) -- [_Liquid_](/dotnet/api/microsoft.semantickernel.prompttemplates.liquid) +> [!TIP] +> API reference: +> +> - [`PromptTemplateConfig`](/dotnet/api/microsoft.semantickernel.prompttemplateconfig) +> - [`KernelFunctionYaml.FromPromptYaml`]() +> - [`IPromptTemplateFactory`](/dotnet/api/microsoft.semantickernel.iprompttemplatefactory) +> - [`KernelPromptTemplateFactory`](/dotnet/api/microsoft.semantickernel.kernelprompttemplatefactory) +> - [_Handlebars_](/dotnet/api/microsoft.semantickernel.prompttemplates.handlebars) +> - [_Prompty_](/dotnet/api/microsoft.semantickernel.prompty) +> - [_Liquid_](/dotnet/api/microsoft.semantickernel.prompttemplates.liquid) ::: zone-end ::: zone pivot="programming-language-python" -- [`prompt_template_config`](/python/api/semantic-kernel/semantic_kernel.prompt_template.prompt_template_config) -- [`kernel_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.kernel_prompt_template) -- [`jinja2_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.jinja2_prompt_template) -- [`handlebars_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.handlebars_prompt_template) +> [!TIP] +> API reference: +> +> - [`prompt_template_config`](/python/api/semantic-kernel/semantic_kernel.prompt_template.prompt_template_config) +> - [`kernel_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.kernel_prompt_template) +> - [`jinja2_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.jinja2_prompt_template) +> - [`handlebars_prompt_template`](/python/api/semantic-kernel/semantic_kernel.prompt_template.handlebars_prompt_template) ::: zone-end @@ -45,13 +50,14 @@ Additionally, an agent can be configured directly using a Prompt Template Config ::: zone-end - ## Agent Instructions as a Template Creating an agent with template parameters provides greater flexibility by allowing its instructions to be easily customized based on different scenarios or requirements. This approach enables the agent's behavior to be tailored by substituting specific values or functions into the template, making it adaptable to a variety of tasks or contexts. By leveraging template parameters, developers can design more versatile agents that can be configured to meet diverse use cases without needing to modify the core logic. -#### Chat Completion Agent +### Chat Completion Agent + ::: zone pivot="programming-language-csharp" + ```csharp // Initialize a Kernel with a chat-completion service Kernel kernel = ...; @@ -69,9 +75,11 @@ ChatCompletionAgent agent = } }; ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python agent = ChatCompletionAgent( service=AzureChatCompletion(), # or other supported AI Services @@ -80,6 +88,7 @@ agent = ChatCompletionAgent( arguments=KernelArguments(topic="Dog", length="2"), ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -88,11 +97,12 @@ agent = ChatCompletionAgent( ::: zone-end -#### OpenAI Assistant Agent +### OpenAI Assistant Agent -Templated instructions are especially powerful when working with an [`OpenAIAssistantAgent`](./assistant-agent.md). With this approach, a single assistant definition can be created and reused multiple times, each time with different parameter values tailored to specific tasks or contexts. This enables a more efficient setup, allowing the same assistant framework to handle a wide range of scenarios while maintaining consistency in its core behavior. +Templated instructions are especially powerful when working with an [`OpenAIAssistantAgent`](./agent-types/assistant-agent.md). With this approach, a single assistant definition can be created and reused multiple times, each time with different parameter values tailored to specific tasks or contexts. This enables a more efficient setup, allowing the same assistant framework to handle a wide range of scenarios while maintaining consistency in its core behavior. ::: zone pivot="programming-language-csharp" + ```csharp // Retrieve an existing assistant definition by identifier AzureOpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri("")); @@ -107,9 +117,11 @@ OpenAIAssistantAgent agent = new(assistant, assistantClient, new KernelPromptTem } } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() @@ -126,6 +138,7 @@ agent = AzureAssistantAgent( arguments=KernelArguments(topic="Dog", length="3"), ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -134,11 +147,11 @@ agent = AzureAssistantAgent( ::: zone-end - ## Agent Definition from a Prompt Template The same Prompt Template Config used to create a Kernel Prompt Function can also be leveraged to define an agent. This allows for a unified approach in managing both prompts and agents, promoting consistency and reuse across different components. By externalizing agent definitions from the codebase, this method simplifies the management of multiple agents, making them easier to update and maintain without requiring changes to the underlying logic. This separation also enhances flexibility, enabling developers to modify agent behavior or introduce new agents by simply updating the configuration, rather than adjusting the code itself. -#### YAML Template + +### YAML Template ```yaml name: GenerateStory @@ -155,15 +168,17 @@ input_variables: is_required: true ``` -#### Agent Initialization +### Agent Initialization + ::: zone pivot="programming-language-csharp" + ```csharp // Read YAML resource string generateStoryYaml = File.ReadAllText("./GenerateStory.yaml"); // Convert to a prompt template config PromptTemplateConfig templateConfig = KernelFunctionYaml.ToPromptTemplateConfig(generateStoryYaml); -// Create agent with Instructions, Name and Description +// Create agent with Instructions, Name and Description // provided by the template config. ChatCompletionAgent agent = new(templateConfig) @@ -177,9 +192,11 @@ ChatCompletionAgent agent = } }; ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python import yaml @@ -201,6 +218,7 @@ agent = ChatCompletionAgent( arguments=KernelArguments(topic="Dog", length="3"), ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -209,12 +227,12 @@ agent = ChatCompletionAgent( ::: zone-end +## Overriding Template Values for Direct Invocation -### Overriding Template Values for Direct Invocation - -When invoking an agent directly, without using [`AgentChat`](./agent-chat.md), the agent's parameters can be overridden as needed. This allows for greater control and customization of the agent's behavior during specific tasks, enabling you to modify its instructions or settings on the fly to suit particular requirements. +When invoking an agent directly, the agent's parameters can be overridden as needed. This allows for greater control and customization of the agent's behavior during specific tasks, enabling you to modify its instructions or settings on the fly to suit particular requirements. ::: zone pivot="programming-language-csharp" + ```csharp // Initialize a Kernel with a chat-completion service Kernel kernel = ...; @@ -245,6 +263,7 @@ await foreach (ChatMessageContent response in agent.InvokeAsync([], options: new // Process agent response(s)... } ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -284,14 +303,13 @@ async for response in agent.invoke(messages="user input", arguments=override_arg ::: zone-end - ## How-To For an end-to-end example for creating an agent from a _prompt-template_, see: - [How-To: `ChatCompletionAgent`](./examples/example-chat-agent.md) +## Next steps > [!div class="nextstepaction"] -> [Configuring Agents with Plugins](./agent-functions.md) - +> [Agent orchestration](./agent-orchestration/index.md) diff --git a/semantic-kernel/Frameworks/agent/agent-types/TOC.yml b/semantic-kernel/Frameworks/agent/agent-types/TOC.yml new file mode 100644 index 00000000..42ddb688 --- /dev/null +++ b/semantic-kernel/Frameworks/agent/agent-types/TOC.yml @@ -0,0 +1,10 @@ +- name: Chat Completion Agent + href: chat-completion-agent.md +- name: OpenAI Assistant Agent + href: assistant-agent.md +- name: Azure AI Agent + href: azure-ai-agent.md +- name: OpenAI Responses Agent + href: responses-agent.md +- name: Copilot Studio Agent + href: copilot-studio-agent.md diff --git a/semantic-kernel/Frameworks/agent/assistant-agent.md b/semantic-kernel/Frameworks/agent/agent-types/assistant-agent.md similarity index 94% rename from semantic-kernel/Frameworks/agent/assistant-agent.md rename to semantic-kernel/Frameworks/agent/agent-types/assistant-agent.md index cecb4e9e..01578d5d 100644 --- a/semantic-kernel/Frameworks/agent/assistant-agent.md +++ b/semantic-kernel/Frameworks/agent/agent-types/assistant-agent.md @@ -13,17 +13,22 @@ ms.service: semantic-kernel > [!IMPORTANT] > Single-agent features, such as `OpenAIAssistantAgent`, are in the release candidate stage. These features are nearly complete and generally stable, though they may undergo minor refinements or optimizations before reaching full general availability. -Detailed API documentation related to this discussion is available at: - ::: zone pivot="programming-language-csharp" -- [`OpenAIAssistantAgent`](/dotnet/api/microsoft.semantickernel.agents.openai.openaiassistantagent) + +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`OpenAIAssistantAgent`](/dotnet/api/microsoft.semantickernel.agents.openai.openaiassistantagent) ::: zone-end ::: zone pivot="programming-language-python" -- [`AzureAssistantAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.azure_assistant_agent.azureassistantagent) -- [`OpenAIAssistantAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.open_ai_assistant_agent.openaiassistantagent) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`AzureAssistantAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.azure_assistant_agent.azureassistantagent) +> - [`OpenAIAssistantAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.open_ai_assistant_agent.openaiassistantagent) ::: zone-end @@ -33,7 +38,6 @@ Detailed API documentation related to this discussion is available at: ::: zone-end - ## What is an Assistant? The OpenAI Assistants API is a specialized interface designed for more advanced and interactive AI capabilities, enabling developers to create personalized and multi-step task-oriented agents. Unlike the Chat Completion API, which focuses on simple conversational exchanges, the Assistant API allows for dynamic, goal-driven interactions with additional features like code-interpreter and file-search. @@ -42,10 +46,9 @@ The OpenAI Assistants API is a specialized interface designed for more advanced - [OpenAI Assistant API](https://platform.openai.com/docs/api-reference/assistants) - [Assistant API in Azure](/azure/ai-services/openai/assistants-quickstart) - ## Preparing Your Development Environment -To proceed with developing an `OpenAIAIAssistantAgent`, configure your development environment with the appropriate packages. +To proceed with developing an `OpenAIAssistantAgent`, configure your development environment with the appropriate packages. ::: zone pivot="programming-language-csharp" @@ -60,6 +63,7 @@ You may also want to include the `Azure.Identity` package: ```pwsh dotnet add package Azure.Identity ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -78,12 +82,12 @@ pip install semantic-kernel[azure] ::: zone-end - ## Creating an `OpenAIAssistantAgent` Creating an `OpenAIAssistant` requires first creating a client to be able to talk a remote service. ::: zone pivot="programming-language-csharp" + ```csharp AssistantClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(...).GetAssistantClient(); Assistant assistant = @@ -93,9 +97,11 @@ Assistant assistant = instructions: ""); OpenAIAssistantAgent agent = new(assistant, client); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent, OpenAIAssistantAgent @@ -133,6 +139,7 @@ agent = OpenAIAssistantAgent( definition=definition, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -141,7 +148,6 @@ agent = OpenAIAssistantAgent( ::: zone-end - ## Retrieving an `OpenAIAssistantAgent` Once created, the identifier of the assistant may be access via its identifier. This identifier may be used to create an `OpenAIAssistantAgent` from an existing assistant definition. @@ -155,9 +161,11 @@ AssistantClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(...).GetAs Assistant assistant = await client.GetAssistantAsync(""); OpenAIAssistantAgent agent = new(assistant, client); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python # Using Azure OpenAI Resources @@ -183,6 +191,7 @@ agent = AzureAssistantAgent( definition=new_asst_definition, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -191,7 +200,6 @@ agent = AzureAssistantAgent( ::: zone-end - ## Using an `OpenAIAssistantAgent` As with all aspects of the Assistant API, conversations are stored remotely. Each conversation is referred to as a thread and identified by a unique `string` identifier. Interactions with your `OpenAIAssistantAgent` are tied to this specific thread identifier. The specifics of the Assistant API thread is abstracted away via the `OpenAIAssistantAgentThread` class, which is an implementation of `AgentThread`. @@ -201,6 +209,7 @@ The `OpenAIAssistantAgent` currently only supports threads of type `OpenAIAssist You can invoke the `OpenAIAssistantAgent` without specifying an `AgentThread`, to start a new thread and a new `AgentThread` will be returned as part of the response. ::: zone pivot="programming-language-csharp" + ```csharp // Define agent @@ -250,6 +259,7 @@ AgentThread agentThread = new OpenAIAssistantAgentThread(client, "existing-threa ::: zone-end ::: zone pivot="programming-language-python" + ```python from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent @@ -267,6 +277,7 @@ async for response in agent.invoke(messages="user input", thread=thread): # Delete the thread when it is no longer needed await thread.delete() if thread else None ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -275,7 +286,6 @@ await thread.delete() if thread else None ::: zone-end - ## Deleting an `OpenAIAssistantAgent` Since the assistant's definition is stored remotely, it will persist if not deleted. @@ -291,14 +301,17 @@ For .NET, the agent identifier is exposed as a `string` via the [`Agent.Id`](/do AssistantClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(...).GetAssistantClient(); await client.DeleteAssistantAsync(""); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python await agent.delete() is_deleted = agent._is_deleted ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -447,15 +460,14 @@ AuthorRole.ASSISTANT: You're welcome! If you have any more questions or need fur ::: zone-end - ## How-To For an end-to-end example for a `OpenAIAssistantAgent`, see: -- [How-To: `OpenAIAssistantAgent` Code Interpreter](./examples/example-assistant-code.md) -- [How-To: `OpenAIAssistantAgent` File Search](./examples/example-assistant-search.md) +- [How-To: `OpenAIAssistantAgent` Code Interpreter](./../examples/example-assistant-code.md) +- [How-To: `OpenAIAssistantAgent` File Search](./../examples/example-assistant-search.md) +## Next Steps > [!div class="nextstepaction"] > [Explore the Azure AI Agent](./azure-ai-agent.md) - diff --git a/semantic-kernel/Frameworks/agent/azure-ai-agent.md b/semantic-kernel/Frameworks/agent/agent-types/azure-ai-agent.md similarity index 97% rename from semantic-kernel/Frameworks/agent/azure-ai-agent.md rename to semantic-kernel/Frameworks/agent/agent-types/azure-ai-agent.md index c34ab078..18747014 100644 --- a/semantic-kernel/Frameworks/agent/azure-ai-agent.md +++ b/semantic-kernel/Frameworks/agent/agent-types/azure-ai-agent.md @@ -13,17 +13,21 @@ ms.service: semantic-kernel > [!IMPORTANT] > This feature is in the experimental stage. Features at this stage are under development and subject to change before advancing to the preview or release candidate stage. -Detailed API documentation related to this discussion is available at: - ::: zone pivot="programming-language-csharp" -- [`AzureAIAgent`](/dotnet/api/microsoft.semantickernel.agents.azureai) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`AzureAIAgent`](/dotnet/api/microsoft.semantickernel.agents.azureai) ::: zone-end ::: zone pivot="programming-language-python" -- [`AzureAIAgent`](/python/api/semantic-kernel/semantic_kernel.agents.azure_ai.azure_ai_agent.azureaiagent) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`AzureAIAgent`](/python/api/semantic-kernel/semantic_kernel.agents.azure_ai.azure_ai_agent.azureaiagent) ::: zone-end @@ -44,7 +48,6 @@ To use an `AzureAIAgent`, an Azure AI Foundry Project must be utilized. The fol - [What is Azure AI Agent Service](/azure/ai-services/agents/overview) - [Quickstart: Create a new agent](/azure/ai-services/agents/quickstart) - ## Preparing Your Development Environment To proceed with developing an `AzureAIAgent`, configure your development environment with the appropriate packages. @@ -72,6 +75,7 @@ Install the `semantic-kernel` package with the optional Azure dependencies: ```bash pip install semantic-kernel[azure] ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -80,14 +84,13 @@ pip install semantic-kernel[azure] ::: zone-end - ## Configuring the AI Project Client Accessing an `AzureAIAgent` first requires the creation of a client that is configured for a specific Foundry Project, most commonly by providing your project endpoint ([The Azure AI Foundry SDK: Getting Started with Projects](/azure/ai-foundry/how-to/develop/sdk-overview#get-started-with-projects)). ::: zone pivot="programming-language-csharp" -```c# +```csharp PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); ``` @@ -140,7 +143,7 @@ To create an `AzureAIAgent`, you start by configuring and initializing the Found ::: zone pivot="programming-language-csharp" -```c# +```csharp PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); // 1. Define an agent on the Azure AI agent service @@ -153,6 +156,7 @@ PersistentAgent definition = await agentsClient.Administration.CreateAgentAsync( // 2. Create a Semantic Kernel agent based on the agent definition AzureAIAgent agent = new(definition, agentsClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -199,7 +203,7 @@ The specifics of the _Azure AI Agent thread_ is abstracted away via the `Microso The `AzureAIAgent` currently only supports threads of type `AzureAIAgentThread`. -```c# +```csharp AzureAIAgentThread agentThread = new(agent.Client); try { @@ -235,7 +239,7 @@ finally: await thread.delete() if thread else None ``` -Optionally, an agent may be invoked as: +Optionally, an agent may be invoked as: ```python for user_input in USER_INPUTS: @@ -265,22 +269,26 @@ finally: An agent may also produce a streamed response: ::: zone pivot="programming-language-csharp" -```c# + +```csharp ChatMessageContent message = new(AuthorRole.User, ""); await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread)) { Console.Write(response.Content); } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python for user_input in USER_INPUTS: await agent.add_chat_message(thread_id=thread.id, message=user_input) async for content in agent.invoke_stream(thread_id=thread.id): print(content.content, end="", flush=True) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -294,7 +302,8 @@ for user_input in USER_INPUTS: Semantic Kernel supports extending an `AzureAIAgent` with custom plugins for enhanced functionality: ::: zone pivot="programming-language-csharp" -```c# + +```csharp KernelPlugin plugin = KernelPluginFactory.CreateFromType(); PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); @@ -306,9 +315,11 @@ PersistentAgent definition = await agentsClient.Administration.CreateAgentAsync( AzureAIAgent agent = new(definition, agentsClient, plugins: [plugin]); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from semantic_kernel.functions import kernel_function @@ -331,6 +342,7 @@ async with ( plugins=[SamplePlugin()] ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -353,7 +365,8 @@ An `AzureAIAgent` can leverage advanced tools such as: Code Interpreter allows the agents to write and run Python code in a sandboxed execution environment ([Azure AI Agent Service Code Interpreter](/azure/ai-services/agents/how-to/tools/code-interpreter)). ::: zone pivot="programming-language-csharp" -```c# + +```csharp PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); PersistentAgent definition = await agentsClient.CreateAgentAsync( @@ -373,9 +386,11 @@ PersistentAgent definition = await agentsClient.CreateAgentAsync( AzureAIAgent agent = new(definition, agentsClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from azure.ai.projects.models import CodeInterpreterTool @@ -390,6 +405,7 @@ async with ( tool_resources=code_interpreter.resources, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -404,7 +420,7 @@ File search augments agents with knowledge from outside its model ([Azure AI Age ::: zone pivot="programming-language-csharp" -```c# +```csharp PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); PersistentAgent definition = await agentsClient.CreateAgentAsync( @@ -424,9 +440,11 @@ PersistentAgent definition = await agentsClient.CreateAgentAsync( AzureAIAgent agent = new(definition, agentsClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from azure.ai.projects.models import FileSearchTool @@ -441,6 +459,7 @@ async with ( tool_resources=file_search.resources, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -454,7 +473,8 @@ async with ( Connects your agent to an external API ([How to use Azure AI Agent Service with OpenAPI Specified Tools](/azure/ai-services/agents/how-to/tools/openapi-spec)). ::: zone pivot="programming-language-csharp" -```c# + +```csharp PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); string apiJsonSpecification = ...; // An Open API JSON specification @@ -475,9 +495,11 @@ PersistentAgent definition = await agentsClient.CreateAgentAsync( AzureAIAgent agent = new(definition, agentsClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from azure.ai.projects.models import OpenApiTool, OpenApiAnonymousAuthDetails @@ -511,6 +533,7 @@ async with ( tools=openapi_tool_one.definitions + openapi_tool_two.definitions, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -524,7 +547,8 @@ async with ( Use an existing Azure AI Search index with with your agent ([Use an existing AI Search index](/azure/ai-services/agents/how-to/tools/azure-ai-search)). ::: zone pivot="programming-language-csharp" -```c# + +```csharp PersistentAgentsClient client = AzureAIAgent.CreateAgentsClient("", new AzureCliCredential()); PersistentAgent definition = await agentsClient.CreateAgentAsync( @@ -543,9 +567,11 @@ PersistentAgent definition = await agentsClient.CreateAgentAsync( AzureAIAgent agent = new(definition, agentsClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python from azure.ai.projects.models import AzureAISearchTool, ConnectionType @@ -574,6 +600,7 @@ async with ( headers={"x-ms-enable-preview": "true"}, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -588,7 +615,7 @@ An existing agent can be retrieved and reused by specifying its assistant ID: ::: zone pivot="programming-language-csharp" -```c# +```csharp PersistentAgent definition = await agentsClient.Administration.GetAgentAsync(""); AzureAIAgent agent = new(definition, agentsClient); ``` @@ -596,10 +623,12 @@ AzureAIAgent agent = new(definition, agentsClient); ::: zone-end ::: zone pivot="programming-language-python" + ```python agent_definition = await client.agents.get_agent(assistant_id="your-agent-id") agent = AzureAIAgent(client=client, definition=agent_definition) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -614,33 +643,40 @@ Agents and their associated threads can be deleted when no longer needed: ::: zone pivot="programming-language-csharp" -```c# +```csharp await agentThread.DeleteAsync(); await agentsClient.Administration.DeleteAgentAsync(agent.Id); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python await client.agents.delete_thread(thread.id) await client.agents.delete_agent(agent.id) ``` + ::: zone-end If working with a vector store or files, they may be deleted as well: ::: zone pivot="programming-language-csharp" -```c# + +```csharp await agentsClient.VectorStores.DeleteVectorStoreAsync(""); await agentsClient.Files.DeleteFileAsync(""); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python await client.agents.files.delete(file_id=file.id) await client.agents.vector_stores.delete(vector_store_id=vector_store.id) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -817,5 +853,7 @@ Agent: You're welcome! Enjoy your meal! 😊 ::: zone-end +## Next Steps + > [!div class="nextstepaction"] > [Explore the OpenAI Responses Agent](./responses-agent.md) \ No newline at end of file diff --git a/semantic-kernel/Frameworks/agent/chat-completion-agent.md b/semantic-kernel/Frameworks/agent/agent-types/chat-completion-agent.md similarity index 83% rename from semantic-kernel/Frameworks/agent/chat-completion-agent.md rename to semantic-kernel/Frameworks/agent/agent-types/chat-completion-agent.md index b7fd1e8e..037d6066 100644 --- a/semantic-kernel/Frameworks/agent/chat-completion-agent.md +++ b/semantic-kernel/Frameworks/agent/agent-types/chat-completion-agent.md @@ -10,34 +10,41 @@ ms.service: semantic-kernel --- # Exploring the Semantic Kernel `ChatCompletionAgent` -Detailed API documentation related to this discussion is available at: - ::: zone pivot="programming-language-csharp" -- [`ChatCompletionAgent`](/dotnet/api/microsoft.semantickernel.agents.chatcompletionagent) -- [`Microsoft.SemanticKernel.Agents`](/dotnet/api/microsoft.semantickernel.agents) -- [`IChatCompletionService`](/dotnet/api/microsoft.semantickernel.chatcompletion.ichatcompletionservice) -- [`Microsoft.SemanticKernel.ChatCompletion`](/dotnet/api/microsoft.semantickernel.chatcompletion ) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`ChatCompletionAgent`](/dotnet/api/microsoft.semantickernel.agents.chatcompletionagent) +> - [`Microsoft.SemanticKernel.Agents`](/dotnet/api/microsoft.semantickernel.agents) +> - [`IChatCompletionService`](/dotnet/api/microsoft.semantickernel.chatcompletion.ichatcompletionservice) +> - [`Microsoft.SemanticKernel.ChatCompletion`](/dotnet/api/microsoft.semantickernel.chatcompletion ) ::: zone-end ::: zone pivot="programming-language-python" -- [`ChatCompletionAgent`](/python/api/semantic-kernel/semantic_kernel.agents.chat_completion.chat_completion_agent.chatcompletionagent) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`ChatCompletionAgent`](/python/api/semantic-kernel/semantic_kernel.agents.chat_completion.chat_completion_agent.chatcompletionagent) ::: zone-end ::: zone pivot="programming-language-java" -- [`ChatCompletionAgent`](/java/api/com.microsoft.semantickernel.agents.chatcompletion.chatcompletionagent) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`ChatCompletionAgent`](/java/api/com.microsoft.semantickernel.agents.chatcompletion.chatcompletionagent) ::: zone-end ## Chat Completion in Semantic Kernel -[Chat Completion](../../concepts/ai-services/chat-completion/index.md) is fundamentally a protocol for a chat-based interaction with an AI model where the chat-history is maintained and presented to the model with each request. Semantic Kernel [AI services](../../concepts/ai-services/index.md) offer a unified framework for integrating the chat-completion capabilities of various AI models. +[Chat Completion](../../../concepts/ai-services/chat-completion/index.md) is fundamentally a protocol for a chat-based interaction with an AI model where the chat-history is maintained and presented to the model with each request. Semantic Kernel [AI services](../../../concepts/ai-services/index.md) offer a unified framework for integrating the chat-completion capabilities of various AI models. -A `ChatCompletionAgent` can leverage any of these [AI services](../../concepts/ai-services/chat-completion/index.md) to generate responses, whether directed to a user or another agent. +A `ChatCompletionAgent` can leverage any of these [AI services](../../../concepts/ai-services/chat-completion/index.md) to generate responses, whether directed to a user or another agent. ## Preparing Your Development Environment @@ -62,7 +69,7 @@ pip install semantic-kernel ``` > [!IMPORTANT] -> Depending upon which AI Service you use as part of the `ChatCompletionAgent`, you may need to install extra packages. Please check for the required extra on the following [page](../../concepts/ai-services/chat-completion/index.md#creating-a-chat-completion-service) +> Depending upon which AI Service you use as part of the `ChatCompletionAgent`, you may need to install extra packages. Please check for the required extra on the following [page](../../../concepts/ai-services/chat-completion/index.md#creating-a-chat-completion-service) ::: zone-end @@ -81,7 +88,7 @@ pip install semantic-kernel ## Creating a `ChatCompletionAgent` -A `ChatCompletionAgent` is fundamentally based on an [AI services](../../concepts/ai-services/index.md). As such, creating a `ChatCompletionAgent` starts with creating a [`Kernel`](../../concepts/kernel.md) instance that contains one or more chat-completion services and then instantiating the agent with a reference to that [`Kernel`](../../concepts/kernel.md) instance. +A `ChatCompletionAgent` is fundamentally based on an [AI services](../../../concepts/ai-services/index.md). As such, creating a `ChatCompletionAgent` starts with creating a [`Kernel`](../../../concepts/kernel.md) instance that contains one or more chat-completion services and then instantiating the agent with a reference to that [`Kernel`](../../../concepts/kernel.md) instance. ::: zone pivot="programming-language-csharp" @@ -164,9 +171,10 @@ var agent = ChatCompletionAgent.builder() ## AI Service Selection -No different from using Semantic Kernel [AI services](../../concepts/ai-services/index.md) directly, a `ChatCompletionAgent` supports the specification of a service-selector. A service-selector identifies which [AI service](../../concepts/ai-services/index.md) to target when the [`Kernel`](../../concepts/kernel.md) contains more than one. +No different from using Semantic Kernel [AI services](../../../concepts/ai-services/index.md) directly, a `ChatCompletionAgent` supports the specification of a service-selector. A service-selector identifies which [AI service](../../../concepts/ai-services/index.md) to target when the [`Kernel`](../../../concepts/kernel.md) contains more than one. -> Note: If multiple [AI services](../../concepts/ai-services/index.md) are present and no service-selector is provided, the same default logic is applied for the agent that you'd find when using an [AI services](../../concepts/ai-services/index.md) outside of the `Agent Framework` +> [!NOTE] +> If multiple [AI services](../../../concepts/ai-services/index.md) are present and no service-selector is provided, the same default logic is applied for the agent that you'd find when using an [AI services](../../../concepts/ai-services/index.md) outside of the `Agent Framework` ::: zone pivot="programming-language-csharp" @@ -234,7 +242,7 @@ agent = ChatCompletionAgent( ::: zone pivot="programming-language-csharp" -Conversing with your `ChatCompletionAgent` is based on a `ChatHistory` instance, no different from interacting with a Chat Completion [AI service](../../concepts/ai-services/index.md). +Conversing with your `ChatCompletionAgent` is based on a `ChatHistory` instance, no different from interacting with a Chat Completion [AI service](../../../concepts/ai-services/index.md). You can simply invoke the agent with your user message. @@ -481,7 +489,9 @@ AuthorRole.ASSISTANT: You're welcome! If you have any more questions, feel free For an end-to-end example for a `ChatCompletionAgent`, see: -- [How-To: `ChatCompletionAgent`](./examples/example-chat-agent.md) +- [How-To: `ChatCompletionAgent`](./../examples/example-chat-agent.md) + +## Next Steps > [!div class="nextstepaction"] > [Explore the OpenAI Assistant Agent](./assistant-agent.md) diff --git a/semantic-kernel/Frameworks/agent/copilot-studio-agent.md b/semantic-kernel/Frameworks/agent/agent-types/copilot-studio-agent.md similarity index 98% rename from semantic-kernel/Frameworks/agent/copilot-studio-agent.md rename to semantic-kernel/Frameworks/agent/agent-types/copilot-studio-agent.md index c7e77c59..a7e69b63 100644 --- a/semantic-kernel/Frameworks/agent/copilot-studio-agent.md +++ b/semantic-kernel/Frameworks/agent/agent-types/copilot-studio-agent.md @@ -8,6 +8,7 @@ ms.author: evmattso ms.date: 05/20/2025 ms.service: semantic-kernel --- + # Exploring the Semantic Kernel `CopilotStudioAgent` > [!IMPORTANT] @@ -60,6 +61,7 @@ To develop with the `CopilotStudioAgent`, you must have your environment and aut 1. **Python 3.10 or higher** 2. **Semantic Kernel** with Copilot Studio dependencies: + - Until dependencies are broadly available on PyPI: ```bash pip install semantic-kernel @@ -67,6 +69,7 @@ To develop with the `CopilotStudioAgent`, you must have your environment and aut ``` 3. **Microsoft Copilot Studio** agent: + - Create an agent at [Microsoft Copilot Studio](https://copilotstudio.microsoft.com). - Publish your agent, and under `Settings → Advanced → Metadata` obtain: - `Schema Name` (used as `agent_identifier`) @@ -85,6 +88,7 @@ COPILOT_STUDIO_AGENT_ENVIRONMENT_ID= COPILOT_STUDIO_AGENT_AGENT_IDENTIFIER= COPILOT_STUDIO_AGENT_AUTH_MODE=interactive ``` + > [!TIP] > See [Power Platform API Authentication](/power-platform/admin/programmability-authentication-v2) for help with permissions. @@ -108,7 +112,7 @@ You may rely on environment variables for most configuration, but can explicitly ::: zone pivot="programming-language-python" -#### Basic Usage — Environment Variable Driven +### Basic Usage — Environment Variable Driven ```python from semantic_kernel.agents import CopilotStudioAgent @@ -118,9 +122,10 @@ agent = CopilotStudioAgent( instructions="You help answer questions about physics.", ) ``` + No explicit client setup is required if your environment variables are set. -#### Explicit Client Construction +### Explicit Client Construction Override config or use custom identity: @@ -141,6 +146,7 @@ agent = CopilotStudioAgent( instructions="You help answer custom questions.", ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -293,6 +299,7 @@ agent = CopilotStudioAgent( plugins=[SamplePlugin()], ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -317,11 +324,11 @@ A `CopilotStudioAgent` can leverage advanced Copilot Studio-enhanced abilities, ::: zone pivot="programming-language-python" -#### Knowledge Retrieval +### Knowledge Retrieval No specific Python code is needed; knowledge sources must be configured in Copilot Studio. When user messages require facts from these sources, the agent will return information as appropriate. -#### Web Search +### Web Search Configure your Copilot within Studio to allow Bing Search. Then use as above. For more information about configuring Bing Search see the following [guide](/microsoft-copilot-studio/nlu-generative-answers-bing). @@ -377,6 +384,7 @@ For practical examples of using a `CopilotStudioAgent`, see our code samples on > Feature currently unavailable in Java. ::: zone-end + --- **Notes:** @@ -387,5 +395,7 @@ For practical examples of using a `CopilotStudioAgent`, see our code samples on --- +## Next Steps + > [!div class="nextstepaction"] -> [Explore Agent Collaboration in Agent Chat](./agent-chat.md) \ No newline at end of file +> [Explore Agent Orchestration](../agent-orchestration/index.md) diff --git a/semantic-kernel/Frameworks/agent/responses-agent.md b/semantic-kernel/Frameworks/agent/agent-types/responses-agent.md similarity index 95% rename from semantic-kernel/Frameworks/agent/responses-agent.md rename to semantic-kernel/Frameworks/agent/agent-types/responses-agent.md index 139c5c21..fe5eddf4 100644 --- a/semantic-kernel/Frameworks/agent/responses-agent.md +++ b/semantic-kernel/Frameworks/agent/agent-types/responses-agent.md @@ -8,21 +8,25 @@ ms.author: evmattso ms.date: 04/02/2025 ms.service: semantic-kernel --- + # Exploring the Semantic Kernel `OpenAIResponsesAgent` > [!IMPORTANT] -> This feature is in the experimental stage. Features at this stage are under development and subject to change before advancing to the preview or release candidate stage. The current `OpenAIResponsesAgent` is not supported as part of Semantic Kernel's `AgentGroupChat` patterns. Stayed tuned for updates. - -Detailed API documentation related to this discussion is available at: +> This feature is in the experimental stage. Features at this stage are under development and subject to change before advancing to the preview or release candidate stage. ::: zone pivot="programming-language-csharp" + > The `OpenAIResponsesAgent` is coming soon. + ::: zone-end ::: zone pivot="programming-language-python" -- [`AzureResponsesAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.azure_responses_agent.azureresponsesagent) -- [`OpenAIResponsesAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.open_ai_responses_agent.openairesponsesagent) +> [!TIP] +> Detailed API documentation related to this discussion is available at: +> +> - [`AzureResponsesAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.azure_responses_agent.azureresponsesagent) +> - [`OpenAIResponsesAgent`](/python/api/semantic-kernel/semantic_kernel.agents.open_ai.open_ai_responses_agent.openairesponsesagent) ::: zone-end @@ -32,7 +36,6 @@ Detailed API documentation related to this discussion is available at: ::: zone-end - ## What is a Responses Agent? The OpenAI Responses API is OpenAI's most advanced interface for generating model responses. It supports text and image inputs, and text outputs. You are able to create stateful interactions with the model, using the output of previous responses as input. It is also possible to extend the model's capabilities with built-in tools for file search, web search, computer use, and more. @@ -40,13 +43,14 @@ The OpenAI Responses API is OpenAI's most advanced interface for generating mode - [OpenAI Responses API](https://platform.openai.com/docs/api-reference/responses) - [Responses API in Azure](/azure/ai-services/openai/how-to/responses?tabs=python-secure) - ## Preparing Your Development Environment To proceed with developing an `OpenAIResponsesAgent`, configure your development environment with the appropriate packages. ::: zone pivot="programming-language-csharp" + > The `OpenAIResponsesAgent` is coming soon. + ::: zone-end ::: zone pivot="programming-language-python" @@ -68,13 +72,14 @@ pip install semantic-kernel ::: zone-end - ## Creating an `OpenAIResponsesAgent` Creating an `OpenAIResponsesAgent` requires first creating a client to be able to talk a remote service. ::: zone pivot="programming-language-csharp" + > The `OpenAIResponsesAgent` is coming soon. + ::: zone-end ::: zone pivot="programming-language-python" @@ -89,7 +94,7 @@ AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME="" Set the appropriate variable depending on which provider you're using. > [!TIP] -> The minimum allowed Azure OpenAI api version is `2025-03-01-preview`. Please visit the following [link](azure/ai-services/openai/how-to/responses) to view region availability, model support, and further details. +> The minimum allowed Azure OpenAI api version is `2025-03-01-preview`. Please visit the following [link](azure/ai-services/openai/how-to/responses) to view region availability, model support, and further details. To create an `AzureResponsesAgent` to use with Azure OpenAI models: @@ -136,7 +141,9 @@ agent = OpenAIResponsesAgent( ## Using an `OpenAIResponsesAgent` ::: zone pivot="programming-language-csharp" + > The `OpenAIResponsesAgent` is coming soon. + ::: zone-end ::: zone pivot="programming-language-python" @@ -185,6 +192,7 @@ for user_input in USER_INPUTS: # Delete the thread when it is no longer needed await thread.delete() if thread else None ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -198,7 +206,9 @@ await thread.delete() if thread else None The Semantic Kernel `OpenAIResponsesAgent` is designed to invoke an agent that fulfills user queries or questions. During invocation, the agent may execute tools to derive the final answer. To access intermediate messages produced during this process, callers can supply a callback function that handles instances of `FunctionCallContent` or `FunctionResultContent`. ::: zone pivot="programming-language-csharp" + > The `OpenAIResponsesAgent` is coming soon. + ::: zone-end ::: zone pivot="programming-language-python" @@ -293,7 +303,7 @@ AuthorRole.USER: 'Hello' Host: Hi there! How can I assist you with the menu today? AuthorRole.USER: 'What is the special soup?' Function Call:> MenuPlugin-get_specials with arguments: {} -Function Result:> +Function Result:> Special Soup: Clam Chowder Special Salad: Cobb Salad Special Drink: Chai Tea @@ -317,5 +327,7 @@ Host: You're welcome! If you have any more questions, feel free to ask. Enjoy yo ::: zone-end +## Next Steps + > [!div class="nextstepaction"] > [Explore the Copilot Studio Agent](./copilot-studio-agent.md) diff --git a/semantic-kernel/Frameworks/agent/examples/TOC.yml b/semantic-kernel/Frameworks/agent/examples/TOC.yml index afec67ee..6fa2818a 100644 --- a/semantic-kernel/Frameworks/agent/examples/TOC.yml +++ b/semantic-kernel/Frameworks/agent/examples/TOC.yml @@ -4,5 +4,3 @@ href: example-assistant-code.md - name: How-To use Assistant Agent - File Search href: example-assistant-search.md -- name: How-To use Agent Group Chat - href: example-agent-collaboration.md diff --git a/semantic-kernel/Frameworks/agent/examples/example-assistant-code.md b/semantic-kernel/Frameworks/agent/examples/example-assistant-code.md index c0796308..4f744fe9 100644 --- a/semantic-kernel/Frameworks/agent/examples/example-assistant-code.md +++ b/semantic-kernel/Frameworks/agent/examples/example-assistant-code.md @@ -15,11 +15,10 @@ ms.service: semantic-kernel ## Overview -In this sample, we will explore how to use the code-interpreter tool of an [`OpenAIAssistantAgent`](../assistant-agent.md) to complete data-analysis tasks. The approach will be broken down step-by-step to high-light the key parts of the coding process. As part of the task, the agent will generate both image and text responses. This will demonstrate the versatility of this tool in performing quantitative analysis. +In this sample, we will explore how to use the code-interpreter tool of an [`OpenAIAssistantAgent`](../agent-types/assistant-agent.md) to complete data-analysis tasks. The approach will be broken down step-by-step to high-light the key parts of the coding process. As part of the task, the agent will generate both image and text responses. This will demonstrate the versatility of this tool in performing quantitative analysis. Streaming will be used to deliver the agent's responses. This will provide real-time updates as the task progresses. - ## Getting Started Before proceeding with feature coding, make sure your development environment is fully set up and configured. @@ -40,6 +39,7 @@ dotnet add package Microsoft.SemanticKernel dotnet add package Microsoft.SemanticKernel.Agents.OpenAI --prerelease ``` +> [!IMPORTANT] > If managing NuGet packages in Visual Studio, ensure `Include prerelease` is checked. The project file (`.csproj`) should contain the following `PackageReference` definitions: @@ -161,11 +161,12 @@ public class Settings } } ``` + ::: zone-end ::: zone pivot="programming-language-python" -The quickest way to get started with the proper configuration to run the sample code is to create a `.env` file at the root of your project (where your script is run). +The quickest way to get started with the proper configuration to run the sample code is to create a `.env` file at the root of your project (where your script is run). Configure the following settings in your `.env` file for either Azure OpenAI or OpenAI: @@ -215,6 +216,7 @@ Settings settings = new(); AzureOpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(settings.AzureOpenAI.Endpoint)); ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -233,6 +235,7 @@ OpenAIFileClient fileClient = client.GetOpenAIFileClient(); OpenAIFile fileDataCountryDetail = await fileClient.UploadFileAsync("PopulationByAdmin1.csv", FileUploadPurpose.Assistants); OpenAIFile fileDataCountryList = await fileClient.UploadFileAsync("PopulationByCountry.csv", FileUploadPurpose.Assistants); ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -324,6 +327,7 @@ AssistantClient assistantClient = client.GetAssistantClient(); // Create agent OpenAIAssistantAgent agent = new(assistant, assistantClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -337,6 +341,7 @@ agent = AzureAssistantAgent( definition=definition, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -352,6 +357,7 @@ At last, we are able to coordinate the interaction between the user and the `Age Let's also ensure the resources are removed at the end of execution to minimize unnecessary charges. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine("Creating thread..."); AssistantAgentThread agentThread = new(); @@ -380,9 +386,11 @@ finally ]); } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python thread: AssistantAgentThread = None @@ -397,6 +405,7 @@ finally: await thread.delete() if thread else None await client.beta.assistants.delete(agent.id) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -408,6 +417,7 @@ finally: Now let's capture user input within the previous loop. In this case, empty input will be ignored and the term `EXIT` will signal that the conversation is completed. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine(); Console.Write("> "); @@ -426,9 +436,11 @@ var message = new ChatMessageContent(AuthorRole.User, input); Console.WriteLine(); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python user_input = input("User:> ") if not user_input: @@ -438,6 +450,7 @@ if user_input.lower() == "exit": is_complete = True break ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -491,9 +504,11 @@ private static async Task DownloadFileContentAsync(OpenAIFileClient client, stri } } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python import os @@ -525,6 +540,7 @@ async def download_response_image(agent, file_ids: list[str]): for file_id in file_ids: await download_file_content(agent, file_id) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -536,6 +552,7 @@ async def download_response_image(agent, file_ids: list[str]): To generate an `Agent` response to user input, invoke the agent by providing the message and the `AgentThread`. In this example, we choose a streamed response and capture any generated _File References_ for download and review at the end of the response cycle. It's important to note that generated code is identified by the presence of a _Metadata_ key in the response message, distinguishing it from the conversational reply. ::: zone pivot="programming-language-csharp" + ```csharp bool isCode = false; await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread)) @@ -558,9 +575,11 @@ Console.WriteLine(); await DownloadResponseImageAsync(fileClient, fileIds); fileIds.Clear(); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python is_code = False last_role = None @@ -592,6 +611,7 @@ print() await download_response_image(agent, file_ids) file_ids.clear() ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -600,7 +620,6 @@ file_ids.clear() ::: zone-end - ## Final Bringing all the steps together, we have the final code for this example. The complete implementation is provided below. @@ -612,6 +631,7 @@ Try using these suggested inputs: 3. Provide a bar chart for countries whose names start with the same letter and sort the x axis by highest count to lowest (include all countries) ::: zone pivot="programming-language-csharp" + ```csharp using Azure.AI.OpenAI; using Azure.Identity; @@ -772,9 +792,11 @@ public static class Program } } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python import asyncio import logging @@ -935,7 +957,7 @@ You may find the full [code](https://github.com/microsoft/semantic-kernel/blob/m ::: zone-end +## Next steps > [!div class="nextstepaction"] > [How-To: `OpenAIAssistantAgent` Code File Search](./example-assistant-search.md) - diff --git a/semantic-kernel/Frameworks/agent/examples/example-assistant-search.md b/semantic-kernel/Frameworks/agent/examples/example-assistant-search.md index 15d8d712..a36b1487 100644 --- a/semantic-kernel/Frameworks/agent/examples/example-assistant-search.md +++ b/semantic-kernel/Frameworks/agent/examples/example-assistant-search.md @@ -15,11 +15,10 @@ ms.service: semantic-kernel ## Overview -In this sample, we will explore how to use the file-search tool of an [`OpenAIAssistantAgent`](../assistant-agent.md) to complete comprehension tasks. The approach will be step-by-step, ensuring clarity and precision throughout the process. As part of the task, the agent will provide document citations within the response. +In this sample, we will explore how to use the file-search tool of an [`OpenAIAssistantAgent`](../agent-types/assistant-agent.md) to complete comprehension tasks. The approach will be step-by-step, ensuring clarity and precision throughout the process. As part of the task, the agent will provide document citations within the response. Streaming will be used to deliver the agent's responses. This will provide real-time updates as the task progresses. - ## Getting Started Before proceeding with feature coding, make sure your development environment is fully set up and configured. @@ -38,6 +37,7 @@ dotnet add package Microsoft.SemanticKernel dotnet add package Microsoft.SemanticKernel.Agents.OpenAI --prerelease ``` +> [!IMPORTANT] > If managing NuGet packages in Visual Studio, ensure `Include prerelease` is checked. The project file (`.csproj`) should contain the following `PackageReference` definitions: @@ -77,6 +77,7 @@ Additionally, copy the `Grimms-The-King-of-the-Golden-Mountain.txt`, `Grimms-The ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -100,7 +101,6 @@ Additionally, copy the `Grimms-The-King-of-the-Golden-Mountain.txt`, `Grimms-The ::: zone-end - ## Configuration This sample requires configuration setting in order to connect to remote services. You will need to define settings for either OpenAI or Azure OpenAI. @@ -162,10 +162,11 @@ public class Settings } } ``` + ::: zone-end ::: zone pivot="programming-language-python" -The quickest way to get started with the proper configuration to run the sample code is to create a `.env` file at the root of your project (where your script is run). +The quickest way to get started with the proper configuration to run the sample code is to create a `.env` file at the root of your project (where your script is run). Configure the following settings in your `.env` file for either Azure OpenAI or OpenAI: @@ -192,7 +193,6 @@ Once configured, the respective AI service classes will pick up the required var ::: zone-end - ## Coding The coding process for this sample involves: @@ -216,8 +216,8 @@ Settings settings = new(); AzureOpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(settings.AzureOpenAI.Endpoint)); ``` -::: zone-end +::: zone-end ::: zone pivot="programming-language-python" The class method `setup_resources()` on the Assistant Agent handles creating the client and returning it and the model to use based on the desired configuration. Pydantic settings are used to load environment variables first from environment variables or from the `.env` file. One may pass in the `api_key`, `api_version`, `deployment_name` or `endpoint`, which will take precedence over any environment variables configured. @@ -226,6 +226,7 @@ The class method `setup_resources()` on the Assistant Agent handles creating the # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -246,9 +247,11 @@ VectorStoreClient storeClient = client.GetVectorStoreClient(); CreateVectorStoreOperation operation = await storeClient.CreateVectorStoreAsync(waitUntilCompleted: true); string storeId = operation.VectorStoreId; ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python def get_filepath_for_filename(filename: str) -> str: base_directory = os.path.join( @@ -267,6 +270,7 @@ for path in [get_filepath_for_filename(filename) for filename in filenames]: # Get the file search tool and resources file_search_tools, file_search_tool_resources = AzureAssistantAgent.configure_file_search_tool(file_ids=file_ids) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -287,9 +291,11 @@ private static readonly string[] _fileNames = "Grimms-The-White-Snake.txt", ]; ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python filenames = [ "Grimms-The-King-of-the-Golden-Mountain.txt", @@ -297,6 +303,7 @@ filenames = [ "Grimms-The-White-Snake.txt", ] ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -321,6 +328,7 @@ foreach (string fileName in _fileNames) fileReferences.Add(fileInfo.Id, fileInfo); } ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -356,9 +364,11 @@ Assistant assistant = // Create agent OpenAIAssistantAgent agent = new(assistant, assistantClient); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python # Create the assistant definition definition = await client.beta.assistants.create( @@ -380,6 +390,7 @@ agent = AzureAssistantAgent( definition=definition, ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -395,6 +406,7 @@ At last, we are able to coordinate the interaction between the user and the `Age Let's also ensure the resources are removed at the end of execution to minimize unnecessary charges. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine("Creating thread..."); OpenAIAssistantAgent agentThread = new(); @@ -422,9 +434,11 @@ finally ]); } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python print("Creating thread...") thread_id = await agent.create_thread() @@ -441,6 +455,7 @@ finally: await agent.delete_thread(thread_id) await agent.delete() ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -452,6 +467,7 @@ finally: Now let's capture user input within the previous loop. In this case, empty input will be ignored and the term `EXIT` will signal that the conversation is completed. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine(); Console.Write("> "); @@ -469,9 +485,11 @@ if (input.Trim().Equals("EXIT", StringComparison.OrdinalIgnoreCase)) var message = new ChatMessageContent(AuthorRole.User, input); Console.WriteLine(); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python user_input = input("User:> ") if not user_input: @@ -481,6 +499,7 @@ if user_input.lower() == "exit": is_complete = True break ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -492,16 +511,20 @@ if user_input.lower() == "exit": Before invoking the `Agent` response, let's add a helper method to reformat the unicode annotation brackets to ANSI brackets. ::: zone pivot="programming-language-csharp" + ```csharp private static string ReplaceUnicodeBrackets(this string content) => content?.Replace('【', '[').Replace('】', ']'); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python # No special handling required. ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -513,6 +536,7 @@ private static string ReplaceUnicodeBrackets(this string content) => To generate an `Agent` response to user input, invoke the agent by specifying the message and agent thread. In this example, we choose a streamed response and capture any associated _Citation Annotations_ for display at the end of the response cycle. Note each streamed chunk is being reformatted using the previous helper method. ::: zone pivot="programming-language-csharp" + ```csharp List footnotes = []; await foreach (StreamingChatMessageContent chunk in agent.InvokeStreamingAsync(message, agentThread)) @@ -536,9 +560,11 @@ if (footnotes.Count > 0) } } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python footnotes: list[StreamingAnnotationContent] = [] async for response in agent.invoke_stream(messages=user_input, thread=thread): @@ -556,6 +582,7 @@ if len(footnotes) > 0: f"(Index: {footnote.start_index} - {footnote.end_index})" ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -564,7 +591,6 @@ if len(footnotes) > 0: ::: zone-end - ## Final Bringing all the steps together, we have the final code for this example. The complete implementation is provided below. @@ -576,6 +602,7 @@ Try using these suggested inputs: 3. What is the moral in The White Snake? ::: zone pivot="programming-language-csharp" + ```csharp using Azure.AI.OpenAI; using Azure.Identity; @@ -720,9 +747,11 @@ public static class Program content?.Replace('【', '[').Replace('】', ']'); } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python import asyncio import os @@ -843,7 +872,7 @@ You may find the full [code](https://github.com/microsoft/semantic-kernel/blob/m ::: zone-end +## Next Steps > [!div class="nextstepaction"] -> [How to Coordinate Agent Collaboration using `AgentGroupChat`](./example-agent-collaboration.md) - +> [Agent Orchestration](./../agent-orchestration/index.md) diff --git a/semantic-kernel/Frameworks/agent/examples/example-chat-agent.md b/semantic-kernel/Frameworks/agent/examples/example-chat-agent.md index 7a5aa553..ef4a7e25 100644 --- a/semantic-kernel/Frameworks/agent/examples/example-chat-agent.md +++ b/semantic-kernel/Frameworks/agent/examples/example-chat-agent.md @@ -15,7 +15,7 @@ ms.service: semantic-kernel ## Overview -In this sample, we will explore configuring a plugin to access GitHub API and provide templatized instructions to a [`ChatCompletionAgent`](../chat-completion-agent.md) to answer questions about a GitHub repository. The approach will be broken down step-by-step to high-light the key parts of the coding process. As part of the task, the agent will provide document citations within the response. +In this sample, we will explore configuring a plugin to access GitHub API and provide templatized instructions to a [`ChatCompletionAgent`](../agent-types/chat-completion-agent.md) to answer questions about a GitHub repository. The approach will be broken down step-by-step to high-light the key parts of the coding process. As part of the task, the agent will provide document citations within the response. Streaming will be used to deliver the agent's responses. This will provide real-time updates as the task progresses. @@ -39,6 +39,7 @@ dotnet add package Microsoft.SemanticKernel.Connectors.AzureOpenAI dotnet add package Microsoft.SemanticKernel.Agents.Core --prerelease ``` +> [!IMPORTANT] > If managing NuGet packages in Visual Studio, ensure `Include prerelease` is checked. The project file (`.csproj`) should contain the following `PackageReference` definitions: @@ -69,6 +70,7 @@ Additionally, copy the GitHub plug-in and models (`GitHubPlugin.cs` and `GitHubM ::: zone pivot="programming-language-python" Start by creating a folder that will hold your script (`.py` file) and the sample resources. Include the following imports at the top of your `.py` file: + ```python import asyncio import os @@ -132,7 +134,8 @@ Additionally, copy the GitHub plug-in and models (`GitHubPlugin.java` and `GitHu This sample requires configuration setting in order to connect to remote services. You will need to define settings for either OpenAI or Azure OpenAI and also for GitHub. -> Note: For information on GitHub Personal Access Tokens, see: [Managing your personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). +> [!NOTE] +> For information on GitHub Personal Access Tokens, see: [Managing your personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). ::: zone pivot="programming-language-csharp" @@ -195,6 +198,7 @@ public class Settings } } ``` + ::: zone-end ::: zone pivot="programming-language-python" @@ -246,7 +250,6 @@ private static final String OPENAI_MODEL_ID = System.getenv().getOrDefault("OPEN ::: zone-end - ## Coding The coding process for this sample involves: @@ -268,6 +271,7 @@ Initialize the `Settings` class referenced in the previous [Configuration](#conf ```csharp Settings settings = new(); ``` + ::: zone-end Initialize the plug-in using its settings. @@ -281,15 +285,18 @@ Console.WriteLine("Initialize plugins..."); GitHubSettings githubSettings = settings.GetSettings(); GitHubPlugin githubPlugin = new(githubSettings); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python gh_settings = GitHubSettings( token="" ) kernel.add_plugin(GitHubPlugin(settings=gh_settings), plugin_name="github") ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -303,6 +310,7 @@ var githubPlugin = new GitHubPlugin(GITHUB_PAT); Now initialize a `Kernel` instance with an `IChatCompletionService` and the `GitHubPlugin` previously created. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine("Creating kernel..."); IKernelBuilder builder = Kernel.CreateBuilder(); @@ -316,9 +324,11 @@ builder.Plugins.AddFromObject(githubPlugin); Kernel kernel = builder.Build(); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python kernel = Kernel() @@ -330,6 +340,7 @@ settings = kernel.get_prompt_execution_settings_from_service_id(service_id=servi # Configure the function choice behavior to auto invoke kernel functions settings.function_choice_behavior = FunctionChoiceBehavior.Auto() ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -358,6 +369,7 @@ Kernel kernel = Kernel.builder() Finally we are ready to instantiate a `ChatCompletionAgent` with its Instructions, associated `Kernel`, and the default Arguments and Execution Settings. In this case, we desire to have the any plugin functions automatically executed. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine("Defining agent..."); ChatCompletionAgent agent = @@ -385,9 +397,11 @@ ChatCompletionAgent agent = Console.WriteLine("Ready!"); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python agent = ChatCompletionAgent( kernel=kernel, @@ -408,6 +422,7 @@ agent = ChatCompletionAgent( ), ) ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -446,7 +461,6 @@ ChatCompletionAgent agent = ChatCompletionAgent.builder() .build(); ``` - ::: zone-end ### The Chat Loop @@ -454,6 +468,7 @@ ChatCompletionAgent agent = ChatCompletionAgent.builder() At last, we are able to coordinate the interaction between the user and the `Agent`. Start by creating a `ChatHistoryAgentThread` object to maintain the conversation state and creating an empty loop. ::: zone pivot="programming-language-csharp" + ```csharp ChatHistoryAgentThread agentThread = new(); bool isComplete = false; @@ -462,15 +477,18 @@ do // processing logic here } while (!isComplete); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python thread: ChatHistoryAgentThread = None is_complete: bool = False while not is_complete: # processing logic here ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -484,12 +502,12 @@ while (!isComplete) { } ``` - ::: zone-end Now let's capture user input within the previous loop. In this case, empty input will be ignored and the term `EXIT` will signal that the conversation is completed. ::: zone pivot="programming-language-csharp" + ```csharp Console.WriteLine(); Console.Write("> "); @@ -508,9 +526,11 @@ var message = new ChatMessageContent(AuthorRole.User, input); Console.WriteLine(); ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python user_input = input("User:> ") if not user_input: @@ -520,6 +540,7 @@ if user_input.lower() == "exit": is_complete = True break ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -550,6 +571,7 @@ To generate a `Agent` response to user input, invoke the agent using _Arguments_ The `Agent` response is then then displayed to the user. ::: zone pivot="programming-language-csharp" + ```csharp DateTime now = DateTime.Now; KernelArguments arguments = @@ -562,9 +584,11 @@ await foreach (ChatMessageContent response in agent.InvokeAsync(message, agentTh Console.WriteLine($"{response.Content}"); } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python arguments = KernelArguments( now=datetime.now().strftime("%Y-%m-%d %H:%M") @@ -574,6 +598,7 @@ async for response in agent.invoke(messages=user_input, thread=thread, arguments print(f"{response.content}") thread = response.thread ``` + ::: zone-end ::: zone pivot="programming-language-java" @@ -591,7 +616,6 @@ for (var response : agent.invokeAsync(message, agentThread, options).block()) { } ``` - ::: zone-end ## Final @@ -608,6 +632,7 @@ Try using these suggested inputs: 6. List the 5 most recently opened issues with the "Agents" label ::: zone pivot="programming-language-csharp" + ```csharp using System; using System.Threading.Tasks; @@ -706,9 +731,11 @@ public static class Program } } ``` + ::: zone-end ::: zone pivot="programming-language-python" + ```python import asyncio import os @@ -919,9 +946,7 @@ public class CompletionAgent { ::: zone-end - +## Next Steps > [!div class="nextstepaction"] > [How-To: `OpenAIAssistantAgent` Code Interpreter](./example-assistant-code.md) - - diff --git a/semantic-kernel/Frameworks/agent/index.md b/semantic-kernel/Frameworks/agent/index.md index 8ed0b9b9..9ce7af1a 100644 --- a/semantic-kernel/Frameworks/agent/index.md +++ b/semantic-kernel/Frameworks/agent/index.md @@ -8,10 +8,8 @@ ms.author: crickman ms.date: 09/13/2024 ms.service: semantic-kernel --- -# Semantic Kernel Agent Framework -> [!IMPORTANT] -> `AgentChat` patterns are in the experimental stage. These patterns are under active development and may change significantly before advancing to the preview or release candidate stage. +# Semantic Kernel Agent Framework The Semantic Kernel Agent Framework provides a platform within the Semantic Kernel eco-system that allow for the creation of AI **agents** and the ability to incorporate **agentic patterns** into any application based on the same patterns and features that exist in the core Semantic Kernel framework. @@ -24,14 +22,13 @@ The Semantic Kernel Agent Framework provides a platform within the Semantic Kern An **AI agent** is a software entity designed to perform tasks autonomously or semi-autonomously by receiving input, processing information, and taking actions to achieve specific goals. -Agents can send and receive messages, generating responses using a combination of models, tools, human inputs, or other customizable components. +Agents can send and receive messages, generating responses using a combination of models, tools, human inputs, or other customizable components. Agents are designed to work collaboratively, enabling complex workflows by interacting with each other. The `Agent Framework` allows for the creation of both simple and sophisticated agents, enhancing modularity and ease of maintenance - ## What problems do AI agents solve? -AI agents offers several advantages for application development, particularly by enabling the creation of modular AI components that are able to collaborate to reduce manual intervention in complex tasks. AI agents can operate autonomously or semi-autonomously, making them powerful tools for a range of applications. +AI agents offers several advantages for application development, particularly by enabling the creation of modular AI components that are able to collaborate to reduce manual intervention in complex tasks. AI agents can operate autonomously or semi-autonomously, making them powerful tools for a range of applications. Here are some of the key benefits: @@ -43,7 +40,6 @@ Here are some of the key benefits: - **Process Orchestration**: Agents can coordinate different tasks across systems, tools, and APIs, helping to automate end-to-end processes like application deployments, cloud orchestration, or even creative processes like writing and design. - ## When to use an AI agent? Using an agent framework for application development provides advantages that are especially beneficial for certain types of applications. While traditional AI models are often used as tools to perform specific tasks (e.g., classification, prediction, or recognition), agents introduce more autonomy, flexibility, and interactivity into the development process. @@ -54,7 +50,6 @@ Using an agent framework for application development provides advantages that ar - **Interactive and Goal-Oriented**: If your application involves goal-driven behavior (e.g., completing tasks autonomously or interacting with users to achieve specific objectives), agent-based frameworks are a better choice. Examples include virtual assistants, game AI, and task planners. - ## How do I install the Semantic Kernel Agent Framework? Installing the Agent Framework SDK is specific to the distribution channel associated with your programming language. @@ -63,15 +58,16 @@ Installing the Agent Framework SDK is specific to the distribution channel assoc For .NET SDK, several NuGet packages are available. -> Note: The core Semantic Kernel SDK is required in addition to any agent packages. - +> [!NOTE] +> The core Semantic Kernel SDK is required in addition to any agent packages. Package|Description --|-- [Microsoft.SemanticKernel](https://www.nuget.org/packages/Microsoft.SemanticKernel)|This contains the core Semantic Kernel libraries for getting started with the `Agent Framework`. This must be explicitly referenced by your application. [Microsoft.SemanticKernel.Agents.Abstractions](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.Abstractions)|Defines the core agent abstractions for the `Agent Framework`. Generally not required to be specified as it is included in both the `Microsoft.SemanticKernel.Agents.Core` and `Microsoft.SemanticKernel.Agents.OpenAI` packages. -[Microsoft.SemanticKernel.Agents.Core](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.Core)|Includes the [`ChatCompletionAgent`](./chat-completion-agent.md) and [`AgentGroupChat`](./agent-chat.md) classes. -[Microsoft.SemanticKernel.Agents.OpenAI](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.OpenAI)|Provides ability to use the [OpenAI Assistant API](https://platform.openai.com/docs/assistants) via the [`OpenAIAssistantAgent`](./assistant-agent.md). +[Microsoft.SemanticKernel.Agents.Core](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.Core)|Includes the [`ChatCompletionAgent`](./agent-types/chat-completion-agent.md). +[Microsoft.SemanticKernel.Agents.OpenAI](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.OpenAI)|Provides ability to use the [OpenAI Assistant API](https://platform.openai.com/docs/assistants) via the [`OpenAIAssistantAgent`](./agent-types/assistant-agent.md). +[Microsoft.SemanticKernel.Agents.Orchestration](https://www.nuget.org/packages/Microsoft.SemanticKernel.Agents.Orchestration)|Provides the [orchestration framework](./agent-orchestration/index.md) for the `Agent Framework`. ::: zone-end @@ -79,7 +75,7 @@ Package|Description Module|Description --|-- -[semantic-kernel.agents](https://pypi.org/project/semantic-kernel/)|This is the Semantic Kernel library for getting started with the `Agent Framework`. This must be explicitly referenced by your application. This module contains the [`ChatCompletionAgent`](./chat-completion-agent.md), the [`OpenAIAssistantAgent`](./assistant-agent.md), the [`AzureAIAgent`](./azure-ai-agent.md), and the [`OpenAIResponsesAgent`](./responses-agent.md), as well as [`AgentGroupChat`](./agent-chat.md) class. +[semantic-kernel.agents](https://pypi.org/project/semantic-kernel/)|This is the Semantic Kernel library for getting started with the `Agent Framework`. This must be explicitly referenced by your application. This module contains the [`ChatCompletionAgent`](./agent-types/chat-completion-agent.md), the [`OpenAIAssistantAgent`](./agent-types/assistant-agent.md), the [`AzureAIAgent`](./agent-types/azure-ai-agent.md), and the [`OpenAIResponsesAgent`](./agent-types/responses-agent.md), as well as the [`agent orchestration`](./agent-orchestration/index.md) classes. ::: zone-end @@ -87,12 +83,13 @@ Module|Description Package|Description --|-- - -[semantickernel-agents-core](https://central.sonatype.com/artifact/com.microsoft.semantic-kernel/semantickernel-agents-core)| Includes the [`ChatCompletionAgent`](./chat-completion-agent.md) class. +[semantickernel-agents-core](https://central.sonatype.com/artifact/com.microsoft.semantic-kernel/semantickernel-agents-core)| Includes the [`ChatCompletionAgent`](./agent-types/chat-completion-agent.md) class. [semantickernel-aiservices-openai](https://central.sonatype.com/artifact/com.microsoft.semantic-kernel/semantickernel-aiservices-openai)| This contains Semantic Kernel service library for getting started with the `Agent Framework` using OpenAI. -[semantickernel-api](https://central.sonatype.com/artifact/com.microsoft.semantic-kernel/semantickernel-api)||Defines the core agent abstractions for the `Agent Framework`. Generally not required to be specified as it is included in both above. +[semantickernel-api](https://central.sonatype.com/artifact/com.microsoft.semantic-kernel/semantickernel-api)|Defines the core agent abstractions for the `Agent Framework`. Generally not required to be specified as it is included in both above. ::: zone-end +## Next Steps + > [!div class="nextstepaction"] > [Agent Architecture](./agent-architecture.md) diff --git a/semantic-kernel/concepts/enterprise-readiness/observability/index.md b/semantic-kernel/concepts/enterprise-readiness/observability/index.md index c88edbe5..3363d039 100644 --- a/semantic-kernel/concepts/enterprise-readiness/observability/index.md +++ b/semantic-kernel/concepts/enterprise-readiness/observability/index.md @@ -1,7 +1,7 @@ --- title: Observability in Semantic Kernel description: Introduction to observability in Semantic Kernel -author: taochen +author: TaoChenOSU zone_pivot_groups: programming-languages ms.topic: conceptual ms.author: taochen @@ -31,31 +31,30 @@ Semantic Kernel is designed to be observable. It emits logs, metrics, and traces Specifically, Semantic Kernel provides the following observability features: - **Logging**: Semantic Kernel logs meaningful events and errors from the kernel, kernel plugins and functions, as well as the AI connectors. - ![Logs and events](../../../media/telemetry-log-events-overview-app-insights.png) - > [!IMPORTANT] - > [Traces in Application Insights](/azure/azure-monitor/app/data-model-complete#trace) represent traditional log entries and [OpenTelemetry span events](https://opentelemetry.io/docs/concepts/signals/traces/#span-events). They are not the same as distributed traces. + ![Logs and events](../../../media/telemetry-log-events-overview-app-insights.png) + > [!IMPORTANT] + > [Traces in Application Insights](/azure/azure-monitor/app/data-model-complete#trace) represent traditional log entries and [OpenTelemetry span events](https://opentelemetry.io/docs/concepts/signals/traces/#span-events). They are not the same as distributed traces. - **Metrics**: Semantic Kernel emits metrics from kernel functions and AI connectors. You will be able to monitor metrics such as the kernel function execution time, the token consumption of AI connectors, etc. - ![Metrics](../../../media/telemetry-metrics-overview-app-insights.png) + ![Metrics](../../../media/telemetry-metrics-overview-app-insights.png) - **Tracing**: Semantic Kernel supports distributed tracing. You can track activities across different services and within Semantic Kernel. - ![Complete end-to-end transaction of a request](../../../media/telemetry-trace-overview-app-insights.png) - + ![Complete end-to-end transaction of a request](../../../media/telemetry-trace-overview-app-insights.png) ::: zone pivot="programming-language-csharp" -| Telemetry | Description | -|-----------|---------------------------------------| -| Log | Logs are recorded throughout the Kernel. For more information on Logging in .Net, please refer to this [document](/dotnet/core/extensions/logging). Sensitive data, such as kernel function arguments and results, are logged at the trace level. Please refer to this [table](/dotnet/core/extensions/logging?tabs=command-line#log-level) for more information on log levels. | -| Activity | Each kernel function execution and each call to an AI model are recorded as an activity. All activities are generated by an activity source named "Microsoft.SemanticKernel". | -| Metric | Semantic Kernel captures the following metrics from kernel functions:
  • `semantic_kernel.function.invocation.duration` (Histogram) - function execution time (in seconds)
  • `semantic_kernel.function.streaming.duration` (Histogram) - function streaming execution time (in seconds)
  • `semantic_kernel.function.invocation.token_usage.prompt` (Histogram) - number of prompt token usage (only for `KernelFunctionFromPrompt`)
  • `semantic_kernel.function.invocation.token_usage.completion` (Histogram) - number of completion token usage (only for `KernelFunctionFromPrompt`)
  • | +| Telemetry | Description | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Log | Logs are recorded throughout the Kernel. For more information on Logging in .Net, please refer to this [document](/dotnet/core/extensions/logging). Sensitive data, such as kernel function arguments and results, are logged at the trace level. Please refer to this [table](/dotnet/core/extensions/logging?tabs=command-line#log-level) for more information on log levels. | +| Activity | Each kernel function execution and each call to an AI model are recorded as an activity. All activities are generated by an activity source named "Microsoft.SemanticKernel". | +| Metric | Semantic Kernel captures the following metrics from kernel functions:
    • `semantic_kernel.function.invocation.duration` (Histogram) - function execution time (in seconds)
    • `semantic_kernel.function.streaming.duration` (Histogram) - function streaming execution time (in seconds)
    • `semantic_kernel.function.invocation.token_usage.prompt` (Histogram) - number of prompt token usage (only for `KernelFunctionFromPrompt`)
    • `semantic_kernel.function.invocation.token_usage.completion` (Histogram) - number of completion token usage (only for `KernelFunctionFromPrompt`)
    • | ::: zone-end ::: zone pivot="programming-language-python" -| Telemetry | Description | -|-----------|---------------------------------------| -| Log | Logs are recorded throughout the Kernel. For more information on Logging in Python, please refer to this [document](https://docs.python.org/3/howto/logging.html). Sensitive data, such as kernel function arguments and results, are logged at the debug level.| -| Span | Each auto function invocation loop, each kernel function execution, and each call to an AI model are recorded as a span. | +| Telemetry | Description | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Log | Logs are recorded throughout the Kernel. For more information on Logging in Python, please refer to this [document](https://docs.python.org/3/howto/logging.html). Sensitive data, such as kernel function arguments and results, are logged at the debug level. | +| Span | Each auto function invocation loop, each kernel function execution, and each call to an AI model are recorded as a span. | | Metric | Semantic Kernel captures the following metrics from kernel functions:
      • `semantic_kernel.function.invocation.duration` (Histogram) - function execution time (in seconds)
      • `semantic_kernel.function.streaming.duration` (Histogram) - function streaming execution time (in seconds)
      • | ::: zone-end @@ -67,7 +66,6 @@ Specifically, Semantic Kernel provides the following observability features: ::: zone-end - ## OpenTelemetry Semantic Convention Semantic Kernel follows the [OpenTelemetry Semantic Convention](https://opentelemetry.io/docs/concepts/semantic-conventions/) for Observability. This means that the logs, metrics, and traces emitted by Semantic Kernel are structured and follow a common schema. This ensures that you can more effectively analyze the telemetry data emitted by Semantic Kernel. @@ -81,9 +79,3 @@ Now that you have a basic understanding of observability in Semantic Kernel, you > [!div class="nextstepaction"] > [Console](telemetry-with-console.md) - -> [!div class="nextstepaction"] -> [Application Insights](telemetry-with-app-insights.md) - -> [!div class="nextstepaction"] -> [Aspire Dashboard](telemetry-with-aspire-dashboard.md) diff --git a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-advanced.md b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-advanced.md index 2efebe69..14a73d21 100644 --- a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-advanced.md +++ b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-advanced.md @@ -2,7 +2,7 @@ title: More advanced scenarios for telemetry description: More advanced scenarios for telemetry zone_pivot_groups: programming-languages -author: taochen +author: TaoChenOSU ms.topic: conceptual ms.author: taochen ms.date: 09/12/2024 @@ -555,7 +555,6 @@ Run the application again and observe the trace in the dashboard. You should see ::: zone-end - ::: zone pivot="programming-language-python" Modify the `book_room` function in the Python code to simulate an error: @@ -581,7 +580,6 @@ Run the application again and observe the trace in the dashboard. You should see ::: zone-end - ::: zone pivot="programming-language-java" > [!NOTE] @@ -594,9 +592,3 @@ Run the application again and observe the trace in the dashboard. You should see In production, your services may get a large number of requests. Semantic Kernel will generate a large amount of telemetry data. some of which may not be useful for your use case and will introduce unnecessary costs to store the data. You can use the [sampling](https://opentelemetry.io/docs/concepts/sampling/) feature to reduce the amount of telemetry data that is collected. Observability in Semantic Kernel is constantly improving. You can find the latest updates and new features in the [GitHub repository](https://github.com/microsoft/semantic-kernel). - - - - - - diff --git a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-app-insights.md b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-app-insights.md index 440c9aa9..a8e3cbe1 100644 --- a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-app-insights.md +++ b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-app-insights.md @@ -2,7 +2,7 @@ title: Inspection of telemetry data with Application Insights description: Send telemetry data to Application Insights zone_pivot_groups: programming-languages -author: taochen +author: TaoChenOSU ms.topic: conceptual ms.author: taochen ms.date: 09/12/2024 @@ -68,18 +68,18 @@ dotnet new console -n TelemetryApplicationInsightsQuickstart Navigate to the newly created project directory after the command completes. - ### Install required packages - Semantic Kernel - ```console - dotnet add package Microsoft.SemanticKernel - ``` + + ```console + dotnet add package Microsoft.SemanticKernel + ``` - OpenTelemetry Console Exporter - ```console - dotnet add package Azure.Monitor.OpenTelemetry.Exporter - ``` + ```console + dotnet add package Azure.Monitor.OpenTelemetry.Exporter + ``` ### Create a simple application with Semantic Kernel @@ -182,6 +182,7 @@ python -m venv telemetry-application-insights-quickstart ``` Activate the virtual environment. + ```console telemetry-application-insights-quickstart\Scripts\activate ``` @@ -265,6 +266,7 @@ if __name__ == "__main__": Please refer to this [article](./telemetry-with-console.md#environment-variables) for more information on setting up the required environment variables to enable the kernel to emit spans for AI connectors. #### Code + If you run the script now, you should expect to see a sentence explaining why the sky is blue. To observe the kernel via telemetry, replace the `# Telemetry setup code goes here` comment with the following code: ```python @@ -340,7 +342,7 @@ Please refer to this [article](./telemetry-with-console.md#add-telemetry-1) for > [!NOTE] > Semantic Kernel Observability is not yet available for Java. - + ::: zone-end ## Run @@ -433,7 +435,6 @@ dependencies | summarize total_completion_tokens = sum(completion_token), total_prompt_tokens = sum(prompt_token) ``` - ```kusto // Retrieves all the prompts and completions and their corresponding token usage. dependencies diff --git a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-aspire-dashboard.md b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-aspire-dashboard.md index 6bd39dfe..17273636 100644 --- a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-aspire-dashboard.md +++ b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-aspire-dashboard.md @@ -2,7 +2,7 @@ title: Inspection of telemetry data with Aspire Dashboard description: Send telemetry data to Aspire Dashboard zone_pivot_groups: programming-languages -author: taochen +author: TaoChenOSU ms.topic: conceptual ms.author: taochen ms.date: 09/12/2024 @@ -58,18 +58,18 @@ dotnet new console -n TelemetryAspireDashboardQuickstart Navigate to the newly created project directory after the command completes. - ### Install required packages - Semantic Kernel - ```console - dotnet add package Microsoft.SemanticKernel - ``` + + ```console + dotnet add package Microsoft.SemanticKernel + ``` - OpenTelemetry Console Exporter - ```console - dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol - ``` + ```console + dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol + ``` ### Create a simple application with Semantic Kernel @@ -170,6 +170,7 @@ python -m venv telemetry-aspire-dashboard-quickstart ``` Activate the virtual environment. + ```console telemetry-aspire-dashboard-quickstart\Scripts\activate ``` @@ -250,6 +251,7 @@ if __name__ == "__main__": Please refer to this [article](./telemetry-with-console.md#environment-variables) for more information on setting up the required environment variables to enable the kernel to emit spans for AI connectors. #### Code + If you run the script now, you should expect to see a sentence explaining why the sky is blue. To observe the kernel via telemetry, replace the `# Telemetry setup code goes here` comment with the following code: ```python @@ -325,7 +327,7 @@ Please refer to this [article](./telemetry-with-console.md#add-telemetry-1) for > [!NOTE] > Semantic Kernel Observability is not yet available for Java. - + ::: zone-end ## Start the Aspire Dashboard diff --git a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-azure-ai-foundry-tracing.md b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-azure-ai-foundry-tracing.md index 00ab843c..3e7ce9cf 100644 --- a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-azure-ai-foundry-tracing.md +++ b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-azure-ai-foundry-tracing.md @@ -1,7 +1,7 @@ --- title: Visualize traces on Azure AI Foundry Tracing UI description: Learn how to visualize traces on Azure AI Foundry Tracing UI -author: taochen +author: TaoChenOSU ms.topic: conceptual ms.author: taochen ms.date: 09/12/2024 @@ -15,14 +15,10 @@ ms.service: semantic-kernel > [!IMPORTANT] > Before you start, make sure you have completed the tutorial on [inspecting telemetry data with Application Insights](./telemetry-with-app-insights.md). -> [!IMPORTANT] -> This feature is currently only available on Semantic Kernel Python. Support for other languages is coming soon. - Prerequisites: - An Azure AI Foundry project. Follow this [guide](/azure/ai-studio/how-to/create-projects) to create one if you don't have one. -- A serverless inference API. Follow this [guide](/azure/ai-studio/how-to/deploy-models-serverless) to create one if you don't have one. -- Alternatively, you can attach an Azure OpenAI resource to the project, in which case you don't need to create a serverless API. +- A [chat completion service](../../ai-services/chat-completion/index.md). ## Attach an Application Insights resource to the project @@ -30,31 +26,11 @@ Go to the Azure AI Foundry project, select the **Tracing** tab on the left blade ![Attach an Application Insights resource to the project](../../../media/azure-ai-foundry-attach-app-insights.png) -## Use the Azure AI Inference connector - -We are going to replace the chat completion service with the Azure AI Inference connector. This connector will automatically send traces that can be visualized on the Azure AI Foundry Tracing UI. - -```python -from semantic_kernel.connectors.ai.azure_ai_inference import AzureAIInferenceChatCompletion - -# Create an Azure AI Inference chat completion service with environment variables -kernel.add_service(AzureAIInferenceChatCompletion(ai_model_id="my-deployment", service_id="my-service-id")) - -# If you are using an Azure OpenAI endpoint, you can do the following instead. -from azure.ai.inference.aio import ChatCompletionsClient -from azure.identity.aio import DefaultAzureCredential +## Use an AI service of your choice -kernel.add_service(AzureAIInferenceChatCompletion( - ai_model_id="my-deployment", - client=ChatCompletionsClient( - endpoint=f"{str(endpoint).strip('/')}/openai/deployments/{deployment_name}", - credential=DefaultAzureCredential(), - credential_scopes=["https://cognitiveservices.azure.com/.default"], - ), -)) -``` +All Semantic Kernel [AI connectors](../../ai-services/chat-completion/index.md) emit GenAI telemetry data that can be visualized in the Azure AI Foundry Tracing UI. -Run the script again. +Simply rerun the code from the [inspecting telemetry data with Application Insights](./telemetry-with-app-insights.md) tutorial. ## Visualize traces on Azure AI Foundry Tracing UI diff --git a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-console.md b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-console.md index f066c170..5922c43a 100644 --- a/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-console.md +++ b/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-console.md @@ -2,7 +2,7 @@ title: Inspection of telemetry data with the console description: Output telemetry data to the console for inspection zone_pivot_groups: programming-languages -author: taochen +author: TaoChenOSU ms.topic: conceptual ms.author: taochen ms.date: 09/12/2024 @@ -54,18 +54,18 @@ dotnet new console -n TelemetryConsoleQuickstart Navigate to the newly created project directory after the command completes. - ### Install required packages - Semantic Kernel - ```console - dotnet add package Microsoft.SemanticKernel - ``` + + ```console + dotnet add package Microsoft.SemanticKernel + ``` - OpenTelemetry Console Exporter - ```console - dotnet add package OpenTelemetry.Exporter.Console - ``` + ```console + dotnet add package OpenTelemetry.Exporter.Console + ``` ### Create a simple application with Semantic Kernel @@ -172,6 +172,7 @@ python -m venv telemetry-console-quickstart ``` Activate the virtual environment. + ```console telemetry-console-quickstart\Scripts\activate ``` @@ -280,6 +281,7 @@ export SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true --- #### Code + If you run the script now, you should expect to see a sentence explaining why the sky is blue. To observe the kernel via telemetry, replace the `# Telemetry setup code goes here` comment with the following code: ```python @@ -354,7 +356,7 @@ Finally, we call the three functions to set up logging, tracing, and metrics. Th > [!NOTE] > Semantic Kernel Observability is not yet available for Java. - + ::: zone-end ## Run @@ -417,8 +419,9 @@ telemetry.sdk.version: 1.9.0 ``` There are two parts to each log record: + - The log record itself: contains the timestamp and namespace at which the log record was generated, the severity and body of the log record, and any attributes associated with the log record. -- The resource associated with the log record: contains information about the service, instance, and SDK used to generate the log record. +- The resource associated with the log record: contains information about the service, instance, and SDK used to generate the log record. ### Activities @@ -459,6 +462,7 @@ Resource associated with Activity: ``` There are two parts to each activity: + - The activity itself: contains the span ID and parent span ID that APM tools use to build the traces, the duration of the activity, and any tags and events associated with the activity. - The resource associated with the activity: contains information about the service, instance, and SDK used to generate the activity. @@ -684,6 +688,3 @@ Now that you have successfully output telemetry data to the console, you can lea > [!div class="nextstepaction"] > [Application Insights](telemetry-with-app-insights.md) - -> [!div class="nextstepaction"] -> [Aspire Dashboard](telemetry-with-aspire-dashboard.md) \ No newline at end of file diff --git a/semantic-kernel/media/multi-agent-concurrent.png b/semantic-kernel/media/multi-agent-concurrent.png new file mode 100644 index 00000000..abb3e495 Binary files /dev/null and b/semantic-kernel/media/multi-agent-concurrent.png differ diff --git a/semantic-kernel/media/multi-agent-group-chat.png b/semantic-kernel/media/multi-agent-group-chat.png new file mode 100644 index 00000000..1398aa22 Binary files /dev/null and b/semantic-kernel/media/multi-agent-group-chat.png differ diff --git a/semantic-kernel/media/multi-agent-handoff.png b/semantic-kernel/media/multi-agent-handoff.png new file mode 100644 index 00000000..894d0f56 Binary files /dev/null and b/semantic-kernel/media/multi-agent-handoff.png differ diff --git a/semantic-kernel/media/multi-agent-magentic.png b/semantic-kernel/media/multi-agent-magentic.png new file mode 100644 index 00000000..5001b7c3 Binary files /dev/null and b/semantic-kernel/media/multi-agent-magentic.png differ diff --git a/semantic-kernel/media/multi-agent-sequential.png b/semantic-kernel/media/multi-agent-sequential.png new file mode 100644 index 00000000..b2c940d2 Binary files /dev/null and b/semantic-kernel/media/multi-agent-sequential.png differ diff --git a/semantic-kernel/support/archive/TOC.yml b/semantic-kernel/support/archive/TOC.yml new file mode 100644 index 00000000..6fd3d06f --- /dev/null +++ b/semantic-kernel/support/archive/TOC.yml @@ -0,0 +1,6 @@ +- name: Overview + href: index.md +- name: AgentGroupChat + href: agent-chat.md +- name: AgentGroupChat Example + href: agent-chat-example.md \ No newline at end of file diff --git a/semantic-kernel/Frameworks/agent/examples/example-agent-collaboration.md b/semantic-kernel/support/archive/agent-chat-example.md similarity index 99% rename from semantic-kernel/Frameworks/agent/examples/example-agent-collaboration.md rename to semantic-kernel/support/archive/agent-chat-example.md index f4050d66..dbf36f91 100644 --- a/semantic-kernel/Frameworks/agent/examples/example-agent-collaboration.md +++ b/semantic-kernel/support/archive/agent-chat-example.md @@ -328,7 +328,7 @@ COPYWRITER_NAME = "Writer" ::: zone-end -Defining the _Reviewer_ agent uses the pattern explored in [How-To: Chat Completion Agent](./example-chat-agent.md). +Defining the _Reviewer_ agent uses the pattern explored in [How-To: Chat Completion Agent](./../../Frameworks/agent/examples/example-chat-agent.md). Here the _Reviewer_ is given the role of responding to user input, providing direction to the _Writer_ agent, and verifying result of the _Writer_ agent. diff --git a/semantic-kernel/Frameworks/agent/agent-chat.md b/semantic-kernel/support/archive/agent-chat.md similarity index 95% rename from semantic-kernel/Frameworks/agent/agent-chat.md rename to semantic-kernel/support/archive/agent-chat.md index f492f578..f3923a1e 100644 --- a/semantic-kernel/Frameworks/agent/agent-chat.md +++ b/semantic-kernel/support/archive/agent-chat.md @@ -38,7 +38,7 @@ Detailed API documentation related to this discussion is available at: ## What is `AgentChat`? -`AgentChat` provides a framework that enables interaction between multiple agents, even if they are of different types. This makes it possible for a [`ChatCompletionAgent`](./chat-completion-agent.md) and an [`OpenAIAssistantAgent`](./assistant-agent.md) to work together within the same conversation. `AgentChat` also defines entry points for initiating collaboration between agents, whether through multiple responses or a single agent response. +`AgentChat` provides a framework that enables interaction between multiple agents, even if they are of different types. This makes it possible for a [`ChatCompletionAgent`](./../../Frameworks/agent/agent-types/chat-completion-agent.md) and an [`OpenAIAssistantAgent`](./../../Frameworks/agent/agent-types/assistant-agent.md) to work together within the same conversation. `AgentChat` also defines entry points for initiating collaboration between agents, whether through multiple responses or a single agent response. As an abstract class, `AgentChat` can be subclassed to support custom scenarios. @@ -280,7 +280,7 @@ history = await chat.get_chat_messages() ::: zone-end -Since different agent types or configurations may maintain their own version of the conversation history, agent specific history is also available by specifying an agent. (For example: [`OpenAIAssistant`](./assistant-agent.md) versus [`ChatCompletionAgent`](./chat-completion-agent.md).) +Since different agent types or configurations may maintain their own version of the conversation history, agent specific history is also available by specifying an agent. (For example: [`OpenAIAssistant`](./../../Frameworks/agent/agent-types/assistant-agent.md) versus [`ChatCompletionAgent`](./../../Frameworks/agent/agent-types/chat-completion-agent.md).) ::: zone pivot="programming-language-csharp" ```csharp @@ -643,7 +643,7 @@ if chat.is_complete: ### Clear Full Conversation State -When done using an `AgentChat` where an [`OpenAIAssistant`](./assistant-agent.md) participated, it may be necessary to delete the remote thread associated with the assistant. `AgentChat` supports resetting or clearing the entire conversation state, which includes deleting any remote thread definition. This ensures that no residual conversation data remains linked to the assistant once the chat concludes. +When done using an `AgentChat` where an [`OpenAIAssistant`](./../../Frameworks/agent/agent-types/assistant-agent.md) participated, it may be necessary to delete the remote thread associated with the assistant. `AgentChat` supports resetting or clearing the entire conversation state, which includes deleting any remote thread definition. This ensures that no residual conversation data remains linked to the assistant once the chat concludes. A full reset does not remove the agents that had joined the `AgentChat` and leaves the `AgentChat` in a state where it can be reused. This allows for the continuation of interactions with the same agents without needing to reinitialize them, making future conversations more efficient. @@ -678,8 +678,4 @@ await chat.reset() For an end-to-end example for using `AgentGroupChat` for `Agent` collaboration, see: -- [How to Coordinate Agent Collaboration using `AgentGroupChat`](./examples/example-agent-collaboration.md) - - -> [!div class="nextstepaction"] -> [Create an Agent from a Template](./agent-templates.md) +- [How to Coordinate Agent Collaboration using `AgentGroupChat`](./agent-chat-example.md) diff --git a/semantic-kernel/support/archive/index.md b/semantic-kernel/support/archive/index.md new file mode 100644 index 00000000..af1e1109 --- /dev/null +++ b/semantic-kernel/support/archive/index.md @@ -0,0 +1,19 @@ +--- +title: Semantic Kernel Documentation Archive +description: Archive of Semantic Kernel documentation. +author: TaoChenOSU +ms.topic: conceptual +ms.author: taochen +ms.date: 05/19/2025 +ms.service: semantic-kernel +--- + +# Semantic Kernel Documentation Archive + +This is an archive of Semantic Kernel documentation. The content may be outdated or no longer relevant. + +## Content + +| Title | Description | +| --- | --- | +| [AgentGroupChat](./agent-chat.md) | AgentGroupChat is no longer maintained. We recommend developers to use the new [GroupChatOrchestration](../../Frameworks/agent/agent-orchestration/group-chat.md). a migration guide is provided [here](../migration/group-chat-orchestration-migration-guide.md).| diff --git a/semantic-kernel/support/migration/azureagent-foundry-ga-migration-guide.md b/semantic-kernel/support/migration/azureagent-foundry-ga-migration-guide.md index d3620c94..64808d0f 100644 --- a/semantic-kernel/support/migration/azureagent-foundry-ga-migration-guide.md +++ b/semantic-kernel/support/migration/azureagent-foundry-ga-migration-guide.md @@ -13,19 +13,21 @@ ms.service: semantic-kernel ::: zone pivot="programming-language-csharp" -In Semantic Kernel .NET 1.53.0+, .NET and Python developers using `AzureAIAgent` must to update the patterns they use to interact with the Azure AI Foundry in response to its move to GA. +In Semantic Kernel .NET 1.53.1+, .NET and Python developers using `AzureAIAgent` must to update the patterns they use to interact with the Azure AI Foundry in response to its move to GA. ### GA Foundry Project -- Connect programatically using the _Foundry Project's_ endpoint url. -- Requires Semantic Kernel version 1.53.0 and above. - Must be created on or after May 19th, 2025 +- Connect programatically using the _Foundry Project's_ endpoint url. +- Requires Semantic Kernel version 1.53.1 and above. +- Based on package [Azure.AI.Agents.Persistent](https://www.nuget.org/packages/Azure.AI.Agents.Persistent/1.0.0) ### Pre-GA Foundry Project +- Was created prior to May 19th, 2025 - Connect programatically using the _Foundry Project's_ connection string. -- Continue to use Semantic Kernel versions prior to version 1.53.0 -- Created prior to May 19th, 2025 +- Continue to use Semantic Kernel versions below version 1.53.* +- Based on package [Azure.AI.Projects version 1.0.0-beta.8](https://www.nuget.org/packages/Azure.AI.Projects/1.0.0-beta.8) ## Creating an Client diff --git a/semantic-kernel/support/migration/group-chat-orchestration-migration-guide.md b/semantic-kernel/support/migration/group-chat-orchestration-migration-guide.md new file mode 100644 index 00000000..6479f64d --- /dev/null +++ b/semantic-kernel/support/migration/group-chat-orchestration-migration-guide.md @@ -0,0 +1,328 @@ +--- +title: Group Chat Orchestration Migration Guide +description: Describes the steps for developers to update their AgentGroupChat to the new GroupChatOrchestration. +zone_pivot_groups: programming-languages +author: taochen +ms.topic: tutorial +ms.author: taochen +ms.date: 05/21/2025 +ms.service: semantic-kernel +--- + +# `AgentGroupChat` Orchestration Migration Guide + +This is a migration guide for developers who have been using the [`AgentGroupChat`](../archive/agent-chat.md) in Semantic Kernel and want to transition to the new [`GroupChatOrchestration`](../../Frameworks/agent/agent-orchestration/group-chat.md). The new class provides a more flexible and powerful way to manage group chat interactions among agents. + +::: zone pivot="programming-language-csharp" + +## Migrating from `AgentGroupChat` to `GroupChatOrchestration` + +The new `GroupChatOrchestration` class replaces the `AgentGroupChat` with a unified, extensible orchestration model. Here’s how to migrate your C# code: + +### Step 1: Replace Usings and Class References + +- Remove any `using` statements or references to `AgentChat` and `AgentGroupChat`. For example, remove: + + ```csharp + using Microsoft.SemanticKernel.Agents.Chat; + ``` + +- Add a reference to the new orchestration namespace: + + ```csharp + using Microsoft.SemanticKernel.Agents.Orchestration.GroupChat; + ``` + +### Step 2: Update Initialization + +**Before:** + +```csharp +AgentGroupChat chat = new(agentWriter, agentReviewer) +{ + ExecutionSettings = new() + { + SelectionStrategy = new CustomSelectionStrategy(), + TerminationStrategy = new CustomTerminationStrategy(), + } +}; +``` + +**After:** + +```csharp +using Microsoft.SemanticKernel.Agents.Orchestration.GroupChat; + +GroupChatOrchestration orchestration = new( + new RoundRobinGroupChatManager(), + agentWriter, + agentReviewer); +``` + +### Step 3: Start the Group Chat + +**Before:** + +```csharp +chat.AddChatMessage(input); +await foreach (var response in chat.InvokeAsync()) +{ + // handle response +} +``` + +**After:** + +```csharp +using Microsoft.SemanticKernel.Agents.Orchestration; +using Microsoft.SemanticKernel.Agents.Runtime.InProcess; + +InProcessRuntime runtime = new(); +await runtime.StartAsync(); + +OrchestrationResult result = await orchestration.InvokeAsync(input, runtime); +string text = await result.GetValueAsync(TimeSpan.FromSeconds(timeout)); +``` + +### Step 4: Customizing Orchestration + +The new orchestration model allows you to create custom strategies for termination, agent selection, and more by sub-classing `GroupChatManager` and overriding its methods. Please refer to the [GroupChatOrchestration documentation](../../Frameworks/agent/agent-orchestration/group-chat.md#customize-the-group-chat-manager) for more details. + +### Step 5: Remove Deprecated APIs + +Remove any code that directly manipulates `AgentGroupChat`-specific properties or methods, as they are no longer maintained. + +### Step 6: Review and Test + +- Review your code for any remaining references to the old classes. +- Test your group chat scenarios to ensure the new orchestration behaves as expected. + +## Full Example + +This guide demonstrates how to migrate the core logic of [`Step03_Chat.cs`](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/GettingStartedWithAgents/Step03_Chat.cs) from `AgentGroupChat` to the new `GroupChatOrchestration`, including a custom group chat manager that implements the approval-based termination strategy. + +### Step 1: Agent Definition + +There are no changes needed in the agent definition. You can continue using the same `AgentWriter` and `AgentReviewer` as before. + +### Step 2: Implement a Custom Group Chat Manager + +Create a custom `GroupChatManager` that terminates the chat when the last message contains "approve" and only the reviewer can approve: + +```csharp +private sealed class ApprovalGroupChatManager : RoundRobinGroupChatManager +{ + private readonly string _approverName; + public ApprovalGroupChatManager(string approverName) + { + _approverName = approverName; + } + + public override ValueTask> ShouldTerminate(ChatHistory history, CancellationToken cancellationToken = default) + { + var last = history.LastOrDefault(); + bool shouldTerminate = last?.AuthorName == _approverName && + last.Content?.Contains("approve", StringComparison.OrdinalIgnoreCase) == true; + return ValueTask.FromResult(new GroupChatManagerResult(shouldTerminate) + { + Reason = shouldTerminate ? "Approved by reviewer." : "Not yet approved." + }); + } +} +``` + +### Step 3: Initialize the Orchestration + +Replace the `AgentGroupChat` initialization with: + +```csharp +var orchestration = new GroupChatOrchestration( + new ApprovalGroupChatManager(ReviewerName) + { + MaximumInvocationCount = 10 + }, + agentWriter, + agentReviewer); +``` + +### Step 4: Run the Orchestration + +Replace the message loop with: + +```csharp +var runtime = new InProcessRuntime(); +await runtime.StartAsync(); + +var result = await orchestration.InvokeAsync("concept: maps made out of egg cartons.", runtime); +string text = await result.GetValueAsync(TimeSpan.FromSeconds(60)); +Console.WriteLine($"\n# RESULT: {text}"); + +await runtime.RunUntilIdleAsync(); +``` + +## Summary + +- Use a custom `GroupChatManager` for approval-based termination. +- Replace the chat loop with orchestration invocation. +- The rest of your agent setup and message formatting can remain unchanged. + +::: zone-end + +::: zone pivot="programming-language-python" + +## Migrating from `AgentGroupChat` to `GroupChatOrchestration` + +The new `GroupChatOrchestration` API in Python replaces the older `AgentGroupChat` pattern, providing a more flexible and extensible way to manage multi-agent conversations. Here’s how to migrate your code: + +### Step 1: Replace Imports and Class References + +- Remove any imports or references to `AgentGroupChat` and related strategies. For example, remove: + + ```python + from semantic_kernel.agents import AgentGroupChat + ``` + +- Import the new orchestration classes: + + ```python + from semantic_kernel.agents import GroupChatOrchestration, RoundRobinGroupChatManager + from semantic_kernel.agents.runtime import InProcessRuntime + ``` + +### Step 2: Update Initialization + +Replace `AgentGroupChat` with `GroupChatOrchestration` and a `GroupChatManager` (e.g., `RoundRobinGroupChatManager` or a custom one) to control the flow. + +**Before:** + +```python +group_chat = AgentGroupChat( + agents=[agent_writer, agent_reviewer], + termination_strategy=CustomTerminationStrategy(), + selection_strategy=CustomSelectionStrategy(), +) +``` + +**After:** + +```python +from semantic_kernel.agents import GroupChatOrchestration, RoundRobinGroupChatManager + +orchestration = GroupChatOrchestration( + members=[agent_writer, agent_reviewer], + manager=RoundRobinGroupChatManager(), +) +``` + +### Step 3: Start the Group Chat + +**Before:** + +```python +await group_chat.add_chat_message(message=TASK) +async for content in group_chat.invoke(): + # handle response +``` + +**After:** + +```python +from semantic_kernel.agents.runtime import InProcessRuntime + +runtime = InProcessRuntime() +runtime.start() + +orchestration_result = await group_chat_orchestration.invoke(task=TASK, runtime=runtime) +value = await orchestration_result.get() +``` + +### Step 4: Customizing Orchestration + +The new orchestration model allows you to create custom strategies for termination, agent selection, and more by subclassing `GroupChatManager` and overriding its methods. Please refer to the [GroupChatOrchestration documentation](../../Frameworks/agent/agent-orchestration/group-chat.md#customize-the-group-chat-manager) for more details. + +### Step 5: Remove Deprecated APIs + +Remove any code that directly manipulates `AgentGroupChat`-specific properties or methods, as they are no longer maintained. + +### Step 6: Review and Test + +- Review your code for any remaining references to the old classes. +- Test your group chat scenarios to ensure the new orchestration behaves as expected. + +## Full Example + +This guide demonstrates how to migrate the core logic of [`step06_chat_completion_agent_group_chat.py`](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/chat_completion/step06_chat_completion_agent_group_chat.py) from `AgentGroupChat` to the new `GroupChatOrchestration`, including a custom group chat manager that implements the approval-based termination strategy. + +### Step 1: Agent Definition + +There are no changes needed in the agent definition. You can continue using the same `AgentWriter` and `AgentReviewer` as before. + +### Step 2: Implement a Custom Group Chat Manager + +Create a custom `GroupChatManager` that terminates the chat when the last message contains "approved" and only the reviewer can approve: + +```python +from semantic_kernel.agents import RoundRobinGroupChatManager, BooleanResult + +class ApprovalGroupChatManager(RoundRobinGroupChatManager): + def __init__(self, approver_name: str, max_rounds: int = 10): + super().__init__(max_rounds=max_rounds) + self._approver_name = approver_name + + async def should_terminate(self, chat_history): + last = chat_history[-1] if chat_history else None + should_terminate = ( + last is not None and + getattr(last, 'name', None) == self._approver_name and + 'approved' in (last.content or '').lower() + ) + return BooleanResult(result=should_terminate, reason="Approved by reviewer." if should_terminate else "Not yet approved.") +``` + +### Step 3: Initialize the Orchestration + +Replace the `AgentGroupChat` initialization with: + +```python +from semantic_kernel.agents import GroupChatOrchestration +from semantic_kernel.agents.runtime import InProcessRuntime + +orchestration = GroupChatOrchestration( + members=[agent_writer, agent_reviewer], + manager=ApprovalGroupChatManager(approver_name=REVIEWER_NAME, max_rounds=10), +) +``` + +### Step 4: Run the Orchestration + +Replace the message loop with: + +```python +runtime = InProcessRuntime() +runtime.start() + +orchestration_result = await orchestration.invoke( + task="a slogan for a new line of electric cars.", + runtime=runtime, +) + +value = await orchestration_result.get() +print(f"***** Result *****\n{value}") + +await runtime.stop_when_idle() +``` + +## Summary + +- Use a custom `GroupChatManager` for approval-based termination. +- Replace the chat loop with orchestration invocation. +- The rest of your agent setup and message formatting can remain unchanged. + +::: zone-end + +::: zone pivot="programming-language-java" + +> [!NOTE] +> Agent orchestration is not yet available in Java SDK. + +::: zone-end diff --git a/semantic-kernel/support/migration/toc.yml b/semantic-kernel/support/migration/toc.yml index 36fbbcd3..ad07b7fc 100644 --- a/semantic-kernel/support/migration/toc.yml +++ b/semantic-kernel/support/migration/toc.yml @@ -23,4 +23,6 @@ - name: Sessions Python Plugin Migration Guide - May 2025 href: sessions-python-plugin-migration-guide-2025.md - name: Functions.Markdown to Functions.Yaml Package Migration Guide - href: functions-markdown-migration-guide.md \ No newline at end of file + href: functions-markdown-migration-guide.md +- name: AgentGroupChat to GroupChatOrchestration Migration Guide + href: group-chat-orchestration-migration-guide.md diff --git a/semantic-kernel/support/toc.yml b/semantic-kernel/support/toc.yml index 924cbe48..8268ba08 100644 --- a/semantic-kernel/support/toc.yml +++ b/semantic-kernel/support/toc.yml @@ -10,3 +10,5 @@ href: migration/toc.yml - name: Security href: SECURITY.md +- name: Archive + href: archive/TOC.yml