mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
## Description Updates the SK → Agent Framework migration document, samples, and bridge code from AF preview (`1.0.0-preview.251009.1`) to GA (`1.0.0`). ### Breaking changes addressed | Preview API | AF 1.0 GA | Scope | |---|---|---| | `AgentThread` | `AgentSession` | Core type rename | | `GetNewThread()` | `CreateSessionAsync()` | Now async | | `AgentRunResponse` | `AgentResponse` | Return type rename | | `AgentRunResponseUpdate` | `AgentResponseUpdate` | Streaming type rename | | `CreateAIAgent()` | `AsAIAgent()` | Extension method rename | | `AssistantClient.CreateAIAgentAsync()` | **Removed** | Redirect to Responses API | | `PersistentAgentsClient` | **Obsolete** | Use `AIProjectClient` via `Microsoft.Agents.AI.Foundry` | | `Microsoft.Agents.AI.AzureAI` | `Microsoft.Agents.AI.Foundry` | Package rename | | `InProcessExecution.StreamAsync` | `RunStreamingAsync` | Workflow API | | `AgentRunUpdateEvent` | `AgentResponseUpdateEvent` | Workflow event | | `AIAgent.Id` (virtual) | `IdCore` (protected virtual) | Override pattern | ### Additional discoveries - `using OpenAI.Chat;` required for `ChatClient.AsAIAgent()` extension to resolve - `using OpenAI.Responses;` required for `ResponsesClient.AsAIAgent()` extension to resolve ### What changed **Package versions** (`dotnet/Directory.Packages.props`) - AF packages updated to `1.0.0` - `Microsoft.Agents.AI.AzureAI` → `Microsoft.Agents.AI.Foundry` **Bridge code** (`dotnet/src/Agents/Abstractions/AIAgent/`) - `SemanticKernelAIAgent.cs`: New `Core` method overrides (`CreateSessionCoreAsync`, `RunCoreAsync`, etc.) - `SemanticKernelAIAgentThread` → `SemanticKernelAIAgentSession` (extends `AgentSession`) **31 migration samples** (all compile ✅) - OpenAI/AzureOpenAI: `AsAIAgent`, `CreateSessionAsync`, `using OpenAI.Chat;` - Assistants (8): AF sections rewritten to Responses API - Responses (8): Direct `ResponsesClient.AsAIAgent()` - Foundry (4): `AIProjectClient.AsAIAgent()` via `Microsoft.Agents.AI.Foundry` - Orchestrations (3): `RunStreamingAsync`, `AgentResponseUpdateEvent` **Migration document** (`.github/upgrades/prompts/SemanticKernelToAgentFramework.md`) - All AF preview API references updated to 1.0 GA patterns **Unit/integration tests** (~15 files) - Mechanical renames for `AgentSession`, `AgentResponse`, `CreateSessionAsync` ### Validation 8 standalone console programs were created and executed against AF 1.0.0 NuGet packages with real API keys, validating all migration patterns end-to-end: 1. OpenAI Basics (ChatClient → AsAIAgent, CreateSessionAsync, Run/RunStreaming) 2. OpenAI ToolCall (AIFunctionFactory.Create, tool invocation) 3. OpenAI DI (ServiceProvider registration) 4. OpenAI Responses (ResponsesClient.AsAIAgent) 5. Azure AI Foundry (AIProjectClient.AsAIAgent) 6. Workflows Handoff (HandoffWorkflowBuilder, InProcessExecution.RunStreamingAsync) 7. Session Lifecycle (Create, Serialize, Deserialize, multi-turn) 8. Assistants Migration Path (Responses API as replacement) --------- Co-authored-by: Copilot <[email protected]>
113 lines
4.3 KiB
C#
113 lines
4.3 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using Azure.AI.OpenAI;
|
|
using Azure.Identity;
|
|
using Microsoft.Agents.AI;
|
|
using Microsoft.Agents.AI.Workflows;
|
|
using Microsoft.Extensions.AI;
|
|
using Microsoft.SemanticKernel;
|
|
using Microsoft.SemanticKernel.Agents;
|
|
using Microsoft.SemanticKernel.Agents.Orchestration;
|
|
using Microsoft.SemanticKernel.Agents.Orchestration.Sequential;
|
|
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
|
|
|
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
|
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
|
|
|
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}.";
|
|
|
|
// This sample compares running sequential orchestrations using
|
|
// Semantic Kernel and the Agent Framework.
|
|
Console.WriteLine("=== Semantic Kernel Sequential Orchestration ===");
|
|
await SKSequentialOrchestration();
|
|
|
|
Console.WriteLine("\n=== Agent Framework Sequential Agent Workflow ===");
|
|
await AFSequentialAgentWorkflow();
|
|
|
|
# region SKSequentialOrchestration
|
|
#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.
|
|
async Task SKSequentialOrchestration()
|
|
{
|
|
SequentialOrchestration orchestration = new([
|
|
GetSKTranslationAgent("French"),
|
|
GetSKTranslationAgent("Spanish"),
|
|
GetSKTranslationAgent("English")])
|
|
{
|
|
StreamingResponseCallback = StreamingResultCallback,
|
|
};
|
|
|
|
InProcessRuntime runtime = new();
|
|
await runtime.StartAsync();
|
|
|
|
// Run the orchestration
|
|
OrchestrationResult<string> result = await orchestration.InvokeAsync("Hello, world!", runtime);
|
|
string text = await result.GetValueAsync(TimeSpan.FromSeconds(20));
|
|
|
|
await runtime.RunUntilIdleAsync();
|
|
}
|
|
#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.
|
|
|
|
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
|
|
{
|
|
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
|
return new ChatCompletionAgent()
|
|
{
|
|
Kernel = kernel,
|
|
Instructions = string.Format(agentInstructions, targetLanguage),
|
|
Description = $"Agent that translates texts to {targetLanguage}",
|
|
Name = $"SKTranslationAgent_{targetLanguage}"
|
|
};
|
|
}
|
|
|
|
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
|
{
|
|
Console.Write(streamedResponse.Content);
|
|
|
|
if (isFinal)
|
|
{
|
|
Console.WriteLine();
|
|
}
|
|
|
|
return ValueTask.CompletedTask;
|
|
}
|
|
# endregion
|
|
|
|
# region AFSequentialAgentWorkflow
|
|
async Task AFSequentialAgentWorkflow()
|
|
{
|
|
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
|
var frenchAgent = GetAFTranslationAgent("French", client);
|
|
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
|
var englishAgent = GetAFTranslationAgent("English", client);
|
|
var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential(
|
|
[frenchAgent, spanishAgent, englishAgent]);
|
|
|
|
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(sequentialAgentWorkflow, "Hello, world!");
|
|
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
|
|
|
string? lastExecutorId = null;
|
|
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
|
{
|
|
if (evt is AgentResponseUpdateEvent e)
|
|
{
|
|
if (string.IsNullOrEmpty(e.Update.Text))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (e.ExecutorId != lastExecutorId)
|
|
{
|
|
lastExecutorId = e.ExecutorId;
|
|
Console.WriteLine();
|
|
Console.Write($"{e.Update.AuthorName}: ");
|
|
}
|
|
|
|
Console.Write(e.Update.Text);
|
|
}
|
|
}
|
|
}
|
|
|
|
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
|
|
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
|
|
# endregion
|