--- title: Agent Framework Release Candidate Migration Guide description: Describes the steps for developers to update their Agent Framework code to the latest abstractions. zone_pivot_groups: programming-languages author: moonbox3 ms.topic: conceptual ms.author: evmattso ms.date: 02/26/2025 ms.service: semantic-kernel --- # Agent Framework Release Candidate Migration Guide As we transition some agents from the experimental stage to the release candidate stage, we have updated the APIs to simplify and streamline their use. Refer to the specific scenario guide to learn how to update your existing code to work with the latest available APIs. ::: zone pivot="programming-language-csharp" ## Common Agent Invocation API In version 1.43.0 we are releasing a new common agent invocation API, that will allow all agent types to be invoked via a common API. To enable this new API we are introducing the concept of an `AgentThread`, which represents a conversation thread and abstracts away the different thread management requirements of different agent types. For some agent types it will also, in future, allow different thread implementations to be used with the same agent. The common `Invoke` methods that we are introducing allow you to provide the message(s) that you want to pass to the agent and an optional `AgentThread`. If an `AgentThread` is provided, this will continue the conversation already on the `AgentThread`. If no `AgentThread` is provided, a new default thread will be created and returned as part of the response. It is also possible to manually create an `AgentThread` instance, for example in cases where you may have a thread id from the underlying agent service, and you want to continue that thread. You may also want to customize the options for the thread, e.g. associate tools. Here is a simple example of how any agent can now be used with agent agnostic code. ```csharp private async Task UseAgentAsync(Agent agent, AgentThread? agentThread = null) { // Invoke the agent, and continue the existing thread if provided. var responses = agent.InvokeAsync(new ChatMessageContent(AuthorRole.User, "Hi"), agentThread); // Output results. await foreach (AgentResponseItem response in responses) { Console.WriteLine(response); agentThread = response.Thread; } // Delete the thread if required. if (agentThread is not null) { await agentThread.DeleteAsync(); } } ``` These changes were applied in: - [PR #11116](https://github.com/microsoft/semantic-kernel/pull/11116) ### Azure AI Agent Thread Options The `AzureAIAgent` currently only supports threads of type `AzureAIAgentThread`. In addition to allowing a thread to be created for you automatically on agent invocation, you can also manually construct an instance of an `AzureAIAgentThread`. `AzureAIAgentThread` supports being created with customized tools and metadata, plus messages to seed the conversation with. ```csharp AgentThread thread = new AzureAIAgentThread( agentsClient, messages: seedMessages, toolResources: tools, metadata: metadata); ``` You can also construct an instance of an `AzureAIAgentThread` that continues an existing conversation. ```csharp AgentThread thread = new AzureAIAgentThread( agentsClient, id: "my-existing-thread-id"); ``` ### Bedrock Agent Thread Options The `BedrockAgent` currently only supports threads of type `BedrockAgentThread`. In addition to allowing a thread to be created for you automatically on agent invocation, you can also manually construct an instance of an `BedrockAgentThread`. ```csharp AgentThread thread = new BedrockAgentThread(amazonBedrockAgentRuntimeClient); ``` You can also construct an instance of an `BedrockAgentThread` that continues an existing conversation. ```csharp AgentThread thread = new BedrockAgentThread( amazonBedrockAgentRuntimeClient, sessionId: "my-existing-session-id"); ``` ### Chat Completion Agent Thread Options The `ChatCompletionAgent` currently only supports threads of type `ChatHistoryAgentThread`. `ChatHistoryAgentThread` uses an in-memory `ChatHistory` object to store the messages on the thread. In addition to allowing a thread to be created for you automatically on agent invocation, you can also manually construct an instance of an `ChatHistoryAgentThread`. ```csharp AgentThread thread = new ChatHistoryAgentThread(); ``` You can also construct an instance of an `ChatHistoryAgentThread` that continues an existing conversation by passing in a `ChatHistory` object with the existing messages. ```csharp ChatHistory chatHistory = new([new ChatMessageContent(AuthorRole.User, "Hi")]); AgentThread thread = new ChatHistoryAgentThread(chatHistory: chatHistory); ``` ### OpenAI Assistant Thread Options The `OpenAIAssistantAgent` currently only supports threads of type `OpenAIAssistantAgentThread`. In addition to allowing a thread to be created for you automatically on agent invocation, you can also manually construct an instance of an `OpenAIAssistantAgentThread`. `OpenAIAssistantAgentThread` supports being created with customized tools and metadata, plus messages to seed the conversation with. ```csharp AgentThread thread = new OpenAIAssistantAgentThread( assistantClient, messages: seedMessages, codeInterpreterFileIds: fileIds, vectorStoreId: "my-vector-store", metadata: metadata); ``` You can also construct an instance of an `OpenAIAssistantAgentThread` that continues an existing conversation. ```csharp AgentThread thread = new OpenAIAssistantAgentThread( assistantClient, id: "my-existing-thread-id"); ``` ## OpenAIAssistantAgent C# Migration Guide We recently applied a significant shift around the [`OpenAIAssistantAgent`](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/Agents/OpenAI/OpenAIAssistantAgent.cs) in the _Semantic Kernel Agent Framework_. These changes were applied in: - [PR #10583](https://github.com/microsoft/semantic-kernel/pull/10583) - [PR #10616](https://github.com/microsoft/semantic-kernel/pull/10616) - [PR #10633](https://github.com/microsoft/semantic-kernel/pull/10633) These changes are intended to: - Align with the pattern for using for our [`AzureAIAgent`](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/Agents/AzureAI/AzureAIAgent.cs). - Fix bugs around static initialization pattern. - Avoid limiting features based on our abstraction of the underlying SDK. This guide provides step-by-step instructions for migrating your C# code from the old implementation to the new one. Changes include updates for creating assistants, managing the assistant lifecycle, handling threads, files, and vector stores. ## 1. Client Instantiation Previously, `OpenAIClientProvider` was required for creating any `OpenAIAssistantAgent`. This dependency has been simplified. #### **New Way** ```csharp OpenAIClient client = OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(endpointUrl)); AssistantClient assistantClient = client.GetAssistantClient(); ``` #### **Old Way (Deprecated)** ```csharp var clientProvider = new OpenAIClientProvider(...); ``` ## 2. Assistant Lifecycle ### **Creating an Assistant** You may now directly instantiate an `OpenAIAssistantAgent` using an existing or new Assistant definition from `AssistantClient`. ##### **New Way** ```csharp Assistant definition = await assistantClient.GetAssistantAsync(assistantId); OpenAIAssistantAgent agent = new(definition, client); ``` Plugins can be directly included during initialization: ```csharp KernelPlugin plugin = KernelPluginFactory.CreateFromType(); Assistant definition = await assistantClient.GetAssistantAsync(assistantId); OpenAIAssistantAgent agent = new(definition, client, [plugin]); ``` Creating a new assistant definition using an extension method: ```csharp Assistant assistant = await assistantClient.CreateAssistantAsync( model, name, instructions: instructions, enableCodeInterpreter: true); ``` ##### **Old Way (Deprecated)** Previously, assistant definitions were managed indirectly. ## 3. Invoking the Agent You may specify `RunCreationOptions` directly, enabling full access to underlying SDK capabilities. #### **New Way** ```csharp RunCreationOptions options = new(); // configure as needed var result = await agent.InvokeAsync(options); ``` #### **Old Way (Deprecated)** ```csharp var options = new OpenAIAssistantInvocationOptions(); ``` ## 4. Assistant Deletion You can directly manage assistant deletion with `AssistantClient`. ```csharp await assistantClient.DeleteAssistantAsync(agent.Id); ``` ## 5. Thread Lifecycle ### **Creating a Thread** Threads are now managed via `AssistantAgentThread`. ##### **New Way** ```csharp var thread = new AssistantAgentThread(assistantClient); // Calling CreateAsync is an optional step. // A thread will be created automatically on first use if CreateAsync was not called. // Note that CreateAsync is not on the AgentThread base implementation since not all // agent services support explicit thread creation. await thread.CreateAsync(); ``` ##### **Old Way (Deprecated)** Previously, thread management was indirect or agent-bound. ### **Thread Deletion** ```csharp var thread = new AssistantAgentThread(assistantClient, "existing-thread-id"); await thread.DeleteAsync(); ``` ## 6. File Lifecycle File creation and deletion now utilize `OpenAIFileClient`. ### **File Upload** ```csharp string fileId = await client.UploadAssistantFileAsync(stream, ""); ``` ### **File Deletion** ```csharp await client.DeleteFileAsync(fileId); ``` ## 7. Vector Store Lifecycle Vector stores are managed directly via `VectorStoreClient` with convenient extension methods. ### **Vector Store Creation** ```csharp string vectorStoreId = await client.CreateVectorStoreAsync([fileId1, fileId2], waitUntilCompleted: true); ``` ### **Vector Store Deletion** ```csharp await client.DeleteVectorStoreAsync(vectorStoreId); ``` ## Backwards Compatibility Deprecated patterns are marked with `[Obsolete]`. To suppress obsolete warnings (`CS0618`), update your project file as follows: ```xml $(NoWarn);CS0618 ``` This migration guide helps you transition smoothly to the new implementation, simplifying client initialization, resource management, and integration with the **Semantic Kernel .NET SDK**. ::: zone-end ::: zone pivot="programming-language-python" > [!IMPORTANT] > For developers upgrading to Semantic Kernel Python 1.26.1 or later, significant updates and breaking changes have been introduced to improve our agent framework as we approach GA. These changes were applied in: - [PR #11116](https://github.com/microsoft/semantic-kernel/pull/11116) Previous changes were applied in: - [PR #10666](https://github.com/microsoft/semantic-kernel/pull/10666) - [PR #10667](https://github.com/microsoft/semantic-kernel/pull/10667) - [PR #10701](https://github.com/microsoft/semantic-kernel/pull/10701) - [PR #10707](https://github.com/microsoft/semantic-kernel/pull/10707) This guide provides step-by-step instructions for migrating your Python code from the old implementation to the new implementation. ## Agent Imports All agent import paths have been consolidated under `semantic_kernel.agents`. #### Updated import style ```python from semantic_kernel.agents import ( AutoGenConversableAgent, AzureAIAgent, AzureAssistantAgent, BedrockAgent, ChatCompletionAgent, OpenAIAssistantAgent, ) ``` #### Previous import style (deprecated): ``` from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.agents.autogen import AutoGenConversableAgent from semantic_kernel.agents.azure_ai import AzureAIAgent from semantic_kernel.agents.bedrock import BedrockAgent from semantic_kernel.agents.open_ai import AzureAssistantAgent, OpenAIAssistantAgent ``` ## Common Agent Invocation API As of Semantic Kernel Python 1.26.0 and later, we introduced a new common abstraction to manage threads for all agents. For each agent we now expose a thread class that implements the `AgentThread` base class, allowing context management via methods like `create()` and `delete()`. Agent responses `get_response(...)`, `invoke(...)`, `invoke_stream(...)` now return an `AgentResponseItem[ChatMessageContent]`, which has two attributes: ```python message: TMessage # Usually ChatMessageContent thread: AgentThread # Contains the concrete type for the given agent ``` ### Adding Messages to a Thread Messages should be added to a thread via the `messages` argument as part of the agent's `get_response(...)`, `invoke(...)` or `invoke_stream(...)` methods. ### Azure AI Agent Thread An `AzureAIAgentThread` can be created as follows: ```python from semantic_kernel.agents import AzureAIAgentThread thread = AzureAIAgentThread( client: AIProjectClient, # required messages: list[ThreadMessageOptions] | None = None, # optional metadata: dict[str, str] | None = None, # optional thread_id: str | None = None, # optional tool_resources: "ToolResources | None" = None, # optional ) ``` Providing a `thread_id` (string) allows you to continue an existing conversation. If omitted, a new thread is created and returned as part of the agent response. A complete implementation example: ```python import asyncio from azure.identity.aio import DefaultAzureCredential from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread USER_INPUTS = [ "Why is the sky blue?", "What are we talking about?", ] async def main() -> None: ai_agent_settings = AzureAIAgentSettings.create() async with ( DefaultAzureCredential() as creds, AzureAIAgent.create_client(credential=creds) as client, ): # 1. Create an agent on the Azure AI agent service agent_definition = await client.agents.create_agent( model=ai_agent_settings.model_deployment_name, name="Assistant", instructions="Answer the user's questions.", ) # 2. Create a Semantic Kernel agent for the Azure AI agent agent = AzureAIAgent( client=client, definition=agent_definition, ) # 3. Create a thread for the agent # If no thread is provided, a new thread will be # created and returned with the initial response thread: AzureAIAgentThread = None try: for user_input in USER_INPUTS: print(f"# User: {user_input}") # 4. Invoke the agent with the specified message for response response = await agent.get_response(messages=user_input, thread=thread) print(f"# {response.content}: {response}") thread = response.thread finally: # 6. Cleanup: Delete the thread and agent await thread.delete() if thread else None await client.agents.delete_agent(agent.id) if __name__ == "__main__": asyncio.run(main()) ``` ### Bedrock Agent Thread A `BedrockAgent` uses a `BedrockAgentThread` to manage conversation history and context. You may provide a `session_id` to either continue or initiate a fresh conversation context. ```python from semantic_kernel.agents import BedrockAgentThread thread = BedrockAgentThread( bedrock_runtime_client: Any, session_id: str | None = None, ) ``` If no `session_id` is provided, a new context is created automatically. A complete implementation example: ```python import asyncio from semantic_kernel.agents import BedrockAgent, BedrockAgentThread async def main(): bedrock_agent = await BedrockAgent.create_and_prepare_agent( "semantic-kernel-bedrock-agent", instructions="You are a friendly assistant. You help people find information.", ) # Create a thread for the agent # If no thread is provided, a new thread will be # created and returned with the initial response thread: BedrockAgentThread = None try: while True: user_input = input("User:> ") if user_input == "exit": print("\n\nExiting chat...") break # Invoke the agent # The chat history is maintained in the session response = await bedrock_agent.get_response( input_text=user_input, thread=thread, ) print(f"Bedrock agent: {response}") thread = response.thread except KeyboardInterrupt: print("\n\nExiting chat...") return False except EOFError: print("\n\nExiting chat...") return False finally: # Delete the agent await bedrock_agent.delete_agent() await thread.delete() if thread else None if __name__ == "__main__": asyncio.run(main()) ``` ### Chat History Agent Thread A `ChatCompletionAgent` uses `ChatHistoryAgentThread` to manage conversation history. It can be initialized as follows: ```python from semantic_kernel.agents import ChatHistoryAgentThread thread = ChatHistoryAgentThread( chat_history: ChatHistory | None = None, thread_id: str | None = None ) ``` Providing a `thread_id` allows continuing existing conversations. Omitting it creates a new thread. Serialization and rehydration of thread state are supported for persistent conversation contexts. A complete implementation example: ```python import asyncio from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion # Simulate a conversation with the agent USER_INPUTS = [ "Hello, I am John Doe.", "What is your name?", "What is my name?", ] async def main(): # 1. Create the agent by specifying the service agent = ChatCompletionAgent( service=AzureChatCompletion(), name="Assistant", instructions="Answer the user's questions.", ) # 2. Create a thread to hold the conversation # If no thread is provided, a new thread will be # created and returned with the initial response thread: ChatHistoryAgentThread = None for user_input in USER_INPUTS: print(f"# User: {user_input}") # 3. Invoke the agent for a response response = await agent.get_response( messages=user_input, thread=thread, ) print(f"# {response.name}: {response}") # 4. Store the thread, which allows the agent to # maintain conversation history across multiple messages. thread = response.thread # 5. Cleanup: Clear the thread await thread.delete() if thread else None if __name__ == "__main__": asyncio.run(main()) ``` ### OpenAI Assistant Thread The `AzureAssistantAgent` and `OpenAIAssistantAgent` use `AssistantAgentThread` to manage conversation history and context: ```python from semantic_kernel.agents import ChatHistoryAgentThread thread = AssistantAgentThread( client: AsyncOpenAI, thread_id: str | None = None, messages: Iterable["ThreadCreateMessage"] | NotGiven = NOT_GIVEN, metadata: dict[str, Any] | NotGiven = NOT_GIVEN, tool_resources: ToolResources | NotGiven = NOT_GIVEN, ) ``` Providing a `thread_id` continues an existing conversation; otherwise, a new thread is created. A complete implementation example: ```python # Copyright (c) Microsoft. All rights reserved. import asyncio from semantic_kernel.agents import AzureAssistantAgent # Simulate a conversation with the agent USER_INPUTS = [ "Why is the sky blue?", "What is the speed of light?", "What have we been talking about?", ] async def main(): # 1. Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() # 2. Create the assistant on the Azure OpenAI service definition = await client.beta.assistants.create( model=model, instructions="Answer questions about the world in one sentence.", name="Assistant", ) # 3. Create a Semantic Kernel agent for the Azure OpenAI assistant agent = AzureAssistantAgent( client=client, definition=definition, ) # 4. Create a new thread for use with the assistant # If no thread is provided, a new thread will be # created and returned with the initial response thread = None try: for user_input in USER_INPUTS: print(f"# User: '{user_input}'") # 6. Invoke the agent for the current thread and print the response response = await agent.get_response(messages=user_input, thread=thread) print(f"# {response.name}: {response}") thread = response.thread finally: # 7. Clean up the resources await thread.delete() if thread else None await agent.client.beta.assistants.delete(assistant_id=agent.id) if __name__ == "__main__": asyncio.run(main()) ``` ## Message Inputs for Agent Invocation Previous implementations allowed only a single message input to methods like `get_response(...)`, `invoke(...)`, and `invoke_stream(...)`. We've now updated these methods to support multiple `messages (str | ChatMessageContent | list[str | ChatMessageContent])`. Message inputs need to be passed in with the `messages` keyword argument, such as `agent.get_response(messages="user input")` or `agent.invoke(messages="user input")`. Agent invocation methods need updates as follows: ### Old Way ```python response = await agent.get_response(message="some user input", thread=thread) ``` ### New Way ```python response = await agent.get_response(messages=["some initial inputer", "other input"], thread=thread) ``` ## `AzureAIAgent` In Semantic Kernel Python 1.26.0+, `AzureAIAgent` thread creation is now managed via the `AzureAIAgentThread` object, not directly on the client. ### Old Way ```python thread = await client.agents.create_thread() ``` ### New Way ```python from semantic_kernel.agents import AzureAIAgentThread thread = AzureAIAgentThread( client: AIProjectClient, # required messages: list[ThreadMessageOptions] | None = None, # optional metadata: dict[str, str] | None = None, # optional thread_id: str | None = None, # optional tool_resources: "ToolResources | None" = None, # optional ) ``` If no `thread_id` is provided initially, a new thread is created and returned in the agent response. ## `ChatCompletionAgent` The `ChatCompletionAgent` has been updated to simplify service configuration, plugin handling, and function calling behaviors. Below are the key changes you should consider when migrating. ### 1. Specifying the Service You can now specify the service directly as part of the agent constructor: #### New Way ```python from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion agent = ChatCompletionAgent( service=AzureChatCompletion(), name="", instructions="", ) ``` Note: If both a kernel and a service are provided, the service will take precedence if it shares the same service_id or ai_model_id. Otherwise, if they are separate, the first AI service registered on the kernel will be used. #### Old Way (Still Valid) Previously, you would first add a service to a kernel and then pass the kernel to the agent: ```python from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion kernel = Kernel() kernel.add_service(AzureChatCompletion()) agent = ChatCompletionAgent( kernel=kernel, name="", instructions="", ) ``` ### 2. Adding Plugins Plugins can now be supplied directly through the constructor: #### New Way ```python from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion agent = ChatCompletionAgent( service=AzureChatCompletion(), name="", instructions="", plugins=[SamplePlugin()], ) ``` #### Old Way (Still Valid) Plugins previously had to be added to the kernel separately: ```python from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion kernel = Kernel() kernel.add_plugin(SamplePlugin()) agent = ChatCompletionAgent( kernel=kernel, name="", instructions="", ) ``` Note: Both approaches are valid, but directly specifying plugins simplifies initialization. ### 3. Invoking the Agent You now have two ways to invoke the agent. The new method directly retrieves a single response, while the old method supports streaming. #### New Way (No Conversation Thread/Context) ```python response = await agent.get_response(messages="user input") # response is of type AgentResponseItem[ChatMessageContent] ``` Note: if the next response does not use the returned thread, the conversation will use a new thread and thus will not continue with previous context. #### New Way (Single Response with Context) ```python thread = ChatHistoryAgentThread() for user_input in ["First user input", "Second User Input"]: response = await agent.get_response(messages=user_input, thread=thread) # response is of type AgentResponseItem[ChatMessageContent] thread = response.thread ``` #### Old Way (No Longer Valid) ```python chat_history = ChatHistory() chat_history.add_user_message("") response = agent.get_response(message="user input", chat_history=chat_history) ``` ### 4. Controlling Function Calling Function calling behavior can now be controlled directly when specifying the service within the agent constructor: ```python agent = ChatCompletionAgent( service=AzureChatCompletion(), name="", instructions="", plugins=[MenuPlugin()], function_choice_behavior=FunctionChoiceBehavior.Auto( filters={"included_functions": ["get_specials", "get_item_price"]} ), ) ``` Note: Previously, function calling configuration required separate setup on the kernel or service object. 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. These updates enhance simplicity and configurability, making the ChatCompletionAgent easier to integrate and maintain. ## `OpenAIAssistantAgent` The `AzureAssistantAgent` and `OpenAIAssistantAgent` changes include updates for creating assistants, creating threads, handling plugins, using the code interpreter tool, working with the file search tool, and adding chat messages to a thread. ## Setting up Resources ### Old Way The `AsyncAzureOpenAI` client was created as part of creating the Agent object. ```python agent = await AzureAssistantAgent.create( deployment_name="optional-deployment-name", api_key="optional-api-key", endpoint="optional-endpoint", ad_token="optional-ad-token", ad_token_provider=optional_callable, default_headers={"optional_header": "optional-header-value"}, env_file_path="optional-env-file-path", env_file_encoding="optional-env-file-encoding", ..., ) ``` ### New Way The agent provides a static method to create the required client for the specified resources, where method-level keyword arguments take precedence over environment variables and values in an existing `.env` file. ```python client, model = AzureAssistantAgent.setup_resources( ad_token="optional-ad-token", ad_token_provider=optional_callable, api_key="optional-api-key", api_version="optional-api-version", base_url="optional-base-url", default_headers="optional-default-headers", deployment_name="optional-deployment-name", endpoint="optional-endpoint", env_file_path="optional-env-file-path", env_file_encoding="optional-env-file-encoding", token_scope="optional-token-scope", ) ``` ## 1. Creating an Assistant ### Old Way ```python agent = await AzureAssistantAgent.create( kernel=kernel, service_id=service_id, name=AGENT_NAME, instructions=AGENT_INSTRUCTIONS, enable_code_interpreter=True, ) ``` or ```python agent = await OpenAIAssistantAgent.create( kernel=kernel, service_id=service_id, name=, instructions=, enable_code_interpreter=True, ) ``` ### New Way ```python # Azure AssistantAgent # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() # Create the assistant definition definition = await client.beta.assistants.create( model=model, instructions="", name="", ) # Create the agent using the client and the assistant definition agent = AzureAssistantAgent( client=client, definition=definition, ) ``` or ```python # OpenAI Assistant Agent # Create the client using OpenAI resources and configuration client, model = OpenAIAssistantAgent.setup_resources() # Create the assistant definition definition = await client.beta.assistants.create( model=model, instructions="", name="", ) # Create the agent using the client and the assistant definition agent = OpenAIAssistantAgent( client=client, definition=definition, ) ``` ## 2. Creating a Thread ### Old Way ```python thread_id = await agent.create_thread() ``` ### New Way ```python from semantic_kernel.agents AssistantAgentThread, AzureAssistantAgent client, model = AzureAssistantAgent.setup_resources() # You may create a thread based on an existing thread id # thread = AssistantAgentThread(client=client, thread_id="existing-thread-id") # Otherwise, if not specified, a thread will be created during the first invocation # and returned as part of the response thread = None async for response in agent.invoke(messages="user input", thread=thread): # handle response print(response) thread = response.thread ``` ## 3. Handling Plugins ### Old Way ```python # Create the instance of the Kernel kernel = Kernel() # Add the sample plugin to the kernel kernel.add_plugin(plugin=MenuPlugin(), plugin_name="menu") agent = await AzureAssistantAgent.create( kernel=kernel, name="", instructions="" ) ``` *Note: It is still possible to manage plugins via the kernel. If you do not supply a kernel, a kernel is automatically created at agent creation time and the plugins will be added to that instance.* ### New Way ```python # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() # Create the assistant definition definition = await client.beta.assistants.create( model=model, instructions="", name="", ) # Create the agent with plugins passed in as a list agent = AzureAssistantAgent( client=client, definition=definition, plugins=[MenuPlugin()], ) ``` Refer to the [sample implementation](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/openai_assistant/step2_plugins.py) for full details. ## 4. Using the Code Interpreter Tool ### Old Way ```python csv_file_path = ... agent = await AzureAssistantAgent.create( kernel=kernel, name="", instructions="", enable_code_interpreter=True, code_interpreter_filenames=[csv_file_path], ) ``` ### New Way ```python # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() csv_file_path = ... # Load the CSV file as a FileObject with open(csv_file_path, "rb") as file: file = await client.files.create(file=file, purpose="assistants") # Get the code interpreter tool and resources code_interpreter_tool, code_interpreter_tool_resource = AzureAssistantAgent.configure_code_interpreter_tool(file.id) # Create the assistant definition definition = await client.beta.assistants.create( model=model, name="", instructions=".", tools=code_interpreter_tool, tool_resources=code_interpreter_tool_resource, ) # Create the AzureAssistantAgent instance using the client and the assistant definition agent = AzureAssistantAgent( client=client, definition=definition, ) ``` Refer to the [sample implementation](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/concepts/agents/openai_assistant/openai_assistant_file_manipulation.py) for full details. ## 5. Working with the File Search Tool ### Old Way ```python pdf_file_path = ... agent = await AzureAssistantAgent.create( kernel=kernel, service_id=service_id, name=AGENT_NAME, instructions=AGENT_INSTRUCTIONS, enable_file_search=True, vector_store_filenames=[pdf_file_path], ) ``` ### New Way ```python # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() pdf_file_path = ... # Load the employees PDF file as a FileObject with open(pdf_file_path, "rb") as file: file = await client.files.create(file=file, purpose="assistants") # Create a vector store specifying the file ID to be used for file search vector_store = await client.beta.vector_stores.create( name="step4_assistant_file_search", file_ids=[file.id], ) file_search_tool, file_search_tool_resources = AzureAssistantAgent.configure_file_search_tool(vector_store.id) # Create the assistant definition definition = await client.beta.assistants.create( model=model, instructions="Find answers to the user's questions in the provided file.", name="FileSearch", tools=file_search_tool, tool_resources=file_search_tool_resources, ) # Create the AzureAssistantAgent instance using the client and the assistant definition agent = AzureAssistantAgent( client=client, definition=definition, ) ``` Refer to the [sample implementation](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/getting_started_with_agents/openai_assistant/step4_assistant_tool_file_search.py) for full details. ## 6. Adding Chat Messages to a Thread ### Old Way ```python await agent.add_chat_message( thread_id=thread_id, message=ChatMessageContent(role=AuthorRole.USER, content=user_input) ) ``` ### New Way *Note: The old method still works if you pass in a `ChatMessageContent`, but you can now also pass a simple string.* ```python await agent.add_chat_message( thread_id=thread_id, message=user_input, ) ``` ## 7. Cleaning Up Resources ### Old Way ```python await agent.delete_file(file_id) await agent.delete_thread(thread_id) await agent.delete() ``` ### New Way ```python await client.files.delete(file_id) await thread.delete() await client.beta.assistants.delete(agent.id) ``` ## Handling Structured Outputs ### Old Way *Unavailable in the old way* ### New Way ```python # Define a Pydantic model that represents the structured output from the OpenAI service class ResponseModel(BaseModel): response: str items: list[str] # Create the client using Azure OpenAI resources and configuration client, model = AzureAssistantAgent.setup_resources() # Create the assistant definition definition = await client.beta.assistants.create( model=model, name="", instructions="", response_format=AzureAssistantAgent.configure_response_format(ResponseModel), ) # Create the AzureAssistantAgent instance using the client and the assistant definition agent = AzureAssistantAgent( client=client, definition=definition, ) ``` Refer to the [sample implementation](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/concepts/agents/openai_assistant/openai_assistant_structured_outputs.py) for full details. This migration guide should help you update your code to the new implementation, leveraging client-based configuration and enhanced features. ::: zone-end ::: zone pivot="programming-language-java" > Agents are unavailable in Java. ::: zone-end