diff --git a/.github/upgrades/prompts/SemanticKernelToAgentFramework.md b/.github/upgrades/prompts/SemanticKernelToAgentFramework.md index cd5a54de1d49..6644b3b1e001 100644 --- a/.github/upgrades/prompts/SemanticKernelToAgentFramework.md +++ b/.github/upgrades/prompts/SemanticKernelToAgentFramework.md @@ -1,4 +1,4 @@ -# Instructions for migrating from Semantic Kernel Agents to Agent Framework in .NET projects. +# Instructions for migrating from Semantic Kernel Agents to Agent Framework in .NET projects. ## Scope @@ -22,13 +22,13 @@ For each project that needs to be migrated, you need to do the following: solution or you could not find the project, notify user and continue with other projects). - Identify the specific Semantic Kernel agent types being used: - `ChatCompletionAgent` → `ChatClientAgent` - - `OpenAIAssistantAgent` → `assistantsClient.CreateAIAgent()` (via OpenAI Assistants client extension) - - `AzureAIAgent` → `persistentAgentsClient.CreateAIAgent()` (via Azure AI Foundry client extension) - - `OpenAIResponseAgent` → `responsesClient.CreateAIAgent()` (via OpenAI Responses client extension) + - `OpenAIAssistantAgent` → `assistantsClient.AsAIAgent()` (via OpenAI Assistants client extension) + - `AzureAIAgent` → `persistentAgentsClient.AsAIAgent()` (via Azure AI Foundry client extension) + - `OpenAIResponseAgent` → `responsesClient.AsAIAgent()` (via OpenAI Responses client extension) - `A2AAgent` → `AIAgent` (via A2A card resolver) - `BedrockAgent` → Custom implementation required (not supported) - Determine if agents are being created new or retrieved from hosted services: - - **New agents**: Use `CreateAIAgent()` methods + - **New agents**: Use `AsAIAgent()` methods - **Existing hosted agents**: Use `GetAIAgent(agentId)` methods for OpenAI Assistants and Azure AI Foundry @@ -105,8 +105,8 @@ 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>` -5. **Thread Creation**: Validate all thread creation uses `agent.GetNewThread()` pattern +4. **Return Types**: Confirm handling of `AgentResponse` instead of `IAsyncEnumerable>` +5. **Thread Creation**: Validate all thread creation uses `agent.CreateSessionAsync()` pattern 6. **Tool Registration**: Ensure `[KernelFunction]` attributes are removed and `AIFunctionFactory.Create()` is used 7. **Options Configuration**: Verify `AgentRunOptions` or `ChatClientAgentRunOptions` replaces `AgentInvokeOptions` 8. **Breaking Glass**: Test `RawRepresentation` access replaces `InnerContent` access @@ -119,8 +119,8 @@ 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>` → `AgentRunResponse` -- Thread creation: Provider-specific constructors → `agent.GetNewThread()` +- Return types: `IAsyncEnumerable>` → `AgentResponse` +- Thread creation: Provider-specific constructors → `agent.CreateSessionAsync()` - Tool registration: `KernelPlugin` system → Direct `AIFunction` registration - Options: `AgentInvokeOptions` → Provider-specific run options (e.g., `ChatClientAgentRunOptions`) @@ -142,14 +142,14 @@ 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)` | -| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.CreateAIAgent()`
**Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` | -| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetOpenAIResponseClient().CreateAIAgent()` | +| `OpenAIAssistantAgent` | `AIAgent` (via extension) | **New**: `OpenAIClient.GetAssistantClient().AsAIAgent()`
**Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` | +| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.AsAIAgent()`
**Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` | +| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetResponsesClient().AsAIAgent()` | | `A2AAgent` | `AIAgent` (via extension) | Replace with `A2ACardResolver.GetAIAgentAsync()` | | `BedrockAgent` | Not supported | Custom implementation required | **Important distinction:** -- **CreateAIAgent()**: Use when creating new agents in the hosted service +- **AsAIAgent()**: Use when creating new agents in the hosted service - **GetAIAgent(agentId)**: Use when retrieving existing agents from the hosted service @@ -158,16 +158,16 @@ Replace these method calls: | Semantic Kernel Method | Agent Framework Method | Parameter Changes | |----------------------|----------------------|------------------| -| `agent.InvokeAsync(message, thread, options)` | `agent.RunAsync(message, thread, options)` | Same parameters, different return type | -| `agent.InvokeStreamingAsync(message, thread, options)` | `agent.RunStreamingAsync(message, thread, options)` | Same parameters, different return type | -| `new ChatHistoryAgentThread()` | `agent.GetNewThread()` | No parameters needed | -| `new OpenAIAssistantAgentThread(client)` | `agent.GetNewThread()` | No parameters needed | -| `new AzureAIAgentThread(client)` | `agent.GetNewThread()` | No parameters needed | +| `agent.InvokeAsync(message, thread, options)` | `agent.RunAsync(message, session, options)` | Same parameters, different return type | +| `agent.InvokeStreamingAsync(message, thread, options)` | `agent.RunStreamingAsync(message, session, options)` | Same parameters, different return type | +| `new ChatHistoryAgentThread()` | `await agent.CreateSessionAsync()` | Returns `AgentSession` | +| `new OpenAIAssistantAgentThread(client)` | `await agent.CreateSessionAsync()` | Returns `AgentSession` | +| `new AzureAIAgentThread(client)` | `await agent.CreateSessionAsync()` | Returns `AgentSession` | | `thread.DeleteAsync()` | Provider-specific cleanup | Use provider client directly | Return type changes: -- `IAsyncEnumerable>` → `AgentRunResponse` -- `IAsyncEnumerable` → `IAsyncEnumerable` +- `IAsyncEnumerable>` → `AgentResponse` +- `IAsyncEnumerable` → `IAsyncEnumerable` @@ -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>` - - Streaming: Returns `IAsyncEnumerable` instead of `IAsyncEnumerable` + - Non-streaming: Returns single `AgentResponse` instead of `IAsyncEnumerable>` + - Streaming: Returns `IAsyncEnumerable` instead of `IAsyncEnumerable` 3. **Tool Registration**: Agent Framework uses direct function registration without requiring `[KernelFunction]` attributes. @@ -222,6 +222,8 @@ using Microsoft.Extensions.AI; using Microsoft.Agents.AI; // Provider-specific namespaces (add only if needed): using OpenAI; // For OpenAI provider +using OpenAI.Chat; // For ChatClient.AsAIAgent() extension +using OpenAI.Responses; // For ResponsesClient.AsAIAgent() extension using Azure.AI.OpenAI; // For Azure OpenAI provider using Azure.AI.Agents.Persistent; // For Azure AI Foundry provider using Azure.Identity; // For Azure authentication @@ -254,7 +256,7 @@ AIAgent agent = new ChatClientAgent(chatClient, instructions: "You are a helpful // Method 2: Extension method (recommended) AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: "You are a helpful assistant"); + .AsAIAgent(instructions: "You are a helpful assistant"); ``` @@ -314,7 +316,7 @@ AIAgent agent = new ChatClientAgent(chatClient, instructions: "You are a helpful // Method 2: Extension method (recommended) AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: "You are a helpful assistant"); + .AsAIAgent(instructions: "You are a helpful assistant"); ``` **Required changes:** @@ -338,12 +340,12 @@ AgentThread thread = new AzureAIAgentThread(azureClient); **With this unified Agent Framework pattern:** ```csharp // Use this single pattern for all agent types: -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); ``` **Required changes:** 1. Remove all `new [Provider]AgentThread()` constructor calls -2. Replace with `agent.GetNewThread()` method call +2. Replace with `agent.CreateSessionAsync()` method call 3. Remove provider client parameters from thread creation 4. Use the same pattern regardless of agent provider type @@ -369,7 +371,7 @@ ChatCompletionAgent agent = new() { Kernel = kernel }; [Description("Get the weather for a location")] // Keep Description attribute static string GetWeather(string location) => $"Weather in {location}"; -AIAgent agent = chatClient.CreateAIAgent( +AIAgent agent = chatClient.AsAIAgent( instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); ``` @@ -415,12 +417,12 @@ await foreach (var item in agent.InvokeAsync(userInput, thread)) { ... } static string GetWeather(string location) => $"Weather in {location}"; // Start with an existing agent -AIAgent existingAgent = chatClient.CreateAIAgent( +AIAgent existingAgent = chatClient.AsAIAgent( instructions: "You are a helpful assistant"); // Create an augmented agent with additional tools using builder middleware var augmentedAgent = existingAgent.AsBuilder() - .Use(async (chatMessages, agentThread, agentRunOptions, next, cancellationToken) => + .Use(async (chatMessages, agentSession, agentRunOptions, next, cancellationToken) => { if (agentRunOptions is ChatClientAgentRunOptions chatClientAgentRunOptions) { @@ -429,12 +431,12 @@ var augmentedAgent = existingAgent.AsBuilder() chatClientAgentRunOptions.ChatOptions.Tools.Add(AIFunctionFactory.Create(GetWeather)); } - return await next(chatMessages, agentThread, agentRunOptions, cancellationToken); + return await next(chatMessages, agentSession, agentRunOptions, cancellationToken); }) .Build(); // Use the augmented agent with the additional tools -AgentRunResponse result = await augmentedAgent.RunAsync(userInput, thread); +AgentResponse result = await augmentedAgent.RunAsync(userInput, session); ``` **Required changes:** @@ -464,7 +466,7 @@ await foreach (AgentResponseItem 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, session, options); Console.WriteLine(result); ``` @@ -478,7 +480,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, session, options)) { Console.Write(update); } @@ -487,8 +489,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>` to `AgentRunResponse` -4. Change streaming type from `StreamingChatMessageContent` to `AgentRunResponseUpdate` +3. Change return type handling from `IAsyncEnumerable>` 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 @@ -537,7 +539,7 @@ services.AddTransient(sp => new() services.AddTransient(sp => new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: "You are helpful")); + .AsAIAgent(instructions: "You are helpful")); ``` **Required changes:** @@ -564,11 +566,11 @@ For every thread created if there's intent to cleanup, the caller should track a ```csharp // For OpenAI Assistants (when cleanup is needed): var assistantClient = new OpenAIClient(apiKey).GetAssistantClient(); -await assistantClient.DeleteThreadAsync(thread.ConversationId); +await assistantClient.DeleteThreadAsync(session.ConversationId); // For Azure AI Foundry (when cleanup is needed): var persistentClient = new PersistentAgentsClient(endpoint, credential); -await persistentClient.Threads.DeleteThreadAsync(thread.ConversationId); +await persistentClient.Threads.DeleteThreadAsync(session.ConversationId); // No thread and agent cleanup is needed for non-hosted agent providers like // - Azure OpenAI Chat Completion @@ -580,7 +582,7 @@ await persistentClient.Threads.DeleteThreadAsync(thread.ConversationId); **Required changes:** 1. Remove `thread.DeleteAsync()` calls 2. Use provider-specific client for cleanup when required -3. Access thread ID via `thread.ConversationId` property +3. Access thread ID via `session.ConversationId` property 4. Only implement cleanup for providers that require it (Assistants, Azure AI Foundry) @@ -593,14 +595,14 @@ Use these exact patterns for each provider: ```csharp AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: instructions); + .AsAIAgent(instructions: instructions); ``` **OpenAI Assistants (New):** ```csharp AIAgent agent = new OpenAIClient(apiKey) .GetAssistantClient() - .CreateAIAgent(modelId, instructions: instructions); + .AsAIAgent(modelId, instructions: instructions); ``` **OpenAI Assistants (Existing):** @@ -614,13 +616,13 @@ AIAgent agent = new OpenAIClient(apiKey) ```csharp AIAgent agent = new AzureOpenAIClient(endpoint, credential) .GetChatClient(deploymentName) - .CreateAIAgent(instructions: instructions); + .AsAIAgent(instructions: instructions); ``` **Azure AI Foundry (New):** ```csharp AIAgent agent = new PersistentAgentsClient(endpoint, credential) - .CreateAIAgent(model: deploymentName, instructions: instructions); + .AsAIAgent(model: deploymentName, instructions: instructions); ``` **Azure AI Foundry (Existing):** @@ -665,9 +667,9 @@ using OpenAI; AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: "You are helpful"); + .AsAIAgent(instructions: "You are helpful"); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); ``` @@ -691,7 +693,7 @@ kernel.Plugins.Add(plugin); static string GetWeather([Description("Location")] string location) => $"Weather in {location}"; -AIAgent agent = chatClient.CreateAIAgent( +AIAgent agent = chatClient.AsAIAgent( instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); ``` @@ -714,7 +716,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, session, options); Console.WriteLine(result); // Access underlying content when needed: @@ -742,7 +744,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, session, options); Console.WriteLine($"Tokens: {result.Usage.TotalTokenCount}"); ``` @@ -762,7 +764,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, session, options)) { if (update.Contents.OfType().FirstOrDefault() is { } usageContent) { @@ -787,7 +789,7 @@ 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 agentRunResponse = await agent.RunAsync(userInput, session); // If the agent uses a ChatClient the first breaking glass probably will be a Microsoft.Extensions.AI.ChatResponse ChatResponse? chatResponse = agentRunResponse.RawRepresentation as ChatResponse; @@ -829,7 +831,7 @@ await foreach (var content in agent.InvokeAsync(userInput, thread)) **With this Agent Framework CodeInterpreter pattern:** ```csharp -var result = await agent.RunAsync(userInput, thread); +var result = await agent.RunAsync(userInput, session); Console.WriteLine(result); // Extract chat response MEAI type via first level breaking glass @@ -919,7 +921,7 @@ var openAIResponse = chatCompletion.GetRawResponse(); **Issue: Thread Type Mismatches** - **Problem**: Provider-specific thread constructors not found -- **Solution**: Replace all thread constructors with `agent.GetNewThread()` +- **Solution**: Replace all thread constructors with `agent.CreateSessionAsync()` **Issue: Options Configuration** - **Problem**: `AgentInvokeOptions` type not found @@ -937,7 +939,7 @@ var openAIResponse = chatCompletion.GetRawResponse(); 2. **Update Namespaces**: Replace SK namespaces with AF namespaces 3. **Update Agent Creation**: Remove Kernel, use direct client creation 4. **Update Method Calls**: Replace `InvokeAsync` with `RunAsync` -5. **Update Thread Creation**: Replace provider-specific constructors with `GetNewThread()` +5. **Update Thread Creation**: Replace provider-specific constructors with `await agent.CreateSessionAsync()` 6. **Update Tool Registration**: Remove attributes, use `AIFunctionFactory.Create()` 7. **Update Options**: Replace `AgentInvokeOptions` with provider-specific options 8. **Test and Validate**: Compile and test all functionality @@ -988,9 +990,9 @@ using OpenAI; AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: "You are a helpful assistant"); + .AsAIAgent(instructions: "You are a helpful assistant"); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); ``` ### 2. Azure OpenAI Chat Completion Migration @@ -1038,7 +1040,7 @@ using Azure.Identity; AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) .GetChatClient(deploymentName) - .CreateAIAgent(instructions: "You are a helpful assistant"); + .AsAIAgent(instructions: "You are a helpful assistant"); ``` ### 3. OpenAI Assistants Migration @@ -1083,12 +1085,12 @@ using OpenAI; AIAgent agent = new OpenAIClient(apiKey) .GetAssistantClient() - .CreateAIAgent(modelId, instructions: "You are a helpful assistant"); + .AsAIAgent(modelId, instructions: "You are a helpful assistant"); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); // Cleanup when needed -await assistantClient.DeleteThreadAsync(thread.ConversationId); +await assistantClient.DeleteThreadAsync(session.ConversationId); ``` **Retrieving an existing assistant:** @@ -1100,7 +1102,7 @@ AIAgent agent = new OpenAIClient(apiKey) .GetAssistantClient() .GetAIAgent(assistantId); // Use existing assistant ID -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); ``` @@ -1163,12 +1165,12 @@ using Azure.Identity; var client = new PersistentAgentsClient(endpoint, new AzureCliCredential()); // Create a new AIAgent using Agent Framework -AIAgent agent = client.CreateAIAgent( +AIAgent agent = client.AsAIAgent( model: deploymentName, instructions: "You are a helpful assistant", tools: [/* List of specialized Azure.AI.Agents.Persistent.ToolDefinition types */]); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); ``` **Retrieving an existing agent:** @@ -1182,7 +1184,7 @@ var client = new PersistentAgentsClient(endpoint, new AzureCliCredential()); // Retrieve an existing AIAgent using its ID AIAgent agent = await client.GetAIAgentAsync(agentId); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); ``` @@ -1269,20 +1271,21 @@ await foreach (AgentResponseItem responseItem in responseIte Agent Framework automatically manages the thread, so there's no need to manually update it. ```csharp -using Microsoft.Agents.AI.OpenAI; +using OpenAI.Chat; // For ChatClient.AsAIAgent() +using OpenAI.Responses; // For ResponsesClient.AsAIAgent() AIAgent agent = new OpenAIClient(apiKey) - .GetOpenAIResponseClient(modelId) - .CreateAIAgent( + .GetResponsesClient(modelId) + .AsAIAgent( name: "ResponseAgent", instructions: "Answer all queries in English and French.", tools: [/* AITools */]); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); -var result = await agent.RunAsync(userInput, thread); +var result = await agent.RunAsync(userInput, session); -// The thread will be automatically updated with the new response id from this point +// The session will be automatically updated with the new response id from this point ``` @@ -1336,21 +1339,22 @@ await foreach (AgentResponseItem responseItem in responseIte Agent Framework automatically manages the thread, so there's no need to manually update it. ```csharp -using Microsoft.Agents.AI.OpenAI; +using OpenAI.Chat; // For ChatClient.AsAIAgent() +using OpenAI.Responses; // For ResponsesClient.AsAIAgent() using Azure.AI.OpenAI; AIAgent agent = new AzureOpenAIClient(endpoint, new AzureCliCredential()) - .GetOpenAIResponseClient(modelId) - .CreateAIAgent( + .GetResponsesClient(modelId) + .AsAIAgent( name: "ResponseAgent", instructions: "Answer all queries in English and French.", tools: [/* AITools */]); -AgentThread thread = agent.GetNewThread(); +AgentSession session = await agent.CreateSessionAsync(); -var result = await agent.RunAsync(userInput, thread); +var result = await agent.RunAsync(userInput, session); -// The thread will be automatically updated with the new response id from this point +// The session will be automatically updated with the new response id from this point ``` @@ -1513,7 +1517,7 @@ AITool[] tools = AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent( + .AsAIAgent( instructions: "You are a weather assistant", tools: tools); ``` @@ -1562,10 +1566,10 @@ var renderedTemplate = await new KernelPromptTemplateFactory() AIAgent agent = new OpenAIClient(apiKey) .GetChatClient(modelId) - .CreateAIAgent(instructions: renderedTemplate); + .AsAIAgent(instructions: renderedTemplate); // No template variables in invocation - use plain string -var result = await agent.RunAsync("What's the weather?", thread); +var result = await agent.RunAsync("What's the weather?"); Console.WriteLine(result); ``` diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 95db60cb6f98..77bdd2b1e59b 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -50,10 +50,10 @@ - - - - + + + + diff --git a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/AgentOrchestrations_Step01_Concurrent.csproj b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/AgentOrchestrations_Step01_Concurrent.csproj index 64306d74be5a..6ba4a6f1efe4 100644 --- a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/AgentOrchestrations_Step01_Concurrent.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/AgentOrchestrations_Step01_Concurrent.csproj @@ -1,4 +1,4 @@ - + Exe @@ -11,7 +11,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/Program.cs b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/Program.cs index ac6c2764349f..e1bd615ff139 100644 --- a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step01_Concurrent/Program.cs @@ -79,13 +79,13 @@ async Task AFConcurrentAgentWorkflow() var spanishAgent = GetAFTranslationAgent("Spanish", client); var concurrentAgentWorkflow = AgentWorkflowBuilder.BuildConcurrent([frenchAgent, spanishAgent]); - await using StreamingRun run = await InProcessExecution.StreamAsync(concurrentAgentWorkflow, "Hello, world!"); + await using StreamingRun run = await InProcessExecution.RunStreamingAsync(concurrentAgentWorkflow, "Hello, world!"); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); string? lastExecutorId = null; await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) { - if (evt is AgentRunUpdateEvent e) + if (evt is AgentResponseUpdateEvent e) { if (string.IsNullOrEmpty(e.Update.Text)) { diff --git a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/AgentOrchestrations_Step02_Sequential.csproj b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/AgentOrchestrations_Step02_Sequential.csproj index 64306d74be5a..6ba4a6f1efe4 100644 --- a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/AgentOrchestrations_Step02_Sequential.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/AgentOrchestrations_Step02_Sequential.csproj @@ -1,4 +1,4 @@ - + Exe @@ -11,7 +11,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/Program.cs b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/Program.cs index e317ac0ff873..81507d67ff00 100644 --- a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step02_Sequential/Program.cs @@ -82,13 +82,13 @@ async Task AFSequentialAgentWorkflow() var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential( [frenchAgent, spanishAgent, englishAgent]); - await using StreamingRun run = await InProcessExecution.StreamAsync(sequentialAgentWorkflow, "Hello, world!"); + 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 AgentRunUpdateEvent e) + if (evt is AgentResponseUpdateEvent e) { if (string.IsNullOrEmpty(e.Update.Text)) { diff --git a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/AgentOrchestrations_Step03_Handoff.csproj b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/AgentOrchestrations_Step03_Handoff.csproj index 64306d74be5a..6ba4a6f1efe4 100644 --- a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/AgentOrchestrations_Step03_Handoff.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/AgentOrchestrations_Step03_Handoff.csproj @@ -1,4 +1,4 @@ - + Exe @@ -11,7 +11,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/Program.cs b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/Program.cs index f66fefe535bf..9d29efbd7fad 100644 --- a/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AgentOrchestrations/Step03_Handoff/Program.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +#pragma warning disable MAAIW001 // Experimental: HandoffWorkflowBuilder + using System.ComponentModel; using System.Text.Json; using Azure.AI.OpenAI; @@ -207,13 +209,13 @@ async Task AFHandoffAgentWorkflow() Console.WriteLine($"User: {query}"); messages.Add(new(ChatRole.User, query)); - await using var run = await InProcessExecution.StreamAsync(handoffAgentWorkflow, messages); + await using var run = await InProcessExecution.RunStreamingAsync(handoffAgentWorkflow, messages); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); string? lastExecutorId = null; await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false)) { - if (evt is AgentRunUpdateEvent e) + if (evt is AgentResponseUpdateEvent e) { if (string.IsNullOrEmpty(e.Update.Text) && e.Update.Contents.Count == 0) { diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/AzureAIFoundry_Step01_Basics.csproj b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/AzureAIFoundry_Step01_Basics.csproj index ae6b2961bf06..b48fbf454754 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/AzureAIFoundry_Step01_Basics.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/AzureAIFoundry_Step01_Basics.csproj @@ -11,7 +11,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/Program.cs index 58e15a23c117..b608400c3312 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step01_Basics/Program.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using Azure.AI.Agents.Persistent; +using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.SemanticKernel; @@ -67,7 +68,7 @@ async Task SKAgent_As_AFAgentAsync() #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -80,9 +81,9 @@ async Task SKAgent_As_AFAgentAsync() } // Clean up - if (thread is ChatClientAgentThread chatThread) + if (thread is ChatClientAgentSession chatSession) { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); + await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId); } await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); } @@ -91,29 +92,23 @@ async Task AFAgentAsync() { Console.WriteLine("\n=== AF Agent ===\n"); - var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential()); + // AF 1.0: Use AIProjectClient.AsAIAgent() from Microsoft.Agents.AI.Foundry + var projectClient = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()); - var agent = await azureAgentClient.CreateAIAgentAsync( + var agent = projectClient.AsAIAgent( deploymentName, - name: "GenerateStory", - instructions: "You are good at telling jokes."); + instructions: "You are good at telling jokes.", + name: "GenerateStory"); - var thread = agent.GetNewThread(); + var session = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - var result = await agent.RunAsync(userInput, thread, agentOptions); + var result = await agent.RunAsync(userInput, session, agentOptions); Console.WriteLine(result); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) + await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions)) { Console.Write(update); } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); - } - await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); } diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/AzureAIFoundry_Step02_ToolCall.csproj b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/AzureAIFoundry_Step02_ToolCall.csproj index 8928edd44064..a8f443dc5012 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/AzureAIFoundry_Step02_ToolCall.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/AzureAIFoundry_Step02_ToolCall.csproj @@ -10,7 +10,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/Program.cs index 8742cbcf61e1..cc586560740c 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step02_ToolCall/Program.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using Azure.AI.Agents.Persistent; +using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; @@ -85,7 +86,7 @@ async Task SKAgent_As_AFAgentAsync() #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -98,9 +99,9 @@ async Task SKAgent_As_AFAgentAsync() } // Clean up - if (thread is ChatClientAgentThread chatThread) + if (thread is ChatClientAgentSession chatSession) { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); + await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId); } await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); } @@ -109,26 +110,22 @@ async Task AFAgentAsync() { Console.WriteLine("\n=== AF Agent ===\n"); - var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential()); + var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()) + .AsAIAgent(model: deploymentName, + instructions: "You are a helpful assistant", + tools: [AIFunctionFactory.Create(GetWeather)]); - var agent = await azureAgentClient.CreateAIAgentAsync(deploymentName, instructions: "Answer questions about the menu"); + var session = await agent.CreateSessionAsync(); + var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); + var result = await agent.RunAsync(userInput, session, agentOptions); Console.WriteLine(result); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) + await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions)) { Console.Write(update); } - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); - } - await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); + // No cleanup needed - non-hosted path doesn't create server-side resources. } diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/AzureAIFoundry_Step03_DependencyInjection.csproj b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/AzureAIFoundry_Step03_DependencyInjection.csproj index 7631ed8887f5..60aee8306b56 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/AzureAIFoundry_Step03_DependencyInjection.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/AzureAIFoundry_Step03_DependencyInjection.csproj @@ -10,7 +10,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/Program.cs index 7b3d5a8245c7..12f82b250de6 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step03_DependencyInjection/Program.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using Azure.AI.Agents.Persistent; +using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; @@ -90,7 +91,7 @@ async Task SKAgent_As_AFAgentAsync() var agent = skAgent.AsAIAgent(); - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var result = await agent.RunAsync(userInput, thread); Console.WriteLine(result); @@ -103,9 +104,9 @@ async Task SKAgent_As_AFAgentAsync() // Clean up var azureAgentClient = serviceProvider.GetRequiredService(); - if (thread is ChatClientAgentThread chatThread) + if (thread is ChatClientAgentSession chatSession) { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); + await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId); } await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); } @@ -115,36 +116,29 @@ async Task AFAgentAsync() Console.WriteLine("\n=== AF Agent ===\n"); var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new PersistentAgentsClient(azureEndpoint, new AzureCliCredential())); + serviceCollection.AddSingleton((sp) => new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())); serviceCollection.AddTransient((sp) => { - var azureAgentClient = sp.GetRequiredService(); - - return azureAgentClient.CreateAIAgent( - deploymentName, - name: "GenerateStory", - instructions: "You are good at telling jokes."); + var client = sp.GetRequiredService(); + return client.AsAIAgent( + deploymentName, + instructions: "You are good at telling jokes.", + name: "GenerateStory"); }); await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); var agent = serviceProvider.GetRequiredService(); - var thread = agent.GetNewThread(); + var session = await agent.CreateSessionAsync(); - var result = await agent.RunAsync(userInput, thread); + var result = await agent.RunAsync(userInput, session); Console.WriteLine(result); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread)) + await foreach (var update in agent.RunStreamingAsync(userInput, session)) { Console.Write(update); } - // Clean up - var azureAgentClient = serviceProvider.GetRequiredService(); - if (thread is ChatClientAgentThread chatThread) - { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); - } - await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); + // No cleanup needed - non-hosted path doesn't create server-side resources. } diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/AzureAIFoundry_Step04_CodeInterpreter.csproj b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/AzureAIFoundry_Step04_CodeInterpreter.csproj index e56e323b72a4..a8f443dc5012 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/AzureAIFoundry_Step04_CodeInterpreter.csproj +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/AzureAIFoundry_Step04_CodeInterpreter.csproj @@ -1,4 +1,4 @@ - + Exe @@ -10,7 +10,7 @@ - + diff --git a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/Program.cs index 4ad372455740..11d0e2bd82e0 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureAIFoundry/Step04_CodeInterpreter/Program.cs @@ -2,6 +2,7 @@ using System.Text; using Azure.AI.Agents.Persistent; +using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; @@ -76,7 +77,7 @@ async Task SKAgent_As_AFAgentAsync() var agent = skAgent.AsAIAgent(); - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var result = await agent.RunAsync(userInput, thread); Console.WriteLine(result); @@ -124,9 +125,9 @@ async Task SKAgent_As_AFAgentAsync() } // Clean up - if (thread is ChatClientAgentThread chatThread) + if (thread is ChatClientAgentSession chatSession) { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); + await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId); } await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); } @@ -135,59 +136,15 @@ async Task AFAgentAsync() { Console.WriteLine("\n=== AF Agent ===\n"); - var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential()); - var agent = await azureAgentClient.CreateAIAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]); - var thread = agent.GetNewThread(); + // Note: Code interpreter via hosted APIs requires versioned Foundry Agents. + // This sample creates a basic agent without code interpreter capabilities. + var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()) + .AsAIAgent(deploymentName, instructions: "You are a helpful assistant with code execution capabilities."); - var result = await agent.RunAsync(userInput, thread); - Console.WriteLine(result); - - // Extracts via breaking glass the code generated by code interpreter tool - var chatResponse = result.RawRepresentation as ChatResponse; - StringBuilder generatedCode = new(); - foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable ?? []) - { - // To capture the code interpreter input we need to break glass all the updates raw representations, to check for the RunStepDetailsUpdate type and - // get the CodeInterpreterInput property which contains the generated code. - // Note: Similar logic would needed for each individual update if used in the agent.RunStreamingAsync streaming API to aggregate or yield the generated code. - if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null) - { - generatedCode.Append(update.CodeInterpreterInput); - } - } - - if (!string.IsNullOrEmpty(generatedCode.ToString())) - { - Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}"); - } + var session = await agent.CreateSessionAsync(); - // Update the citations - foreach (var textContent in result.Messages[0].Contents.OfType()) - { - foreach (var annotation in textContent.Annotations ?? []) - { - if (annotation is CitationAnnotation citation) - { - if (citation.Url is null) - { - Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}"); - } - - foreach (var region in citation.AnnotatedRegions ?? []) - { - if (region is TextSpanAnnotatedRegion textSpanRegion) - { - Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}"); - } - } - } - } - } + var result = await agent.RunAsync(userInput, session); + Console.WriteLine(result); - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId); - } - await azureAgentClient.Administration.DeleteAgentAsync(agent.Id); + // No cleanup needed - non-hosted path doesn't create server-side resources. } diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step01_Basics/Program.cs index 76e190840b15..6c4889244d24 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step01_Basics/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step01_Basics/Program.cs @@ -6,7 +6,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; +using OpenAI.Chat; var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; @@ -65,7 +65,7 @@ async Task SKAgent_As_AFAgentAsync() #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -83,9 +83,9 @@ async Task AFAgent() Console.WriteLine("\n=== AF Agent ===\n"); var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."); + .AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."); - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step02_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step02_ToolCall/Program.cs index 394415c09f18..f68c2e405b07 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step02_ToolCall/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step02_ToolCall/Program.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.AI; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; -using OpenAI; +using OpenAI.Chat; var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; @@ -73,7 +73,7 @@ async Task SKAgent_As_AFAgentAsync() async Task AFAgent() { var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName) - .CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); + .AsAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); Console.WriteLine("\n=== AF Agent Response ===\n"); diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs index fb682301b515..164b2e832c4e 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step03_DependencyInjection/Program.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; -using OpenAI; +using OpenAI.Chat; var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; @@ -72,7 +72,7 @@ async Task AFAgent() var serviceCollection = new ServiceCollection(); serviceCollection.AddTransient((sp) => new AzureOpenAIClient(new(endpoint), new AzureCliCredential()) .GetChatClient(deploymentName) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.")); + .AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.")); await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); var agent = serviceProvider.GetRequiredService(); diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step04_ToolCall_WithOpenAPI/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step04_ToolCall_WithOpenAPI/Program.cs index 5898050f5d7a..a6b0840b5091 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step04_ToolCall_WithOpenAPI/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAI/Step04_ToolCall_WithOpenAPI/Program.cs @@ -9,7 +9,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Plugins.OpenApi; -using OpenAI; +using OpenAI.Chat; 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"; @@ -59,7 +59,7 @@ async Task AFAgent() new Uri(endpoint), new AzureCliCredential()) .GetChatClient(deploymentName) - .CreateAIAgent(instructions: "You are a helpful assistant", tools: tools); + .AsAIAgent(instructions: "You are a helpful assistant", tools: tools); // Run the agent with the OpenAPI function tools. Console.WriteLine(await agent.RunAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github.")); diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj deleted file mode 100644 index a2b89580940c..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step01_Basics/AzureOpenAIAssistants_Step01_Basics.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs deleted file mode 100644 index b0b6ca06bfd6..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step01_Basics/Program.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Azure.AI.OpenAI; -using Azure.Identity; -using Microsoft.Agents.AI; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents.OpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); -var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; -var userInput = "Tell me a joke about a pirate."; - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgent(); -await SKAgent_As_AFAgent(); -await AFAgent(); - -async Task SKAgent() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()); - - var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes."); - - // Create the agent - OpenAIAssistantAgent agent = new(assistant, assistantsClient); - - // Create a thread for the agent conversation. - var thread = new OpenAIAssistantAgentThread(assistantsClient); - var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 }; - var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) }; - - await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions)) - { - Console.WriteLine(result.Message); - } - - Console.WriteLine("---"); - await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update.Message); - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgent() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()); - - var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes."); - - // Create the agent - OpenAIAssistantAgent skAgent = new(assistant, assistantsClient); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgent() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - - var agent = await assistantClient.CreateAIAgentAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes."); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj deleted file mode 100644 index a2b89580940c..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step02_ToolCall/AzureOpenAIAssistants_Step02_ToolCall.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs deleted file mode 100644 index 9566dd7f8ddc..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step02_ToolCall/Program.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.ComponentModel; -using Azure.AI.OpenAI; -using Azure.Identity; -using Microsoft.Agents.AI; -using Microsoft.Extensions.AI; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents.OpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); -var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; -var userInput = "What is the weather like in Amsterdam?"; - -[KernelFunction] -[Description("Get the weather for a given location.")] -static string GetWeather([Description("The location to get the weather for.")] string location) - => $"The weather in {location} is cloudy with a high of 15°C."; - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgent(); -await SKAgent_As_AFAgent(); -await AFAgent(); - -async Task SKAgent() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - - var builder = Kernel.CreateBuilder(); - var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - - Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, - instructions: "You are a helpful assistant"); - - OpenAIAssistantAgent agent = new(assistant, assistantsClient) - { - Kernel = builder.Build(), - Arguments = new KernelArguments(new OpenAIPromptExecutionSettings() - { - MaxTokens = 1000, - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() - }), - }; - - // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage). - agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)])); - - // Create a thread for the agent conversation. - var thread = new OpenAIAssistantAgentThread(assistantsClient); - - await foreach (var result in agent.InvokeAsync(userInput, thread)) - { - Console.WriteLine(result.Message); - } - - Console.WriteLine("---"); - await foreach (var update in agent.InvokeStreamingAsync(userInput, thread)) - { - Console.Write(update.Message); - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgent() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - - var builder = Kernel.CreateBuilder(); - var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - - Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, - instructions: "You are a helpful assistant"); - - OpenAIAssistantAgent skAgent = new(assistant, assistantsClient) - { - Kernel = builder.Build(), - Arguments = new KernelArguments(new OpenAIPromptExecutionSettings() - { - MaxTokens = 1000, - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() - }), - }; - - // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage). - skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)])); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgent() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - - var agent = await assistantClient.CreateAIAgentAsync(deploymentName, - instructions: "You are a helpful assistant", - tools: [AIFunctionFactory.Create(GetWeather)]); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj deleted file mode 100644 index 8696e583426e..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step03_DependencyInjection/AzureOpenAIAssistants_Step03_DependencyInjection.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs deleted file mode 100644 index 548f02348032..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step03_DependencyInjection/Program.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Azure.AI.OpenAI; -using Azure.Identity; -using Microsoft.Agents.AI; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents.OpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); -var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; -var userInput = "Tell me a joke about a pirate."; - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgent(); -await SKAgent_As_AFAgent(); -await AFAgent(); - -async Task SKAgent() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient()); - serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()); - serviceCollection.AddTransient((sp) => - { - var assistantsClient = sp.GetRequiredService(); - - Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." }); - - return new OpenAIAssistantAgent(assistant, assistantsClient); - }); - - await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var agent = serviceProvider.GetRequiredService(); - - // Create a thread for the agent conversation. - var assistantsClient = serviceProvider.GetRequiredService(); - var thread = new OpenAIAssistantAgentThread(assistantsClient); - var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 }; - var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) }; - - await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions)) - { - Console.WriteLine(result.Message); - } - - Console.WriteLine("---"); - await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update.Message); - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgent() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient()); - serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()); - serviceCollection.AddTransient((sp) => - { - var assistantsClient = sp.GetRequiredService(); - - Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." }); - - return new OpenAIAssistantAgent(assistant, assistantsClient); - }); - - await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var skAgent = serviceProvider.GetRequiredService(); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - var assistantClient = serviceProvider.GetRequiredService(); - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgent() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient()); - serviceCollection.AddTransient((sp) => - { - var assistantClient = sp.GetRequiredService(); - - return assistantClient.CreateAIAgent(deploymentName, name: "Joker", instructions: "You are good at telling jokes."); - }); - - await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var agent = serviceProvider.GetRequiredService(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - var assistantClient = serviceProvider.GetRequiredService(); - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj deleted file mode 100644 index a2b89580940c..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/AzureOpenAIAssistants_Step04_CodeInterpreter.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs deleted file mode 100644 index 324de34731e9..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIAssistants/Step04_CodeInterpreter/Program.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Text; -using Azure.AI.OpenAI; -using Azure.Identity; -using Microsoft.Agents.AI; -using Microsoft.Extensions.AI; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents; -using Microsoft.SemanticKernel.Agents.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); -var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o"; -var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101"; - -var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient(); - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgent(); -await SKAgent_As_AFAgent(); -await AFAgent(); - -async Task SKAgent() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true); - - // Create the agent - OpenAIAssistantAgent agent = new(assistant, assistantsClient); - - // Create a thread for the agent conversation. - var thread = new OpenAIAssistantAgentThread(assistantsClient); - - // Respond to user input - await foreach (var content in agent.InvokeAsync(userInput, thread)) - { - if (!string.IsNullOrWhiteSpace(content.Message.Content)) - { - bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false; - Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}"); - } - - // Check for the citations - foreach (var item in content.Message.Items) - { - // Process each item in the message - if (item is AnnotationContent annotation) - { - if (annotation.Kind != AnnotationKind.UrlCitation) - { - Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}"); - } - } - else if (item is FileReferenceContent fileReference) - { - Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}"); - } - } - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgent() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true); - - // Create the agent - OpenAIAssistantAgent skAgent = new(assistant, assistantsClient); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - - var result = await agent.RunAsync(userInput, thread); - Console.WriteLine(result); - - // Extracts via breaking glass the code generated by code interpreter tool - var chatResponse = result.RawRepresentation as ChatResponse; - StringBuilder generatedCode = new(); - foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable ?? []) - { - if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null) - { - generatedCode.Append(update.CodeInterpreterInput); - } - } - - if (!string.IsNullOrEmpty(generatedCode.ToString())) - { - Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}"); - } - - // Check for the citations - foreach (var textContent in result.Messages[0].Contents.OfType()) - { - foreach (var annotation in textContent.Annotations ?? []) - { - if (annotation is CitationAnnotation citation) - { - if (citation.Url is null) - { - Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}"); - } - - foreach (var region in citation.AnnotatedRegions ?? []) - { - if (region is TextSpanAnnotatedRegion textSpanRegion) - { - Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}"); - } - } - } - } - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgent() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var agent = await assistantsClient.CreateAIAgentAsync(deploymentName, tools: [new HostedCodeInterpreterTool()]); - - var thread = agent.GetNewThread(); - - var result = await agent.RunAsync(userInput, thread); - Console.WriteLine(result); - - // Extracts via breaking glass the code generated by code interpreter tool - var chatResponse = result.RawRepresentation as ChatResponse; - StringBuilder generatedCode = new(); - foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable ?? []) - { - if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null) - { - generatedCode.Append(update.CodeInterpreterInput); - } - } - - if (!string.IsNullOrEmpty(generatedCode.ToString())) - { - Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}"); - } - - // Check for the citations - foreach (var textContent in result.Messages[0].Contents.OfType()) - { - foreach (var annotation in textContent.Annotations ?? []) - { - if (annotation is CitationAnnotation citation) - { - if (citation.Url is null) - { - Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}"); - } - - foreach (var region in citation.AnnotatedRegions ?? []) - { - if (region is TextSpanAnnotatedRegion textSpanRegion) - { - Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}"); - } - } - } - } - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step01_Basics/Program.cs index 5f3552b2beab..8637a035cf4a 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step01_Basics/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step01_Basics/Program.cs @@ -5,7 +5,7 @@ using Microsoft.Agents.AI; using Microsoft.Extensions.AI; using Microsoft.SemanticKernel.Agents.OpenAI; -using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -66,7 +66,7 @@ async Task SKAgent_As_AFAgentAsync() var agent = skAgent.AsAIAgent(); - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -84,17 +84,17 @@ async Task AFAgentAsync() Console.WriteLine("\n=== AF Agent ===\n"); var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) - .GetResponsesClient().AsIChatClient(deploymentName) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."); + .GetResponsesClient() + .AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes."); - var thread = agent.GetNewThread(); + var session = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 }); - var result = await agent.RunAsync(userInput, thread, agentOptions); + var result = await agent.RunAsync(userInput, session, agentOptions); Console.WriteLine(result); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) + await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions)) { Console.Write(update); } diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step02_ReasoningModel/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step02_ReasoningModel/Program.cs index dc864675fbf9..5941a4de0097 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step02_ReasoningModel/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step02_ReasoningModel/Program.cs @@ -7,7 +7,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; -using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -134,7 +134,7 @@ async Task SKAgent_As_AFAgentAsync() #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000, @@ -180,10 +180,10 @@ async Task AFAgentAsync() Console.WriteLine("\n=== AF Agent ===\n"); var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) - .GetResponsesClient().AsIChatClient(deploymentName) - .CreateAIAgent(name: "Thinker", instructions: "You are good at thinking hard before answering."); + .GetResponsesClient() + .AsAIAgent(model: deploymentName, name: "Thinker", instructions: "You are good at thinking hard before answering."); - var thread = agent.GetNewThread(); + var session = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000, @@ -194,7 +194,7 @@ async Task AFAgentAsync() } }); - var result = await agent.RunAsync(userInput, thread, agentOptions); + var result = await agent.RunAsync(userInput, session, agentOptions); // Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists. string assistantThinking = string.Join("\n", result.Messages @@ -207,7 +207,7 @@ async Task AFAgentAsync() Console.WriteLine($"Assistant: \n{assistantText}\n---\n"); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) + await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions)) { var thinkingContents = update.Contents .OfType() diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step03_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step03_ToolCall/Program.cs index 04b25861c54d..613b04ed914c 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step03_ToolCall/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step03_ToolCall/Program.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.AI; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.OpenAI; -using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -66,8 +66,8 @@ async Task SKAgent_As_AFAgentAsync() async Task AFAgentAsync() { var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) - .GetResponsesClient().AsIChatClient(deploymentName) - .CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); + .GetResponsesClient() + .AsAIAgent(model: deploymentName, instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); Console.WriteLine("\n=== AF Agent Response ===\n"); diff --git a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step04_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step04_DependencyInjection/Program.cs index a7b612c0a277..dfaf6a6a712e 100644 --- a/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step04_DependencyInjection/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/AzureOpenAIResponses/Step04_DependencyInjection/Program.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel.Agents.OpenAI; -using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -71,8 +71,8 @@ async Task AFAgentAsync() var serviceCollection = new ServiceCollection(); serviceCollection.AddTransient((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) - .GetResponsesClient().AsIChatClient(deploymentName) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.")); + .GetResponsesClient() + .AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes.")); await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); var agent = serviceProvider.GetRequiredService(); diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAI/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAI/Step01_Basics/Program.cs index 9734b8abb016..9e7189c7bcfe 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAI/Step01_Basics/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAI/Step01_Basics/Program.cs @@ -5,6 +5,7 @@ using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Connectors.OpenAI; using OpenAI; +using OpenAI.Chat; var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; @@ -64,7 +65,7 @@ async Task SKAgent_As_AFAgentAsync() #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -83,9 +84,9 @@ async Task AFAgentAsync() Console.WriteLine("\n=== AF Agent ===\n"); var agent = new OpenAIClient(apiKey).GetChatClient(model) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."); + .AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."); - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAI/Step02_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAI/Step02_ToolCall/Program.cs index 00c687ca568e..333d7cb14afd 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAI/Step02_ToolCall/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAI/Step02_ToolCall/Program.cs @@ -6,6 +6,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using OpenAI; +using OpenAI.Chat; var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; @@ -65,7 +66,7 @@ async Task SKAgent_As_AFAgentAsync() var agent = skAgent.AsAIAgent(); #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -86,7 +87,7 @@ async Task SKAgent_As_AFAgentAsync() async Task AFAgentAsync() { - var agent = new OpenAIClient(apiKey).GetChatClient(model).CreateAIAgent( + var agent = new OpenAIClient(apiKey).GetChatClient(model).AsAIAgent( instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAI/Step03_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAI/Step03_DependencyInjection/Program.cs index 0d8890d9dc8b..49c614517fc1 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAI/Step03_DependencyInjection/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAI/Step03_DependencyInjection/Program.cs @@ -5,6 +5,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using OpenAI; +using OpenAI.Chat; var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; @@ -70,7 +71,7 @@ async Task AFAgentAsync() var serviceCollection = new ServiceCollection(); serviceCollection.AddTransient((sp) => new OpenAIClient(apiKey) .GetChatClient(model) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.")); + .AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.")); await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); var agent = serviceProvider.GetRequiredService(); diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step01_Basics/OpenAIAssistants_Step01_Basics.csproj b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step01_Basics/OpenAIAssistants_Step01_Basics.csproj deleted file mode 100644 index a2b89580940c..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step01_Basics/OpenAIAssistants_Step01_Basics.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step01_Basics/Program.cs deleted file mode 100644 index 42e8c9bce711..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step01_Basics/Program.cs +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Agents.AI; -using Microsoft.SemanticKernel.Agents.OpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); -var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; -var userInput = "Tell me a joke about a pirate."; - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgentAsync(); -await SKAgent_As_AFAgentAsync(); -await AFAgentAsync(); - -async Task SKAgentAsync() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - - var assistantsClient = new AssistantClient(apiKey); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(model, name: "Joker", instructions: "You are good at telling jokes."); - - // Create the agent - OpenAIAssistantAgent agent = new(assistant, assistantsClient); - - // Create a thread for the agent conversation. - var thread = new OpenAIAssistantAgentThread(assistantsClient); - var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 }; - var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) }; - - await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions)) - { - Console.WriteLine(result.Message); - } - - Console.WriteLine("---"); - await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update.Message); - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -// Example of Semantic Kernel Agent code converted as an Agent Framework Agent -async Task SKAgent_As_AFAgentAsync() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - - var assistantsClient = new AssistantClient(apiKey); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(model, name: "Joker", instructions: "You are good at telling jokes."); - - // Create the agent - OpenAIAssistantAgent agent = new(assistant, assistantsClient); - - var afAgent = agent.AsAIAgent(); - - var thread = afAgent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await afAgent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in afAgent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgentAsync() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var assistantClient = new AssistantClient(apiKey); - - var agent = await assistantClient.CreateAIAgentAsync(model, name: "Joker", instructions: "You are good at telling jokes."); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step02_ToolCall/OpenAIAssistants_Step02_ToolCall.csproj b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step02_ToolCall/OpenAIAssistants_Step02_ToolCall.csproj deleted file mode 100644 index a2b89580940c..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step02_ToolCall/OpenAIAssistants_Step02_ToolCall.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step02_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step02_ToolCall/Program.cs deleted file mode 100644 index c50204a2f6b8..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step02_ToolCall/Program.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.ComponentModel; -using Microsoft.Agents.AI; -using Microsoft.Extensions.AI; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents.OpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); -var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; -var userInput = "What is the weather like in Amsterdam?"; - -[KernelFunction] -[Description("Get the weather for a given location.")] -static string GetWeather([Description("The location to get the weather for.")] string location) - => $"The weather in {location} is cloudy with a high of 15°C."; - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgentAsync(); -await SKAgent_As_AFAgentAsync(); -await AFAgentAsync(); - -async Task SKAgentAsync() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - - var builder = Kernel.CreateBuilder(); - var assistantsClient = new AssistantClient(apiKey); - - Assistant assistant = await assistantsClient.CreateAssistantAsync(model, - instructions: "You are a helpful assistant"); - - OpenAIAssistantAgent agent = new(assistant, assistantsClient) - { - Kernel = builder.Build(), - Arguments = new KernelArguments(new OpenAIPromptExecutionSettings() - { - MaxTokens = 1000, - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() - }), - }; - - // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage). - agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)])); - - // Create a thread for the agent conversation. - var thread = new OpenAIAssistantAgentThread(assistantsClient); - - await foreach (var result in agent.InvokeAsync(userInput, thread)) - { - Console.WriteLine(result.Message); - } - - Console.WriteLine("---"); - await foreach (var update in agent.InvokeStreamingAsync(userInput, thread)) - { - Console.Write(update.Message); - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgentAsync() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - - var builder = Kernel.CreateBuilder(); - var assistantsClient = new AssistantClient(apiKey); - - Assistant assistant = await assistantsClient.CreateAssistantAsync(model, - instructions: "You are a helpful assistant"); - - OpenAIAssistantAgent skAgent = new(assistant, assistantsClient) - { - Kernel = builder.Build(), - Arguments = new KernelArguments(new OpenAIPromptExecutionSettings() - { - MaxTokens = 1000, - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() - }), - }; - - // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage). - skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)])); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgentAsync() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var assistantClient = new AssistantClient(apiKey); - - var agent = await assistantClient.CreateAIAgentAsync(model, - instructions: "You are a helpful assistant", - tools: [AIFunctionFactory.Create(GetWeather)]); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step03_DependencyInjection/OpenAIAssistants_Step03_DependencyInjection.csproj b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step03_DependencyInjection/OpenAIAssistants_Step03_DependencyInjection.csproj deleted file mode 100644 index 8696e583426e..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step03_DependencyInjection/OpenAIAssistants_Step03_DependencyInjection.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step03_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step03_DependencyInjection/Program.cs deleted file mode 100644 index 2a3497a7e5f0..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step03_DependencyInjection/Program.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Agents.AI; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents.OpenAI; -using Microsoft.SemanticKernel.Connectors.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); -var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; -var userInput = "Tell me a joke about a pirate."; - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgentAsync(); -await SKAgent_As_AFAgentAsync(); -await AFAgentAsync(); - -async Task SKAgentAsync() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey)); - serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey); - serviceCollection.AddTransient((sp) => - { - var assistantsClient = sp.GetRequiredService(); - - Assistant assistant = assistantsClient.CreateAssistant(model, new() { Name = "Joker", Instructions = "You are good at telling jokes." }); - - return new OpenAIAssistantAgent(assistant, assistantsClient); - }); - - await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var agent = serviceProvider.GetRequiredService(); - - // Create a thread for the agent conversation. - var assistantsClient = serviceProvider.GetRequiredService(); - var thread = new OpenAIAssistantAgentThread(assistantsClient); - var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 }; - var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) }; - - await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions)) - { - Console.WriteLine(result.Message); - } - - Console.WriteLine("---"); - await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update.Message); - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgentAsync() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey)); - serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey); - serviceCollection.AddTransient((sp) => - { - var assistantsClient = sp.GetRequiredService(); - - Assistant assistant = assistantsClient.CreateAssistant(model, new() { Name = "Joker", Instructions = "You are good at telling jokes." }); - - return new OpenAIAssistantAgent(assistant, assistantsClient); - }); - - await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var skAgent = serviceProvider.GetRequiredService(); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - var assistantClient = serviceProvider.GetRequiredService(); - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgentAsync() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey)); - serviceCollection.AddTransient((sp) => - { - var assistantClient = sp.GetRequiredService(); - - return assistantClient.CreateAIAgent(model, name: "Joker", instructions: "You are good at telling jokes."); - }); - - await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var agent = serviceProvider.GetRequiredService(); - - var thread = agent.GetNewThread(); - var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 }); - - var result = await agent.RunAsync(userInput, thread, agentOptions); - Console.WriteLine(result); - - Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) - { - Console.Write(update); - } - - // Clean up - var assistantClient = serviceProvider.GetRequiredService(); - if (thread is ChatClientAgentThread chatThread) - { - await assistantClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step04_CodeInterpreter/OpenAIAssistants_Step04_CodeInterpreter.csproj b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step04_CodeInterpreter/OpenAIAssistants_Step04_CodeInterpreter.csproj deleted file mode 100644 index a2b89580940c..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step04_CodeInterpreter/OpenAIAssistants_Step04_CodeInterpreter.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net10.0 - enable - enable - $(NoWarn);CA1707;CA2007;VSTHRD111 - - - - - - - - - - - - - - - diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step04_CodeInterpreter/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step04_CodeInterpreter/Program.cs deleted file mode 100644 index b8c0db023c9d..000000000000 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIAssistants/Step04_CodeInterpreter/Program.cs +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Text; -using Microsoft.Agents.AI; -using Microsoft.Extensions.AI; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Agents; -using Microsoft.SemanticKernel.Agents.OpenAI; -using OpenAI; -using OpenAI.Assistants; - -#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -#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. - -var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); -var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o"; -var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101"; - -var assistantsClient = new AssistantClient(apiKey); - -Console.WriteLine($"User Input: {userInput}"); - -await SKAgentAsync(); -await SKAgent_As_AFAgentAsync(); -await AFAgentAsync(); - -async Task SKAgentAsync() -{ - Console.WriteLine("\n=== SK Agent ===\n"); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(model, enableCodeInterpreter: true); - - // Create the agent - OpenAIAssistantAgent agent = new(assistant, assistantsClient); - - // Create a thread for the agent conversation. - var thread = new OpenAIAssistantAgentThread(assistantsClient); - - // Respond to user input - await foreach (var content in agent.InvokeAsync(userInput, thread)) - { - if (!string.IsNullOrWhiteSpace(content.Message.Content)) - { - bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false; - Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}"); - } - - // Check for the citations - foreach (var item in content.Message.Items) - { - // Process each item in the message - if (item is AnnotationContent annotation) - { - if (annotation.Kind != AnnotationKind.UrlCitation) - { - Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}"); - } - } - else if (item is FileReferenceContent fileReference) - { - Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}"); - } - } - } - - // Clean up - await thread.DeleteAsync(); - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task SKAgent_As_AFAgentAsync() -{ - Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n"); - - // Define the assistant - Assistant assistant = await assistantsClient.CreateAssistantAsync(model, enableCodeInterpreter: true); - - // Create the agent - OpenAIAssistantAgent skAgent = new(assistant, assistantsClient); - - var agent = skAgent.AsAIAgent(); - - var thread = agent.GetNewThread(); - - var result = await agent.RunAsync(userInput, thread); - Console.WriteLine(result); - - // Extracts via breaking glass the code generated by code interpreter tool - var chatResponse = result.RawRepresentation as ChatResponse; - StringBuilder generatedCode = new(); - foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable ?? []) - { - if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null) - { - generatedCode.Append(update.CodeInterpreterInput); - } - } - - if (!string.IsNullOrEmpty(generatedCode.ToString())) - { - Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}"); - } - - // Check for the citations - foreach (var textContent in result.Messages[0].Contents.OfType()) - { - foreach (var annotation in textContent.Annotations ?? []) - { - if (annotation is CitationAnnotation citation) - { - if (citation.Url is null) - { - Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}"); - } - - foreach (var region in citation.AnnotatedRegions ?? []) - { - if (region is TextSpanAnnotatedRegion textSpanRegion) - { - Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}"); - } - } - } - } - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} - -async Task AFAgentAsync() -{ - Console.WriteLine("\n=== AF Agent ===\n"); - - var agent = await assistantsClient.CreateAIAgentAsync(model, tools: [new HostedCodeInterpreterTool()]); - - var thread = agent.GetNewThread(); - - var result = await agent.RunAsync(userInput, thread); - Console.WriteLine(result); - - // Extracts via breaking glass the code generated by code interpreter tool - var chatResponse = result.RawRepresentation as ChatResponse; - StringBuilder generatedCode = new(); - foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable ?? []) - { - if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null) - { - generatedCode.Append(update.CodeInterpreterInput); - } - } - - if (!string.IsNullOrEmpty(generatedCode.ToString())) - { - Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}"); - } - - // Check for the citations - foreach (var textContent in result.Messages[0].Contents.OfType()) - { - foreach (var annotation in textContent.Annotations ?? []) - { - if (annotation is CitationAnnotation citation) - { - if (citation.Url is null) - { - Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}"); - } - - foreach (var region in citation.AnnotatedRegions ?? []) - { - if (region is TextSpanAnnotatedRegion textSpanRegion) - { - Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}"); - } - } - } - } - } - - // Clean up - if (thread is ChatClientAgentThread chatThread) - { - await assistantsClient.DeleteThreadAsync(chatThread.ConversationId); - } - await assistantsClient.DeleteAssistantAsync(agent.Id); -} diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step01_Basics/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step01_Basics/Program.cs index b130a3e2a0cc..c58d2fd1b89b 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step01_Basics/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step01_Basics/Program.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.AI; using Microsoft.SemanticKernel.Agents.OpenAI; using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -63,7 +64,7 @@ async Task SKAgent_As_AFAgentAsync() var agent = skAgent.AsAIAgent(); - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 }); var result = await agent.RunAsync(userInput, thread, agentOptions); @@ -80,17 +81,17 @@ async Task AFAgentAsync() { Console.WriteLine("\n=== AF Agent ===\n"); - var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."); + var agent = new OpenAIClient(apiKey).GetResponsesClient() + .AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes."); - var thread = agent.GetNewThread(); + var session = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 }); - var result = await agent.RunAsync(userInput, thread, agentOptions); + var result = await agent.RunAsync(userInput, session, agentOptions); Console.WriteLine(result); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) + await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions)) { Console.Write(update); } diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step02_ReasoningModel/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step02_ReasoningModel/Program.cs index d7519abd347d..9face250635a 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step02_ReasoningModel/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step02_ReasoningModel/Program.cs @@ -6,6 +6,7 @@ using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -131,7 +132,7 @@ async Task SKAgent_As_AFAgentAsync() #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. - var thread = agent.GetNewThread(); + var thread = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000, @@ -176,10 +177,10 @@ async Task AFAgentAsync() { Console.WriteLine("\n=== AF Agent ===\n"); - var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model) - .CreateAIAgent(name: "Thinker", instructions: "You are at thinking hard before answering."); + var agent = new OpenAIClient(apiKey).GetResponsesClient() + .AsAIAgent(model: model, name: "Thinker", instructions: "You are at thinking hard before answering."); - var thread = agent.GetNewThread(); + var session = await agent.CreateSessionAsync(); var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000, @@ -190,7 +191,7 @@ async Task AFAgentAsync() } }); - var result = await agent.RunAsync(userInput, thread, agentOptions); + var result = await agent.RunAsync(userInput, session, agentOptions); // Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists. string assistantThinking = string.Join("\n", result.Messages @@ -203,7 +204,7 @@ async Task AFAgentAsync() Console.WriteLine($"Assistant: \n{assistantText}\n---\n"); Console.WriteLine("---"); - await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions)) + await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions)) { var thinkingContents = update.Contents .OfType() diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step03_ToolCall/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step03_ToolCall/Program.cs index ff9fdae2d4d6..14fa1c601beb 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step03_ToolCall/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step03_ToolCall/Program.cs @@ -5,6 +5,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.OpenAI; using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -63,7 +64,8 @@ async Task SKAgent_As_AFAgentAsync() async Task AFAgentAsync() { - var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model).CreateAIAgent( + var agent = new OpenAIClient(apiKey).GetResponsesClient().AsAIAgent( + model: model, instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]); diff --git a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step04_DependencyInjection/Program.cs b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step04_DependencyInjection/Program.cs index 403ec70e6575..36245131e702 100644 --- a/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step04_DependencyInjection/Program.cs +++ b/dotnet/samples/AgentFrameworkMigration/OpenAIResponses/Step04_DependencyInjection/Program.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel.Agents.OpenAI; using OpenAI; +using OpenAI.Responses; #pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. #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. @@ -65,8 +66,8 @@ async Task AFAgentAsync() var serviceCollection = new ServiceCollection(); serviceCollection.AddTransient((sp) => new OpenAIClient(apiKey) - .GetResponsesClient().AsIChatClient(model) - .CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.")); + .GetResponsesClient() + .AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes.")); await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); var agent = serviceProvider.GetRequiredService(); diff --git a/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgent.cs b/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgent.cs index 08407e0ae801..1408c5d21814 100644 --- a/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgent.cs +++ b/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgent.cs @@ -50,7 +50,7 @@ public SemanticKernelAIAgent( } /// - public override string Id => this._innerAgent.Id; + protected override string? IdCore => this._innerAgent.Id; /// public override string? Name => this._innerAgent.Name; @@ -59,19 +59,31 @@ public SemanticKernelAIAgent( public override string? Description => this._innerAgent.Description; /// - public override MAAI.AgentThread DeserializeThread(JsonElement serializedThread, JsonSerializerOptions? jsonSerializerOptions = null) - => new SemanticKernelAIAgentThread(this._threadDeserializationFactory(serializedThread, jsonSerializerOptions), this._threadSerializer); + protected override ValueTask CreateSessionCoreAsync(CancellationToken cancellationToken = default) + => new(new SemanticKernelAIAgentSession(this._threadFactory())); /// - public override MAAI.AgentThread GetNewThread() => new SemanticKernelAIAgentThread(this._threadFactory(), this._threadSerializer); + protected override ValueTask SerializeSessionCoreAsync(MAAI.AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default) + { + if (session is not SemanticKernelAIAgentSession typedSession) + { + throw new InvalidOperationException("The provided session is not compatible with the agent. Only sessions created by the agent can be used."); + } + + return new(this._threadSerializer(typedSession.InnerThread, jsonSerializerOptions)); + } + + /// + protected override ValueTask DeserializeSessionCoreAsync(JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default) + => new(new SemanticKernelAIAgentSession(this._threadDeserializationFactory(serializedState, jsonSerializerOptions))); /// - public override async Task RunAsync(IEnumerable messages, MAAI.AgentThread? thread = null, MAAI.AgentRunOptions? options = null, CancellationToken cancellationToken = default) + protected override async Task RunCoreAsync(IEnumerable messages, MAAI.AgentSession? session = null, MAAI.AgentRunOptions? options = null, CancellationToken cancellationToken = default) { - thread ??= this.GetNewThread(); - if (thread is not SemanticKernelAIAgentThread typedThread) + session ??= await this.CreateSessionCoreAsync(cancellationToken).ConfigureAwait(false); + if (session is not SemanticKernelAIAgentSession typedSession) { - throw new InvalidOperationException("The provided thread is not compatible with the agent. Only threads created by the agent can be used."); + throw new InvalidOperationException("The provided session is not compatible with the agent. Only sessions created by the agent can be used."); } List responseMessages = []; @@ -98,13 +110,14 @@ public override MAAI.AgentThread DeserializeThread(JsonElement serializedThread, }; AgentResponseItem? lastResponseItem = null; - ChatMessage? lastResponseMessage = null; - await foreach (var responseItem in this._innerAgent.InvokeAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedThread.InnerThread, invokeOptions, cancellationToken).ConfigureAwait(false)) + await foreach (var responseItem in this._innerAgent.InvokeAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedSession.InnerThread, invokeOptions, cancellationToken).ConfigureAwait(false)) { lastResponseItem = responseItem; } - return new MAAI.AgentRunResponse(responseMessages) + var lastResponseMessage = lastResponseItem?.Message.ToChatMessage(); + + return new MAAI.AgentResponse(responseMessages) { AgentId = this._innerAgent.Id, RawRepresentation = lastResponseItem, @@ -114,23 +127,23 @@ public override MAAI.AgentThread DeserializeThread(JsonElement serializedThread, } /// - public override async IAsyncEnumerable RunStreamingAsync( + protected override async IAsyncEnumerable RunCoreStreamingAsync( IEnumerable messages, - MAAI.AgentThread? thread = null, + MAAI.AgentSession? session = null, MAAI.AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { - thread ??= this.GetNewThread(); - if (thread is not SemanticKernelAIAgentThread typedThread) + session ??= await this.CreateSessionCoreAsync(cancellationToken).ConfigureAwait(false); + if (session is not SemanticKernelAIAgentSession typedSession) { - throw new InvalidOperationException("The provided thread is not compatible with the agent. Only threads created by the agent can be used."); + throw new InvalidOperationException("The provided session is not compatible with the agent. Only sessions created by the agent can be used."); } - await foreach (var responseItem in this._innerAgent.InvokeStreamingAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedThread.InnerThread, cancellationToken: cancellationToken).ConfigureAwait(false)) + await foreach (var responseItem in this._innerAgent.InvokeStreamingAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedSession.InnerThread, cancellationToken: cancellationToken).ConfigureAwait(false)) { var update = responseItem.Message.ToChatResponseUpdate(); - yield return new MAAI.AgentRunResponseUpdate + yield return new MAAI.AgentResponseUpdate { AuthorName = update.AuthorName, AgentId = this._innerAgent.Id, diff --git a/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgentThread.cs b/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgentSession.cs similarity index 56% rename from dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgentThread.cs rename to dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgentSession.cs index 274a9a839cf0..86a8d6557adf 100644 --- a/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgentThread.cs +++ b/dotnet/src/Agents/Abstractions/AIAgent/SemanticKernelAIAgentSession.cs @@ -2,23 +2,17 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.Text.Json; using MAAI = Microsoft.Agents.AI; namespace Microsoft.SemanticKernel.Agents; [Experimental("SKEXP0110")] -internal sealed class SemanticKernelAIAgentThread : MAAI.AgentThread +internal sealed class SemanticKernelAIAgentSession : MAAI.AgentSession { - private readonly Func _threadSerializer; - - internal SemanticKernelAIAgentThread(AgentThread thread, Func threadSerializer) + internal SemanticKernelAIAgentSession(AgentThread thread) { Throw.IfNull(thread); - Throw.IfNull(threadSerializer); - this.InnerThread = thread; - this._threadSerializer = threadSerializer; } /// @@ -26,10 +20,6 @@ internal SemanticKernelAIAgentThread(AgentThread thread, Func public AgentThread InnerThread { get; } - /// - public override JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null) - => this._threadSerializer(this.InnerThread, jsonSerializerOptions); - /// public override object? GetService(Type serviceType, object? serviceKey = null) { diff --git a/dotnet/src/Agents/UnitTests/A2A/A2AAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/A2A/A2AAgentExtensionsTests.cs index f85ee5ca0fee..45d587d3e7b8 100644 --- a/dotnet/src/Agents/UnitTests/A2A/A2AAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/A2A/A2AAgentExtensionsTests.cs @@ -3,11 +3,11 @@ using System; using System.Net.Http; using System.Text.Json; +using System.Threading.Tasks; using A2A; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.A2A; using Xunit; - namespace SemanticKernel.Agents.UnitTests.A2A; public sealed class A2AAgentExtensionsTests @@ -40,7 +40,7 @@ public void AsAIAgent_WithNullA2AAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactory() + public async Task AsAIAgent_CreatesWorkingThreadFactory() { // Arrange using var httpClient = new HttpClient(); @@ -50,17 +50,17 @@ public void AsAIAgent_CreatesWorkingThreadFactory() // Act var result = a2aAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() { // Arrange using var httpClient = new HttpClient(); @@ -71,17 +71,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThr // Act var result = a2aAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() { // Arrange using var httpClient = new HttpClient(); @@ -93,18 +93,18 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThrea // Act var result = a2aAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); Assert.Equal(threadId, threadAdapter.InnerThread.Id); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesThreadId() + public async Task AsAIAgent_ThreadSerializer_SerializesThreadId() { // Arrange using var httpClient = new HttpClient(); @@ -116,10 +116,10 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId); var result = a2aAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.String, serializedElement.ValueKind); diff --git a/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentThreadTests.cs b/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentSessionTests.cs similarity index 51% rename from dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentThreadTests.cs rename to dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentSessionTests.cs index 8f730a8e22ef..d23fcc8d838e 100644 --- a/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentThreadTests.cs +++ b/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentSessionTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using System; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.SemanticKernel; @@ -11,76 +10,33 @@ namespace SemanticKernel.Agents.UnitTests.AIAgent; -public sealed class SemanticKernelAIAgentThreadTests +public sealed class SemanticKernelAIAgentSessionTests { [Fact] public void Constructor_InitializesProperties() { // Arrange var threadMock = new Mock(); - JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) => default; // Act - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); // Assert Assert.Equal(threadMock.Object, adapter.InnerThread); } - [Fact] - public void Serialize_CallsThreadSerializer() - { - // Arrange - var threadMock = new Mock(); - var serializerCallCount = 0; - var expectedJsonElement = JsonElement.Parse("{\"test\": \"value\"}"); - - JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) - { - serializerCallCount++; - Assert.Same(threadMock.Object, t); - return expectedJsonElement; - } - - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer); - - // Act - var result = adapter.Serialize(); - - // Assert - Assert.Equal(1, serializerCallCount); - Assert.Equal(expectedJsonElement.ToString(), result.ToString()); - } - - [Fact] - public void Serialize_WithJsonSerializerOptions_PassesOptionsToSerializer() - { - // Arrange - var threadMock = new Mock(); - var expectedOptions = new JsonSerializerOptions(); - JsonSerializerOptions? capturedOptions = null; - - JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) - { - capturedOptions = o; - return default; - } - - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer); + // AF 1.0: Serialize_CallsThreadSerializer test removed - serialization moved to agent. + // See SemanticKernelAIAgentTests for serialization coverage. - // Act - adapter.Serialize(expectedOptions); - - // Assert - Assert.Same(expectedOptions, capturedOptions); - } + // AF 1.0: Serialize() moved from AgentSession to AIAgent.SerializeSessionCoreAsync(). + // These tests are covered by SemanticKernelAIAgentTests instead. [Fact] public void GetService_WithAgentThreadType_ReturnsInnerThread() { // Arrange var threadMock = new Mock(); - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); // Act var result = adapter.GetService(typeof(AgentThread)); @@ -94,7 +50,7 @@ public void GetService_WithAgentThreadTypeAndServiceKey_ReturnsNull() { // Arrange var threadMock = new Mock(); - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); var serviceKey = new object(); // Act @@ -109,7 +65,7 @@ public void GetService_WithNonAgentThreadType_ReturnsNull() { // Arrange var threadMock = new Mock(); - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); // Act var result = adapter.GetService(typeof(string)); @@ -123,56 +79,29 @@ public void GetService_WithNullType_ThrowsArgumentNullException() { // Arrange var threadMock = new Mock(); - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); // Act & Assert Assert.Throws(() => adapter.GetService(null!)); } - [Fact] - public void Serialize_WithNullOptions_CallsSerializerWithNull() - { - // Arrange - var threadMock = new Mock(); - JsonSerializerOptions? capturedOptions = new(); - - JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) - { - capturedOptions = o; - return default; - } - - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer); - - // Act - adapter.Serialize(null); - - // Assert - Assert.Null(capturedOptions); - } + // AF 1.0: Serialize_WithNullOptions test removed - serialization moved to agent. [Fact] public void Constructor_WithNullThread_ThrowsArgumentNullException() { // Arrange & Act - JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) => default; - Assert.Throws(() => new SemanticKernelAIAgentThread(null!, ThreadSerializer)); + Assert.Throws(() => new SemanticKernelAIAgentSession(null!)); } - [Fact] - public void Constructor_WithNullSerializer_ThrowsArgumentNullException() - { - // Arrange & Act - var threadMock = new Mock(); - Assert.Throws(() => new SemanticKernelAIAgentThread(threadMock.Object, null!)); - } + // Constructor_WithNullSerializer test removed: serializer is no longer stored on the session. [Fact] public void GetService_WithBaseClassType_ReturnsInnerThread() { // Arrange var concreteThread = new TestAgentThread(); - var adapter = new SemanticKernelAIAgentThread(concreteThread, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(concreteThread); // Act var result = adapter.GetService(typeof(AgentThread)); @@ -186,7 +115,7 @@ public void GetService_WithDerivedType_ReturnsInnerThreadWhenMatches() { // Arrange var concreteThread = new TestAgentThread(); - var adapter = new SemanticKernelAIAgentThread(concreteThread, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(concreteThread); // Act var result = adapter.GetService(typeof(TestAgentThread)); @@ -200,7 +129,7 @@ public void GetService_WithIncompatibleDerivedType_ReturnsNull() { // Arrange var threadMock = new Mock(); - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); // Act var result = adapter.GetService(typeof(TestAgentThread)); @@ -214,7 +143,7 @@ public void GetService_WithInterfaceType_ReturnsNull() { // Arrange var threadMock = new Mock(); - var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default); + var adapter = new SemanticKernelAIAgentSession(threadMock.Object); // Act var result = adapter.GetService(typeof(IServiceProvider)); diff --git a/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentTests.cs b/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentTests.cs index ebb271a4cef7..ed178c4be09d 100644 --- a/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentTests.cs +++ b/dotnet/src/Agents/UnitTests/AIAgent/SemanticKernelAIAgentTests.cs @@ -84,7 +84,7 @@ public void Constructor_WithNullThreadSerializer_ThrowsArgumentNullException() } [Fact] - public void DeserializeThread_ReturnsSemanticKernelAIAgentThread() + public async Task DeserializeThread_ReturnsSemanticKernelAIAgentSession() { // Arrange var agentMock = new Mock(); @@ -95,14 +95,14 @@ public void DeserializeThread_ReturnsSemanticKernelAIAgentThread() var json = JsonElement.Parse("{}"); // Act - var result = adapter.DeserializeThread(json); + var result = await adapter.DeserializeSessionAsync(json); // Assert - Assert.IsType(result); + Assert.IsType(result); } [Fact] - public void GetNewThread_ReturnsSemanticKernelAIAgentThread() + public async Task GetNewThread_ReturnsSemanticKernelAIAgentSession() { // Arrange var agentMock = new Mock(); @@ -111,15 +111,15 @@ public void GetNewThread_ReturnsSemanticKernelAIAgentThread() var adapter = new SemanticKernelAIAgent(agentMock.Object, () => expectedThread, (e, o) => expectedThread, ThreadSerializer); // Act - var result = adapter.GetNewThread(); + var result = await adapter.CreateSessionAsync(); // Assert - Assert.IsType(result); - Assert.Equal(expectedThread, ((SemanticKernelAIAgentThread)result).InnerThread); + Assert.IsType(result); + Assert.Equal(expectedThread, ((SemanticKernelAIAgentSession)result).InnerThread); } [Fact] - public void DeserializeThread_CallsDeserializationFactory() + public async Task DeserializeThread_CallsDeserializationFactory() { // Arrange var agentMock = new Mock(); @@ -136,15 +136,15 @@ AgentThread DeserializationFactory(JsonElement e, JsonSerializerOptions? o) var json = JsonElement.Parse("{}"); // Act - var result = adapter.DeserializeThread(json); + var result = await adapter.DeserializeSessionAsync(json); // Assert Assert.Equal(1, factoryCallCount); - Assert.IsType(result); + Assert.IsType(result); } [Fact] - public void GetNewThread_CallsThreadFactory() + public async Task GetNewThread_CallsThreadFactory() { // Arrange var agentMock = new Mock(); @@ -160,11 +160,11 @@ AgentThread ThreadFactory() var adapter = new SemanticKernelAIAgent(agentMock.Object, ThreadFactory, (e, o) => expectedThread, (t, o) => default); // Act - var result = adapter.GetNewThread(); + var result = await adapter.CreateSessionAsync(); // Assert Assert.Equal(1, factoryCallCount); - Assert.IsType(result); + Assert.IsType(result); } [Fact] @@ -211,13 +211,13 @@ async IAsyncEnumerable> MockInvokeAsync(IC yield return new AgentResponseItem(message, innerThread); } - var thread = new SemanticKernelAIAgentThread(innerThread, (t, o) => default); + var thread = new SemanticKernelAIAgentSession(innerThread); // Act var result = await adapter.RunAsync("Input text", thread); // Assert - Assert.IsType(result); + Assert.IsType(result); Assert.Equal("Final response", result.Text); agentMock.Verify(a => a.InvokeAsync( It.Is>(x => x.First().Content == "Input text"), @@ -246,13 +246,13 @@ async IAsyncEnumerable> GetAsyncE yield return new AgentResponseItem(new StreamingChatMessageContent(AuthorRole.Assistant, "Final response"), innerThread); } - var thread = new SemanticKernelAIAgentThread(innerThread, (t, o) => default); + var thread = new SemanticKernelAIAgentSession(innerThread); // Act var results = await adapter.RunStreamingAsync("Input text", thread).ToListAsync(); // Assert - Assert.IsType(results.First()); + Assert.IsType(results.First()); Assert.Equal("Final response", results.First().Text); agentMock.Verify(a => a.InvokeStreamingAsync( It.Is>(x => x.First().Content == "Input text"), @@ -288,13 +288,13 @@ async IAsyncEnumerable> GetEnumerableWithD yield return new AgentResponseItem(final, thread); } - var threadWrapper = new SemanticKernelAIAgentThread(innerThread, (t, o) => default); + var threadWrapper = new SemanticKernelAIAgentSession(innerThread); // Act var response = await adapter.RunAsync("input", threadWrapper); // Assert - // Use reflection to inspect Messages collection inside AgentRunResponse + // Use reflection to inspect Messages collection inside AgentResponse var messages = response.Messages; var contents = messages.First().Contents; Assert.Single(contents); // Duplicate text content should have been removed @@ -327,7 +327,7 @@ async IAsyncEnumerable> GetEnumerableWithN yield return new AgentResponseItem(final, thread); } - var threadWrapper = new SemanticKernelAIAgentThread(innerThread, (t, o) => default); + var threadWrapper = new SemanticKernelAIAgentSession(innerThread); // Act var response = await adapter.RunAsync("input", threadWrapper); diff --git a/dotnet/src/Agents/UnitTests/AgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/AgentExtensionsTests.cs index 158dd689e7c2..191b475cdab5 100644 --- a/dotnet/src/Agents/UnitTests/AgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/AgentExtensionsTests.cs @@ -2,10 +2,10 @@ using System; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.SemanticKernel.Agents; using Moq; using Xunit; - namespace SemanticKernel.Agents.UnitTests; public sealed class AgentExtensionsTests @@ -77,7 +77,7 @@ public void AsAIAgent_WithNullThreadSerializer_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_WithValidFactories_CreatesWorkingAdapter() + public async Task AsAIAgent_WithValidFactories_CreatesWorkingAdapter() { // Arrange var agentMock = new Mock(); @@ -95,17 +95,17 @@ AgentThread ThreadFactory() // Act var result = agentMock.Object.AsAIAgent(ThreadFactory, ThreadDeserializationFactory, ThreadSerializer); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); Assert.Equal(1, factoryCallCount); - Assert.IsType(thread); - Assert.Same(expectedThread, ((SemanticKernelAIAgentThread)thread).InnerThread); + Assert.IsType(thread); + Assert.Same(expectedThread, ((SemanticKernelAIAgentSession)thread).InnerThread); } [Fact] - public void AsAIAgent_WithDeserializationFactory_CreatesWorkingAdapter() + public async Task AsAIAgent_WithDeserializationFactory_CreatesWorkingAdapter() { // Arrange var agentMock = new Mock(); @@ -125,12 +125,12 @@ AgentThread ThreadDeserializationFactory(JsonElement e, JsonSerializerOptions? o // Act var result = agentMock.Object.AsAIAgent(ThreadFactory, ThreadDeserializationFactory, ThreadSerializer); var json = JsonElement.Parse("{}"); - var thread = result.DeserializeThread(json); + var thread = await result.DeserializeSessionAsync(json); // Assert Assert.NotNull(thread); Assert.Equal(1, deserializationCallCount); - Assert.IsType(thread); - Assert.Same(expectedThread, ((SemanticKernelAIAgentThread)thread).InnerThread); + Assert.IsType(thread); + Assert.Same(expectedThread, ((SemanticKernelAIAgentSession)thread).InnerThread); } } diff --git a/dotnet/src/Agents/UnitTests/AzureAI/AzureAIAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/AzureAI/AzureAIAgentExtensionsTests.cs index 03dbf1c80b5d..aaf62c7fc921 100644 --- a/dotnet/src/Agents/UnitTests/AzureAI/AzureAIAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/AzureAI/AzureAIAgentExtensionsTests.cs @@ -3,12 +3,12 @@ using System; using System.ClientModel.Primitives; using System.Text.Json; +using System.Threading.Tasks; using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; using Moq; using Xunit; - namespace SemanticKernel.Agents.UnitTests.AzureAI; public sealed class AzureAIAgentExtensionsTests @@ -49,24 +49,24 @@ public void AsAIAgent_WithNullAzureAIAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactory() + public async Task AsAIAgent_CreatesWorkingThreadFactory() { var clientMock = new Mock(); var azureAIAgent = new AzureAIAgent(s_agentMetadata, clientMock.Object); // Act var result = azureAIAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() { // Arrange var clientMock = new Mock(); @@ -75,17 +75,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThr // Act var result = azureAIAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() { // Arrange var clientMock = new Mock(); @@ -96,18 +96,18 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThrea // Act var result = azureAIAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); Assert.Equal(threadId, threadAdapter.InnerThread.Id); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesThreadId() + public async Task AsAIAgent_ThreadSerializer_SerializesThreadId() { // Arrange var clientMock = new Mock(); @@ -118,10 +118,10 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId); var result = azureAIAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.String, serializedElement.ValueKind); diff --git a/dotnet/src/Agents/UnitTests/Bedrock/Extensions.cs/BedrockAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/Bedrock/Extensions.cs/BedrockAgentExtensionsTests.cs index fcd68bf90a76..a7871194aeb3 100644 --- a/dotnet/src/Agents/UnitTests/Bedrock/Extensions.cs/BedrockAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/Bedrock/Extensions.cs/BedrockAgentExtensionsTests.cs @@ -59,7 +59,7 @@ public void AsAIAgent_WithNullBedrockAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactory() + public async Task AsAIAgent_CreatesWorkingThreadFactory() { // Arrange var (mockClient, mockRuntimeClient) = this.CreateMockClients(); @@ -67,17 +67,17 @@ public void AsAIAgent_CreatesWorkingThreadFactory() // Act var result = bedrockAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() { // Arrange var (mockClient, mockRuntimeClient) = this.CreateMockClients(); @@ -86,17 +86,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThr // Act var result = bedrockAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() { // Arrange var (mockClient, mockRuntimeClient) = this.CreateMockClients(); @@ -106,17 +106,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThrea // Act var result = bedrockAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesThreadId() + public async Task AsAIAgent_ThreadSerializer_SerializesThreadId() { // Arrange var (mockClient, mockRuntimeClient) = this.CreateMockClients(); @@ -126,10 +126,10 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId); var result = bedrockAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.String, serializedElement.ValueKind); diff --git a/dotnet/src/Agents/UnitTests/Copilot/CopilotStudioAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/Copilot/CopilotStudioAgentExtensionsTests.cs index 73185ac6d69f..aa666cad688f 100644 --- a/dotnet/src/Agents/UnitTests/Copilot/CopilotStudioAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/Copilot/CopilotStudioAgentExtensionsTests.cs @@ -2,12 +2,12 @@ using System; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.Agents.CopilotStudio.Client; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.Copilot; using Moq; using Xunit; - namespace SemanticKernel.Agents.UnitTests.Copilot; public sealed class CopilotStudioAgentExtensionsTests @@ -38,7 +38,7 @@ public void AsAIAgent_WithNullCopilotStudioAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactory() + public async Task AsAIAgent_CreatesWorkingThreadFactory() { // Arrange var clientMock = new Mock(null, null, null, null); @@ -46,17 +46,17 @@ public void AsAIAgent_CreatesWorkingThreadFactory() // Act var result = copilotStudioAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() { // Arrange var clientMock = new Mock(null, null, null, null); @@ -65,17 +65,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThr // Act var result = copilotStudioAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() { // Arrange var clientMock = new Mock(null, null, null, null); @@ -85,17 +85,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThrea // Act var result = copilotStudioAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesThreadId() + public async Task AsAIAgent_ThreadSerializer_SerializesThreadId() { // Arrange var clientMock = new Mock(null, null, null, null); @@ -105,10 +105,10 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId); var result = copilotStudioAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.String, serializedElement.ValueKind); diff --git a/dotnet/src/Agents/UnitTests/Core/ChatCompletionAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/Core/ChatCompletionAgentExtensionsTests.cs index 31bae18429f5..e47675307e9a 100644 --- a/dotnet/src/Agents/UnitTests/Core/ChatCompletionAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/Core/ChatCompletionAgentExtensionsTests.cs @@ -2,10 +2,10 @@ using System; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.ChatCompletion; using Xunit; - namespace SemanticKernel.Agents.UnitTests.Core; public sealed class ChatCompletionAgentExtensionsTests @@ -39,7 +39,7 @@ public void AsAIAgent_WithNullChatCompletionAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactory() + public async Task AsAIAgent_CreatesWorkingThreadFactory() { // Arrange var chatCompletionAgent = new ChatCompletionAgent() @@ -50,17 +50,17 @@ public void AsAIAgent_CreatesWorkingThreadFactory() // Act var result = chatCompletionAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullChatHistory_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullChatHistory_CreatesNewThread() { // Arrange var chatCompletionAgent = new ChatCompletionAgent() @@ -72,17 +72,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullChatHistory_CreatesNe // Act var result = chatCompletionAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidChatHistory_CreatesThreadWithHistory() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidChatHistory_CreatesThreadWithHistory() { // Arrange var chatCompletionAgent = new ChatCompletionAgent() @@ -98,19 +98,19 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidChatHistory_CreatesT // Act var result = chatCompletionAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); var chatHistoryThread = (ChatHistoryAgentThread)threadAdapter.InnerThread; Assert.Equal(2, chatHistoryThread.ChatHistory.Count); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesChatHistory() + public async Task AsAIAgent_ThreadSerializer_SerializesChatHistory() { // Arrange var chatCompletionAgent = new ChatCompletionAgent() @@ -126,10 +126,10 @@ public void AsAIAgent_ThreadSerializer_SerializesChatHistory() var jsonElement = JsonSerializer.SerializeToElement(chatHistory); var result = chatCompletionAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.Array, serializedElement.ValueKind); diff --git a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentExtensionsTests.cs index bd6493907b28..7c62e0037550 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentExtensionsTests.cs @@ -3,12 +3,12 @@ using System; using System.ClientModel.Primitives; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.OpenAI; using Moq; using OpenAI.Assistants; using Xunit; - namespace SemanticKernel.Agents.UnitTests.OpenAI; public sealed class OpenAIAssistantAgentExtensionsTests @@ -54,7 +54,7 @@ public void AsAIAgent_WithNullOpenAIAssistantAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactory() + public async Task AsAIAgent_CreatesWorkingThreadFactory() { // Arrange var clientMock = new Mock(); @@ -62,17 +62,17 @@ public void AsAIAgent_CreatesWorkingThreadFactory() // Act var result = assistantAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() { // Arrange var clientMock = new Mock(); @@ -81,17 +81,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThr // Act var result = assistantAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() { // Arrange var clientMock = new Mock(); @@ -101,18 +101,18 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThrea // Act var result = assistantAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); Assert.Equal(threadId, threadAdapter.InnerThread.Id); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesThreadId() + public async Task AsAIAgent_ThreadSerializer_SerializesThreadId() { // Arrange var clientMock = new Mock(); @@ -122,10 +122,10 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId); var result = assistantAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.String, serializedElement.ValueKind); diff --git a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIResponseAgentExtensionsTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIResponseAgentExtensionsTests.cs index 8f124b33a49f..197e333c240d 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIResponseAgentExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIResponseAgentExtensionsTests.cs @@ -3,12 +3,12 @@ using System; using System.ClientModel; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; using OpenAI.Responses; using Xunit; - namespace SemanticKernel.Agents.UnitTests.OpenAI; public sealed class OpenAIResponseAgentExtensionsTests @@ -39,7 +39,7 @@ public void AsAIAgent_WithNullOpenAIResponseAgent_ThrowsArgumentNullException() } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactoryStoreTrue() + public async Task AsAIAgent_CreatesWorkingThreadFactoryStoreTrue() { // Arrange var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); @@ -50,17 +50,17 @@ public void AsAIAgent_CreatesWorkingThreadFactoryStoreTrue() // Act var result = responseAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_CreatesWorkingThreadFactoryStoreFalse() + public async Task AsAIAgent_CreatesWorkingThreadFactoryStoreFalse() { // Arrange var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); @@ -71,17 +71,17 @@ public void AsAIAgent_CreatesWorkingThreadFactoryStoreFalse() // Act var result = responseAgent.AsAIAgent(); - var thread = result.GetNewThread(); + var thread = await result.CreateSessionAsync(); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread() { // Arrange var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); @@ -93,17 +93,17 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThr // Act var result = responseAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() + public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId() { // Arrange var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); @@ -116,18 +116,18 @@ public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThrea // Act var result = responseAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; Assert.IsType(threadAdapter.InnerThread); Assert.Equal(threadId, threadAdapter.InnerThread.Id); } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesThreadId() + public async Task AsAIAgent_ThreadSerializer_SerializesThreadId() { // Arrange var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); @@ -140,10 +140,10 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId); var result = responseAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.String, serializedElement.ValueKind); @@ -151,7 +151,7 @@ public void AsAIAgent_ThreadSerializer_SerializesThreadId() } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithNullJson_CreatesThreadWithEmptyChatHistory() + public async Task AsAIAgent_ThreadDeserializationFactory_WithNullJson_CreatesThreadWithEmptyChatHistory() { var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); var responseAgent = new OpenAIResponseAgent(responseClient); @@ -159,18 +159,18 @@ public void AsAIAgent_ThreadDeserializationFactory_WithNullJson_CreatesThreadWit // Act var result = responseAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; var chatHistoryAgentThread = Assert.IsType(threadAdapter.InnerThread); Assert.Empty(chatHistoryAgentThread.ChatHistory); } [Fact] - public void AsAIAgent_ThreadDeserializationFactory_WithChatHistory_CreatesThreadWithChatHistory() + public async Task AsAIAgent_ThreadDeserializationFactory_WithChatHistory_CreatesThreadWithChatHistory() { var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); var responseAgent = new OpenAIResponseAgent(responseClient); @@ -179,12 +179,12 @@ public void AsAIAgent_ThreadDeserializationFactory_WithChatHistory_CreatesThread // Act var result = responseAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Assert Assert.NotNull(thread); - Assert.IsType(thread); - var threadAdapter = (SemanticKernelAIAgentThread)thread; + Assert.IsType(thread); + var threadAdapter = (SemanticKernelAIAgentSession)thread; var chatHistoryAgentThread = Assert.IsType(threadAdapter.InnerThread); Assert.Single(chatHistoryAgentThread.ChatHistory); var firstMessage = chatHistoryAgentThread.ChatHistory[0]; @@ -193,7 +193,7 @@ public void AsAIAgent_ThreadDeserializationFactory_WithChatHistory_CreatesThread } [Fact] - public void AsAIAgent_ThreadSerializer_SerializesChatHistory() + public async Task AsAIAgent_ThreadSerializer_SerializesChatHistory() { // Arrange var responseClient = new ResponsesClient(new ApiKeyCredential("apikey")); @@ -202,10 +202,10 @@ public void AsAIAgent_ThreadSerializer_SerializesChatHistory() var jsonElement = JsonSerializer.SerializeToElement(expectedChatHistory); var result = responseAgent.AsAIAgent(); - var thread = result.DeserializeThread(jsonElement); + var thread = await result.DeserializeSessionAsync(jsonElement); // Act - var serializedElement = thread.Serialize(); + var serializedElement = await result.SerializeSessionAsync(thread); // Assert Assert.Equal(JsonValueKind.Array, serializedElement.ValueKind); diff --git a/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/SemanticKernelAIAgentConformance/SemanticKernelAIAgentTests.cs b/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/SemanticKernelAIAgentConformance/SemanticKernelAIAgentTests.cs index 41aaf3797e26..950955ca2ebf 100644 --- a/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/SemanticKernelAIAgentConformance/SemanticKernelAIAgentTests.cs +++ b/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/SemanticKernelAIAgentConformance/SemanticKernelAIAgentTests.cs @@ -18,16 +18,16 @@ public abstract class SemanticKernelAIAgentTests(Func createAgentF public virtual async Task ConvertAndRunAgentAsync() { var aiagent = this.Fixture.AIAgent; - var thread = aiagent.GetNewThread(); + var session = await aiagent.CreateSessionAsync(); - var result = await aiagent.RunAsync("What is the capital of France?", thread); + var result = await aiagent.RunAsync("What is the capital of France?", session); Assert.Contains("Paris", result.Text, StringComparison.OrdinalIgnoreCase); - var serialisedTreadJsonElement = thread.Serialize(); + var serialisedSessionJsonElement = await aiagent.SerializeSessionAsync(session); - var deserializedThread = aiagent.DeserializeThread(serialisedTreadJsonElement); + var deserializedSession = await aiagent.DeserializeSessionAsync(serialisedSessionJsonElement); - var secondResult = await aiagent.RunAsync("And Austria?", deserializedThread); + var secondResult = await aiagent.RunAsync("And Austria?", deserializedSession); Assert.Contains("Vienna", secondResult.Text, StringComparison.OrdinalIgnoreCase); } diff --git a/dotnet/src/SemanticKernel.Abstractions/AI/PromptExecutionSettingsExtensions.cs b/dotnet/src/SemanticKernel.Abstractions/AI/PromptExecutionSettingsExtensions.cs index 59274f537261..e756249b225d 100644 --- a/dotnet/src/SemanticKernel.Abstractions/AI/PromptExecutionSettingsExtensions.cs +++ b/dotnet/src/SemanticKernel.Abstractions/AI/PromptExecutionSettingsExtensions.cs @@ -176,16 +176,16 @@ public static class PromptExecutionSettingsExtensions options.AllowMultipleToolCalls = autoChoiceBehavior.Options?.AllowParallelCalls; } else - if (settings.FunctionChoiceBehavior is NoneFunctionChoiceBehavior noneFunctionChoiceBehavior) - { - options.ToolMode = ChatToolMode.None; - } - else - if (settings.FunctionChoiceBehavior is RequiredFunctionChoiceBehavior requiredFunctionChoiceBehavior) - { - options.ToolMode = ChatToolMode.RequireAny; - options.AllowMultipleToolCalls = requiredFunctionChoiceBehavior.Options?.AllowParallelCalls; - } + if (settings.FunctionChoiceBehavior is NoneFunctionChoiceBehavior noneFunctionChoiceBehavior) + { + options.ToolMode = ChatToolMode.None; + } + else + if (settings.FunctionChoiceBehavior is RequiredFunctionChoiceBehavior requiredFunctionChoiceBehavior) + { + options.ToolMode = ChatToolMode.RequireAny; + options.AllowMultipleToolCalls = requiredFunctionChoiceBehavior.Options?.AllowParallelCalls; + } options.Tools = []; foreach (var function in functions)