Skip to content
Closed
30 changes: 15 additions & 15 deletions .github/upgrades/prompts/SemanticKernelToAgentFramework.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ After completing migration, verify these specific items:
1. **Compilation**: Execute `dotnet build` on all modified projects - zero errors required
2. **Namespace Updates**: Confirm all `using Microsoft.SemanticKernel.Agents` statements are replaced
3. **Method Calls**: Verify all `InvokeAsync` calls are changed to `RunAsync`
4. **Return Types**: Confirm handling of `AgentRunResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
4. **Return Types**: Confirm handling of `AgentResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
5. **Thread Creation**: Validate all thread creation uses `agent.GetNewThread()` pattern
6. **Tool Registration**: Ensure `[KernelFunction]` attributes are removed and `AIFunctionFactory.Create()` is used
7. **Options Configuration**: Verify `AgentRunOptions` or `ChatClientAgentRunOptions` replaces `AgentInvokeOptions`
Expand All @@ -119,7 +119,7 @@ Agent Framework provides functionality for creating and managing AI agents throu
Key API differences:
- Agent creation: Remove Kernel dependency, use direct client-based creation
- Method names: `InvokeAsync` → `RunAsync`, `InvokeStreamingAsync` → `RunStreamingAsync`
- Return types: `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentRunResponse`
- Return types: `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentResponse`
- Thread creation: Provider-specific constructors → `agent.GetNewThread()`
- Tool registration: `KernelPlugin` system → Direct `AIFunction` registration
- Options: `AgentInvokeOptions` → Provider-specific run options (e.g., `ChatClientAgentRunOptions`)
Expand Down Expand Up @@ -166,8 +166,8 @@ Replace these method calls:
| `thread.DeleteAsync()` | Provider-specific cleanup | Use provider client directly |

Return type changes:
- `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentRunResponse`
- `IAsyncEnumerable<StreamingChatMessageContent>` → `IAsyncEnumerable<AgentRunResponseUpdate>`
- `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentResponse`
- `IAsyncEnumerable<StreamingChatMessageContent>` → `IAsyncEnumerable<AgentResponseUpdate>`
</api_changes>

<configuration_changes>
Expand All @@ -191,8 +191,8 @@ Agent Framework changes these behaviors compared to Semantic Kernel Agents:
1. **Thread Management**: Agent Framework automatically manages thread state. Semantic Kernel required manual thread updates in some scenarios (e.g., OpenAI Responses).

2. **Return Types**:
- Non-streaming: Returns single `AgentRunResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
- Streaming: Returns `IAsyncEnumerable<AgentRunResponseUpdate>` instead of `IAsyncEnumerable<StreamingChatMessageContent>`
- Non-streaming: Returns single `AgentResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
- Streaming: Returns `IAsyncEnumerable<AgentResponseUpdate>` instead of `IAsyncEnumerable<StreamingChatMessageContent>`

3. **Tool Registration**: Agent Framework uses direct function registration without requiring `[KernelFunction]` attributes.

Expand Down Expand Up @@ -397,7 +397,7 @@ await foreach (AgentResponseItem<ChatMessageContent> item in agent.InvokeAsync(u

**With this Agent Framework non-streaming pattern:**
```csharp
AgentRunResponse result = await agent.RunAsync(userInput, thread, options);
AgentResponse result = await agent.RunAsync(userInput, thread, options);
Console.WriteLine(result);
```

Expand All @@ -411,7 +411,7 @@ await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(

**With this Agent Framework streaming pattern:**
```csharp
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInput, thread, options))
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(userInput, thread, options))
{
Console.Write(update);
}
Expand All @@ -420,8 +420,8 @@ await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInpu
**Required changes:**
1. Replace `agent.InvokeAsync()` with `agent.RunAsync()`
2. Replace `agent.InvokeStreamingAsync()` with `agent.RunStreamingAsync()`
3. Change return type handling from `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` to `AgentRunResponse`
4. Change streaming type from `StreamingChatMessageContent` to `AgentRunResponseUpdate`
3. Change return type handling from `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` to `AgentResponse`
4. Change streaming type from `StreamingChatMessageContent` to `AgentResponseUpdate`
5. Remove `await foreach` for non-streaming calls
6. Access message content directly from result object instead of iterating
</api_changes>
Expand Down Expand Up @@ -661,7 +661,7 @@ await foreach (var result in agent.InvokeAsync(input, thread, options))
```csharp
ChatClientAgentRunOptions options = new(new ChatOptions { MaxOutputTokens = 1000 });

AgentRunResponse result = await agent.RunAsync(input, thread, options);
AgentResponse result = await agent.RunAsync(input, thread, options);
Console.WriteLine(result);

// Access underlying content when needed:
Expand Down Expand Up @@ -689,7 +689,7 @@ await foreach (var result in agent.InvokeAsync(input, thread, options))

**With this Agent Framework non-streaming usage pattern:**
```csharp
AgentRunResponse result = await agent.RunAsync(input, thread, options);
AgentResponse result = await agent.RunAsync(input, thread, options);
Console.WriteLine($"Tokens: {result.Usage.TotalTokenCount}");
```

Expand All @@ -709,7 +709,7 @@ await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsyn

**With this Agent Framework streaming usage pattern:**
```csharp
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(input, thread, options))
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(input, thread, options))
{
if (update.Contents.OfType<UsageContent>().FirstOrDefault() is { } usageContent)
{
Expand All @@ -734,10 +734,10 @@ await foreach (var content in agent.InvokeAsync(userInput, thread))

**With this Agent Framework breaking glass pattern:**
```csharp
var agentRunResponse = await agent.RunAsync(userInput, thread);
var agentResponse = await agent.RunAsync(userInput, thread);

// If the agent uses a ChatClient the first breaking glass probably will be a Microsoft.Extensions.AI.ChatResponse
ChatResponse? chatResponse = agentRunResponse.RawRepresentation as ChatResponse;
ChatResponse? chatResponse = agentResponse.RawRepresentation as ChatResponse;

// If thats the case, to access the underlying SDK types you will need to break glass again.
UnderlyingSdkType? underlyingChatMessage = chatResponse?.RawRepresentation as UnderlyingSdkType;
Expand Down
10 changes: 5 additions & 5 deletions docs/specs/001-foundry-sdk-alignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ The proposed solution is to add helper methods which allow developers to either
- [Foundry SDK] Create a `PersistentAgentsClient`
- [Foundry SDK] Create a `PersistentAgent` using the `PersistentAgentsClient`
- [Foundry SDK] Retrieve an `AIAgent` using the `PersistentAgentsClient`
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentRunResponse`
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentResponse`
- [Foundry SDK] Clean up the agent


Expand Down Expand Up @@ -156,7 +156,7 @@ await persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);

- [Foundry SDK] Create a `PersistentAgentsClient`
- [Foundry SDK] Create a `AIAgent` using the `PersistentAgentsClient`
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentRunResponse`
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentResponse`
- [Foundry SDK] Clean up the agent

```csharp
Expand Down Expand Up @@ -184,7 +184,7 @@ await persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
- [Foundry SDK] Create a `PersistentAgentsClient`
- [Foundry SDK] Create a `AIAgent` using the `PersistentAgentsClient`
- [Agent Framework SDK] Optionally create an `AgentThread` for the agent run
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentRunResponse`
- [Agent Framework SDK] Invoke the `AIAgent` instance and access response from the `AgentResponse`
- [Foundry SDK] Clean up the agent and the agent thread

```csharp
Expand Down Expand Up @@ -227,7 +227,7 @@ await persistentAgentsClient.Administration.DeleteAgentAsync(agent.Id);
- [Foundry SDK] Create a `PersistentAgentsClient`
- [Foundry SDK] Create multiple `AIAgent` instances using the `PersistentAgentsClient`
- [Agent Framework SDK] Create a `SequentialOrchestration` and add all of the agents to it
- [Agent Framework SDK] Invoke the `SequentialOrchestration` instance and access response from the `AgentRunResponse`
- [Agent Framework SDK] Invoke the `SequentialOrchestration` instance and access response from the `AgentResponse`
- [Foundry SDK] Clean up the agents

```csharp
Expand Down Expand Up @@ -281,7 +281,7 @@ SequentialOrchestration orchestration =
// Run the orchestration
string input = "An eco-friendly stainless steel water bottle that keeps drinks cold for 24 hours";
Console.WriteLine($"\n# INPUT: {input}\n");
AgentRunResponse result = await orchestration.RunAsync(input);
AgentResponse result = await orchestration.RunAsync(input);
Console.WriteLine($"\n# RESULT: {result}");

// Cleanup
Expand Down
2 changes: 1 addition & 1 deletion dotnet/samples/AGUIClientServer/AGUIClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private static async Task HandleCommandsAsync(CancellationToken cancellationToke
bool isFirstUpdate = true;
string? threadId = null;
var updates = new List<ChatResponseUpdate>();
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(messages, thread, cancellationToken: cancellationToken))
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, thread, cancellationToken: cancellationToken))
{
// Use AsChatResponseUpdate to access ChatResponseUpdate properties
ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public AgenticUIAgent(AIAgent innerAgent, JsonSerializerOptions jsonSerializerOp
this._jsonSerializerOptions = jsonSerializerOptions;
}

protected override Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
protected override Task<AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
{
return this.RunCoreStreamingAsync(messages, thread, options, cancellationToken).ToAgentRunResponseAsync(cancellationToken);
return this.RunCoreStreamingAsync(messages, thread, options, cancellationToken).ToAgentResponseAsync(cancellationToken);
}

protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
IEnumerable<ChatMessage> messages,
AgentThread? thread = null,
AgentRunOptions? options = null,
Expand Down Expand Up @@ -69,7 +69,7 @@ protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreami

yield return update;

yield return new AgentRunResponseUpdate(
yield return new AgentResponseUpdate(
new ChatResponseUpdate(role: ChatRole.System, stateEventsToEmit)
{
MessageId = "delta_" + Guid.NewGuid().ToString("N"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public PredictiveStateUpdatesAgent(AIAgent innerAgent, JsonSerializerOptions jso
this._jsonSerializerOptions = jsonSerializerOptions;
}

protected override Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
protected override Task<AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
{
return this.RunCoreStreamingAsync(messages, thread, options, cancellationToken).ToAgentRunResponseAsync(cancellationToken);
return this.RunCoreStreamingAsync(messages, thread, options, cancellationToken).ToAgentResponseAsync(cancellationToken);
}

protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
IEnumerable<ChatMessage> messages,
AgentThread? thread = null,
AgentRunOptions? options = null,
Expand Down Expand Up @@ -79,7 +79,7 @@ protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreami
stateUpdate,
this._jsonSerializerOptions.GetTypeInfo(typeof(DocumentState)));

yield return new AgentRunResponseUpdate(
yield return new AgentResponseUpdate(
new ChatResponseUpdate(role: ChatRole.Assistant, [new DataContent(stateBytes, "application/json")])
{
MessageId = "snapshot" + Guid.NewGuid().ToString("N"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public SharedStateAgent(AIAgent innerAgent, JsonSerializerOptions jsonSerializer
this._jsonSerializerOptions = jsonSerializerOptions;
}

protected override Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
protected override Task<AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
{
return this.RunCoreStreamingAsync(messages, thread, options, cancellationToken).ToAgentRunResponseAsync(cancellationToken);
return this.RunCoreStreamingAsync(messages, thread, options, cancellationToken).ToAgentResponseAsync(cancellationToken);
}

protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
IEnumerable<ChatMessage> messages,
AgentThread? thread = null,
AgentRunOptions? options = null,
Expand Down Expand Up @@ -63,7 +63,7 @@ protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreami

var firstRunMessages = messages.Append(stateUpdateMessage);

var allUpdates = new List<AgentRunResponseUpdate>();
var allUpdates = new List<AgentResponseUpdate>();
await foreach (var update in this.InnerAgent.RunStreamingAsync(firstRunMessages, thread, firstRunOptions, cancellationToken).ConfigureAwait(false))
{
allUpdates.Add(update);
Expand All @@ -76,14 +76,14 @@ protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreami
}
}

var response = allUpdates.ToAgentRunResponse();
var response = allUpdates.ToAgentResponse();

if (response.TryDeserialize(this._jsonSerializerOptions, out JsonElement stateSnapshot))
{
byte[] stateBytes = JsonSerializer.SerializeToUtf8Bytes(
stateSnapshot,
this._jsonSerializerOptions.GetTypeInfo(typeof(JsonElement)));
yield return new AgentRunResponseUpdate
yield return new AgentResponseUpdate
{
Contents = [new DataContent(stateBytes, "application/json")]
};
Expand Down
10 changes: 5 additions & 5 deletions dotnet/samples/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public A2AAgentClient(ILogger logger, Uri baseUri)
this._uri = baseUri;
}

public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public override async IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
Expand All @@ -37,7 +37,7 @@ public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync
var contextId = threadId ?? Guid.NewGuid().ToString("N");

// Convert and send messages via A2A without try-catch in yield method
var results = new List<AgentRunResponseUpdate>();
var results = new List<AgentResponseUpdate>();

try
{
Expand All @@ -60,7 +60,7 @@ public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync
var responseMessage = message.ToChatMessage();
if (responseMessage is { Contents.Count: > 0 })
{
results.Add(new AgentRunResponseUpdate(responseMessage.Role, responseMessage.Contents)
results.Add(new AgentResponseUpdate(responseMessage.Role, responseMessage.Contents)
{
MessageId = message.MessageId,
CreatedAt = DateTimeOffset.UtcNow
Expand Down Expand Up @@ -90,7 +90,7 @@ public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync
RawRepresentation = artifact,
};

results.Add(new AgentRunResponseUpdate(chatMessage.Role, chatMessage.Contents)
results.Add(new AgentResponseUpdate(chatMessage.Role, chatMessage.Contents)
{
MessageId = agentTask.Id,
CreatedAt = DateTimeOffset.UtcNow
Expand All @@ -108,7 +108,7 @@ public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync
{
this._logger.LogError(ex, "Error running agent {AgentName} via A2A", agentName);

results.Add(new AgentRunResponseUpdate(ChatRole.Assistant, $"Error: {ex.Message}")
results.Add(new AgentResponseUpdate(ChatRole.Assistant, $"Error: {ex.Message}")
{
MessageId = Guid.NewGuid().ToString("N"),
CreatedAt = DateTimeOffset.UtcNow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal abstract class AgentClientBase
/// <param name="threadId">Optional thread identifier for conversation continuity.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>An asynchronous enumerable of agent response updates.</returns>
public abstract IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public abstract IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace AgentWebChat.Web;
/// </summary>
internal sealed class OpenAIChatCompletionsAgentClient(HttpClient httpClient) : AgentClientBase
{
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
public override async IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
string agentName,
IList<ChatMessage> messages,
string? threadId = null,
Expand All @@ -31,7 +31,7 @@ public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync
var openAiClient = new ChatClient(model: "myModel!", credential: new ApiKeyCredential("dummy-key"), options: options).AsIChatClient();
await foreach (var update in openAiClient.GetStreamingResponseAsync(messages, cancellationToken: cancellationToken))
{
yield return new AgentRunResponseUpdate(update);
yield return new AgentResponseUpdate(update);
}
}
}
Loading