Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 58 additions & 86 deletions .github/upgrades/prompts/SemanticKernelToAgentFramework.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()` <br> **Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` |
| `OpenAIAssistantAgent` | `AIAgent` (via extension) | ⚠️ **Deprecated** - Use Responses API instead. <br> **New**: `OpenAIClient.GetAssistantClient().CreateAIAgent()` <br> **Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` |
| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.CreateAIAgent()` <br> **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 |

Expand Down Expand Up @@ -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()
Expand All @@ -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));
Expand Down Expand Up @@ -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<CodeInterpreterToolCallContent>()
.FirstOrDefault();

if (toolCallContent?.Inputs is not null)
{
DataContent? codeInput = toolCallContent.Inputs.OfType<DataContent>().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<object?> ?? [];
// Get the CodeInterpreterToolResultContent (code output)
CodeInterpreterToolResultContent? toolResultContent = result.Messages
.SelectMany(m => m.Contents)
.OfType<CodeInterpreterToolResultContent>()
.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<TextContent>().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
</behavioral_changes>

#### Provider-Specific Options Configuration
Expand Down Expand Up @@ -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).

<configuration_changes>
**Remove Semantic Kernel Packages:**
```xml
Expand Down Expand Up @@ -1291,52 +1329,7 @@ var result = await agent.RunAsync(userInput, thread);
```
</api_changes>

### 8. A2A Migration

<configuration_changes>
**Remove Semantic Kernel Packages:**
```xml
<PackageReference Include="Microsoft.SemanticKernel.Agents.A2A" />
```

**Add Agent Framework Packages:**
```xml
<PackageReference Include="Microsoft.Agents.AI.A2A" />
```
</configuration_changes>

<api_changes>
**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();
```
</api_changes>

### 9. Unsupported Providers (Require Custom Implementation)
### 8. Unsupported Providers (Require Custom Implementation)

<behavioral_changes>
#### BedrockAgent Migration
Expand Down Expand Up @@ -1507,7 +1500,7 @@ Console.WriteLine(result);
```
</behavioral_changes>

### 10. Function Invocation Filtering
### 9. Function Invocation Filtering

**Invocation Context**

Expand Down Expand Up @@ -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 |