diff --git a/.github/upgrades/prompts/SemanticKernelToAgentFramework.md b/.github/upgrades/prompts/SemanticKernelToAgentFramework.md index 1b28626ea8..a8c3dcb0a6 100644 --- a/.github/upgrades/prompts/SemanticKernelToAgentFramework.md +++ b/.github/upgrades/prompts/SemanticKernelToAgentFramework.md @@ -142,9 +142,9 @@ Replace these Semantic Kernel agent classes with their Agent Framework equivalen |----------------------|----------------------------|-------------------| | `IChatCompletionService` | `IChatClient` | Convert to `IChatClient` using `chatService.AsChatClient()` extensions | | `ChatCompletionAgent` | `ChatClientAgent` | Remove `Kernel` parameter, add `IChatClient` parameter | -| `OpenAIAssistantAgent` | `AIAgent` (via extension) | **New**: `OpenAIClient.GetAssistantClient().CreateAIAgent()`
**Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` | +| `OpenAIAssistantAgent` | `AIAgent` (via extension) | ⚠️ **Deprecated** - Use Responses API instead.
**New**: `OpenAIClient.GetAssistantClient().CreateAIAgent()`
**Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` | | `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.CreateAIAgent()`
**Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` | -| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetOpenAIResponseClient().CreateAIAgent()` | +| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetOpenAIResponseClient(modelId).CreateAIAgent()` | | `A2AAgent` | `AIAgent` (via extension) | Replace with `A2ACardResolver.GetAIAgentAsync()` | | `BedrockAgent` | Not supported | Custom implementation required | @@ -529,14 +529,14 @@ AIAgent agent = new OpenAIClient(apiKey) .CreateAIAgent(instructions: instructions); ``` -**OpenAI Assistants (New):** +**OpenAI Assistants (New):** ⚠️ *Deprecated - Use Responses API instead* ```csharp AIAgent agent = new OpenAIClient(apiKey) .GetAssistantClient() .CreateAIAgent(modelId, instructions: instructions); ``` -**OpenAI Assistants (Existing):** +**OpenAI Assistants (Existing):** ⚠️ *Deprecated - Use Responses API instead* ```csharp AIAgent agent = new OpenAIClient(apiKey) .GetAssistantClient() @@ -562,6 +562,20 @@ AIAgent agent = await new PersistentAgentsClient(endpoint, credential) .GetAIAgentAsync(agentId); ``` +**OpenAI Responses:** *(Recommended for OpenAI)* +```csharp +AIAgent agent = new OpenAIClient(apiKey) + .GetOpenAIResponseClient(modelId) + .CreateAIAgent(instructions: instructions); +``` + +**Azure OpenAI Responses:** *(Recommended for Azure OpenAI)* +```csharp +AIAgent agent = new AzureOpenAIClient(endpoint, credential) + .GetOpenAIResponseClient(deploymentName) + .CreateAIAgent(instructions: instructions); +``` + **A2A:** ```csharp A2ACardResolver resolver = new(new Uri(agentHost)); @@ -762,35 +776,57 @@ await foreach (var content in agent.InvokeAsync(userInput, thread)) **With this Agent Framework CodeInterpreter pattern:** ```csharp +using System.Text; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + var result = await agent.RunAsync(userInput, thread); Console.WriteLine(result); -// Extract chat response MEAI type via first level breaking glass -var chatResponse = result.RawRepresentation as ChatResponse; +// Get the CodeInterpreterToolCallContent (code input) +CodeInterpreterToolCallContent? toolCallContent = result.Messages + .SelectMany(m => m.Contents) + .OfType() + .FirstOrDefault(); + +if (toolCallContent?.Inputs is not null) +{ + DataContent? codeInput = toolCallContent.Inputs.OfType().FirstOrDefault(); + if (codeInput?.HasTopLevelMediaType("text") ?? false) + { + Console.WriteLine($"Code Input: {Encoding.UTF8.GetString(codeInput.Data.ToArray())}"); + } +} -// Extract underlying SDK updates via second level breaking glass -var underlyingStreamingUpdates = chatResponse?.RawRepresentation as IEnumerable ?? []; +// Get the CodeInterpreterToolResultContent (code output) +CodeInterpreterToolResultContent? toolResultContent = result.Messages + .SelectMany(m => m.Contents) + .OfType() + .FirstOrDefault(); -StringBuilder generatedCode = new(); -foreach (object? underlyingUpdate in underlyingStreamingUpdates ?? []) +if (toolResultContent?.Outputs is not null) { - if (underlyingUpdate is RunStepDetailsUpdate stepDetailsUpdate && stepDetailsUpdate.CodeInterpreterInput is not null) + TextContent? resultOutput = toolResultContent.Outputs.OfType().FirstOrDefault(); + if (resultOutput is not null) { - generatedCode.Append(stepDetailsUpdate.CodeInterpreterInput); + Console.WriteLine($"Code Tool Result: {resultOutput.Text}"); } } -if (!string.IsNullOrEmpty(generatedCode.ToString())) +// Getting any annotations generated by the tool +foreach (AIAnnotation annotation in result.Messages + .SelectMany(m => m.Contents) + .SelectMany(c => c.Annotations ?? [])) { - Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}"); + Console.WriteLine($"Annotation: {annotation}"); } ``` **Functional differences:** -1. Code interpreter output is separate from text content, not a metadata property -2. Access code via `RunStepDetailsUpdate.CodeInterpreterInput` instead of metadata -3. Use breaking glass pattern to access underlying SDK objects -4. Process text content and code interpreter output independently +1. Code interpreter content is now available via MEAI abstractions - no breaking glass required +2. Use `CodeInterpreterToolCallContent` to access code inputs (the generated code) +3. Use `CodeInterpreterToolResultContent` to access code outputs (execution results) +4. Annotations are accessible via `AIAnnotation` on content items #### Provider-Specific Options Configuration @@ -980,6 +1016,8 @@ AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential( ### 3. OpenAI Assistants Migration +> ⚠️ **DEPRECATION WARNING**: The OpenAI Assistants API has been deprecated. The Agent Framework extension methods for Assistants are marked as `[Obsolete]`. **Please use the Responses API instead** (see Section 6: OpenAI Responses Migration). + **Remove Semantic Kernel Packages:** ```xml @@ -1291,52 +1329,7 @@ var result = await agent.RunAsync(userInput, thread); ``` -### 8. A2A Migration - - -**Remove Semantic Kernel Packages:** -```xml - -``` - -**Add Agent Framework Packages:** -```xml - -``` - - - -**Replace this Semantic Kernel pattern:** -```csharp -using A2A; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents; -using Microsoft.SemanticKernel.Agents.A2A; - -using var httpClient = CreateHttpClient(); -var client = new A2AClient(agentUrl, httpClient); -var cardResolver = new A2ACardResolver(url, httpClient); -var agentCard = await cardResolver.GetAgentCardAsync(); -Console.WriteLine(JsonSerializer.Serialize(agentCard, s_jsonSerializerOptions)); -var agent = new A2AAgent(client, agentCard); -``` - -**With this Agent Framework pattern:** -```csharp -using System; -using A2A; -using Microsoft.Agents.AI; -using Microsoft.Agents.AI.A2A; - -// Initialize an A2ACardResolver to get an A2A agent card. -A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost)); - -// Create an instance of the AIAgent for an existing A2A agent specified by the agent card. -AIAgent agent = await agentCardResolver.GetAIAgentAsync(); -``` - - -### 9. Unsupported Providers (Require Custom Implementation) +### 8. Unsupported Providers (Require Custom Implementation) #### BedrockAgent Migration @@ -1507,7 +1500,7 @@ Console.WriteLine(result); ``` -### 10. Function Invocation Filtering +### 9. Function Invocation Filtering **Invocation Context** @@ -1615,25 +1608,4 @@ var filteredAgent = originalAgent .Build(); ``` -### 11. Function Invocation Contexts -**Invocation Context** - -Semantic Kernel's `IAutoFunctionInvocationFilter` provides a `AutoFunctionInvocationContext` where Agent Framework provides `FunctionInvocationContext` - -The property mapping guide from a `AutoFunctionInvocationContext` to a `FunctionInvocationContext` is as follows: - -| Semantic Kernel | Agent Framework | -| --- | --- | -| RequestSequenceIndex | Iteration | -| FunctionSequenceIndex | FunctionCallIndex | -| ToolCallId | CallContent.CallId | -| ChatMessageContent | Messages[0] | -| ExecutionSettings | Options | -| ChatHistory | Messages | -| Function | Function | -| Kernel | N/A | -| Result | Use `return` from the delegate | -| Terminate | Terminate | -| CancellationToken | provided via argument to middleware delegate | -| Arguments | Arguments |