From cf0e779638ea0737252829a719593a9574122d7f Mon Sep 17 00:00:00 2001
From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Date: Mon, 1 Sep 2025 13:04:26 +0100
Subject: [PATCH] .NET: Add missing Azure OpenAI Migration Sample code (#559)
* Add missing Azure OpenAI Migration Sample code
* Add Azure OpenAI Assistants Samples
* Address miner README typos
* Remove leftover
---
dotnet/agent-framework-dotnet.slnx | 11 ++
.../AzureOpenAI_Step01_Basics.csproj | 24 ++++
.../AzureOpenAI/Step01_Basics/Program.cs | 67 +++++++++
.../AzureOpenAI_Step02_ToolCall.csproj | 24 ++++
.../AzureOpenAI/Step02_ToolCall/Program.cs | 54 ++++++++
...reOpenAI_Step03_DependencyInjection.csproj | 24 ++++
.../Step03_DependencyInjection/Program.cs | 55 ++++++++
...AzureOpenAIAssistants_Step01_Basics.csproj | 24 ++++
.../Step01_Basics/Program.cs | 81 +++++++++++
...ureOpenAIAssistants_Step02_ToolCall.csproj | 24 ++++
.../Step02_ToolCall/Program.cs | 97 +++++++++++++
...sistants_Step03_DependencyInjection.csproj | 24 ++++
.../Step03_DependencyInjection/Program.cs | 99 ++++++++++++++
...AIAssistants_Step04_CodeInterpreter.csproj | 24 ++++
.../Step04_CodeInterpreter/Program.cs | 129 ++++++++++++++++++
.../OpenAI/Step01_Basics/Program.cs | 1 +
.../OpenAIAssistants/Step01_Basics/Program.cs | 1 -
.../samples/SemanticKernelMigration/README.md | 21 ++-
18 files changed, 776 insertions(+), 8 deletions(-)
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/AzureOpenAI_Step01_Basics.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/Program.cs
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/AzureOpenAI_Step02_ToolCall.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/Program.cs
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/AzureOpenAI_Step03_DependencyInjection.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj
create mode 100644 dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs
diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index c1dd73d982..8edd8bffcd 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -23,6 +23,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/AzureOpenAI_Step01_Basics.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/AzureOpenAI_Step01_Basics.csproj
new file mode 100644
index 0000000000..3f455d079f
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/AzureOpenAI_Step01_Basics.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/Program.cs
new file mode 100644
index 0000000000..941858b8dd
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step01_Basics/Program.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI.Agents;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using OpenAI;
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "Tell me a joke about a pirate.";
+
+Console.WriteLine($"User Input: {userInput}");
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ Console.WriteLine("\n=== SK Agent ===\n");
+
+ var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
+
+ var agent = new ChatCompletionAgent()
+ {
+ Kernel = builder.Build(),
+ Name = "Joker",
+ Instructions = "You are good at telling jokes.",
+ };
+
+ var thread = new ChatHistoryAgentThread();
+ var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
+ var agentOptions = new AgentInvokeOptions() { KernelArguments = new(settings) };
+
+ await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
+ {
+ Console.WriteLine(result.Message);
+ }
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update.Message);
+ }
+}
+
+async Task AFAgent()
+{
+ Console.WriteLine("\n=== AF Agent ===\n");
+
+ var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
+ .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
+
+ var thread = agent.GetNewThread();
+ var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
+
+ var result = await agent.RunAsync(userInput, thread, agentOptions);
+ Console.WriteLine(result);
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update);
+ }
+}
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/AzureOpenAI_Step02_ToolCall.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/AzureOpenAI_Step02_ToolCall.csproj
new file mode 100644
index 0000000000..dcf6e25469
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/AzureOpenAI_Step02_ToolCall.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707;CA1050;CA1052
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/Program.cs
new file mode 100644
index 0000000000..b01cff8e38
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step02_ToolCall/Program.cs
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.ComponentModel;
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents;
+using OpenAI;
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "What is the weather like in Amsterdam?";
+
+Console.WriteLine($"User Input: {userInput}");
+
+[KernelFunction]
+[Description("Get the weather for a given location.")]
+static string GetWeather([Description("The location to get the weather for.")] string location)
+ => $"The weather in {location} is cloudy with a high of 15°C.";
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
+
+ ChatCompletionAgent agent = new()
+ {
+ Instructions = "You are a helpful assistant",
+ Kernel = builder.Build(),
+ Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
+ };
+
+ // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
+ agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
+
+ Console.WriteLine("\n=== SK Agent Response ===\n");
+
+ var result = await agent.InvokeAsync(userInput).FirstAsync();
+ Console.WriteLine(result.Message);
+}
+
+async Task AFAgent()
+{
+ var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
+ .CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
+
+ Console.WriteLine("\n=== AF Agent Response ===\n");
+
+ var result = await agent.RunAsync(userInput);
+ Console.WriteLine(result);
+}
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/AzureOpenAI_Step03_DependencyInjection.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/AzureOpenAI_Step03_DependencyInjection.csproj
new file mode 100644
index 0000000000..3f455d079f
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/AzureOpenAI_Step03_DependencyInjection.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs
new file mode 100644
index 0000000000..f0f5b383c8
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.AI.Agents;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents;
+using OpenAI;
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "Tell me a joke about a pirate.";
+
+Console.WriteLine($"User Input: {userInput}");
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ Console.WriteLine("\n=== SK Agent ===\n");
+
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
+ serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
+ {
+ Kernel = sp.GetRequiredService(),
+ Name = "Joker",
+ Instructions = "You are good at telling jokes."
+ });
+
+ await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
+ var agent = serviceProvider.GetRequiredService();
+
+ var result = await agent.InvokeAsync(userInput).FirstAsync();
+ Console.WriteLine(result.Message);
+}
+
+async Task AFAgent()
+{
+ Console.WriteLine("\n=== AF Agent ===\n");
+
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddTransient((sp) => new AzureOpenAIClient(new(endpoint), new AzureCliCredential())
+ .GetChatClient(deploymentName)
+ .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
+
+ await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
+ var agent = serviceProvider.GetRequiredService();
+
+ var result = await agent.RunAsync(userInput);
+ Console.WriteLine(result);
+}
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj
new file mode 100644
index 0000000000..3f455d079f
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs
new file mode 100644
index 0000000000..b245aa237e
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI.Agents;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents.OpenAI;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using OpenAI;
+using OpenAI.Assistants;
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "Tell me a joke about a pirate.";
+
+Console.WriteLine($"User Input: {userInput}");
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ Console.WriteLine("\n=== SK Agent ===\n");
+
+ var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
+
+ var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
+
+ // Define the assistant
+ Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
+
+ // Create the agent
+ OpenAIAssistantAgent agent = new(assistant, assistantsClient);
+
+ // Create a thread for the agent conversation.
+ var thread = new OpenAIAssistantAgentThread(assistantsClient);
+ var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
+ var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) };
+
+ await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
+ {
+ Console.WriteLine(result.Message);
+ }
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update.Message);
+ }
+
+ // Clean up
+ await thread.DeleteAsync();
+ await assistantsClient.DeleteAssistantAsync(agent.Id);
+}
+
+async Task AFAgent()
+{
+ Console.WriteLine("\n=== AF Agent ===\n");
+
+ var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
+
+ var agent = await assistantClient.CreateAIAgentAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
+
+ var thread = agent.GetNewThread();
+ var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
+
+ var result = await agent.RunAsync(userInput, thread, agentOptions);
+ Console.WriteLine(result);
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update);
+ }
+
+ // Clean up
+ await assistantClient.DeleteThreadAsync(thread.ConversationId);
+ await assistantClient.DeleteAssistantAsync(agent.Id);
+}
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj
new file mode 100644
index 0000000000..dcf6e25469
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707;CA1050;CA1052
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs
new file mode 100644
index 0000000000..279a96c0af
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs
@@ -0,0 +1,97 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+using System.ComponentModel;
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.AI.Agents;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents.OpenAI;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using OpenAI;
+using OpenAI.Assistants;
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "What is the weather like in Amsterdam?";
+
+[KernelFunction]
+[Description("Get the weather for a given location.")]
+static string GetWeather([Description("The location to get the weather for.")] string location)
+ => $"The weather in {location} is cloudy with a high of 15°C.";
+
+Console.WriteLine($"User Input: {userInput}");
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ Console.WriteLine("\n=== SK Agent ===\n");
+
+ var builder = Kernel.CreateBuilder();
+ var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
+
+ Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName,
+ instructions: "You are a helpful assistant");
+
+ OpenAIAssistantAgent agent = new(assistant, assistantsClient)
+ {
+ Kernel = builder.Build(),
+ Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
+ {
+ MaxTokens = 1000,
+ FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
+ }),
+ };
+
+ // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
+ agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
+
+ // Create a thread for the agent conversation.
+ var thread = new OpenAIAssistantAgentThread(assistantsClient);
+
+ await foreach (var result in agent.InvokeAsync(userInput, thread))
+ {
+ Console.WriteLine(result.Message);
+ }
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.InvokeStreamingAsync(userInput, thread))
+ {
+ Console.Write(update.Message);
+ }
+
+ // Clean up
+ await thread.DeleteAsync();
+ await assistantsClient.DeleteAssistantAsync(agent.Id);
+}
+
+async Task AFAgent()
+{
+ Console.WriteLine("\n=== AF Agent ===\n");
+
+ var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
+
+ var agent = await assistantClient.CreateAIAgentAsync(deploymentName,
+ instructions: "You are a helpful assistant",
+ tools: [AIFunctionFactory.Create(GetWeather)]);
+
+ var thread = agent.GetNewThread();
+ var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
+
+ var result = await agent.RunAsync(userInput, thread, agentOptions);
+ Console.WriteLine(result);
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update);
+ }
+
+ // Clean up
+ await assistantClient.DeleteThreadAsync(thread.ConversationId);
+ await assistantClient.DeleteAssistantAsync(agent.Id);
+}
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj
new file mode 100644
index 0000000000..3f455d079f
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs
new file mode 100644
index 0000000000..add47b4954
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs
@@ -0,0 +1,99 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI.Agents;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents.OpenAI;
+using Microsoft.SemanticKernel.Connectors.OpenAI;
+using OpenAI;
+using OpenAI.Assistants;
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "Tell me a joke about a pirate.";
+
+Console.WriteLine($"User Input: {userInput}");
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ Console.WriteLine("\n=== SK Agent ===\n");
+
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
+ serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
+ serviceCollection.AddTransient((sp) =>
+ {
+ var assistantsClient = sp.GetRequiredService();
+
+ Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
+
+ return new OpenAIAssistantAgent(assistant, assistantsClient);
+ });
+
+ await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
+ var agent = serviceProvider.GetRequiredService();
+
+ // Create a thread for the agent conversation.
+ var assistantsClient = serviceProvider.GetRequiredService();
+ var thread = new OpenAIAssistantAgentThread(assistantsClient);
+ var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
+ var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) };
+
+ await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
+ {
+ Console.WriteLine(result.Message);
+ }
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update.Message);
+ }
+
+ // Clean up
+ await thread.DeleteAsync();
+ await assistantsClient.DeleteAssistantAsync(agent.Id);
+}
+
+async Task AFAgent()
+{
+ Console.WriteLine("\n=== AF Agent ===\n");
+
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
+ serviceCollection.AddTransient((sp) =>
+ {
+ var assistantClient = sp.GetRequiredService();
+
+ var agent = assistantClient.CreateAIAgent(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
+
+ return agent;
+ });
+
+ await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
+ var agent = serviceProvider.GetRequiredService();
+
+ var thread = agent.GetNewThread();
+ var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
+
+ var result = await agent.RunAsync(userInput, thread, agentOptions);
+ Console.WriteLine(result);
+
+ Console.WriteLine("---");
+ await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
+ {
+ Console.Write(update);
+ }
+
+ // Clean up
+ var assistantClient = serviceProvider.GetRequiredService();
+ await assistantClient.DeleteThreadAsync(thread.ConversationId);
+ await assistantClient.DeleteAssistantAsync(agent.Id);
+}
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj
new file mode 100644
index 0000000000..3f455d079f
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj
@@ -0,0 +1,24 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ $(NoWarn);CA1812;RCS1102;CA1707
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs
new file mode 100644
index 0000000000..8805a52e38
--- /dev/null
+++ b/dotnet/samples/SemanticKernelMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs
@@ -0,0 +1,129 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Text;
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Extensions.AI;
+using Microsoft.SemanticKernel;
+using Microsoft.SemanticKernel.Agents;
+using Microsoft.SemanticKernel.Agents.OpenAI;
+using OpenAI;
+using OpenAI.Assistants;
+
+#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+#pragma warning disable CS8321 // Local function is declared but never used
+
+var endpoint = Environment.GetEnvironmentVariable("AZUREOPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZUREOPENAI_ENDPOINT is not set.");
+var deploymentName = System.Environment.GetEnvironmentVariable("AZUREOPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
+var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101";
+
+var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
+
+Console.WriteLine($"User Input: {userInput}");
+
+await SKAgent();
+await AFAgent();
+
+async Task SKAgent()
+{
+ Console.WriteLine("\n=== SK Agent ===\n");
+
+ var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
+
+ // Define the assistant
+ Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true);
+
+ // Create the agent
+ OpenAIAssistantAgent agent = new(assistant, assistantsClient);
+
+ // Create a thread for the agent conversation.
+ var thread = new OpenAIAssistantAgentThread(assistantsClient);
+
+ // Respond to user input
+ await foreach (var content in agent.InvokeAsync(userInput, thread))
+ {
+ if (!string.IsNullOrWhiteSpace(content.Message.Content))
+ {
+ bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false;
+ Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}");
+ }
+
+ // Check for the citations
+ foreach (var item in content.Message.Items)
+ {
+ // Process each item in the message
+#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+ if (item is AnnotationContent annotation)
+ {
+ if (annotation.Kind != AnnotationKind.UrlCitation)
+ {
+ Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
+ }
+ }
+ else if (item is FileReferenceContent fileReference)
+ {
+ Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
+ }
+ }
+ }
+#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+ // Clean up
+ await thread.DeleteAsync();
+ await assistantsClient.DeleteAssistantAsync(agent.Id);
+}
+
+async Task AFAgent()
+{
+ Console.WriteLine("\n=== AF Agent ===\n");
+
+ var agent = await assistantsClient.CreateAIAgentAsync(deploymentName, tools: [new HostedCodeInterpreterTool()]);
+
+ var thread = agent.GetNewThread();
+
+ var result = await agent.RunAsync(userInput, thread);
+ Console.WriteLine(result);
+
+ // Extracts via breaking glass the code generated by code interpreter tool
+ var chatResponse = result.RawRepresentation as ChatResponse;
+ StringBuilder generatedCode = new();
+ foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable