Skip to content

Commit df54779

Browse files
authored
.NET: Add Orchestration SK->AF migration samples (#1044)
* Add Orchestration SK->AF migration samples * fix samples * clean up * Add handoff * Comments * Address comments * Fix build error * Comments
1 parent 93577f7 commit df54779

File tree

7 files changed

+551
-0
lines changed

7 files changed

+551
-0
lines changed

dotnet/agent-framework-dotnet.slnx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@
171171
<Project Path="samples/SemanticKernelMigration/AzureOpenAIResponses/Step03_ToolCall/AzureOpenAIResponses_Step03_ToolCall.csproj" />
172172
<Project Path="samples/SemanticKernelMigration/AzureOpenAIResponses/Step04_DependencyInjection/AzureOpenAIResponses_Step04_DependencyInjection.csproj" />
173173
</Folder>
174+
<Folder Name="/Samples/SemanticKernelMigration/AgentOrchestrations/">
175+
<Project Path="samples/SemanticKernelMigration/AgentOrchestrations/Step01_Concurrent/AgentOrchestrations_Step01_Concurrent.csproj" />
176+
<Project Path="samples/SemanticKernelMigration/AgentOrchestrations/Step02_Sequential/AgentOrchestrations_Step02_Sequential.csproj" />
177+
<Project Path="samples/SemanticKernelMigration/AgentOrchestrations/Step03_Handoff/AgentOrchestrations_Step03_Handoff.csproj" />
178+
</Folder>
174179
<Folder Name="/Solution Items/">
175180
<File Path=".editorconfig" />
176181
<File Path=".gitignore" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<NoWarn>$(NoWarn);CA1812;RCS1102;CA1707;VSTHRD200</NoWarn>
9+
<InjectSharedThrow>true</InjectSharedThrow>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.SemanticKernel" VersionOverride="1.*" />
14+
<PackageReference Include="Microsoft.SemanticKernel.Agents.AzureAI" VersionOverride="1.*-*" />
15+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" VersionOverride="1.*" />
16+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Orchestration" VersionOverride="1.*-*" />
17+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Runtime.InProcess" VersionOverride="1.*-*" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
22+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
23+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj" />
24+
</ItemGroup>
25+
26+
</Project>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using Azure.AI.OpenAI;
4+
using Azure.Identity;
5+
using Microsoft.Agents.AI;
6+
using Microsoft.Agents.AI.Workflows;
7+
using Microsoft.Extensions.AI;
8+
using Microsoft.SemanticKernel;
9+
using Microsoft.SemanticKernel.Agents;
10+
using Microsoft.SemanticKernel.Agents.Orchestration;
11+
using Microsoft.SemanticKernel.Agents.Orchestration.Concurrent;
12+
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
13+
14+
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
15+
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
16+
17+
var agentInstructions = "You are a translation assistant who only responds in {0}. Respond to any input by outputting the name of the input language and then translating the input to {0}.";
18+
19+
// This sample compares running concurrent orchestrations using
20+
// Semantic Kernel and the Agent Framework.
21+
Console.WriteLine("=== Semantic Kernel Concurrent Orchestration ===");
22+
await SKConcurrentOrchestration();
23+
24+
Console.WriteLine("\n=== Agent Framework Concurrent Agent Workflow ===");
25+
await AFConcurrentAgentWorkflow();
26+
27+
# region SKConcurrentOrchestration
28+
#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.
29+
async Task SKConcurrentOrchestration()
30+
{
31+
ConcurrentOrchestration orchestration = new([
32+
GetSKTranslationAgent("French"),
33+
GetSKTranslationAgent("Spanish")])
34+
{
35+
StreamingResponseCallback = StreamingResultCallback,
36+
};
37+
38+
InProcessRuntime runtime = new();
39+
await runtime.StartAsync();
40+
41+
// Run the orchestration
42+
OrchestrationResult<string[]> result = await orchestration.InvokeAsync("Hello, world!", runtime);
43+
string[] texts = await result.GetValueAsync(TimeSpan.FromSeconds(20));
44+
45+
await runtime.RunUntilIdleAsync();
46+
}
47+
#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.
48+
49+
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
50+
{
51+
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
52+
return new ChatCompletionAgent()
53+
{
54+
Kernel = kernel,
55+
Instructions = string.Format(agentInstructions, targetLanguage),
56+
Description = $"Agent that translates texts to {targetLanguage}",
57+
Name = $"SKTranslationAgent_{targetLanguage}"
58+
};
59+
}
60+
61+
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
62+
{
63+
Console.Write(streamedResponse.Content);
64+
65+
if (isFinal)
66+
{
67+
Console.WriteLine();
68+
}
69+
70+
return ValueTask.CompletedTask;
71+
}
72+
# endregion
73+
74+
# region AFConcurrentAgentWorkflow
75+
async Task AFConcurrentAgentWorkflow()
76+
{
77+
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
78+
var frenchAgent = GetAFTranslationAgent("French", client);
79+
var spanishAgent = GetAFTranslationAgent("Spanish", client);
80+
var concurrentAgentWorkflow = AgentWorkflowBuilder.BuildConcurrent([frenchAgent, spanishAgent]);
81+
82+
await using StreamingRun run = await InProcessExecution.StreamAsync(concurrentAgentWorkflow, "Hello, world!");
83+
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
84+
85+
string? lastExecutorId = null;
86+
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
87+
{
88+
if (evt is AgentRunUpdateEvent e)
89+
{
90+
if (string.IsNullOrEmpty(e.Update.Text))
91+
{
92+
continue;
93+
}
94+
95+
if (e.ExecutorId != lastExecutorId)
96+
{
97+
lastExecutorId = e.ExecutorId;
98+
Console.WriteLine();
99+
Console.Write($"{e.Update.AuthorName}: ");
100+
}
101+
102+
Console.Write(e.Update.Text);
103+
}
104+
}
105+
}
106+
107+
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
108+
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
109+
# endregion
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<NoWarn>$(NoWarn);CA1812;RCS1102;CA1707;VSTHRD200</NoWarn>
9+
<InjectSharedThrow>true</InjectSharedThrow>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.SemanticKernel" VersionOverride="1.*" />
14+
<PackageReference Include="Microsoft.SemanticKernel.Agents.AzureAI" VersionOverride="1.*-*" />
15+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" VersionOverride="1.*" />
16+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Orchestration" VersionOverride="1.*-*" />
17+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Runtime.InProcess" VersionOverride="1.*-*" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
22+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
23+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj" />
24+
</ItemGroup>
25+
26+
</Project>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using Azure.AI.OpenAI;
4+
using Azure.Identity;
5+
using Microsoft.Agents.AI;
6+
using Microsoft.Agents.AI.Workflows;
7+
using Microsoft.Extensions.AI;
8+
using Microsoft.SemanticKernel;
9+
using Microsoft.SemanticKernel.Agents;
10+
using Microsoft.SemanticKernel.Agents.Orchestration;
11+
using Microsoft.SemanticKernel.Agents.Orchestration.Sequential;
12+
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
13+
14+
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
15+
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
16+
17+
var agentInstructions = "You are a translation assistant who only responds in {0}. Respond to any input by outputting the name of the input language and then translating the input to {0}.";
18+
19+
// This sample compares running sequential orchestrations using
20+
// Semantic Kernel and the Agent Framework.
21+
Console.WriteLine("=== Semantic Kernel Sequential Orchestration ===");
22+
await SKSequentialOrchestration();
23+
24+
Console.WriteLine("\n=== Agent Framework Sequential Agent Workflow ===");
25+
await AFSequentialAgentWorkflow();
26+
27+
# region SKSequentialOrchestration
28+
#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.
29+
async Task SKSequentialOrchestration()
30+
{
31+
SequentialOrchestration orchestration = new([
32+
GetSKTranslationAgent("French"),
33+
GetSKTranslationAgent("Spanish"),
34+
GetSKTranslationAgent("English")])
35+
{
36+
StreamingResponseCallback = StreamingResultCallback,
37+
};
38+
39+
InProcessRuntime runtime = new();
40+
await runtime.StartAsync();
41+
42+
// Run the orchestration
43+
OrchestrationResult<string> result = await orchestration.InvokeAsync("Hello, world!", runtime);
44+
string text = await result.GetValueAsync(TimeSpan.FromSeconds(20));
45+
46+
await runtime.RunUntilIdleAsync();
47+
}
48+
#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.
49+
50+
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
51+
{
52+
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
53+
return new ChatCompletionAgent()
54+
{
55+
Kernel = kernel,
56+
Instructions = string.Format(agentInstructions, targetLanguage),
57+
Description = $"Agent that translates texts to {targetLanguage}",
58+
Name = $"SKTranslationAgent_{targetLanguage}"
59+
};
60+
}
61+
62+
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
63+
{
64+
Console.Write(streamedResponse.Content);
65+
66+
if (isFinal)
67+
{
68+
Console.WriteLine();
69+
}
70+
71+
return ValueTask.CompletedTask;
72+
}
73+
# endregion
74+
75+
# region AFSequentialAgentWorkflow
76+
async Task AFSequentialAgentWorkflow()
77+
{
78+
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
79+
var frenchAgent = GetAFTranslationAgent("French", client);
80+
var spanishAgent = GetAFTranslationAgent("Spanish", client);
81+
var englishAgent = GetAFTranslationAgent("English", client);
82+
var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential(
83+
[frenchAgent, spanishAgent, englishAgent]);
84+
85+
await using StreamingRun run = await InProcessExecution.StreamAsync(sequentialAgentWorkflow, "Hello, world!");
86+
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
87+
88+
string? lastExecutorId = null;
89+
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
90+
{
91+
if (evt is AgentRunUpdateEvent e)
92+
{
93+
if (string.IsNullOrEmpty(e.Update.Text))
94+
{
95+
continue;
96+
}
97+
98+
if (e.ExecutorId != lastExecutorId)
99+
{
100+
lastExecutorId = e.ExecutorId;
101+
Console.WriteLine();
102+
Console.Write($"{e.Update.AuthorName}: ");
103+
}
104+
105+
Console.Write(e.Update.Text);
106+
}
107+
}
108+
}
109+
110+
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
111+
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
112+
# endregion
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<NoWarn>$(NoWarn);CA1812;RCS1102;CA1707;VSTHRD200</NoWarn>
9+
<InjectSharedThrow>true</InjectSharedThrow>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.SemanticKernel" VersionOverride="1.*" />
14+
<PackageReference Include="Microsoft.SemanticKernel.Agents.AzureAI" VersionOverride="1.*-*" />
15+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" VersionOverride="1.*" />
16+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Orchestration" VersionOverride="1.*-*" />
17+
<PackageReference Include="Microsoft.SemanticKernel.Agents.Runtime.InProcess" VersionOverride="1.*-*" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
22+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
23+
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj" />
24+
</ItemGroup>
25+
26+
</Project>

0 commit comments

Comments
 (0)