From 5b291d6d0e3db64781426bf8b89045b54cf49ba7 Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Mon, 9 Feb 2026 15:45:26 +0100 Subject: [PATCH 1/2] restructure: create new sample structure (01-05) and move old files to _to_delete New structure: - 01-get-started/ (6 progressive samples, single-file .cs) - 02-agents/ (tools, middleware, conversations, providers) - 03-workflows/ (9 workflow patterns) - 04-hosting/ (a2a, ag-ui, azure-functions, openai-endpoints - multi-project) - 05-end-to-end/ (full apps) - _to_delete/ (old samples for reviewer reference) Uses Azure AI Foundry Responses API via AIProjectClient as default provider. Old files preserved in _to_delete/ for review before deletion. --- .../samples/01-get-started/01_HelloAgent.cs | 40 + dotnet/samples/01-get-started/02_AddTools.cs | 51 + dotnet/samples/01-get-started/03_MultiTurn.cs | 42 + dotnet/samples/01-get-started/04_Memory.cs | 55 + .../01-get-started/05_FirstWorkflow.cs | 45 + .../01-get-started/06_HostYourAgent.cs | 40 + dotnet/samples/01-get-started/README.md | 24 + .../samples/02-agents/BackgroundResponses.cs | 59 + dotnet/samples/02-agents/DeclarativeAgents.cs | 50 + dotnet/samples/02-agents/Observability.cs | 100 ++ dotnet/samples/02-agents/README.md | 57 + dotnet/samples/02-agents/Rag.cs | 88 ++ dotnet/samples/02-agents/StructuredOutput.cs | 70 + .../02-agents/conversations/CustomStorage.cs | 115 ++ .../conversations/PersistentConversation.cs | 41 + .../middleware/ChatClientMiddleware.cs | 41 + .../middleware/DefiningMiddleware.cs | 47 + .../02-agents/middleware/FunctionOverride.cs | 50 + .../02-agents/middleware/Guardrails.cs | 53 + .../02-agents/middleware/HumanApproval.cs | 61 + .../02-agents/middleware/PIIFiltering.cs | 58 + .../middleware/PerRequestMiddleware.cs | 68 + .../02-agents/providers/AnthropicProvider.cs | 30 + .../02-agents/providers/AzureAIFoundry.cs | 30 + .../02-agents/providers/AzureOpenAI.cs | 23 + .../02-agents/providers/CopilotStudio.cs | 21 + .../02-agents/providers/CustomProvider.cs | 84 ++ .../02-agents/providers/GitHubCopilot.cs | 34 + .../02-agents/providers/OllamaProvider.cs | 22 + .../02-agents/providers/OpenAIProvider.cs | 23 + .../02-agents/tools/CodeInterpreter.cs | 53 + dotnet/samples/02-agents/tools/FileSearch.cs | 40 + .../samples/02-agents/tools/FunctionTools.cs | 44 + .../samples/02-agents/tools/HostedMcpTools.cs | 76 ++ .../samples/02-agents/tools/LocalMcpTools.cs | 42 + .../samples/02-agents/tools/ToolApproval.cs | 59 + dotnet/samples/02-agents/tools/WebSearch.cs | 29 + dotnet/samples/03-workflows/README.md | 17 + .../agents-in-workflows/AgentsInWorkflows.cs | 56 + .../03-workflows/branching/Branching.cs | 177 +++ .../03-workflows/checkpoints/Checkpoints.cs | 173 +++ .../03-workflows/concurrent/Concurrent.cs | 98 ++ .../03-workflows/declarative/Declarative.cs | 83 ++ .../human-in-the-loop/HumanInTheLoop.cs | 124 ++ .../03-workflows/sequential/Sequential.cs | 54 + .../state-management/StateManagement.cs | 106 ++ .../visualization/Visualization.cs | 43 + dotnet/samples/04-hosting/README.md | 13 + .../a2a}/A2AClient/A2AClient.csproj | 0 .../a2a}/A2AClient/HostClientAgent.cs | 0 .../a2a}/A2AClient/Program.cs | 0 .../a2a}/A2AClient/README.md | 0 .../a2a}/A2AServer/A2AServer.csproj | 0 .../a2a}/A2AServer/A2AServer.http | 0 .../a2a}/A2AServer/HostAgentFactory.cs | 0 .../a2a}/A2AServer/Models/InvoiceQuery.cs | 0 .../a2a}/A2AServer/Program.cs | 0 .../a2a}/README.md | 0 .../ag-ui}/AGUIClient/AGUIClient.csproj | 0 .../AGUIClient/AGUIClientSerializerContext.cs | 0 .../ag-ui}/AGUIClient/Program.cs | 0 .../ag-ui}/AGUIClient/README.md | 0 .../ag-ui}/AGUIClient/SensorRequest.cs | 0 .../ag-ui}/AGUIClient/SensorResponse.cs | 0 .../ag-ui}/AGUIServer/AGUIServer.csproj | 0 .../ag-ui}/AGUIServer/AGUIServer.http | 0 .../AGUIServer/AGUIServerSerializerContext.cs | 0 .../ag-ui}/AGUIServer/Program.cs | 0 .../AGUIServer/Properties/launchSettings.json | 0 .../ServerWeatherForecastRequest.cs | 0 .../ServerWeatherForecastResponse.cs | 0 .../ag-ui}/README.md | 0 .../01_SingleAgent/01_SingleAgent.csproj | 0 .../01_SingleAgent/Program.cs | 0 .../azure-functions}/01_SingleAgent/README.md | 0 .../azure-functions}/01_SingleAgent/demo.http | 0 .../azure-functions}/01_SingleAgent/host.json | 0 .../02_AgentOrchestration_Chaining.csproj | 0 .../FunctionTriggers.cs | 0 .../02_AgentOrchestration_Chaining/Program.cs | 0 .../02_AgentOrchestration_Chaining/README.md | 0 .../02_AgentOrchestration_Chaining/demo.http | 0 .../02_AgentOrchestration_Chaining/host.json | 0 .../01_SingleAgent/01_SingleAgent.csproj | 0 .../ConsoleApps/01_SingleAgent/Program.cs | 0 .../ConsoleApps/01_SingleAgent/README.md | 0 .../azure-functions}/Directory.Build.props | 0 .../AgentWithHostedMCP.csproj | 0 .../AgentWithHostedMCP/Dockerfile | 0 .../AgentWithHostedMCP/Program.cs | 0 .../AgentWithHostedMCP/README.md | 0 .../AgentWithHostedMCP/agent.yaml | 0 .../AgentWithHostedMCP/run-requests.http | 0 .../AgentWithTextSearchRag.csproj | 0 .../AgentWithTextSearchRag/Dockerfile | 0 .../AgentWithTextSearchRag/Program.cs | 0 .../AgentWithTextSearchRag/README.md | 0 .../AgentWithTextSearchRag/agent.yaml | 0 .../AgentWithTextSearchRag/run-requests.http | 0 .../AgentsInWorkflows.csproj | 0 .../AgentsInWorkflows/Dockerfile | 0 .../AgentsInWorkflows/Program.cs | 0 .../AgentsInWorkflows/README.md | 0 .../AgentsInWorkflows/agent.yaml | 0 .../AgentsInWorkflows/run-requests.http | 0 dotnet/samples/05-end-to-end/README.md | 10 + .../ActorFrameworkWebApplicationExtensions.cs | 0 .../AgentWebChat.AgentHost.csproj | 0 .../Custom/CustomAITools.cs | 0 .../AgentWebChat.AgentHost/Program.cs | 0 .../Properties/launchSettings.json | 0 .../Utilities/ChatClientConnectionInfo.cs | 0 .../Utilities/ChatClientExtensions.cs | 0 .../appsettings.Development.json | 0 .../AgentWebChat.AgentHost/appsettings.json | 0 .../AgentWebChat.AppHost.csproj | 0 .../AgentWebChat.AppHost/ModelExtensions.cs | 0 .../AgentWebChat.AppHost/Program.cs | 0 .../Properties/launchSettings.json | 0 .../appsettings.Development.json | 0 .../AgentWebChat.AppHost/appsettings.json | 0 .../AgentWebChat.ServiceDefaults.csproj | 0 .../ServiceDefaultsExtensions.cs | 0 .../AgentWebChat.Web/A2AAgentClient.cs | 0 .../AgentWebChat.Web/AgentDiscoveryClient.cs | 0 .../AgentWebChat.Web/AgentWebChat.Web.csproj | 0 .../AgentWebChat.Web/Components/App.razor | 0 .../Components/Layout/MainLayout.razor | 0 .../Components/Layout/MainLayout.razor.css | 0 .../Components/Pages/Error.razor | 0 .../Components/Pages/Home.razor | 0 .../AgentWebChat.Web}/Components/Routes.razor | 0 .../Components/_Imports.razor | 0 .../AgentWebChat.Web/IAgentClient.cs | 0 .../OpenAIChatCompletionsAgentClient.cs | 0 .../OpenAIResponsesAgentClient.cs | 0 .../AgentWebChat.Web/Program.cs | 0 .../Properties/launchSettings.json | 0 .../appsettings.Development.json | 0 .../AgentWebChat.Web/appsettings.json | 0 .../AgentWebChat.Web/wwwroot/app.css | 0 .../AgentWebChat.Web}/wwwroot/favicon.png | Bin .../Client/AGUIWebChatClient.csproj | 0 .../Client/Components/App.razor | 0 .../Components/Layout/LoadingSpinner.razor | 0 .../Layout/LoadingSpinner.razor.css | 0 .../Client/Components/Layout/MainLayout.razor | 0 .../Components/Layout/MainLayout.razor.css | 0 .../Client/Components/Pages/Chat/Chat.razor | 0 .../Components/Pages/Chat/Chat.razor.css | 0 .../Components/Pages/Chat/ChatCitation.razor | 0 .../Pages/Chat/ChatCitation.razor.css | 0 .../Components/Pages/Chat/ChatHeader.razor | 0 .../Pages/Chat/ChatHeader.razor.css | 0 .../Components/Pages/Chat/ChatInput.razor | 0 .../Components/Pages/Chat/ChatInput.razor.css | 0 .../Components/Pages/Chat/ChatInput.razor.js | 0 .../Pages/Chat/ChatMessageItem.razor | 0 .../Pages/Chat/ChatMessageItem.razor.css | 0 .../Pages/Chat/ChatMessageList.razor | 0 .../Pages/Chat/ChatMessageList.razor.css | 0 .../Pages/Chat/ChatMessageList.razor.js | 0 .../Pages/Chat/ChatSuggestions.razor | 0 .../Pages/Chat/ChatSuggestions.razor.css | 0 .../Client}/Components/Routes.razor | 0 .../Client/Components/_Imports.razor | 0 .../agui-web-chat}/Client/Program.cs | 0 .../Client/Properties/launchSettings.json | 0 .../agui-web-chat}/Client/wwwroot/app.css | 0 .../agui-web-chat/Client}/wwwroot/favicon.png | Bin .../agui-web-chat}/README.md | 0 .../Server/AGUIWebChatServer.csproj | 0 .../agui-web-chat}/Server/Program.cs | 0 .../Server/Properties/launchSettings.json | 0 .../m365-agent}/AFAgentApplication.cs | 0 .../Agents/AdaptiveCardAIContent.cs | 0 .../Agents/WeatherForecastAgent.cs | 0 .../Agents/WeatherForecastAgentResponse.cs | 0 ...WeatherForecastAgentResponseContentType.cs | 0 .../m365-agent}/Auth/AspNetExtensions.cs | 0 .../Auth/TokenValidationOptions.cs | 0 .../m365-agent}/JsonUtilities.cs | 0 .../m365-agent}/M365Agent.csproj | 0 .../m365-agent}/Program.cs | 0 .../Properties/launchSettings.json | 0 .../m365-agent}/README.md | 0 .../m365-agent}/appManifest/color.png | Bin .../m365-agent}/appManifest/manifest.json | 0 .../m365-agent}/appManifest/outline.png | Bin .../m365-agent}/appsettings.json.template | 0 .../AgentWithPurview/AgentWithPurview.csproj | 0 .../purview}/AgentWithPurview/Program.cs | 0 .../01_SingleAgent/local.settings.json | 10 - .../local.settings.json | 10 - .../local.settings.json | 10 - .../local.settings.json | 10 - .../local.settings.json | 10 - .../06_LongRunningTools/local.settings.json | 10 - .../07_AgentAsMcpTool/local.settings.json | 10 - .../08_ReliableStreaming/local.settings.json | 12 - .../A2AClient/A2AClient.csproj | 23 + .../A2AClient/HostClientAgent.cs | 62 + .../A2AClientServer/A2AClient/Program.cs | 79 ++ .../A2AClientServer/A2AClient/README.md | 26 + .../A2AServer/A2AServer.csproj | 30 + .../A2AClientServer/A2AServer/A2AServer.http | 85 ++ .../A2AServer/HostAgentFactory.cs | 148 ++ .../A2AServer/Models/InvoiceQuery.cs | 167 +++ .../A2AClientServer/A2AServer/Program.cs | 113 ++ .../_to_delete/A2AClientServer/README.md | 235 ++++ .../a2a-inspector-agent-card.png | Bin .../a2a-inspector-raw-json-response.png | Bin .../a2a-inspector-send-message.png | Bin .../A2AClientServer/demo-architecture.png | Bin .../rest-client-agent-card.png | Bin .../rest-client-send-message.png | Bin .../AGUIClient/AGUIClient.csproj | 21 + .../AGUIClient/AGUIClientSerializerContext.cs | 12 + .../AGUIClientServer/AGUIClient/Program.cs | 213 +++ .../AGUIClientServer/AGUIClient/README.md | 34 + .../AGUIClient/SensorRequest.cs | 13 + .../AGUIClient/SensorResponse.cs | 13 + .../AGUIDojoServer/AGUIDojoServer.csproj | 0 .../AGUIDojoServerSerializerContext.cs | 0 .../AgenticUI/AgenticPlanningTools.cs | 0 .../AgenticUI/AgenticUIAgent.cs | 0 .../AgenticUI/JsonPatchOperation.cs | 0 .../AGUIDojoServer/AgenticUI/Plan.cs | 0 .../AGUIDojoServer/AgenticUI/Step.cs | 0 .../AGUIDojoServer/AgenticUI/StepStatus.cs | 0 .../BackendToolRendering/WeatherInfo.cs | 0 .../AGUIDojoServer/ChatClientAgentFactory.cs | 0 .../PredictiveStateUpdates/DocumentState.cs | 0 .../PredictiveStateUpdatesAgent.cs | 0 .../AGUIDojoServer/Program.cs | 0 .../Properties/launchSettings.json | 0 .../AGUIDojoServer/SharedState/Ingredient.cs | 0 .../AGUIDojoServer/SharedState/Recipe.cs | 0 .../SharedState/RecipeResponse.cs | 0 .../SharedState/SharedStateAgent.cs | 0 .../appsettings.Development.json | 0 .../AGUIDojoServer/appsettings.json | 0 .../AGUIServer/AGUIServer.csproj | 22 + .../AGUIServer/AGUIServer.http | 17 + .../AGUIServer/AGUIServerSerializerContext.cs | 9 + .../AGUIClientServer/AGUIServer/Program.cs | 51 + .../AGUIServer/Properties/launchSettings.json | 12 + .../ServerWeatherForecastRequest.cs | 9 + .../ServerWeatherForecastResponse.cs | 12 + .../_to_delete/AGUIClientServer/README.md | 208 +++ .../Client/AGUIWebChatClient.csproj | 14 + .../AGUIWebChat/Client/Components/App.razor | 23 + .../Components/Layout/LoadingSpinner.razor | 1 + .../Layout/LoadingSpinner.razor.css | 89 ++ .../Client/Components/Layout/MainLayout.razor | 9 + .../Components/Layout/MainLayout.razor.css | 20 + .../Client/Components/Pages/Chat/Chat.razor | 94 ++ .../Components/Pages/Chat/Chat.razor.css | 11 + .../Components/Pages/Chat/ChatCitation.razor | 38 + .../Pages/Chat/ChatCitation.razor.css | 37 + .../Components/Pages/Chat/ChatHeader.razor | 17 + .../Pages/Chat/ChatHeader.razor.css | 25 + .../Components/Pages/Chat/ChatInput.razor | 51 + .../Components/Pages/Chat/ChatInput.razor.css | 57 + .../Components/Pages/Chat/ChatInput.razor.js | 43 + .../Pages/Chat/ChatMessageItem.razor | 73 + .../Pages/Chat/ChatMessageItem.razor.css | 67 + .../Pages/Chat/ChatMessageList.razor | 42 + .../Pages/Chat/ChatMessageList.razor.css | 22 + .../Pages/Chat/ChatMessageList.razor.js | 34 + .../Pages/Chat/ChatSuggestions.razor | 78 ++ .../Pages/Chat/ChatSuggestions.razor.css | 9 + .../Client/Components/Routes.razor | 6 + .../Client/Components/_Imports.razor | 12 + .../_to_delete/AGUIWebChat/Client/Program.cs | 34 + .../Client/Properties/launchSettings.json | 15 + .../AGUIWebChat/Client/wwwroot/app.css | 93 ++ .../AGUIWebChat/Client/wwwroot/favicon.png | Bin 0 -> 1148 bytes .../samples/_to_delete/AGUIWebChat/README.md | 185 +++ .../Server/AGUIWebChatServer.csproj | 21 + .../_to_delete/AGUIWebChat/Server/Program.cs | 35 + .../Server/Properties/launchSettings.json | 14 + .../ActorFrameworkWebApplicationExtensions.cs | 40 + .../AgentWebChat.AgentHost.csproj | 33 + .../Custom/CustomAITools.cs | 15 + .../AgentWebChat.AgentHost/Program.cs | 181 +++ .../Properties/launchSettings.json | 25 + .../Utilities/ChatClientConnectionInfo.cs | 80 ++ .../Utilities/ChatClientExtensions.cs | 106 ++ .../appsettings.Development.json | 0 .../AgentWebChat.AgentHost}/appsettings.json | 0 .../AgentWebChat.AppHost.csproj | 24 + .../AgentWebChat.AppHost/ModelExtensions.cs | 266 ++++ .../AgentWebChat.AppHost/Program.cs | 21 + .../Properties/launchSettings.json | 29 + .../appsettings.Development.json | 0 .../AgentWebChat.AppHost/appsettings.json | 9 + .../AgentWebChat.ServiceDefaults.csproj | 22 + .../ServiceDefaultsExtensions.cs | 124 ++ .../AgentWebChat.Web/A2AAgentClient.cs | 168 +++ .../AgentWebChat.Web/AgentDiscoveryClient.cs | 30 + .../AgentWebChat.Web/AgentWebChat.Web.csproj | 18 + .../AgentWebChat.Web/Components/App.razor | 20 + .../Components/Layout/MainLayout.razor | 15 + .../Components/Layout/MainLayout.razor.css | 33 + .../Components/Pages/Error.razor | 35 + .../Components/Pages/Home.razor | 1207 +++++++++++++++++ .../AgentWebChat.Web/Components/Routes.razor | 6 + .../Components/_Imports.razor | 11 + .../AgentWebChat.Web/IAgentClient.cs | 36 + .../OpenAIChatCompletionsAgentClient.cs | 37 + .../OpenAIResponsesAgentClient.cs | 41 + .../AgentWebChat/AgentWebChat.Web/Program.cs | 52 + .../Properties/launchSettings.json | 23 + .../appsettings.Development.json | 0 .../AgentWebChat.Web}/appsettings.json | 0 .../AgentWebChat.Web/wwwroot/app.css | 16 + .../AgentWebChat.Web/wwwroot/favicon.png | Bin 0 -> 1148 bytes .../Agents/AzureFunctions/.editorconfig | 0 .../01_SingleAgent/01_SingleAgent.csproj | 42 + .../AzureFunctions/01_SingleAgent/Program.cs | 39 + .../AzureFunctions/01_SingleAgent/README.md | 89 ++ .../AzureFunctions/01_SingleAgent/demo.http | 8 + .../AzureFunctions/01_SingleAgent}/host.json | 0 .../02_AgentOrchestration_Chaining.csproj | 42 + .../FunctionTriggers.cs | 92 ++ .../02_AgentOrchestration_Chaining/Program.cs | 42 + .../02_AgentOrchestration_Chaining/README.md | 59 + .../02_AgentOrchestration_Chaining/demo.http | 3 + .../02_AgentOrchestration_Chaining}/host.json | 0 .../03_AgentOrchestration_Concurrency.csproj | 0 .../FunctionTriggers.cs | 0 .../Program.cs | 0 .../README.md | 0 .../demo.http | 0 .../host.json | 0 .../04_AgentOrchestration_Conditionals.csproj | 0 .../FunctionTriggers.cs | 0 .../Models.cs | 0 .../Program.cs | 0 .../README.md | 0 .../demo.http | 0 .../host.json | 0 .../05_AgentOrchestration_HITL.csproj | 0 .../FunctionTriggers.cs | 0 .../05_AgentOrchestration_HITL/Models.cs | 0 .../05_AgentOrchestration_HITL/Program.cs | 0 .../05_AgentOrchestration_HITL/README.md | 0 .../05_AgentOrchestration_HITL/demo.http | 0 .../05_AgentOrchestration_HITL/host.json | 20 + .../06_LongRunningTools.csproj | 0 .../06_LongRunningTools/FunctionTriggers.cs | 0 .../06_LongRunningTools/Models.cs | 0 .../06_LongRunningTools/Program.cs | 0 .../06_LongRunningTools/README.md | 0 .../06_LongRunningTools/Tools.cs | 0 .../06_LongRunningTools/demo.http | 0 .../06_LongRunningTools/host.json | 20 + .../07_AgentAsMcpTool.csproj | 0 .../07_AgentAsMcpTool/Program.cs | 0 .../07_AgentAsMcpTool/README.md | 0 .../07_AgentAsMcpTool/host.json | 0 .../08_ReliableStreaming.csproj | 0 .../08_ReliableStreaming/FunctionTriggers.cs | 0 .../08_ReliableStreaming/Program.cs | 0 .../08_ReliableStreaming/README.md | 0 .../RedisStreamResponseHandler.cs | 0 .../08_ReliableStreaming/Tools.cs | 0 .../08_ReliableStreaming/host.json | 0 .../Durable/Agents/AzureFunctions/README.md | 0 .../01_SingleAgent/01_SingleAgent.csproj | 30 + .../ConsoleApps/01_SingleAgent/Program.cs | 103 ++ .../ConsoleApps/01_SingleAgent/README.md | 56 + .../02_AgentOrchestration_Chaining.csproj | 0 .../02_AgentOrchestration_Chaining/Models.cs | 0 .../02_AgentOrchestration_Chaining/Program.cs | 0 .../02_AgentOrchestration_Chaining/README.md | 0 .../03_AgentOrchestration_Concurrency.csproj | 0 .../Models.cs | 0 .../Program.cs | 0 .../README.md | 0 .../04_AgentOrchestration_Conditionals.csproj | 0 .../Models.cs | 0 .../Program.cs | 0 .../README.md | 0 .../05_AgentOrchestration_HITL.csproj | 0 .../05_AgentOrchestration_HITL/Models.cs | 0 .../05_AgentOrchestration_HITL/Program.cs | 0 .../05_AgentOrchestration_HITL/README.md | 0 .../06_LongRunningTools.csproj | 0 .../ConsoleApps/06_LongRunningTools/Models.cs | 0 .../06_LongRunningTools/Program.cs | 0 .../ConsoleApps/06_LongRunningTools/README.md | 0 .../07_ReliableStreaming.csproj | 0 .../07_ReliableStreaming/Program.cs | 0 .../07_ReliableStreaming/README.md | 0 .../RedisStreamResponseHandler.cs | 0 .../Durable/Agents/ConsoleApps/README.md | 0 .../_to_delete/Durable/Directory.Build.props | 9 + .../A2AAgent_AsFunctionTools.csproj | 0 .../A2A/A2AAgent_AsFunctionTools/Program.cs | 0 .../A2A/A2AAgent_AsFunctionTools/README.md | 0 .../A2AAgent_PollingForTaskCompletion.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../GettingStarted/A2A/README.md | 0 .../GettingStarted/AGUI/README.md | 0 .../Client/Client.csproj | 0 .../Step01_GettingStarted/Client/Program.cs | 0 .../Step01_GettingStarted/Server/Program.cs | 0 .../Server/Properties/launchSettings.json | 0 .../Server/Server.csproj | 0 .../Server/appsettings.Development.json | 0 .../Server/appsettings.json | 0 .../Step02_BackendTools/Client/Client.csproj | 0 .../Step02_BackendTools/Client/Program.cs | 0 .../Step02_BackendTools/Server/Program.cs | 0 .../Server/Properties/launchSettings.json | 0 .../Step02_BackendTools/Server/Server.csproj | 0 .../Server/appsettings.Development.json | 8 + .../Server/appsettings.json | 0 .../Step03_FrontendTools/Client/Client.csproj | 0 .../Step03_FrontendTools/Client/Program.cs | 0 .../Step03_FrontendTools/Server/Program.cs | 0 .../Server/Properties/launchSettings.json | 0 .../Step03_FrontendTools/Server/Server.csproj | 0 .../Server/appsettings.Development.json | 8 + .../Server/appsettings.json | 0 .../Step04_HumanInLoop/Client/Client.csproj | 0 .../AGUI/Step04_HumanInLoop/Client/Program.cs | 0 .../ServerFunctionApprovalClientAgent.cs | 0 .../AGUI/Step04_HumanInLoop/Server/Program.cs | 0 .../Server/Properties/launchSettings.json | 0 .../Step04_HumanInLoop/Server/Server.csproj | 0 .../ServerFunctionApprovalServerAgent.cs | 0 .../Server/appsettings.Development.json | 0 .../Server/appsettings.json | 9 + .../Client/Client.csproj | 0 .../Step05_StateManagement/Client/Program.cs | 0 .../Client/StatefulAgent.cs | 0 .../Step05_StateManagement/Server/Program.cs | 0 .../Server/Properties/launchSettings.json | 0 .../Server/RecipeModels.cs | 0 .../Server/Server.csproj | 0 .../Server/SharedStateAgent.cs | 0 .../Server/appsettings.Development.json | 8 + .../Server/appsettings.json | 9 + .../AgentOpenTelemetry.csproj | 0 .../AgentOpenTelemetry/Program.cs | 0 .../AgentOpenTelemetry/README.md | 0 .../AgentOpenTelemetry/start-demo.ps1 | 0 .../Agent_With_A2A/Agent_With_A2A.csproj | 0 .../AgentProviders/Agent_With_A2A/Program.cs | 0 .../AgentProviders/Agent_With_A2A/README.md | 0 .../Agent_With_Anthropic.csproj | 0 .../Agent_With_Anthropic/Program.cs | 0 .../Agent_With_Anthropic/README.md | 0 .../Agent_With_AzureAIAgentsPersistent.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Agent_With_AzureAIProject.csproj | 0 .../Agent_With_AzureAIProject/Program.cs | 0 .../Agent_With_AzureAIProject/README.md | 0 .../Agent_With_AzureFoundryModel.csproj | 0 .../Agent_With_AzureFoundryModel/Program.cs | 0 .../Agent_With_AzureFoundryModel/README.md | 0 ...gent_With_AzureOpenAIChatCompletion.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Agent_With_AzureOpenAIResponses.csproj | 0 .../Program.cs | 0 .../Agent_With_AzureOpenAIResponses/README.md | 0 .../Agent_With_CustomImplementation.csproj | 0 .../Program.cs | 0 .../Agent_With_CustomImplementation/README.md | 0 .../Agent_With_GitHubCopilot.csproj | 0 .../Agent_With_GitHubCopilot/Program.cs | 0 .../Agent_With_GitHubCopilot/README.md | 0 .../Agent_With_GoogleGemini.csproj | 0 .../Agent_With_GoogleGemini/Program.cs | 0 .../Agent_With_GoogleGemini/README.md | 0 .../Agent_With_ONNX/Agent_With_ONNX.csproj | 0 .../AgentProviders/Agent_With_ONNX/Program.cs | 0 .../AgentProviders/Agent_With_ONNX/README.md | 0 .../Agent_With_Ollama.csproj | 0 .../Agent_With_Ollama/Program.cs | 0 .../Agent_With_Ollama/README.md | 0 .../Agent_With_OpenAIAssistants.csproj | 0 .../Agent_With_OpenAIAssistants/Program.cs | 0 .../Agent_With_OpenAIAssistants/README.md | 0 .../Agent_With_OpenAIChatCompletion.csproj | 0 .../Program.cs | 0 .../Agent_With_OpenAIChatCompletion/README.md | 0 .../Agent_With_OpenAIResponses.csproj | 0 .../Agent_With_OpenAIResponses/Program.cs | 0 .../Agent_With_OpenAIResponses/README.md | 0 .../GettingStarted/AgentProviders/README.md | 0 .../Agent_Anthropic_Step01_Running.csproj | 0 .../Agent_Anthropic_Step01_Running/Program.cs | 0 .../Agent_Anthropic_Step01_Running/README.md | 0 .../Agent_Anthropic_Step02_Reasoning.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...Anthropic_Step03_UsingFunctionTools.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Agent_Anthropic_Step04_UsingSkills.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../AgentWithAnthropic/README.md | 0 ...WithMemory_Step01_ChatHistoryMemory.csproj | 0 .../Program.cs | 0 ...ntWithMemory_Step02_MemoryUsingMem0.csproj | 0 .../Program.cs | 0 ...AgentWithMemory_Step03_CustomMemory.csproj | 0 .../Program.cs | 0 .../GettingStarted/AgentWithMemory/README.md | 0 .../Agent_OpenAI_Step01_Running.csproj | 0 .../Agent_OpenAI_Step01_Running/Program.cs | 0 .../Agent_OpenAI_Step02_Reasoning.csproj | 0 .../Agent_OpenAI_Step02_Reasoning/Program.cs | 0 ..._OpenAI_Step03_CreateFromChatClient.csproj | 0 .../OpenAIChatClientAgent.cs | 0 .../Program.cs | 0 .../README.md | 0 ...ep04_CreateFromOpenAIResponseClient.csproj | 0 .../OpenAIResponseClientAgent.cs | 0 .../Program.cs | 0 .../README.md | 0 .../Agent_OpenAI_Step05_Conversation.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../GettingStarted/AgentWithOpenAI/README.md | 0 .../AgentWithRAG_Step01_BasicTextRAG.csproj | 0 .../Program.cs | 0 .../TextSearchStore/TextSearchDocument.cs | 0 .../TextSearchStore/TextSearchStore.cs | 0 .../TextSearchStore/TextSearchStoreOptions.cs | 0 .../TextSearchStoreUpsertOptions.cs | 0 ...WithRAG_Step02_CustomVectorStoreRAG.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...tWithRAG_Step03_CustomRAGDataSource.csproj | 0 .../Program.cs | 0 ...entWithRAG_Step04_FoundryServiceRAG.csproj | 0 .../Program.cs | 0 .../contoso-outdoors-knowledge-base.md | 0 .../GettingStarted/AgentWithRAG/README.md | 0 .../Agent_Step01_Running.csproj | 0 .../Agents/Agent_Step01_Running/Program.cs | 0 .../Agent_Step02_MultiturnConversation.csproj | 0 .../Program.cs | 0 .../Agent_Step03_UsingFunctionTools.csproj | 0 .../Program.cs | 0 ...p04_UsingFunctionToolsWithApprovals.csproj | 0 .../Program.cs | 0 .../Agent_Step05_StructuredOutput.csproj | 0 .../Agent_Step05_StructuredOutput/Program.cs | 0 ...Agent_Step06_PersistedConversations.csproj | 0 .../Program.cs | 0 ...t_Step07_3rdPartyChatHistoryStorage.csproj | 0 .../Program.cs | 0 .../Agent_Step08_Observability.csproj | 0 .../Agent_Step08_Observability/Program.cs | 0 .../Agent_Step09_DependencyInjection.csproj | 0 .../Program.cs | 0 .../Agent_Step10_AsMcpTool.csproj | 0 .../Agents/Agent_Step10_AsMcpTool/Program.cs | 0 .../Agents/Agent_Step10_AsMcpTool/README.md | 0 .../Agent_Step11_UsingImages.csproj | 0 .../Agent_Step11_UsingImages/Program.cs | 0 .../Agents/Agent_Step11_UsingImages/README.md | 0 .../Agent_Step12_AsFunctionTool.csproj | 0 .../Agent_Step12_AsFunctionTool/Program.cs | 0 ...undResponsesWithToolsAndPersistence.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Agent_Step14_Middleware.csproj | 0 .../Agents/Agent_Step14_Middleware/Program.cs | 0 .../Agents/Agent_Step14_Middleware/README.md | 0 .../Agent_Step15_Plugins.csproj | 0 .../Agents/Agent_Step15_Plugins/Program.cs | 0 .../Agent_Step16_ChatReduction.csproj | 0 .../Agent_Step16_ChatReduction/Program.cs | 0 .../Agent_Step17_BackgroundResponses.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Agent_Step18_DeepResearch.csproj | 0 .../Agent_Step18_DeepResearch/Program.cs | 0 .../Agent_Step18_DeepResearch/README.md | 0 .../Agent_Step19_Declarative.csproj | 0 .../Agent_Step19_Declarative/Program.cs | 0 .../Agent_Step20_AdditionalAIContext.csproj | 0 .../Program.cs | 0 .../GettingStarted/Agents/README.md | 0 .../DeclarativeChatClientAgents.csproj | 0 .../DeclarativeAgents/ChatClient/Program.cs | 0 .../ChatClient/Properties/launchSettings.json | 0 .../DevUI_Step01_BasicUsage.csproj | 0 .../DevUI/DevUI_Step01_BasicUsage/Program.cs | 0 .../Properties/launchSettings.json | 0 .../DevUI/DevUI_Step01_BasicUsage/README.md | 0 .../GettingStarted/DevUI/README.md | 0 .../FoundryAgents_Step01.1_Basics.csproj | 0 .../FoundryAgents_Step01.1_Basics/Program.cs | 0 .../FoundryAgents_Step01.1_Basics/README.md | 0 .../FoundryAgents_Step01.2_Running.csproj | 0 .../FoundryAgents_Step01.2_Running/Program.cs | 0 .../FoundryAgents_Step01.2_Running/README.md | 0 ...Agents_Step02_MultiturnConversation.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...dryAgents_Step03_UsingFunctionTools.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...p04_UsingFunctionToolsWithApprovals.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...undryAgents_Step05_StructuredOutput.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...gents_Step06_PersistedConversations.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../FoundryAgents_Step07_Observability.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...ryAgents_Step08_DependencyInjection.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...Agents_Step09_UsingMcpClientAsTools.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Assets/walkway.jpg | Bin .../FoundryAgents_Step10_UsingImages.csproj | 0 .../Program.cs | 0 .../README.md | 0 ...FoundryAgents_Step11_AsFunctionTool.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../FoundryAgents_Step12_Middleware.csproj | 0 .../Program.cs | 0 .../FoundryAgents_Step12_Middleware/README.md | 0 .../FoundryAgents_Step13_Plugins.csproj | 0 .../FoundryAgents_Step13_Plugins/Program.cs | 0 .../FoundryAgents_Step13_Plugins/README.md | 0 ...oundryAgents_Step14_CodeInterpreter.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../Assets/cua_browser_search.png | Bin .../Assets/cua_search_results.png | Bin .../Assets/cua_search_typed.png | Bin .../ComputerUseUtil.cs | 0 .../FoundryAgents_Step15_ComputerUse.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../GettingStarted/FoundryAgents/README.md | 0 .../Agent_MCP_Server/Agent_MCP_Server.csproj | 0 .../Agent_MCP_Server/Program.cs | 0 .../Agent_MCP_Server/README.md | 0 .../Agent_MCP_Server_Auth.csproj | 0 .../Agent_MCP_Server_Auth/Program.cs | 0 .../Agent_MCP_Server_Auth/README.md | 0 .../FoundryAgent_Hosted_MCP.csproj | 0 .../FoundryAgent_Hosted_MCP/Program.cs | 0 .../FoundryAgent_Hosted_MCP/README.md | 0 .../ModelContextProtocol/README.md | 0 .../ResponseAgent_Hosted_MCP/Program.cs | 0 .../ResponseAgent_Hosted_MCP/README.md | 0 .../ResponseAgent_Hosted_MCP.csproj | 0 .../{ => _to_delete}/GettingStarted/README.md | 0 .../CustomAgentExecutors.csproj | 0 .../Agents/CustomAgentExecutors/Program.cs | 0 .../Agents/FoundryAgent/FoundryAgent.csproj | 0 .../Workflows/Agents/FoundryAgent/Program.cs | 0 .../DeploymentGroupChatManager.cs | 0 .../GroupChatToolApproval.csproj | 0 .../Agents/GroupChatToolApproval/Program.cs | 0 .../Agents/GroupChatToolApproval/README.md | 0 .../Agents/WorkflowAsAnAgent/Program.cs | 0 .../WorkflowAsAnAgent.csproj | 0 .../WorkflowAsAnAgent/WorkflowFactory.cs | 0 .../CheckpointAndRehydrate.csproj | 0 .../CheckpointAndRehydrate/Program.cs | 0 .../CheckpointAndRehydrate/WorkflowFactory.cs | 0 .../CheckpointAndResume.csproj | 0 .../Checkpoint/CheckpointAndResume/Program.cs | 0 .../CheckpointAndResume/WorkflowFactory.cs | 0 .../CheckpointWithHumanInTheLoop.csproj | 0 .../CheckpointWithHumanInTheLoop/Program.cs | 0 .../WorkflowFactory.cs | 0 .../Concurrent/Concurrent/Concurrent.csproj | 0 .../Concurrent/Concurrent/Program.cs | 0 .../Concurrent/MapReduce/MapReduce.csproj | 0 .../Workflows/Concurrent/MapReduce/Program.cs | 0 .../01_EdgeCondition/01_EdgeCondition.csproj | 0 .../01_EdgeCondition/Program.cs | 0 .../01_EdgeCondition/Resources.cs | 0 .../02_SwitchCase/02_SwitchCase.csproj | 0 .../ConditionalEdges/02_SwitchCase/Program.cs | 0 .../02_SwitchCase/Resources.cs | 0 .../03_MultiSelection.csproj | 0 .../03_MultiSelection/Program.cs | 0 .../03_MultiSelection/Resources.cs | 0 .../ConfirmInput/ConfirmInput.csproj | 0 .../ConfirmInput/ConfirmInput.yaml | 0 .../Declarative/ConfirmInput/Program.cs | 0 .../CustomerSupport/CustomerSupport.csproj | 0 .../Declarative/CustomerSupport/Program.cs | 0 .../CustomerSupport/TicketingPlugin.cs | 0 .../DeepResearch/DeepResearch.csproj | 0 .../Declarative/DeepResearch/Program.cs | 0 .../Declarative/DeepResearch/wttr.json | 0 .../ExecuteCode/ExecuteCode.csproj | 0 .../Declarative/ExecuteCode/Generated.cs | 0 .../Declarative/ExecuteCode/Program.cs | 0 .../ExecuteWorkflow/ExecuteWorkflow.csproj | 0 .../Declarative/ExecuteWorkflow/Program.cs | 0 .../FunctionTools/FunctionTools.csproj | 0 .../FunctionTools/FunctionTools.yaml | 0 .../Declarative/FunctionTools/MenuPlugin.cs | 0 .../Declarative/FunctionTools/Program.cs | 0 .../GenerateCode/GenerateCode.csproj | 0 .../Declarative/GenerateCode/Program.cs | 0 .../HostedWorkflow/HostedWorkflow.csproj | 0 .../Declarative/HostedWorkflow/Program.cs | 0 .../InputArguments/InputArguments.csproj | 0 .../InputArguments/InputArguments.yaml | 0 .../Declarative/InputArguments/Program.cs | 0 .../Declarative/Marketing/Marketing.csproj | 0 .../Declarative/Marketing/Program.cs | 0 .../Workflows/Declarative/README.md | 0 .../Declarative/StudentTeacher/Program.cs | 0 .../StudentTeacher/StudentTeacher.csproj | 0 .../Declarative/ToolApproval/Program.cs | 0 .../ToolApproval/ToolApproval.csproj | 0 .../ToolApproval/ToolApproval.yaml | 0 .../Workflows/Directory.Build.props | 0 .../HumanInTheLoopBasic.csproj | 0 .../HumanInTheLoopBasic/Program.cs | 0 .../HumanInTheLoopBasic/WorkflowFactory.cs | 0 .../GettingStarted/Workflows/Loop/Loop.csproj | 0 .../GettingStarted/Workflows/Loop/Program.cs | 0 .../ApplicationInsights.csproj | 0 .../ApplicationInsights/Program.cs | 0 .../AspireDashboard/AspireDashboard.csproj | 0 .../Observability/AspireDashboard/Program.cs | 0 .../WorkflowAsAnAgent/Program.cs | 0 .../WorkflowAsAnAgentObservability.csproj | 0 .../WorkflowAsAnAgent/WorkflowHelper.cs | 0 .../GettingStarted/Workflows/README.md | 0 .../Workflows/Resources/Lorem_Ipsum.txt | 0 .../Workflows/Resources/ambiguous_email.txt | 0 .../Workflows/Resources/email.txt | 0 .../Workflows/Resources/spam.txt | 0 .../Workflows/SharedStates/Program.cs | 0 .../Workflows/SharedStates/Resources.cs | 0 .../SharedStates/SharedStates.csproj | 0 .../Workflows/Visualization/Program.cs | 0 .../Workflows/Visualization/README.md | 0 .../Resources/graphviz_render.png | Bin .../Resources/mermaid_render.png | Bin .../Visualization/Visualization.csproj | 0 .../01_ExecutorsAndEdges.csproj | 0 .../01_ExecutorsAndEdges/Program.cs | 0 .../02_Streaming/02_Streaming.csproj | 0 .../_Foundational/02_Streaming/Program.cs | 0 .../03_AgentsInWorkflows.csproj | 0 .../03_AgentsInWorkflows/Program.cs | 0 .../04_AgentWorkflowPatterns.csproj | 0 .../04_AgentWorkflowPatterns/Program.cs | 0 .../05_MultiModelService.csproj | 0 .../05_MultiModelService/Program.cs | 0 .../06_SubWorkflows/06_SubWorkflows.csproj | 0 .../_Foundational/06_SubWorkflows/Program.cs | 0 .../07_MixedWorkflowAgentsAndExecutors.csproj | 0 .../Program.cs | 0 .../README.md | 0 .../08_WriterCriticWorkflow.csproj | 0 .../08_WriterCriticWorkflow/Program.cs | 0 .../AgentWithHostedMCP.csproj | 70 + .../AgentWithHostedMCP/Dockerfile | 20 + .../AgentWithHostedMCP/Program.cs | 34 + .../HostedAgents/AgentWithHostedMCP/README.md | 43 + .../AgentWithHostedMCP/agent.yaml | 31 + .../AgentWithHostedMCP/run-requests.http | 30 + .../AgentWithTextSearchRag.csproj | 69 + .../AgentWithTextSearchRag/Dockerfile | 20 + .../AgentWithTextSearchRag/Program.cs | 76 ++ .../AgentWithTextSearchRag/README.md | 41 + .../AgentWithTextSearchRag/agent.yaml | 31 + .../AgentWithTextSearchRag/run-requests.http | 30 + .../AgentsInWorkflows.csproj | 69 + .../HostedAgents/AgentsInWorkflows/Dockerfile | 20 + .../HostedAgents/AgentsInWorkflows/Program.cs | 37 + .../HostedAgents/AgentsInWorkflows/README.md | 26 + .../HostedAgents/AgentsInWorkflows/agent.yaml | 28 + .../AgentsInWorkflows/run-requests.http | 30 + .../M365Agent/AFAgentApplication.cs | 184 +++ .../M365Agent/Agents/AdaptiveCardAIContent.cs | 36 + .../M365Agent/Agents/WeatherForecastAgent.cs | 115 ++ .../Agents/WeatherForecastAgentResponse.cs | 47 + ...WeatherForecastAgentResponseContentType.cs | 17 + .../M365Agent/Auth/AspNetExtensions.cs | 206 +++ .../M365Agent/Auth/TokenValidationOptions.cs | 52 + .../_to_delete/M365Agent/JsonUtilities.cs | 73 + .../_to_delete/M365Agent/M365Agent.csproj | 29 + .../samples/_to_delete/M365Agent/Program.cs | 104 ++ .../M365Agent/Properties/launchSettings.json | 12 + dotnet/samples/_to_delete/M365Agent/README.md | 119 ++ .../M365Agent/appManifest/color.png | Bin 0 -> 3415 bytes .../M365Agent/appManifest/manifest.json | 50 + .../M365Agent/appManifest/outline.png | Bin 0 -> 407 bytes .../M365Agent/appsettings.json.template | 54 + .../AgentWithPurview/AgentWithPurview.csproj | 21 + .../Purview/AgentWithPurview/Program.cs | 43 + 816 files changed, 10988 insertions(+), 82 deletions(-) create mode 100644 dotnet/samples/01-get-started/01_HelloAgent.cs create mode 100644 dotnet/samples/01-get-started/02_AddTools.cs create mode 100644 dotnet/samples/01-get-started/03_MultiTurn.cs create mode 100644 dotnet/samples/01-get-started/04_Memory.cs create mode 100644 dotnet/samples/01-get-started/05_FirstWorkflow.cs create mode 100644 dotnet/samples/01-get-started/06_HostYourAgent.cs create mode 100644 dotnet/samples/01-get-started/README.md create mode 100644 dotnet/samples/02-agents/BackgroundResponses.cs create mode 100644 dotnet/samples/02-agents/DeclarativeAgents.cs create mode 100644 dotnet/samples/02-agents/Observability.cs create mode 100644 dotnet/samples/02-agents/README.md create mode 100644 dotnet/samples/02-agents/Rag.cs create mode 100644 dotnet/samples/02-agents/StructuredOutput.cs create mode 100644 dotnet/samples/02-agents/conversations/CustomStorage.cs create mode 100644 dotnet/samples/02-agents/conversations/PersistentConversation.cs create mode 100644 dotnet/samples/02-agents/middleware/ChatClientMiddleware.cs create mode 100644 dotnet/samples/02-agents/middleware/DefiningMiddleware.cs create mode 100644 dotnet/samples/02-agents/middleware/FunctionOverride.cs create mode 100644 dotnet/samples/02-agents/middleware/Guardrails.cs create mode 100644 dotnet/samples/02-agents/middleware/HumanApproval.cs create mode 100644 dotnet/samples/02-agents/middleware/PIIFiltering.cs create mode 100644 dotnet/samples/02-agents/middleware/PerRequestMiddleware.cs create mode 100644 dotnet/samples/02-agents/providers/AnthropicProvider.cs create mode 100644 dotnet/samples/02-agents/providers/AzureAIFoundry.cs create mode 100644 dotnet/samples/02-agents/providers/AzureOpenAI.cs create mode 100644 dotnet/samples/02-agents/providers/CopilotStudio.cs create mode 100644 dotnet/samples/02-agents/providers/CustomProvider.cs create mode 100644 dotnet/samples/02-agents/providers/GitHubCopilot.cs create mode 100644 dotnet/samples/02-agents/providers/OllamaProvider.cs create mode 100644 dotnet/samples/02-agents/providers/OpenAIProvider.cs create mode 100644 dotnet/samples/02-agents/tools/CodeInterpreter.cs create mode 100644 dotnet/samples/02-agents/tools/FileSearch.cs create mode 100644 dotnet/samples/02-agents/tools/FunctionTools.cs create mode 100644 dotnet/samples/02-agents/tools/HostedMcpTools.cs create mode 100644 dotnet/samples/02-agents/tools/LocalMcpTools.cs create mode 100644 dotnet/samples/02-agents/tools/ToolApproval.cs create mode 100644 dotnet/samples/02-agents/tools/WebSearch.cs create mode 100644 dotnet/samples/03-workflows/README.md create mode 100644 dotnet/samples/03-workflows/agents-in-workflows/AgentsInWorkflows.cs create mode 100644 dotnet/samples/03-workflows/branching/Branching.cs create mode 100644 dotnet/samples/03-workflows/checkpoints/Checkpoints.cs create mode 100644 dotnet/samples/03-workflows/concurrent/Concurrent.cs create mode 100644 dotnet/samples/03-workflows/declarative/Declarative.cs create mode 100644 dotnet/samples/03-workflows/human-in-the-loop/HumanInTheLoop.cs create mode 100644 dotnet/samples/03-workflows/sequential/Sequential.cs create mode 100644 dotnet/samples/03-workflows/state-management/StateManagement.cs create mode 100644 dotnet/samples/03-workflows/visualization/Visualization.cs create mode 100644 dotnet/samples/04-hosting/README.md rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AClient/A2AClient.csproj (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AClient/HostClientAgent.cs (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AClient/Program.cs (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AClient/README.md (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AServer/A2AServer.csproj (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AServer/A2AServer.http (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AServer/HostAgentFactory.cs (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AServer/Models/InvoiceQuery.cs (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/A2AServer/Program.cs (100%) rename dotnet/samples/{A2AClientServer => 04-hosting/a2a}/README.md (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIClient/AGUIClient.csproj (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIClient/AGUIClientSerializerContext.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIClient/Program.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIClient/README.md (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIClient/SensorRequest.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIClient/SensorResponse.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/AGUIServer.csproj (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/AGUIServer.http (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/AGUIServerSerializerContext.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/Program.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/Properties/launchSettings.json (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/ServerWeatherForecastRequest.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/AGUIServer/ServerWeatherForecastResponse.cs (100%) rename dotnet/samples/{AGUIClientServer => 04-hosting/ag-ui}/README.md (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/01_SingleAgent/01_SingleAgent.csproj (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/01_SingleAgent/Program.cs (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/01_SingleAgent/README.md (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/01_SingleAgent/demo.http (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/01_SingleAgent/host.json (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/02_AgentOrchestration_Chaining/FunctionTriggers.cs (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/02_AgentOrchestration_Chaining/Program.cs (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/02_AgentOrchestration_Chaining/README.md (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/02_AgentOrchestration_Chaining/demo.http (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions => 04-hosting/azure-functions}/02_AgentOrchestration_Chaining/host.json (100%) rename dotnet/samples/{Durable/Agents => 04-hosting/azure-functions}/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj (100%) rename dotnet/samples/{Durable/Agents => 04-hosting/azure-functions}/ConsoleApps/01_SingleAgent/Program.cs (100%) rename dotnet/samples/{Durable/Agents => 04-hosting/azure-functions}/ConsoleApps/01_SingleAgent/README.md (100%) rename dotnet/samples/{Durable => 04-hosting/azure-functions}/Directory.Build.props (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithHostedMCP/AgentWithHostedMCP.csproj (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithHostedMCP/Dockerfile (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithHostedMCP/Program.cs (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithHostedMCP/README.md (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithHostedMCP/agent.yaml (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithHostedMCP/run-requests.http (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithTextSearchRag/Dockerfile (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithTextSearchRag/Program.cs (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithTextSearchRag/README.md (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithTextSearchRag/agent.yaml (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentWithTextSearchRag/run-requests.http (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentsInWorkflows/AgentsInWorkflows.csproj (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentsInWorkflows/Dockerfile (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentsInWorkflows/Program.cs (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentsInWorkflows/README.md (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentsInWorkflows/agent.yaml (100%) rename dotnet/samples/{HostedAgents => 04-hosting/openai-endpoints}/AgentsInWorkflows/run-requests.http (100%) create mode 100644 dotnet/samples/05-end-to-end/README.md rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/Custom/CustomAITools.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/Program.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/Properties/launchSettings.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/appsettings.Development.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AgentHost/appsettings.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AppHost/ModelExtensions.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AppHost/Program.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AppHost/Properties/launchSettings.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AppHost/appsettings.Development.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.AppHost/appsettings.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/A2AAgentClient.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/AgentDiscoveryClient.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/AgentWebChat.Web.csproj (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Components/App.razor (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Components/Layout/MainLayout.razor (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Components/Layout/MainLayout.razor.css (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Components/Pages/Error.razor (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Components/Pages/Home.razor (100%) rename dotnet/samples/{AGUIWebChat/Client => 05-end-to-end/agent-web-chat/AgentWebChat.Web}/Components/Routes.razor (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Components/_Imports.razor (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/IAgentClient.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/OpenAIResponsesAgentClient.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Program.cs (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/Properties/launchSettings.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/appsettings.Development.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/appsettings.json (100%) rename dotnet/samples/{AgentWebChat => 05-end-to-end/agent-web-chat}/AgentWebChat.Web/wwwroot/app.css (100%) rename dotnet/samples/{AGUIWebChat/Client => 05-end-to-end/agent-web-chat/AgentWebChat.Web}/wwwroot/favicon.png (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/AGUIWebChatClient.csproj (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/App.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Layout/LoadingSpinner.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Layout/LoadingSpinner.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Layout/MainLayout.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Layout/MainLayout.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/Chat.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/Chat.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatCitation.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatCitation.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatHeader.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatHeader.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatInput.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatInput.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatInput.razor.js (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatMessageItem.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatMessageItem.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatMessageList.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatMessageList.razor.css (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatMessageList.razor.js (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatSuggestions.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/Pages/Chat/ChatSuggestions.razor.css (100%) rename dotnet/samples/{AgentWebChat/AgentWebChat.Web => 05-end-to-end/agui-web-chat/Client}/Components/Routes.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Components/_Imports.razor (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Program.cs (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/Properties/launchSettings.json (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Client/wwwroot/app.css (100%) rename dotnet/samples/{AgentWebChat/AgentWebChat.Web => 05-end-to-end/agui-web-chat/Client}/wwwroot/favicon.png (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/README.md (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Server/AGUIWebChatServer.csproj (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Server/Program.cs (100%) rename dotnet/samples/{AGUIWebChat => 05-end-to-end/agui-web-chat}/Server/Properties/launchSettings.json (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/AFAgentApplication.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Agents/AdaptiveCardAIContent.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Agents/WeatherForecastAgent.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Agents/WeatherForecastAgentResponse.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Agents/WeatherForecastAgentResponseContentType.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Auth/AspNetExtensions.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Auth/TokenValidationOptions.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/JsonUtilities.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/M365Agent.csproj (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Program.cs (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/Properties/launchSettings.json (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/README.md (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/appManifest/color.png (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/appManifest/manifest.json (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/appManifest/outline.png (100%) rename dotnet/samples/{M365Agent => 05-end-to-end/m365-agent}/appsettings.json.template (100%) rename dotnet/samples/{Purview => 05-end-to-end/purview}/AgentWithPurview/AgentWithPurview.csproj (100%) rename dotnet/samples/{Purview => 05-end-to-end/purview}/AgentWithPurview/Program.cs (100%) delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/local.settings.json delete mode 100644 dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/local.settings.json create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AClient/A2AClient.csproj create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AClient/HostClientAgent.cs create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AClient/Program.cs create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AClient/README.md create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.csproj create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.http create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AServer/HostAgentFactory.cs create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AServer/Models/InvoiceQuery.cs create mode 100644 dotnet/samples/_to_delete/A2AClientServer/A2AServer/Program.cs create mode 100644 dotnet/samples/_to_delete/A2AClientServer/README.md rename dotnet/samples/{ => _to_delete}/A2AClientServer/a2a-inspector-agent-card.png (100%) rename dotnet/samples/{ => _to_delete}/A2AClientServer/a2a-inspector-raw-json-response.png (100%) rename dotnet/samples/{ => _to_delete}/A2AClientServer/a2a-inspector-send-message.png (100%) rename dotnet/samples/{ => _to_delete}/A2AClientServer/demo-architecture.png (100%) rename dotnet/samples/{ => _to_delete}/A2AClientServer/rest-client-agent-card.png (100%) rename dotnet/samples/{ => _to_delete}/A2AClientServer/rest-client-send-message.png (100%) create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClient.csproj create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClientSerializerContext.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/Program.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/README.md create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorRequest.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorResponse.cs rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AGUIDojoServer.csproj (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AGUIDojoServerSerializerContext.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticPlanningTools.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticUIAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AgenticUI/JsonPatchOperation.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AgenticUI/Plan.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AgenticUI/Step.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/AgenticUI/StepStatus.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/BackendToolRendering/WeatherInfo.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/ChatClientAgentFactory.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/DocumentState.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/PredictiveStateUpdatesAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/SharedState/Ingredient.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/SharedState/Recipe.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/SharedState/RecipeResponse.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/appsettings.Development.json (100%) rename dotnet/samples/{ => _to_delete}/AGUIClientServer/AGUIDojoServer/appsettings.json (100%) create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.csproj create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.http create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServerSerializerContext.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Program.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Properties/launchSettings.json create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastRequest.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastResponse.cs create mode 100644 dotnet/samples/_to_delete/AGUIClientServer/README.md create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/AGUIWebChatClient.csproj create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/App.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.js create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.js create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Routes.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Components/_Imports.razor create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Program.cs create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/Properties/launchSettings.json create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/app.css create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/favicon.png create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/README.md create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Server/AGUIWebChatServer.csproj create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Server/Program.cs create mode 100644 dotnet/samples/_to_delete/AGUIWebChat/Server/Properties/launchSettings.json create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Custom/CustomAITools.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Program.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Properties/launchSettings.json create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs rename dotnet/samples/{GettingStarted/AGUI/Step01_GettingStarted/Server => _to_delete/AgentWebChat/AgentWebChat.AgentHost}/appsettings.Development.json (100%) rename dotnet/samples/{GettingStarted/AGUI/Step01_GettingStarted/Server => _to_delete/AgentWebChat/AgentWebChat.AgentHost}/appsettings.json (100%) create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/ModelExtensions.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Program.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Properties/launchSettings.json rename dotnet/samples/{GettingStarted/AGUI/Step02_BackendTools/Server => _to_delete/AgentWebChat/AgentWebChat.AppHost}/appsettings.Development.json (100%) create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/appsettings.json create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentDiscoveryClient.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/App.razor create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Error.razor create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Home.razor create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Routes.razor create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/_Imports.razor create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/IAgentClient.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Program.cs create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Properties/launchSettings.json rename dotnet/samples/{GettingStarted/AGUI/Step03_FrontendTools/Server => _to_delete/AgentWebChat/AgentWebChat.Web}/appsettings.Development.json (100%) rename dotnet/samples/{GettingStarted/AGUI/Step02_BackendTools/Server => _to_delete/AgentWebChat/AgentWebChat.Web}/appsettings.json (100%) create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/app.css create mode 100644 dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/favicon.png rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/.editorconfig (100%) create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/01_SingleAgent.csproj create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/Program.cs create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/README.md create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/demo.http rename dotnet/samples/{Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency => _to_delete/Durable/Agents/AzureFunctions/01_SingleAgent}/host.json (100%) create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/FunctionTriggers.cs create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/Program.cs create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/README.md create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/demo.http rename dotnet/samples/{Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals => _to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining}/host.json (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/FunctionTriggers.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/demo.http (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL => _to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency}/host.json (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/FunctionTriggers.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/demo.http (100%) rename dotnet/samples/{Durable/Agents/AzureFunctions/06_LongRunningTools => _to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals}/host.json (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/FunctionTriggers.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/demo.http (100%) create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/host.json rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/06_LongRunningTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/FunctionTriggers.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/Tools.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/06_LongRunningTools/demo.http (100%) create mode 100644 dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/host.json rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/07_AgentAsMcpTool.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/host.json (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/08_ReliableStreaming.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/FunctionTriggers.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/RedisStreamResponseHandler.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/Tools.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/08_ReliableStreaming/host.json (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/AzureFunctions/README.md (100%) create mode 100644 dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj create mode 100644 dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/Program.cs create mode 100644 dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/README.md rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/06_LongRunningTools/06_LongRunningTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/06_LongRunningTools/Models.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/06_LongRunningTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/06_LongRunningTools/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/07_ReliableStreaming/07_ReliableStreaming.csproj (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/07_ReliableStreaming/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/07_ReliableStreaming/README.md (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/07_ReliableStreaming/RedisStreamResponseHandler.cs (100%) rename dotnet/samples/{ => _to_delete}/Durable/Agents/ConsoleApps/README.md (100%) create mode 100644 dotnet/samples/_to_delete/Durable/Directory.Build.props rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/A2AAgent_AsFunctionTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/A2AAgent_AsFunctionTools/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/A2A/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step01_GettingStarted/Client/Client.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step01_GettingStarted/Client/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step01_GettingStarted/Server/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step01_GettingStarted/Server/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step01_GettingStarted/Server/Server.csproj (100%) rename dotnet/samples/{GettingStarted/AGUI/Step05_StateManagement => _to_delete/GettingStarted/AGUI/Step01_GettingStarted}/Server/appsettings.Development.json (100%) rename dotnet/samples/{GettingStarted/AGUI/Step03_FrontendTools => _to_delete/GettingStarted/AGUI/Step01_GettingStarted}/Server/appsettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step02_BackendTools/Client/Client.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step02_BackendTools/Client/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step02_BackendTools/Server/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step02_BackendTools/Server/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step02_BackendTools/Server/Server.csproj (100%) create mode 100644 dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.Development.json rename dotnet/samples/{GettingStarted/AGUI/Step04_HumanInLoop => _to_delete/GettingStarted/AGUI/Step02_BackendTools}/Server/appsettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step03_FrontendTools/Client/Client.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step03_FrontendTools/Client/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step03_FrontendTools/Server/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step03_FrontendTools/Server/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step03_FrontendTools/Server/Server.csproj (100%) create mode 100644 dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.Development.json rename dotnet/samples/{GettingStarted/AGUI/Step05_StateManagement => _to_delete/GettingStarted/AGUI/Step03_FrontendTools}/Server/appsettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Client/Client.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Client/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Server/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Server/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Server/Server.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.Development.json (100%) create mode 100644 dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.json rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Client/Client.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Client/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Client/StatefulAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Server/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Server/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Server/RecipeModels.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Server/Server.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs (100%) create mode 100644 dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.Development.json create mode 100644 dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.json rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentOpenTelemetry/AgentOpenTelemetry.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentOpenTelemetry/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentOpenTelemetry/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentOpenTelemetry/start-demo.ps1 (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_A2A/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_A2A/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_Anthropic/Agent_With_Anthropic.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_Anthropic/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_Anthropic/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Agent_With_AzureAIAgentsPersistent.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Agent_With_AzureAIProject.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureAIProject/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Agent_With_GitHubCopilot.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Agent_With_GoogleGemini.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_GoogleGemini/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_ONNX/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_Ollama/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Agent_With_OpenAIAssistants.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentProviders/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Agent_Anthropic_Step01_Running.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Agent_Anthropic_Step02_Reasoning.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithAnthropic/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/AgentWithMemory_Step02_MemoryUsingMem0.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/AgentWithMemory_Step03_CustomMemory.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithMemory/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Agent_OpenAI_Step02_Reasoning.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Agent_OpenAI_Step03_CreateFromChatClient.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/OpenAIChatClientAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Agent_OpenAI_Step05_Conversation.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithOpenAI/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/AgentWithRAG_Step01_BasicTextRAG.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchDocument.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStore.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreOptions.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreUpsertOptions.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/AgentWithRAG_Step02_CustomVectorStoreRAG.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/contoso-outdoors-knowledge-base.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/AgentWithRAG/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step01_Running/Agent_Step01_Running.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step01_Running/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Agent_Step02_MultiturnConversation.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step06_PersistedConversations/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Agent_Step07_3rdPartyChatHistoryStorage.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step08_Observability/Agent_Step08_Observability.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step08_Observability/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step09_DependencyInjection/Agent_Step09_DependencyInjection.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step09_DependencyInjection/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step10_AsMcpTool/Agent_Step10_AsMcpTool.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step10_AsMcpTool/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step10_AsMcpTool/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step11_UsingImages/Agent_Step11_UsingImages.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step11_UsingImages/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step11_UsingImages/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Agent_Step12_AsFunctionTool.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Agent_Step13_BackgroundResponsesWithToolsAndPersistence.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step14_Middleware/Agent_Step14_Middleware.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step14_Middleware/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step14_Middleware/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step15_Plugins/Agent_Step15_Plugins.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step17_BackgroundResponses/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step18_DeepResearch/Agent_Step18_DeepResearch.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step18_DeepResearch/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step18_DeepResearch/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step19_Declarative/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Agent_Step20_AdditionalAIContext.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Agents/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DeclarativeAgents/ChatClient/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DeclarativeAgents/ChatClient/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DevUI/DevUI_Step01_BasicUsage/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/DevUI/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/FoundryAgents/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/Agent_MCP_Server/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Agent_MCP_Server_Auth.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/FoundryAgent_Hosted_MCP.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/ResponseAgent_Hosted_MCP.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/CustomAgentExecutors/CustomAgentExecutors.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/FoundryAgent/FoundryAgent.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/GroupChatToolApproval/DeploymentGroupChatManager.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/GroupChatToolApproval/GroupChatToolApproval.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/GroupChatToolApproval/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/GroupChatToolApproval/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowAsAnAgent.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/CheckpointAndRehydrate.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/CheckpointAndResume.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/CheckpointWithHumanInTheLoop.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Concurrent/Concurrent/Concurrent.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Concurrent/MapReduce/MapReduce.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/01_EdgeCondition.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Resources.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/02_SwitchCase.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Resources.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/03_MultiSelection.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Resources.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.yaml (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ConfirmInput/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/CustomerSupport/CustomerSupport.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/CustomerSupport/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/CustomerSupport/TicketingPlugin.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/DeepResearch/DeepResearch.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/DeepResearch/wttr.json (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ExecuteCode/ExecuteCode.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ExecuteWorkflow/ExecuteWorkflow.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.yaml (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/FunctionTools/MenuPlugin.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/FunctionTools/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/GenerateCode/GenerateCode.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/GenerateCode/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/HostedWorkflow/HostedWorkflow.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/HostedWorkflow/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.yaml (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/InputArguments/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/Marketing/Marketing.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/Marketing/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/StudentTeacher/StudentTeacher.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ToolApproval/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.yaml (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Directory.Build.props (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/HumanInTheLoopBasic.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Loop/Loop.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Loop/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/ApplicationInsights/ApplicationInsights.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/AspireDashboard/AspireDashboard.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowAsAnAgentObservability.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowHelper.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Resources/Lorem_Ipsum.txt (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Resources/ambiguous_email.txt (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Resources/email.txt (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Resources/spam.txt (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/SharedStates/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/SharedStates/Resources.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/SharedStates/SharedStates.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Visualization/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Visualization/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Visualization/Resources/graphviz_render.png (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Visualization/Resources/mermaid_render.png (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/Visualization/Visualization.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/01_ExecutorsAndEdges.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/02_Streaming/02_Streaming.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/03_AgentsInWorkflows.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/04_AgentWorkflowPatterns.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/05_MultiModelService/05_MultiModelService.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/06_SubWorkflows/06_SubWorkflows.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/06_SubWorkflows/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/07_MixedWorkflowAgentsAndExecutors.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/Program.cs (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/README.md (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/08_WriterCriticWorkflow.csproj (100%) rename dotnet/samples/{ => _to_delete}/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs (100%) create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Dockerfile create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Program.cs create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/README.md create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/agent.yaml create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/run-requests.http create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Dockerfile create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Program.cs create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/README.md create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/agent.yaml create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/run-requests.http create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Dockerfile create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Program.cs create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/README.md create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/agent.yaml create mode 100644 dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/run-requests.http create mode 100644 dotnet/samples/_to_delete/M365Agent/AFAgentApplication.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Agents/AdaptiveCardAIContent.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgent.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponse.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponseContentType.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Auth/AspNetExtensions.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Auth/TokenValidationOptions.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/JsonUtilities.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/M365Agent.csproj create mode 100644 dotnet/samples/_to_delete/M365Agent/Program.cs create mode 100644 dotnet/samples/_to_delete/M365Agent/Properties/launchSettings.json create mode 100644 dotnet/samples/_to_delete/M365Agent/README.md create mode 100644 dotnet/samples/_to_delete/M365Agent/appManifest/color.png create mode 100644 dotnet/samples/_to_delete/M365Agent/appManifest/manifest.json create mode 100644 dotnet/samples/_to_delete/M365Agent/appManifest/outline.png create mode 100644 dotnet/samples/_to_delete/M365Agent/appsettings.json.template create mode 100644 dotnet/samples/_to_delete/Purview/AgentWithPurview/AgentWithPurview.csproj create mode 100644 dotnet/samples/_to_delete/Purview/AgentWithPurview/Program.cs diff --git a/dotnet/samples/01-get-started/01_HelloAgent.cs b/dotnet/samples/01-get-started/01_HelloAgent.cs new file mode 100644 index 0000000000..43db8cd3f8 --- /dev/null +++ b/dotnet/samples/01-get-started/01_HelloAgent.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Step 1: Your First Agent +// The simplest possible agent — send a message, get a response. +// Uses Azure AI Foundry Responses API as the default provider. +// +// For more on agents, see: ../02-agents/README.md +// For docs: https://learn.microsoft.com/agent-framework/get-started/your-first-agent + +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; + +// +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "Assistant", + model: deploymentName, + instructions: "You are a helpful assistant."); +// + +// +Console.WriteLine(await agent.RunAsync("What is the capital of France?")); +// + +// +await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me a fun fact about Paris.")) +{ + Console.Write(update); +} +Console.WriteLine(); +// + +// Cleanup +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/01-get-started/02_AddTools.cs b/dotnet/samples/01-get-started/02_AddTools.cs new file mode 100644 index 0000000000..6059c0b174 --- /dev/null +++ b/dotnet/samples/01-get-started/02_AddTools.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Step 2: Add Tools +// Give your agent the ability to call functions (tools) to retrieve external data. +// This sample adds a weather function tool and demonstrates automatic tool invocation. +// +// For tools deep dive, see: ../02-agents/tools/ +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using System.ComponentModel; +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +// +[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."; +// + +// +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +AITool tool = AIFunctionFactory.Create(GetWeather); +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "WeatherAssistant", + model: deploymentName, + instructions: "You are a helpful assistant that can get weather information.", + tools: [tool]); +// + +// +AgentSession session = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", session)); +// + +// Streaming with tools +session = await agent.CreateSessionAsync(); +await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("What is the weather like in Amsterdam?", session)) +{ + Console.Write(update); +} +Console.WriteLine(); + +// Cleanup +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/01-get-started/03_MultiTurn.cs b/dotnet/samples/01-get-started/03_MultiTurn.cs new file mode 100644 index 0000000000..ca6f0ea7b1 --- /dev/null +++ b/dotnet/samples/01-get-started/03_MultiTurn.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Step 3: Multi-Turn Conversations +// Maintain conversation context across multiple exchanges with the agent. +// The session object preserves conversation state between calls. +// +// For more on conversations, see: ../02-agents/conversations/ +// For docs: https://learn.microsoft.com/agent-framework/agents/conversations + +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +ChatClientAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "JokerAgent", + options: new AgentVersionCreationOptions( + new PromptAgentDefinition(model: deploymentName) + { + Instructions = "You are good at telling jokes." + })); + +// +// Create a conversation for tracking in Foundry UI +ProjectConversationsClient conversationsClient = aiProjectClient.GetProjectOpenAIClient().GetProjectConversationsClient(); +ProjectConversation conversation = await conversationsClient.CreateProjectConversationAsync(); + +AgentSession session = await agent.CreateSessionAsync(conversation.Id); + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session)); +Console.WriteLine(await agent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", session)); +// + +// Cleanup +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); +await conversationsClient.DeleteConversationAsync(conversation.Id); diff --git a/dotnet/samples/01-get-started/04_Memory.cs b/dotnet/samples/01-get-started/04_Memory.cs new file mode 100644 index 0000000000..66114da6ba --- /dev/null +++ b/dotnet/samples/01-get-started/04_Memory.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Step 4: Memory +// Add persistent memory so the agent can remember information across sessions. +// Uses ChatHistoryMemoryProvider with an in-memory vector store to recall prior conversations. +// +// For more on conversations, see: ../02-agents/conversations/ +// For docs: https://learn.microsoft.com/agent-framework/agents/memory + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.VectorData; +using Microsoft.SemanticKernel.Connectors.InMemory; +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"; +var embeddingDeploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME") ?? "text-embedding-3-large"; + +// +// Create a vector store for storing chat messages (replace with a persistent store in production). +VectorStore vectorStore = new InMemoryVectorStore(new InMemoryVectorStoreOptions() +{ + EmbeddingGenerator = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetEmbeddingClient(embeddingDeploymentName) + .AsIEmbeddingGenerator() +}); + +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsAIAgent(new ChatClientAgentOptions + { + ChatOptions = new() { Instructions = "You are good at telling jokes." }, + Name = "Joker", + AIContextProviderFactory = (ctx, ct) => new ValueTask(new ChatHistoryMemoryProvider( + vectorStore, + collectionName: "chathistory", + vectorDimensions: 3072, + storageScope: new() { UserId = "UID1", SessionId = Guid.NewGuid().ToString() }, + searchScope: new() { UserId = "UID1" })) + }); +// + +// +// Session 1: Tell the agent what you like +AgentSession session1 = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("I like jokes about Pirates. Tell me a joke about a pirate.", session1)); + +// Session 2: The agent remembers your preferences from session 1 +AgentSession session2 = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("Tell me a joke that I might like.", session2)); +// diff --git a/dotnet/samples/01-get-started/05_FirstWorkflow.cs b/dotnet/samples/01-get-started/05_FirstWorkflow.cs new file mode 100644 index 0000000000..4c154e1293 --- /dev/null +++ b/dotnet/samples/01-get-started/05_FirstWorkflow.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Step 5: Your First Workflow +// Chain processing steps together in a sequential workflow. +// Executors are processing units connected by edges that define data flow. +// +// For more on workflows, see: ../03-workflows/ +// For docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Microsoft.Agents.AI.Workflows; + +// +// First executor: converts input text to uppercase +Func uppercaseFunc = s => s.ToUpperInvariant(); +var uppercase = uppercaseFunc.BindAsExecutor("UppercaseExecutor"); + +// Second executor: reverses the text +var reverse = new ReverseTextExecutor(); +// + +// +WorkflowBuilder builder = new(uppercase); +builder.AddEdge(uppercase, reverse).WithOutputFrom(reverse); +var workflow = builder.Build(); +// + +// +await using Run run = await InProcessExecution.RunAsync(workflow, "Hello, World!"); +foreach (WorkflowEvent evt in run.NewEvents) +{ + if (evt is ExecutorCompletedEvent executorComplete) + { + Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}"); + } +} +// + +/// +/// Executor that reverses the input text. +/// +internal sealed class ReverseTextExecutor() : Executor("ReverseTextExecutor") +{ + public override ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + => ValueTask.FromResult(string.Concat(message.Reverse())); +} diff --git a/dotnet/samples/01-get-started/06_HostYourAgent.cs b/dotnet/samples/01-get-started/06_HostYourAgent.cs new file mode 100644 index 0000000000..e4107a9b78 --- /dev/null +++ b/dotnet/samples/01-get-started/06_HostYourAgent.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Step 6: Host Your Agent +// Expose an agent over the A2A (Agent-to-Agent) protocol so other agents can call it. +// This sample shows how to consume an A2A agent's skills as function tools. +// +// For more on hosting, see: ../04-hosting/ +// For docs: https://learn.microsoft.com/agent-framework/hosting/a2a + +using A2A; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +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"; +var a2aAgentHost = Environment.GetEnvironmentVariable("A2A_AGENT_HOST") + ?? throw new InvalidOperationException("A2A_AGENT_HOST is not set."); + +// +// Discover and connect to a remote A2A agent +A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost)); +AgentCard agentCard = await agentCardResolver.GetAgentCardAsync(); +AIAgent a2aAgent = agentCard.AsAIAgent(); +// + +// +// Create a local agent that can use the remote agent's skills as tools +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsAIAgent( + instructions: "You are a helpful assistant that helps people with travel planning.", + tools: [.. a2aAgent.AsAIFunctions(agentCard)]); + +Console.WriteLine(await agent.RunAsync( + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport'")); +// diff --git a/dotnet/samples/01-get-started/README.md b/dotnet/samples/01-get-started/README.md new file mode 100644 index 0000000000..186d3f5a7e --- /dev/null +++ b/dotnet/samples/01-get-started/README.md @@ -0,0 +1,24 @@ +# Get Started with Agent Framework (.NET) + +Progressive samples that build up from a simple agent to a hosted application. + +| # | Sample | What You'll Learn | Go Deeper | +|---|--------|-------------------|-----------| +| 1 | [Hello Agent](./01_HelloAgent.cs) | Create and run a minimal agent | [Agents Overview](../02-agents/) | +| 2 | [Add Tools](./02_AddTools.cs) | Give your agent function tools | [Tools Deep Dive](../02-agents/tools/) | +| 3 | [Multi-Turn](./03_MultiTurn.cs) | Maintain conversation context | [Conversations](../02-agents/conversations/) | +| 4 | [Memory](./04_Memory.cs) | Add persistent memory/context | [Conversations](../02-agents/conversations/) | +| 5 | [First Workflow](./05_FirstWorkflow.cs) | Chain steps in a workflow | [Workflows](../03-workflows/) | +| 6 | [Host Your Agent](./06_HostYourAgent.cs) | Expose agent via A2A protocol | [Hosting](../04-hosting/) | + +## Prerequisites + +```bash +dotnet add package Microsoft.Agents.AI +``` + +## Running + +```bash +dotnet run 01_HelloAgent.cs +``` diff --git a/dotnet/samples/02-agents/BackgroundResponses.cs b/dotnet/samples/02-agents/BackgroundResponses.cs new file mode 100644 index 0000000000..b53135887c --- /dev/null +++ b/dotnet/samples/02-agents/BackgroundResponses.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Background Responses +// Use background responses for long-running agent tasks with polling and resumption. +// Supports both non-streaming (polling) and streaming (with interruption recovery). +// +// For docs: https://learn.microsoft.com/agent-framework/agents/background-responses + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using OpenAI.Responses; + +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"; + +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetResponsesClient(deploymentName) + .AsAIAgent(); + +// +AgentRunOptions options = new() { AllowBackgroundResponses = true }; +AgentSession session = await agent.CreateSessionAsync(); + +AgentResponse response = await agent.RunAsync("Write a very long novel about otters in space.", session, options); + +// Poll until the response is complete. +while (response.ContinuationToken is { } token) +{ + await Task.Delay(TimeSpan.FromSeconds(2)); + options.ContinuationToken = token; + response = await agent.RunAsync(session, options); +} + +Console.WriteLine(response.Text); +// + +// +options = new() { AllowBackgroundResponses = true }; +session = await agent.CreateSessionAsync(); + +AgentResponseUpdate? lastUpdate = null; +await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Write a very long novel about otters in space.", session, options)) +{ + Console.Write(update.Text); + lastUpdate = update; + + // Simulate connection loss + if (update.Text.Length > 0) break; +} + +// Resume from interruption point +options.ContinuationToken = lastUpdate?.ContinuationToken; +await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(session, options)) +{ + Console.Write(update.Text); +} +// diff --git a/dotnet/samples/02-agents/DeclarativeAgents.cs b/dotnet/samples/02-agents/DeclarativeAgents.cs new file mode 100644 index 0000000000..0905a6287e --- /dev/null +++ b/dotnet/samples/02-agents/DeclarativeAgents.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Declarative Agents +// Load an agent definition from a YAML file and run it. +// Enables no-code/low-code agent definitions with optional function tools. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/declarative-agents + +using System.ComponentModel; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +IChatClient chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient(); + +if (args.Length < 2) +{ + Console.WriteLine("Usage: DeclarativeAgents "); + return; +} + +var yamlFilePath = args[0]; +var prompt = args[1]; + +if (!File.Exists(yamlFilePath)) +{ + Console.WriteLine($"Error: File not found: {yamlFilePath}"); + return; +} + +// +[Description("Get the weather for a given location.")] +static string GetWeather( + [Description("The city and state, e.g. San Francisco, CA")] string location, + [Description("The unit of temperature. Possible values are 'celsius' and 'fahrenheit'.")] string unit) + => $"The weather in {location} is cloudy with a high of {(unit.Equals("celsius", StringComparison.Ordinal) ? "15°C" : "59°F")}."; + +var text = await File.ReadAllTextAsync(yamlFilePath); +var agentFactory = new ChatClientPromptAgentFactory(chatClient, [AIFunctionFactory.Create(GetWeather, "GetWeather")]); +var agent = await agentFactory.CreateFromYamlAsync(text); + +Console.WriteLine(await agent!.RunAsync(prompt)); +// diff --git a/dotnet/samples/02-agents/Observability.cs b/dotnet/samples/02-agents/Observability.cs new file mode 100644 index 0000000000..47c4de9eac --- /dev/null +++ b/dotnet/samples/02-agents/Observability.cs @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Observability with OpenTelemetry +// Add tracing, metrics, and structured logging to your agent using OpenTelemetry. +// Telemetry data can be viewed in Aspire Dashboard or Azure Monitor. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/observability + +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.Metrics; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; + +// +const string SourceName = "OpenTelemetryAspire.ConsoleApp"; +const string ServiceName = "AgentOpenTelemetry"; + +var otlpEndpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"; + +using var tracerProvider = Sdk.CreateTracerProviderBuilder() + .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(ServiceName, serviceVersion: "1.0.0")) + .AddSource(SourceName) + .AddSource("*Microsoft.Agents.AI") + .AddHttpClientInstrumentation() + .AddOtlpExporter(options => options.Endpoint = new Uri(otlpEndpoint)) + .Build(); + +using var meterProvider = Sdk.CreateMeterProviderBuilder() + .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(ServiceName, serviceVersion: "1.0.0")) + .AddMeter(SourceName) + .AddMeter("*Microsoft.Agents.AI") + .AddHttpClientInstrumentation() + .AddOtlpExporter(options => options.Endpoint = new Uri(otlpEndpoint)) + .Build(); + +var serviceCollection = new ServiceCollection(); +serviceCollection.AddLogging(loggingBuilder => loggingBuilder + .SetMinimumLevel(LogLevel.Debug) + .AddOpenTelemetry(options => + { + options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(ServiceName, serviceVersion: "1.0.0")); + options.AddOtlpExporter(otlpOptions => otlpOptions.Endpoint = new Uri(otlpEndpoint)); + options.IncludeScopes = true; + options.IncludeFormattedMessage = true; + })); + +using var activitySource = new ActivitySource(SourceName); +// + +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"; + +[Description("Get the weather for a given location.")] +static async Task GetWeatherAsync([Description("The location to get the weather for.")] string location) +{ + await Task.Delay(2000); + return $"The weather in {location} is cloudy with a high of 15°C."; +} + +// +using var instrumentedChatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .AsBuilder() + .UseFunctionInvocation() + .UseOpenTelemetry(sourceName: SourceName, configure: (cfg) => cfg.EnableSensitiveData = true) + .Build(); + +var agent = new ChatClientAgent(instrumentedChatClient, + name: "OpenTelemetryDemoAgent", + instructions: "You are a helpful assistant that provides concise and informative responses.", + tools: [AIFunctionFactory.Create(GetWeatherAsync)]) + .AsBuilder() + .UseOpenTelemetry(SourceName, configure: (cfg) => cfg.EnableSensitiveData = true) + .Build(); +// + +// +var session = await agent.CreateSessionAsync(); + +using var sessionActivity = activitySource.StartActivity("Agent Session"); +sessionActivity?.SetTag("agent.name", "OpenTelemetryDemoAgent"); + +await foreach (var update in agent.RunStreamingAsync("What's the weather in Seattle?", session)) +{ + Console.Write(update.Text); +} +Console.WriteLine(); +// diff --git a/dotnet/samples/02-agents/README.md b/dotnet/samples/02-agents/README.md new file mode 100644 index 0000000000..419e0741b8 --- /dev/null +++ b/dotnet/samples/02-agents/README.md @@ -0,0 +1,57 @@ +# Agents (.NET) + +Deep-dive samples covering agents, tools, middleware, conversations, and providers. + +## Agent Capabilities + +| Sample | What You'll Learn | +|--------|-------------------| +| [Structured Output](./StructuredOutput.cs) | Configure agents to return typed JSON responses | +| [Background Responses](./BackgroundResponses.cs) | Handle long-running tasks with polling and resumption | +| [RAG](./Rag.cs) | Add retrieval augmented generation with vector search | +| [Declarative Agents](./DeclarativeAgents.cs) | Load agent definitions from YAML files | +| [Observability](./Observability.cs) | Add OpenTelemetry tracing, metrics, and logging | + +## Tools + +| Sample | What You'll Learn | +|--------|-------------------| +| [Function Tools](./tools/FunctionTools.cs) | Define and register function tools | +| [Tool Approval](./tools/ToolApproval.cs) | Require human approval before tool invocation | +| [Code Interpreter](./tools/CodeInterpreter.cs) | Use hosted code interpreter for math and code | +| [File Search](./tools/FileSearch.cs) | Search uploaded documents with file search tool | +| [Web Search](./tools/WebSearch.cs) | Search the internet with web search tool | +| [Hosted MCP Tools](./tools/HostedMcpTools.cs) | Use server-side MCP tools via Responses API | +| [Local MCP Tools](./tools/LocalMcpTools.cs) | Use tools from a local MCP server process | + +## Middleware + +| Sample | What You'll Learn | +|--------|-------------------| +| [Defining Middleware](./middleware/DefiningMiddleware.cs) | Basic middleware setup with function tools | +| [Chat Client Middleware](./middleware/ChatClientMiddleware.cs) | Intercept LLM requests at the chat client level | +| [PII Filtering](./middleware/PIIFiltering.cs) | Redact personally identifiable information | +| [Guardrails](./middleware/Guardrails.cs) | Block forbidden content with keyword filtering | +| [Function Override](./middleware/FunctionOverride.cs) | Modify or override function tool results | +| [Human Approval](./middleware/HumanApproval.cs) | Prompt users for consent before function calls | +| [Per-Request Middleware](./middleware/PerRequestMiddleware.cs) | Scope middleware to a single agent run | + +## Conversations + +| Sample | What You'll Learn | +|--------|-------------------| +| [Persistent Conversation](./conversations/PersistentConversation.cs) | Serialize and resume agent sessions | +| [Custom Storage](./conversations/CustomStorage.cs) | Implement custom chat history storage | + +## Providers + +| Sample | Backend | +|--------|---------| +| [Azure AI Foundry](./providers/AzureAIFoundry.cs) | Azure AI Foundry Responses API (default) | +| [Azure OpenAI](./providers/AzureOpenAI.cs) | Azure OpenAI Chat Completion | +| [OpenAI](./providers/OpenAIProvider.cs) | OpenAI Chat Completion | +| [Anthropic](./providers/AnthropicProvider.cs) | Anthropic Claude (direct or via Foundry) | +| [Ollama](./providers/OllamaProvider.cs) | Ollama local models | +| [GitHub Copilot](./providers/GitHubCopilot.cs) | GitHub Copilot SDK | +| [Copilot Studio](./providers/CopilotStudio.cs) | Microsoft Copilot Studio via A2A | +| [Custom](./providers/CustomProvider.cs) | Fully custom AIAgent implementation | diff --git a/dotnet/samples/02-agents/Rag.cs b/dotnet/samples/02-agents/Rag.cs new file mode 100644 index 0000000000..74e3f239e5 --- /dev/null +++ b/dotnet/samples/02-agents/Rag.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Retrieval Augmented Generation (RAG) +// Add RAG capabilities using TextSearchProvider with a vector store. +// The provider searches relevant documents before each model invocation. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/rag + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Samples; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.VectorData; +using Microsoft.SemanticKernel.Connectors.InMemory; +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"; +var embeddingDeploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME") ?? "text-embedding-3-large"; + +AzureOpenAIClient azureOpenAIClient = new(new Uri(endpoint), new AzureCliCredential()); + +// +VectorStore vectorStore = new InMemoryVectorStore(new() +{ + EmbeddingGenerator = azureOpenAIClient.GetEmbeddingClient(embeddingDeploymentName).AsIEmbeddingGenerator() +}); + +TextSearchStore textSearchStore = new(vectorStore, "product-and-policy-info", 3072); +await textSearchStore.UpsertDocumentsAsync(GetSampleDocuments()); + +Func>> SearchAdapter = async (text, ct) => +{ + var searchResults = await textSearchStore.SearchAsync(text, 1, ct); + return searchResults.Select(r => new TextSearchProvider.TextSearchResult + { + SourceName = r.SourceName, + SourceLink = r.SourceLink, + Text = r.Text ?? string.Empty, + RawRepresentation = r + }); +}; + +AIAgent agent = azureOpenAIClient + .GetChatClient(deploymentName) + .AsAIAgent(new ChatClientAgentOptions + { + ChatOptions = new() { Instructions = "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available." }, + AIContextProviderFactory = (ctx, ct) => new ValueTask(new TextSearchProvider(SearchAdapter, ctx.SerializedState, ctx.JsonSerializerOptions)), + ChatHistoryProviderFactory = (ctx, ct) => new ValueTask(new InMemoryChatHistoryProvider(ctx.SerializedState, ctx.JsonSerializerOptions) + .WithAIContextProviderMessageRemoval()), + }); +// + +// +AgentSession session = await agent.CreateSessionAsync(); + +Console.WriteLine(await agent.RunAsync("Hi! I need help understanding the return policy.", session)); +Console.WriteLine(await agent.RunAsync("How long does standard shipping usually take?", session)); +Console.WriteLine(await agent.RunAsync("What is the best way to maintain the TrailRunner tent fabric?", session)); +// + +static IEnumerable GetSampleDocuments() +{ + yield return new TextSearchDocument + { + SourceId = "return-policy-001", + SourceName = "Contoso Outdoors Return Policy", + SourceLink = "https://contoso.com/policies/returns", + Text = "Customers may return any item within 30 days of delivery. Items should be unused and include original packaging. Refunds are issued to the original payment method within 5 business days of inspection." + }; + yield return new TextSearchDocument + { + SourceId = "shipping-guide-001", + SourceName = "Contoso Outdoors Shipping Guide", + SourceLink = "https://contoso.com/help/shipping", + Text = "Standard shipping is free on orders over $50 and typically arrives in 3-5 business days within the continental United States. Expedited options are available at checkout." + }; + yield return new TextSearchDocument + { + SourceId = "tent-care-001", + SourceName = "TrailRunner Tent Care Instructions", + SourceLink = "https://contoso.com/manuals/trailrunner-tent", + Text = "Clean the tent fabric with lukewarm water and a non-detergent soap. Allow it to air dry completely before storage and avoid prolonged UV exposure to extend the lifespan of the waterproof coating." + }; +} diff --git a/dotnet/samples/02-agents/StructuredOutput.cs b/dotnet/samples/02-agents/StructuredOutput.cs new file mode 100644 index 0000000000..c6d79e8241 --- /dev/null +++ b/dotnet/samples/02-agents/StructuredOutput.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Structured Output +// Configure an agent to produce structured (typed) JSON output. +// Demonstrates both RunAsync and streaming with deserialization. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/structured-output + +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; +using SampleApp; + +#pragma warning disable CA5399 + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +// +ChatClientAgent agent = await aiProjectClient.CreateAIAgentAsync( + model: deploymentName, + new ChatClientAgentOptions() + { + Name = "StructuredOutputAssistant", + ChatOptions = new() + { + Instructions = "You are a helpful assistant that extracts structured information about people.", + ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema() + } + }); + +AgentResponse response = await agent.RunAsync( + "Please provide information about John Smith, who is a 35-year-old software engineer."); + +Console.WriteLine($"Name: {response.Result.Name}"); +Console.WriteLine($"Age: {response.Result.Age}"); +Console.WriteLine($"Occupation: {response.Result.Occupation}"); +// + +// +IAsyncEnumerable updates = agent.RunStreamingAsync( + "Please provide information about Jane Doe, who is a 28-year-old data scientist."); + +PersonInfo personInfo = (await updates.ToAgentResponseAsync()).Deserialize(JsonSerializerOptions.Web); +Console.WriteLine($"Name: {personInfo.Name}, Age: {personInfo.Age}, Occupation: {personInfo.Occupation}"); +// + +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); + +namespace SampleApp +{ + [Description("Information about a person including their name, age, and occupation")] + public class PersonInfo + { + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("age")] + public int? Age { get; set; } + + [JsonPropertyName("occupation")] + public string? Occupation { get; set; } + } +} diff --git a/dotnet/samples/02-agents/conversations/CustomStorage.cs b/dotnet/samples/02-agents/conversations/CustomStorage.cs new file mode 100644 index 0000000000..18da76a7de --- /dev/null +++ b/dotnet/samples/02-agents/conversations/CustomStorage.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Custom Chat History Storage +// Implement a custom ChatHistoryProvider that stores chat history in a vector store. +// The session state persists only the storage key, not the full message history. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/conversations + +using System.Text.Json; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.VectorData; +using Microsoft.SemanticKernel.Connectors.InMemory; +using OpenAI.Chat; +using SampleApp; +using ChatMessage = Microsoft.Extensions.AI.ChatMessage; + +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"; + +VectorStore vectorStore = new InMemoryVectorStore(); + +// +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsAIAgent(new ChatClientAgentOptions + { + ChatOptions = new() { Instructions = "You are good at telling jokes." }, + Name = "Joker", + ChatHistoryProviderFactory = (ctx, ct) => new ValueTask( + new VectorChatHistoryProvider(vectorStore, ctx.SerializedState, ctx.JsonSerializerOptions)) + }); +// + +AgentSession session = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session)); + +// Serialize — only the storage key is persisted, not the full chat history +JsonElement serializedSession = agent.SerializeSession(session); +Console.WriteLine($"\nSerialized session:\n{JsonSerializer.Serialize(serializedSession, new JsonSerializerOptions { WriteIndented = true })}"); + +// Resume the session +AgentSession resumedSession = await agent.DeserializeSessionAsync(serializedSession); +Console.WriteLine(await agent.RunAsync("Now tell the same joke in the voice of a pirate.", resumedSession)); + +namespace SampleApp +{ + // + internal sealed class VectorChatHistoryProvider : ChatHistoryProvider + { + private readonly VectorStore _vectorStore; + + public VectorChatHistoryProvider(VectorStore vectorStore, JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null) + { + _vectorStore = vectorStore; + if (serializedState.ValueKind is JsonValueKind.String) + { + SessionDbKey = serializedState.Deserialize(); + } + } + + public string? SessionDbKey { get; private set; } + + public override async ValueTask> InvokingAsync(InvokingContext context, CancellationToken cancellationToken = default) + { + var collection = _vectorStore.GetCollection("ChatHistory"); + await collection.EnsureCollectionExistsAsync(cancellationToken); + + var records = await collection + .GetAsync(x => x.SessionId == SessionDbKey, 10, + new() { OrderBy = x => x.Descending(y => y.Timestamp) }, cancellationToken) + .ToListAsync(cancellationToken); + + var messages = records.ConvertAll(x => JsonSerializer.Deserialize(x.SerializedMessage!)!); + messages.Reverse(); + return messages; + } + + public override async ValueTask InvokedAsync(InvokedContext context, CancellationToken cancellationToken = default) + { + if (context.InvokeException is not null) return; + + SessionDbKey ??= Guid.NewGuid().ToString("N"); + + var collection = _vectorStore.GetCollection("ChatHistory"); + await collection.EnsureCollectionExistsAsync(cancellationToken); + + var allNewMessages = context.RequestMessages.Concat(context.ResponseMessages ?? []); + await collection.UpsertAsync(allNewMessages.Select(x => new ChatHistoryItem + { + Key = SessionDbKey + x.MessageId, + Timestamp = DateTimeOffset.UtcNow, + SessionId = SessionDbKey, + SerializedMessage = JsonSerializer.Serialize(x), + MessageText = x.Text + }), cancellationToken); + } + + public override JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null) + => JsonSerializer.SerializeToElement(SessionDbKey); + + private sealed class ChatHistoryItem + { + [VectorStoreKey] public string? Key { get; set; } + [VectorStoreData] public string? SessionId { get; set; } + [VectorStoreData] public DateTimeOffset? Timestamp { get; set; } + [VectorStoreData] public string? SerializedMessage { get; set; } + [VectorStoreData] public string? MessageText { get; set; } + } + } + // +} diff --git a/dotnet/samples/02-agents/conversations/PersistentConversation.cs b/dotnet/samples/02-agents/conversations/PersistentConversation.cs new file mode 100644 index 0000000000..0fbee042d7 --- /dev/null +++ b/dotnet/samples/02-agents/conversations/PersistentConversation.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Persisted Conversations +// Serialize and deserialize agent sessions so conversations can be saved and resumed. +// Works with both Azure AI Foundry and ChatClient-based agents. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/conversations + +using System.Text.Json; +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); +AIAgent agent = await aiProjectClient.CreateAIAgentAsync(name: "JokerAgent", model: deploymentName, instructions: "You are good at telling jokes."); + +// +AgentSession session = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session)); + +// Serialize the session state for storage +JsonElement serializedSession = agent.SerializeSession(session); + +// Save to file (or database, etc.) +string tempFilePath = Path.GetTempFileName(); +await File.WriteAllTextAsync(tempFilePath, JsonSerializer.Serialize(serializedSession)); +// + +// +// Later: Load and resume the session +JsonElement reloadedSession = JsonElement.Parse(await File.ReadAllTextAsync(tempFilePath))!; +AgentSession resumedSession = await agent.DeserializeSessionAsync(reloadedSession); + +Console.WriteLine(await agent.RunAsync("Now tell the same joke in the voice of a pirate, and add some emojis.", resumedSession)); +// + +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/02-agents/middleware/ChatClientMiddleware.cs b/dotnet/samples/02-agents/middleware/ChatClientMiddleware.cs new file mode 100644 index 0000000000..4edb79ac22 --- /dev/null +++ b/dotnet/samples/02-agents/middleware/ChatClientMiddleware.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Chat Client Middleware +// Add middleware at the chat client level to intercept LLM requests and responses. +// Useful for logging, modifying prompts, or transforming responses before they reach the agent. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using System.ComponentModel; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +[Description("The current datetime offset.")] +static string GetDateTime() => DateTimeOffset.Now.ToString(); + +// +async Task ChatClientMiddleware(IEnumerable messages, ChatOptions? options, IChatClient innerChatClient, CancellationToken cancellationToken) +{ + Console.WriteLine("[ChatClient Middleware] Pre-Chat"); + var response = await innerChatClient.GetResponseAsync(messages, options, cancellationToken); + Console.WriteLine("[ChatClient Middleware] Post-Chat"); + return response; +} + +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .AsBuilder() + .Use(getResponseFunc: ChatClientMiddleware, getStreamingResponseFunc: null) + .BuildAIAgent( + instructions: "You are an AI assistant.", + tools: [AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime))]); +// + +Console.WriteLine(await agent.RunAsync("What time is it?")); diff --git a/dotnet/samples/02-agents/middleware/DefiningMiddleware.cs b/dotnet/samples/02-agents/middleware/DefiningMiddleware.cs new file mode 100644 index 0000000000..7120c95b61 --- /dev/null +++ b/dotnet/samples/02-agents/middleware/DefiningMiddleware.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Defining Middleware +// Basic middleware setup showing agent-level middleware with function tools. +// Middleware intercepts agent invocations to add cross-cutting behavior. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using System.ComponentModel; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +[Description("The current datetime offset.")] +static string GetDateTime() => DateTimeOffset.Now.ToString(); + +// +// Function invocation middleware that logs before and after function calls +async ValueTask FunctionCallMiddleware(AIAgent agent, FunctionInvocationContext context, Func> next, CancellationToken cancellationToken) +{ + Console.WriteLine($"[Middleware] Pre-Invoke: {context.Function.Name}"); + var result = await next(context, cancellationToken); + Console.WriteLine($"[Middleware] Post-Invoke: {context.Function.Name}"); + return result; +} +// + +// +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .BuildAIAgent( + instructions: "You are an AI assistant that helps people find information.", + tools: [AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime))]); + +var middlewareAgent = agent + .AsBuilder() + .Use(FunctionCallMiddleware) + .Build(); +// + +Console.WriteLine(await middlewareAgent.RunAsync("What time is it?")); diff --git a/dotnet/samples/02-agents/middleware/FunctionOverride.cs b/dotnet/samples/02-agents/middleware/FunctionOverride.cs new file mode 100644 index 0000000000..818dacc858 --- /dev/null +++ b/dotnet/samples/02-agents/middleware/FunctionOverride.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Function Override Middleware +// Function invocation middleware that can modify or override tool results. +// Useful for testing, caching, or post-processing function outputs. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using System.ComponentModel; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +[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."; + +// +async ValueTask FunctionOverrideMiddleware(AIAgent agent, FunctionInvocationContext context, Func> next, CancellationToken cancellationToken) +{ + var result = await next(context, cancellationToken); + + // Override the weather function result + if (context.Function.Name == nameof(GetWeather)) + { + result = "The weather is sunny with a high of 25°C."; + } + + return result; +} +// + +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .BuildAIAgent( + instructions: "You are a helpful assistant.", + tools: [AIFunctionFactory.Create(GetWeather)]); + +var overriddenAgent = agent + .AsBuilder() + .Use(FunctionOverrideMiddleware) + .Build(); + +Console.WriteLine(await overriddenAgent.RunAsync("What's the weather in Seattle?")); diff --git a/dotnet/samples/02-agents/middleware/Guardrails.cs b/dotnet/samples/02-agents/middleware/Guardrails.cs new file mode 100644 index 0000000000..598ba7c4ff --- /dev/null +++ b/dotnet/samples/02-agents/middleware/Guardrails.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Guardrail Middleware +// Agent-level middleware that filters forbidden content from input and output messages. +// Blocks messages containing specified keywords before they reach or leave the model. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +// +async Task GuardrailMiddleware(IEnumerable messages, AgentSession? session, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken) +{ + var filteredMessages = FilterMessages(messages); + var response = await innerAgent.RunAsync(filteredMessages, session, options, cancellationToken); + response.Messages = FilterMessages(response.Messages); + return response; + + List FilterMessages(IEnumerable messages) + => messages.Select(m => new ChatMessage(m.Role, FilterContent(m.Text))).ToList(); + + static string FilterContent(string content) + { + foreach (var keyword in new[] { "harmful", "illegal", "violence" }) + { + if (content.Contains(keyword, StringComparison.OrdinalIgnoreCase)) + { + return "[REDACTED: Forbidden content]"; + } + } + return content; + } +} +// + +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .BuildAIAgent(instructions: "You are a helpful assistant."); + +var guardedAgent = agent + .AsBuilder() + .Use(GuardrailMiddleware, null) + .Build(); + +Console.WriteLine(await guardedAgent.RunAsync("Tell me something harmful.")); diff --git a/dotnet/samples/02-agents/middleware/HumanApproval.cs b/dotnet/samples/02-agents/middleware/HumanApproval.cs new file mode 100644 index 0000000000..92b3563924 --- /dev/null +++ b/dotnet/samples/02-agents/middleware/HumanApproval.cs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Human Approval Middleware +// Agent-level middleware that intercepts function approval requests and prompts +// the user for consent before allowing sensitive function invocations. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using System.ComponentModel; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +[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."; + +// +async Task ConsoleApprovalMiddleware(IEnumerable messages, AgentSession? session, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken) +{ + AgentResponse response = await innerAgent.RunAsync(messages, session, options, cancellationToken); + + List approvalRequests = response.Messages + .SelectMany(m => m.Contents).OfType().ToList(); + + while (approvalRequests.Count > 0) + { + response.Messages = approvalRequests + .ConvertAll(req => + { + Console.WriteLine($"Approve function '{req.FunctionCall.Name}'? (Y/N):"); + return new ChatMessage(ChatRole.User, [req.CreateResponse( + Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]); + }); + + response = await innerAgent.RunAsync(response.Messages, session, options, cancellationToken); + approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList(); + } + + return response; +} +// + +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .BuildAIAgent( + instructions: "You are a helpful assistant.", + tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather))]); + +var approvalAgent = agent + .AsBuilder() + .Use(ConsoleApprovalMiddleware, null) + .Build(); + +Console.WriteLine(await approvalAgent.RunAsync("What's the weather in Seattle?")); diff --git a/dotnet/samples/02-agents/middleware/PIIFiltering.cs b/dotnet/samples/02-agents/middleware/PIIFiltering.cs new file mode 100644 index 0000000000..6493d11068 --- /dev/null +++ b/dotnet/samples/02-agents/middleware/PIIFiltering.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft. All rights reserved. + +// PII Filtering Middleware +// Agent-level middleware that detects and redacts PII (personally identifiable information) +// from both input and output messages using regex patterns. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using System.Text.RegularExpressions; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +// +async Task PIIMiddleware(IEnumerable messages, AgentSession? session, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken) +{ + var filteredMessages = FilterMessages(messages); + var response = await innerAgent.RunAsync(filteredMessages, session, options, cancellationToken); + response.Messages = FilterMessages(response.Messages); + return response; + + static IList FilterMessages(IEnumerable messages) + => messages.Select(m => new ChatMessage(m.Role, FilterPii(m.Text))).ToList(); + + static string FilterPii(string content) + { + Regex[] piiPatterns = + [ + new(@"\b\d{3}-\d{3}-\d{4}\b", RegexOptions.Compiled), // Phone numbers + new(@"\b[\w\.-]+@[\w\.-]+\.\w+\b", RegexOptions.Compiled), // Email addresses + new(@"\b[A-Z][a-z]+\s[A-Z][a-z]+\b", RegexOptions.Compiled) // Full names + ]; + + foreach (var pattern in piiPatterns) + { + content = pattern.Replace(content, "[REDACTED: PII]"); + } + return content; + } +} +// + +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .BuildAIAgent(instructions: "You are a helpful assistant."); + +var piiAgent = agent + .AsBuilder() + .Use(PIIMiddleware, null) + .Build(); + +Console.WriteLine(await piiAgent.RunAsync("My name is John Doe, call me at 123-456-7890 or email me at john@something.com")); diff --git a/dotnet/samples/02-agents/middleware/PerRequestMiddleware.cs b/dotnet/samples/02-agents/middleware/PerRequestMiddleware.cs new file mode 100644 index 0000000000..4cb997f8a6 --- /dev/null +++ b/dotnet/samples/02-agents/middleware/PerRequestMiddleware.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Per-Request Middleware +// Middleware that is scoped to a single agent run, not the entire agent lifetime. +// Useful for request-specific behavior like adding per-request tools or chat client middleware. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/middleware + +using System.ComponentModel; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +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"; + +[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."; + +[Description("The current datetime offset.")] +static string GetDateTime() => DateTimeOffset.Now.ToString(); + +var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient() + .BuildAIAgent( + instructions: "You are a helpful assistant.", + tools: [AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime))]); + +// +// Per-request function middleware +async ValueTask PerRequestFunctionMiddleware(AIAgent agent, FunctionInvocationContext context, Func> next, CancellationToken cancellationToken) +{ + Console.WriteLine($"[Per-Request] Function: {context.Function.Name}"); + return await next(context, cancellationToken); +} + +// Per-request chat client middleware +async Task PerRequestChatClientMiddleware(IEnumerable messages, ChatOptions? options, IChatClient innerChatClient, CancellationToken cancellationToken) +{ + Console.WriteLine("[Per-Request] Chat Client Middleware"); + return await innerChatClient.GetResponseAsync(messages, options, cancellationToken); +} + +// Add per-request tools and middleware via run options +var options = new ChatClientAgentRunOptions(new() +{ + Tools = [AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather))] +}) +{ + ChatClientFactory = (chatClient) => chatClient + .AsBuilder() + .Use(PerRequestChatClientMiddleware, null) + .Build() +}; + +// Build a per-request middleware pipeline on top of the base agent +var response = await agent + .AsBuilder() + .Use(PerRequestFunctionMiddleware) + .Build() + .RunAsync("What's the current time and the weather in Seattle?", options: options); + +Console.WriteLine(response); +// diff --git a/dotnet/samples/02-agents/providers/AnthropicProvider.cs b/dotnet/samples/02-agents/providers/AnthropicProvider.cs new file mode 100644 index 0000000000..7598d68b62 --- /dev/null +++ b/dotnet/samples/02-agents/providers/AnthropicProvider.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: Anthropic +// Create an agent using Anthropic (Claude) as the backend. +// Supports direct Anthropic API or Azure AI Foundry-hosted Anthropic models. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using Anthropic; +using Anthropic.Foundry; +using Azure.Identity; +using Microsoft.Agents.AI; + +string deploymentName = Environment.GetEnvironmentVariable("ANTHROPIC_DEPLOYMENT_NAME") ?? "claude-haiku-4-5"; + +// The resource is the subdomain in the Azure AI endpoint URI +string? resource = Environment.GetEnvironmentVariable("ANTHROPIC_RESOURCE"); +string? apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY"); + +// +using AnthropicClient client = (resource is null) + ? new AnthropicClient() { ApiKey = apiKey ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is required when no ANTHROPIC_RESOURCE is provided") } + : (apiKey is not null) + ? new AnthropicFoundryClient(new AnthropicFoundryApiKeyCredentials(apiKey, resource)) + : new AnthropicFoundryClient(new AnthropicFoundryIdentityTokenCredentials(new AzureCliCredential(), resource, ["https://ai.azure.com/.default"])); + +AIAgent agent = client.AsAIAgent(model: deploymentName, instructions: "You are good at telling jokes.", name: "JokerAgent"); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/samples/02-agents/providers/AzureAIFoundry.cs b/dotnet/samples/02-agents/providers/AzureAIFoundry.cs new file mode 100644 index 0000000000..ad173dbfec --- /dev/null +++ b/dotnet/samples/02-agents/providers/AzureAIFoundry.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: Azure AI Foundry (Responses API) +// Create an agent using Azure AI Foundry Agents with AIProjectClient. +// This is the default recommended provider for Agent Framework. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +// +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "JokerAgent", + model: deploymentName, + instructions: "You are good at telling jokes."); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); + +// Cleanup +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/02-agents/providers/AzureOpenAI.cs b/dotnet/samples/02-agents/providers/AzureOpenAI.cs new file mode 100644 index 0000000000..eba02eb29f --- /dev/null +++ b/dotnet/samples/02-agents/providers/AzureOpenAI.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: Azure OpenAI (Chat Completion) +// Create an agent using Azure OpenAI Chat Completion as the backend. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +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"; + +// +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsAIAgent(instructions: "You are good at telling jokes.", name: "Joker"); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/samples/02-agents/providers/CopilotStudio.cs b/dotnet/samples/02-agents/providers/CopilotStudio.cs new file mode 100644 index 0000000000..cb1b05d466 --- /dev/null +++ b/dotnet/samples/02-agents/providers/CopilotStudio.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: Copilot Studio +// Create an agent backed by a Microsoft Copilot Studio agent. +// Note: Copilot Studio agents are accessed via the A2A protocol. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using A2A; +using Microsoft.Agents.AI; + +var a2aAgentHost = Environment.GetEnvironmentVariable("A2A_AGENT_HOST") + ?? throw new InvalidOperationException("A2A_AGENT_HOST is not set."); + +// +// Connect to a Copilot Studio agent via its A2A endpoint +A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost)); +AIAgent agent = await agentCardResolver.GetAIAgentAsync(); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/samples/02-agents/providers/CustomProvider.cs b/dotnet/samples/02-agents/providers/CustomProvider.cs new file mode 100644 index 0000000000..c571f97fdc --- /dev/null +++ b/dotnet/samples/02-agents/providers/CustomProvider.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: Custom Implementation +// Build a fully custom agent by extending AIAgent. +// This example creates a parrot agent that echoes input in uppercase. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using System.Runtime.CompilerServices; +using System.Text.Json; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using SampleApp; + +// +AIAgent agent = new UpperCaseParrotAgent(); + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); + +await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate.")) +{ + Console.Write(update); +} +Console.WriteLine(); +// + +namespace SampleApp +{ + // + internal sealed class UpperCaseParrotAgent : AIAgent + { + public override string? Name => "UpperCaseParrotAgent"; + + protected override ValueTask CreateSessionCoreAsync(CancellationToken cancellationToken = default) + => new(new InMemoryAgentSession()); + + protected override JsonElement SerializeSessionCore(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null) + => JsonSerializer.SerializeToElement(new { }); + + protected override ValueTask DeserializeSessionCoreAsync(JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default) + => new(new InMemoryAgentSession()); + + protected override Task RunCoreAsync(IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default) + { + List responseMessages = messages.Select(m => + { + var clone = m.Clone(); + clone.Role = ChatRole.Assistant; + clone.AuthorName = Name; + clone.Contents = m.Contents.Select(c => c switch + { + TextContent tc => new TextContent(tc.Text.ToUpperInvariant()), + _ => c + }).ToList(); + return clone; + }).ToList(); + + return Task.FromResult(new AgentResponse + { + AgentId = Id, + ResponseId = Guid.NewGuid().ToString("N"), + Messages = responseMessages + }); + } + + protected override async IAsyncEnumerable RunCoreStreamingAsync(IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + var response = await RunCoreAsync(messages, session, options, cancellationToken); + foreach (var message in response.Messages) + { + yield return new AgentResponseUpdate + { + AgentId = Id, + AuthorName = message.AuthorName, + Role = ChatRole.Assistant, + Contents = message.Contents, + ResponseId = Guid.NewGuid().ToString("N"), + MessageId = Guid.NewGuid().ToString("N") + }; + } + } + } + // +} diff --git a/dotnet/samples/02-agents/providers/GitHubCopilot.cs b/dotnet/samples/02-agents/providers/GitHubCopilot.cs new file mode 100644 index 0000000000..7aedd616a1 --- /dev/null +++ b/dotnet/samples/02-agents/providers/GitHubCopilot.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: GitHub Copilot +// Create an agent using GitHub Copilot with shell command permissions. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using GitHub.Copilot.SDK; +using Microsoft.Agents.AI; + +// +static Task PromptPermission(PermissionRequest request, PermissionInvocation invocation) +{ + Console.WriteLine($"\n[Permission Request: {request.Kind}]"); + Console.Write("Approve? (y/n): "); + + string? input = Console.ReadLine()?.Trim().ToUpperInvariant(); + string kind = input is "Y" or "YES" ? "approved" : "denied-interactively-by-user"; + + return Task.FromResult(new PermissionRequestResult { Kind = kind }); +} + +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +SessionConfig sessionConfig = new() +{ + OnPermissionRequest = PromptPermission, +}; + +AIAgent agent = copilotClient.AsAIAgent(sessionConfig, ownsClient: true); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/samples/02-agents/providers/OllamaProvider.cs b/dotnet/samples/02-agents/providers/OllamaProvider.cs new file mode 100644 index 0000000000..c573353741 --- /dev/null +++ b/dotnet/samples/02-agents/providers/OllamaProvider.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: Ollama +// Create an agent using Ollama as the backend for local model inference. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OllamaSharp; + +var endpoint = Environment.GetEnvironmentVariable("OLLAMA_ENDPOINT") + ?? throw new InvalidOperationException("OLLAMA_ENDPOINT is not set."); +var modelName = Environment.GetEnvironmentVariable("OLLAMA_MODEL_NAME") + ?? throw new InvalidOperationException("OLLAMA_MODEL_NAME is not set."); + +// +AIAgent agent = new OllamaApiClient(new Uri(endpoint), modelName) + .AsAIAgent(instructions: "You are good at telling jokes.", name: "Joker"); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/samples/02-agents/providers/OpenAIProvider.cs b/dotnet/samples/02-agents/providers/OpenAIProvider.cs new file mode 100644 index 0000000000..8c6a465ec5 --- /dev/null +++ b/dotnet/samples/02-agents/providers/OpenAIProvider.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Provider: OpenAI +// Create an agent using OpenAI Chat Completion as the backend. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/providers + +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI; +using OpenAI.Chat; + +var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") + ?? throw new InvalidOperationException("OPENAI_API_KEY is not set."); +var model = Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o-mini"; + +// +AIAgent agent = new OpenAIClient(apiKey) + .GetChatClient(model) + .AsAIAgent(instructions: "You are good at telling jokes.", name: "Joker"); +// + +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.")); diff --git a/dotnet/samples/02-agents/tools/CodeInterpreter.cs b/dotnet/samples/02-agents/tools/CodeInterpreter.cs new file mode 100644 index 0000000000..7c9d8d0896 --- /dev/null +++ b/dotnet/samples/02-agents/tools/CodeInterpreter.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Code Interpreter Tool +// Use the hosted Code Interpreter tool for math, data analysis, and code execution. +// Shows both MEAI-based and native SDK approaches. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using System.Text; +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI.Responses; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +// +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + model: deploymentName, + name: "CoderAgent", + instructions: "You are a personal math tutor. When asked a math question, write and run code using the python tool to answer the question.", + tools: [new HostedCodeInterpreterTool() { Inputs = [] }]); + +AgentResponse response = await agent.RunAsync("I need to solve the equation sin(x) + x^2 = 42"); +// + +// +CodeInterpreterToolCallContent? toolCallContent = response.Messages + .SelectMany(m => m.Contents).OfType().FirstOrDefault(); +if (toolCallContent?.Inputs is not null) +{ + DataContent? codeInput = toolCallContent.Inputs.OfType().FirstOrDefault(); + if (codeInput?.HasTopLevelMediaType("text") ?? false) + { + Console.WriteLine($"Code Input: {Encoding.UTF8.GetString(codeInput.Data.ToArray())}"); + } +} + +CodeInterpreterToolResultContent? toolResultContent = response.Messages + .SelectMany(m => m.Contents).OfType().FirstOrDefault(); +if (toolResultContent?.Outputs?.OfType().FirstOrDefault() is { } resultOutput) +{ + Console.WriteLine($"Code Tool Result: {resultOutput.Text}"); +} +// + +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/02-agents/tools/FileSearch.cs b/dotnet/samples/02-agents/tools/FileSearch.cs new file mode 100644 index 0000000000..d975dcbf88 --- /dev/null +++ b/dotnet/samples/02-agents/tools/FileSearch.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. + +// File Search Tool +// Use a hosted file search tool to find relevant documents. +// Note: File search is typically available via Azure AI Foundry or OpenAI Assistants. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI.Responses; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +// +// Create an agent with file search capability +// Note: You must first upload files and create a vector store in Azure AI Foundry +var vectorStoreId = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_VECTOR_STORE_ID") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_VECTOR_STORE_ID is not set."); + +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "FileSearchAgent", + creationOptions: new AgentVersionCreationOptions( + new PromptAgentDefinition(model: deploymentName) + { + Instructions = "You are a helpful assistant that answers questions based on uploaded documents.", + Tools = { ResponseTool.CreateFileSearchTool([vectorStoreId]) } + })); + +Console.WriteLine(await agent.RunAsync("What are the key findings in the uploaded document?")); +// + +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/02-agents/tools/FunctionTools.cs b/dotnet/samples/02-agents/tools/FunctionTools.cs new file mode 100644 index 0000000000..d9006eda90 --- /dev/null +++ b/dotnet/samples/02-agents/tools/FunctionTools.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Function Tools +// Create an agent with function tools for automatic invocation. +// Shows both Azure AI Foundry and Azure OpenAI ChatClient approaches. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using System.ComponentModel; +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +// +[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."; +// + +// +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +AITool tool = AIFunctionFactory.Create(GetWeather); +var agent = await aiProjectClient.CreateAIAgentAsync( + name: "WeatherAssistant", + model: deploymentName, + instructions: "You are a helpful assistant that can get weather information.", + tools: [tool]); +// + +// +// When retrieving an existing agent, provide invocable tools so the agent can invoke them automatically. +var existingAgent = await aiProjectClient.GetAIAgentAsync(name: "WeatherAssistant", tools: [tool]); +// + +AgentSession session = await existingAgent.CreateSessionAsync(); +Console.WriteLine(await existingAgent.RunAsync("What is the weather like in Amsterdam?", session)); + +await aiProjectClient.Agents.DeleteAgentAsync(existingAgent.Name); diff --git a/dotnet/samples/02-agents/tools/HostedMcpTools.cs b/dotnet/samples/02-agents/tools/HostedMcpTools.cs new file mode 100644 index 0000000000..77fb1adb27 --- /dev/null +++ b/dotnet/samples/02-agents/tools/HostedMcpTools.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Hosted MCP Tools +// Use hosted MCP (Model Context Protocol) server tools with OpenAI Responses. +// The MCP tools are invoked server-side by the Responses API, not by the Agent Framework. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI.Responses; + +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"; + +// +// MCP tool with automatic approval — the tool is always called without user approval +var mcpTool = new HostedMcpServerTool( + serverName: "microsoft_learn", + serverAddress: "https://learn.microsoft.com/api/mcp") +{ + AllowedTools = ["microsoft_docs_search"], + ApprovalMode = HostedMcpServerToolApprovalMode.NeverRequire +}; + +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetResponsesClient(deploymentName) + .AsAIAgent( + instructions: "You answer questions by searching the Microsoft Learn content only.", + name: "MicrosoftLearnAgent", + tools: [mcpTool]); + +AgentSession session = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("Please summarize the Azure AI Agent documentation related to MCP Tool calling?", session)); +// + +// +// MCP tool with required approval +var mcpToolWithApproval = new HostedMcpServerTool( + serverName: "microsoft_learn", + serverAddress: "https://learn.microsoft.com/api/mcp") +{ + AllowedTools = ["microsoft_docs_search"], + ApprovalMode = HostedMcpServerToolApprovalMode.AlwaysRequire +}; + +AIAgent agentWithApproval = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetResponsesClient(deploymentName) + .AsAIAgent( + instructions: "You answer questions by searching the Microsoft Learn content only.", + name: "MicrosoftLearnAgentWithApproval", + tools: [mcpToolWithApproval]); + +AgentSession approvalSession = await agentWithApproval.CreateSessionAsync(); +AgentResponse response = await agentWithApproval.RunAsync("Summarize the Azure AI Agent documentation?", approvalSession); +List approvalRequests = response.Messages + .SelectMany(m => m.Contents).OfType().ToList(); + +while (approvalRequests.Count > 0) +{ + List userInputResponses = approvalRequests + .ConvertAll(req => + { + Console.WriteLine($"MCP Tool call: {req.ToolCall.ServerName}/{req.ToolCall.ToolName}. Reply Y to approve:"); + return new ChatMessage(ChatRole.User, [req.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]); + }); + + response = await agentWithApproval.RunAsync(userInputResponses, approvalSession); + approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList(); +} + +Console.WriteLine($"\nAgent: {response}"); +// diff --git a/dotnet/samples/02-agents/tools/LocalMcpTools.cs b/dotnet/samples/02-agents/tools/LocalMcpTools.cs new file mode 100644 index 0000000000..d6f25e4794 --- /dev/null +++ b/dotnet/samples/02-agents/tools/LocalMcpTools.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Local MCP Tools +// Use tools from a local MCP (Model Context Protocol) server via stdio transport. +// The agent discovers and invokes MCP tools from an external process. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using ModelContextProtocol.Client; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +// +// Start a local MCP server process (e.g., the GitHub MCP server) +await using var mcpClient = await McpClient.CreateAsync(new StdioClientTransport(new() +{ + Name = "MCPServer", + Command = "npx", + Arguments = ["-y", "--verbose", "@modelcontextprotocol/server-github"], +})); + +// Discover available tools from the MCP server +IList mcpTools = await mcpClient.ListToolsAsync(); + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "AgentWithMCP", + model: deploymentName, + instructions: "You answer questions related to GitHub repositories only.", + tools: [.. mcpTools.Cast()]); + +Console.WriteLine(await agent.RunAsync("Summarize the last four commits to the microsoft/semantic-kernel repository?")); +// + +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/02-agents/tools/ToolApproval.cs b/dotnet/samples/02-agents/tools/ToolApproval.cs new file mode 100644 index 0000000000..00660fd424 --- /dev/null +++ b/dotnet/samples/02-agents/tools/ToolApproval.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Tool Approval (Human-in-the-Loop) +// Require human approval before the agent invokes sensitive function tools. +// Uses ApprovalRequiredAIFunction to gate tool invocation. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using System.ComponentModel; +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +[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."; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +// +ApprovalRequiredAIFunction approvalTool = new(AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather))); + +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "WeatherAssistant", + model: deploymentName, + instructions: "You are a helpful assistant that can get weather information.", + tools: [approvalTool]); +// + +// +AgentSession session = await agent.CreateSessionAsync(); +AgentResponse response = await agent.RunAsync("What is the weather like in Amsterdam?", session); + +List approvalRequests = response.Messages + .SelectMany(m => m.Contents).OfType().ToList(); + +while (approvalRequests.Count > 0) +{ + List userInputMessages = approvalRequests + .ConvertAll(req => + { + Console.WriteLine($"The agent would like to invoke: {req.FunctionCall.Name}. Reply Y to approve:"); + bool approved = Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false; + return new ChatMessage(ChatRole.User, [req.CreateResponse(approved)]); + }); + + response = await agent.RunAsync(userInputMessages, session); + approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList(); +} + +Console.WriteLine($"\nAgent: {response}"); +// + +await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); diff --git a/dotnet/samples/02-agents/tools/WebSearch.cs b/dotnet/samples/02-agents/tools/WebSearch.cs new file mode 100644 index 0000000000..6008bc1bd3 --- /dev/null +++ b/dotnet/samples/02-agents/tools/WebSearch.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Web Search Tool +// Use a hosted web search tool so the agent can search the internet. +// Note: Web search is available via OpenAI Responses API. +// +// For docs: https://learn.microsoft.com/agent-framework/agents/tools + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI.Responses; + +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"; + +// +AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) + .GetResponsesClient(deploymentName) + .AsAIAgent( + instructions: "You are a helpful assistant that can search the web for current information.", + name: "WebSearchAgent", + tools: [new HostedWebSearchTool()]); + +AgentSession session = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("What are the latest developments in AI agents?", session)); +// diff --git a/dotnet/samples/03-workflows/README.md b/dotnet/samples/03-workflows/README.md new file mode 100644 index 0000000000..580addfc57 --- /dev/null +++ b/dotnet/samples/03-workflows/README.md @@ -0,0 +1,17 @@ +# Workflow Samples (.NET) + +Workflow patterns from simple sequential chains to complex orchestrations. + +| Pattern | Sample | What You'll Learn | +|---------|--------|-------------------| +| Sequential | [sequential/](./sequential/) | Linear step-by-step workflows | +| Concurrent | [concurrent/](./concurrent/) | Fan-out/fan-in parallel execution | +| Branching | [branching/](./branching/) | Conditional routing between steps | +| Agents in Workflows | [agents-in-workflows/](./agents-in-workflows/) | Using agents as workflow steps | +| Human-in-the-Loop | [human-in-the-loop/](./human-in-the-loop/) | Pause for human input | +| Checkpoints | [checkpoints/](./checkpoints/) | Save and resume workflow state | +| State Management | [state-management/](./state-management/) | Share state across steps | +| Declarative | [declarative/](./declarative/) | Define workflows in YAML/JSON | +| Visualization | [visualization/](./visualization/) | Visualize workflow execution | + +For docs: https://learn.microsoft.com/agent-framework/workflows/overview diff --git a/dotnet/samples/03-workflows/agents-in-workflows/AgentsInWorkflows.cs b/dotnet/samples/03-workflows/agents-in-workflows/AgentsInWorkflows.cs new file mode 100644 index 0000000000..0e6044979b --- /dev/null +++ b/dotnet/samples/03-workflows/agents-in-workflows/AgentsInWorkflows.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Using AI agents as workflow steps in a translation chain. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; + +namespace WorkflowSamples.AgentsInWorkflows; + +// +/// +/// Demonstrates using AI agents as executors within a workflow. +/// Three translation agents are connected sequentially: +/// French Agent → Spanish Agent → English Agent +/// +public static class Program +{ + private static async Task Main() + { + // Set up the Azure OpenAI client + var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); + var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient(); + + // Create translation agents + AIAgent frenchAgent = GetTranslationAgent("French", chatClient); + AIAgent spanishAgent = GetTranslationAgent("Spanish", chatClient); + AIAgent englishAgent = GetTranslationAgent("English", chatClient); + + // Build the workflow by chaining agents sequentially + var workflow = new WorkflowBuilder(frenchAgent) + .AddEdge(frenchAgent, spanishAgent) + .AddEdge(spanishAgent, englishAgent) + .Build(); + + // Execute the workflow + await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, "Hello World!")); + + // Send the turn token to trigger the agents + await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) + { + if (evt is AgentResponseUpdateEvent executorComplete) + { + Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}"); + } + } + } + + private static ChatClientAgent GetTranslationAgent(string targetLanguage, IChatClient chatClient) => + new(chatClient, $"You are a translation assistant that translates the provided text to {targetLanguage}."); +} +// diff --git a/dotnet/samples/03-workflows/branching/Branching.cs b/dotnet/samples/03-workflows/branching/Branching.cs new file mode 100644 index 0000000000..b2dd6617a5 --- /dev/null +++ b/dotnet/samples/03-workflows/branching/Branching.cs @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Conditional routing between workflow steps using edge conditions. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; + +namespace WorkflowSamples.Branching; + +// +/// +/// Demonstrates conditional routing using edge conditions. +/// An email spam detection system routes emails to different paths: +/// - Legitimate emails → Email Assistant → Send Email +/// - Spam emails → Handle Spam +/// +public static class Program +{ + private static async Task Main() + { + // Set up the Azure OpenAI client + var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); + var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient(); + + // Create agents + AIAgent spamDetectionAgent = GetSpamDetectionAgent(chatClient); + AIAgent emailAssistantAgent = GetEmailAssistantAgent(chatClient); + + // Create executors + var spamDetectionExecutor = new SpamDetectionExecutor(spamDetectionAgent); + var emailAssistantExecutor = new EmailAssistantExecutor(emailAssistantAgent); + var sendEmailExecutor = new SendEmailExecutor(); + var handleSpamExecutor = new HandleSpamExecutor(); + + // Build the workflow with conditional edges + var workflow = new WorkflowBuilder(spamDetectionExecutor) + .AddEdge(spamDetectionExecutor, emailAssistantExecutor, condition: GetCondition(expectedResult: false)) + .AddEdge(emailAssistantExecutor, sendEmailExecutor) + .AddEdge(spamDetectionExecutor, handleSpamExecutor, condition: GetCondition(expectedResult: true)) + .WithOutputFrom(handleSpamExecutor, sendEmailExecutor) + .Build(); + + // Execute the workflow + string email = "Subject: You won $1,000,000! Click here to claim your prize!"; + await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, email)); + await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) + { + if (evt is WorkflowOutputEvent outputEvent) + { + Console.WriteLine($"{outputEvent}"); + } + } + } + + private static Func GetCondition(bool expectedResult) => + detectionResult => detectionResult is DetectionResult result && result.IsSpam == expectedResult; + + private static ChatClientAgent GetSpamDetectionAgent(IChatClient chatClient) => + new(chatClient, new ChatClientAgentOptions() + { + ChatOptions = new() + { + Instructions = "You are a spam detection assistant that identifies spam emails.", + ResponseFormat = ChatResponseFormat.ForJsonSchema() + } + }); + + private static ChatClientAgent GetEmailAssistantAgent(IChatClient chatClient) => + new(chatClient, new ChatClientAgentOptions() + { + ChatOptions = new() + { + Instructions = "You are an email assistant that helps users draft responses to emails with professionalism.", + ResponseFormat = ChatResponseFormat.ForJsonSchema() + } + }); +} +// + +// +public sealed class DetectionResult +{ + [JsonPropertyName("is_spam")] + public bool IsSpam { get; set; } + + [JsonPropertyName("reason")] + public string Reason { get; set; } = string.Empty; + + [JsonIgnore] + public string EmailId { get; set; } = string.Empty; +} + +internal sealed class Email +{ + [JsonPropertyName("email_id")] + public string EmailId { get; set; } = string.Empty; + + [JsonPropertyName("email_content")] + public string EmailContent { get; set; } = string.Empty; +} + +public sealed class EmailResponse +{ + [JsonPropertyName("response")] + public string Response { get; set; } = string.Empty; +} +// + +// +internal static class EmailStateConstants +{ + public const string EmailStateScope = "EmailState"; +} + +internal sealed class SpamDetectionExecutor : Executor +{ + private readonly AIAgent _spamDetectionAgent; + + public SpamDetectionExecutor(AIAgent spamDetectionAgent) : base("SpamDetectionExecutor") + { + this._spamDetectionAgent = spamDetectionAgent; + } + + public override async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + var newEmail = new Email + { + EmailId = Guid.NewGuid().ToString("N"), + EmailContent = message.Text + }; + await context.QueueStateUpdateAsync(newEmail.EmailId, newEmail, scopeName: EmailStateConstants.EmailStateScope, cancellationToken); + + var response = await this._spamDetectionAgent.RunAsync(message, cancellationToken: cancellationToken); + var detectionResult = JsonSerializer.Deserialize(response.Text); + detectionResult!.EmailId = newEmail.EmailId; + + return detectionResult; + } +} + +internal sealed class EmailAssistantExecutor : Executor +{ + private readonly AIAgent _emailAssistantAgent; + + public EmailAssistantExecutor(AIAgent emailAssistantAgent) : base("EmailAssistantExecutor") + { + this._emailAssistantAgent = emailAssistantAgent; + } + + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + var email = await context.ReadStateAsync(message.EmailId, scopeName: EmailStateConstants.EmailStateScope, cancellationToken) + ?? throw new InvalidOperationException("Email not found."); + var response = await this._emailAssistantAgent.RunAsync(email.EmailContent, cancellationToken: cancellationToken); + return JsonSerializer.Deserialize(response.Text)!; + } +} + +internal sealed class SendEmailExecutor() : Executor("SendEmailExecutor") +{ + public override async ValueTask HandleAsync(EmailResponse message, IWorkflowContext context, CancellationToken cancellationToken = default) => + await context.YieldOutputAsync($"Email sent: {message.Response}", cancellationToken); +} + +internal sealed class HandleSpamExecutor() : Executor("HandleSpamExecutor") +{ + public override async ValueTask HandleAsync(DetectionResult message, IWorkflowContext context, CancellationToken cancellationToken = default) => + await context.YieldOutputAsync($"Email marked as spam: {message.Reason}", cancellationToken); +} +// diff --git a/dotnet/samples/03-workflows/checkpoints/Checkpoints.cs b/dotnet/samples/03-workflows/checkpoints/Checkpoints.cs new file mode 100644 index 0000000000..006df86b46 --- /dev/null +++ b/dotnet/samples/03-workflows/checkpoints/Checkpoints.cs @@ -0,0 +1,173 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Save and resume workflow state using checkpoints and rehydration. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Microsoft.Agents.AI.Workflows; + +namespace WorkflowSamples.Checkpoints; + +// +/// +/// Demonstrates checkpoints for saving and restoring workflow state. +/// Key concepts: super steps, automatic checkpointing, and rehydration. +/// Uses a number guessing game to show checkpoint creation and resume. +/// +public static class Program +{ + private static async Task Main() + { + // Create the workflow + var workflow = BuildWorkflow(); + + // Create checkpoint manager + var checkpointManager = CheckpointManager.Default; + var checkpoints = new List(); + + // Execute the workflow and save checkpoints + await using Checkpointed checkpointedRun = await InProcessExecution + .StreamAsync(workflow, NumberSignal.Init, checkpointManager); + + await foreach (WorkflowEvent evt in checkpointedRun.Run.WatchStreamAsync()) + { + if (evt is ExecutorCompletedEvent executorCompletedEvt) + { + Console.WriteLine($"* Executor {executorCompletedEvt.ExecutorId} completed."); + } + + if (evt is SuperStepCompletedEvent superStepCompletedEvt) + { + CheckpointInfo? checkpoint = superStepCompletedEvt.CompletionInfo!.Checkpoint; + if (checkpoint is not null) + { + checkpoints.Add(checkpoint); + Console.WriteLine($"** Checkpoint created at step {checkpoints.Count}."); + } + } + + if (evt is WorkflowOutputEvent outputEvent) + { + Console.WriteLine($"Workflow completed with result: {outputEvent.Data}"); + } + } + + // Rehydrate from a saved checkpoint + var newWorkflow = BuildWorkflow(); + const int CheckpointIndex = 5; + Console.WriteLine($"\n\nHydrating from checkpoint {CheckpointIndex + 1}."); + CheckpointInfo savedCheckpoint = checkpoints[CheckpointIndex]; + + await using Checkpointed newCheckpointedRun = + await InProcessExecution.ResumeStreamAsync(newWorkflow, savedCheckpoint, checkpointManager); + + await foreach (WorkflowEvent evt in newCheckpointedRun.Run.WatchStreamAsync()) + { + if (evt is ExecutorCompletedEvent executorCompletedEvt) + { + Console.WriteLine($"* Executor {executorCompletedEvt.ExecutorId} completed."); + } + + if (evt is WorkflowOutputEvent workflowOutputEvt) + { + Console.WriteLine($"Workflow completed with result: {workflowOutputEvt.Data}"); + } + } + } +// + +// + internal static Workflow BuildWorkflow() + { + GuessNumberExecutor guessNumberExecutor = new(1, 100); + JudgeExecutor judgeExecutor = new(42); + + return new WorkflowBuilder(guessNumberExecutor) + .AddEdge(guessNumberExecutor, judgeExecutor) + .AddEdge(judgeExecutor, guessNumberExecutor) + .WithOutputFrom(judgeExecutor) + .Build(); + } +} + +internal enum NumberSignal +{ + Init, + Above, + Below, +} +// + +// +internal sealed class GuessNumberExecutor() : Executor("Guess") +{ + public int LowerBound { get; private set; } + public int UpperBound { get; private set; } + private const string StateKey = "GuessNumberExecutorState"; + + public GuessNumberExecutor(int lowerBound, int upperBound) : this() + { + this.LowerBound = lowerBound; + this.UpperBound = upperBound; + } + + private int NextGuess => (this.LowerBound + this.UpperBound) / 2; + + public override async ValueTask HandleAsync(NumberSignal message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + switch (message) + { + case NumberSignal.Init: + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); + break; + case NumberSignal.Above: + this.UpperBound = this.NextGuess - 1; + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); + break; + case NumberSignal.Below: + this.LowerBound = this.NextGuess + 1; + await context.SendMessageAsync(this.NextGuess, cancellationToken: cancellationToken); + break; + } + } + + protected override ValueTask OnCheckpointingAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => + context.QueueStateUpdateAsync(StateKey, (this.LowerBound, this.UpperBound), cancellationToken: cancellationToken); + + protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => + (this.LowerBound, this.UpperBound) = await context.ReadStateAsync<(int, int)>(StateKey, cancellationToken: cancellationToken); +} + +internal sealed class JudgeExecutor() : Executor("Judge") +{ + private readonly int _targetNumber; + private int _tries; + private const string StateKey = "JudgeExecutorState"; + + public JudgeExecutor(int targetNumber) : this() + { + this._targetNumber = targetNumber; + } + + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + this._tries++; + if (message == this._targetNumber) + { + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken: cancellationToken); + } + else if (message < this._targetNumber) + { + await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken); + } + else + { + await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken); + } + } + + protected override ValueTask OnCheckpointingAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => + context.QueueStateUpdateAsync(StateKey, this._tries, cancellationToken: cancellationToken); + + protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken cancellationToken = default) => + this._tries = await context.ReadStateAsync(StateKey, cancellationToken: cancellationToken); +} +// diff --git a/dotnet/samples/03-workflows/concurrent/Concurrent.cs b/dotnet/samples/03-workflows/concurrent/Concurrent.cs new file mode 100644 index 0000000000..18d0449c8b --- /dev/null +++ b/dotnet/samples/03-workflows/concurrent/Concurrent.cs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Fan-out/fan-in parallel execution with concurrent AI agents. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; + +namespace WorkflowSamples.Concurrent; + +// +/// +/// Demonstrates concurrent execution using fan-out and fan-in patterns. +/// Two AI agents (Physicist and Chemist) answer the same question in parallel, +/// then an aggregation executor combines their responses. +/// +public static class Program +{ + private static async Task Main() + { + // Set up the Azure OpenAI client + var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); + var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient(); + + // Create the executors + ChatClientAgent physicist = new( + chatClient, + name: "Physicist", + instructions: "You are an expert in physics. You answer questions from a physics perspective." + ); + ChatClientAgent chemist = new( + chatClient, + name: "Chemist", + instructions: "You are an expert in chemistry. You answer questions from a chemistry perspective." + ); + var startExecutor = new ConcurrentStartExecutor(); + var aggregationExecutor = new ConcurrentAggregationExecutor(); + + // Build the workflow with fan-out and fan-in edges + var workflow = new WorkflowBuilder(startExecutor) + .AddFanOutEdge(startExecutor, [physicist, chemist]) + .AddFanInEdge([physicist, chemist], aggregationExecutor) + .WithOutputFrom(aggregationExecutor) + .Build(); + + // Execute the workflow in streaming mode + await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, input: "What is temperature?"); + await foreach (WorkflowEvent evt in run.WatchStreamAsync()) + { + if (evt is WorkflowOutputEvent output) + { + Console.WriteLine($"Workflow completed with results:\n{output.Data}"); + } + } + } +} +// + +// +/// +/// Executor that starts concurrent processing by broadcasting messages to agents. +/// +internal sealed partial class ConcurrentStartExecutor() : + Executor("ConcurrentStartExecutor") +{ + [MessageHandler] + public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + await context.SendMessageAsync(new ChatMessage(ChatRole.User, message), cancellationToken: cancellationToken); + await context.SendMessageAsync(new TurnToken(emitEvents: true), cancellationToken: cancellationToken); + } +} +// + +// +/// +/// Executor that aggregates results from concurrent agents. +/// +internal sealed class ConcurrentAggregationExecutor() : + Executor>("ConcurrentAggregationExecutor") +{ + private readonly List _messages = []; + + public override async ValueTask HandleAsync(List message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + this._messages.AddRange(message); + + if (this._messages.Count == 2) + { + var formattedMessages = string.Join(Environment.NewLine, this._messages.Select(m => $"{m.AuthorName}: {m.Text}")); + await context.YieldOutputAsync(formattedMessages, cancellationToken); + } + } +} +// diff --git a/dotnet/samples/03-workflows/declarative/Declarative.cs b/dotnet/samples/03-workflows/declarative/Declarative.cs new file mode 100644 index 0000000000..129d3c523f --- /dev/null +++ b/dotnet/samples/03-workflows/declarative/Declarative.cs @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Define workflows declaratively using YAML configuration files. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Configuration; +using OpenAI.Responses; +using Shared.Foundry; +using Shared.Workflows; + +namespace WorkflowSamples.Declarative; + +// +/// +/// Demonstrates a declarative workflow defined in YAML. +/// Uses a menu agent with function tools assigned, initialized from +/// a YAML workflow definition file. +/// +internal sealed class Program +{ + public static async Task Main(string[] args) + { + // Initialize configuration + IConfiguration configuration = Application.InitializeConfig(); + Uri foundryEndpoint = new(configuration.GetValue(Application.Settings.FoundryEndpoint)); + + // Create function tools for the menu agent + MenuPlugin menuPlugin = new(); + AIFunction[] functions = + [ + AIFunctionFactory.Create(menuPlugin.GetMenu), + AIFunctionFactory.Create(menuPlugin.GetSpecials), + AIFunctionFactory.Create(menuPlugin.GetItemPrice), + ]; + + await CreateAgentAsync(foundryEndpoint, configuration, functions); + + // Get input from command line or console + string workflowInput = Application.GetInput(args); + + // Create the workflow from a YAML definition file + WorkflowFactory workflowFactory = new("FunctionTools.yaml", foundryEndpoint); + + // Execute the workflow with checkpointing support + WorkflowRunner runner = new(functions) { UseJsonCheckpoints = true }; + await runner.ExecuteAsync(workflowFactory.CreateWorkflow, workflowInput); + } + + private static async Task CreateAgentAsync(Uri foundryEndpoint, IConfiguration configuration, AIFunction[] functions) + { + AIProjectClient aiProjectClient = new(foundryEndpoint, new AzureCliCredential()); + + await aiProjectClient.CreateAgentAsync( + agentName: "MenuAgent", + agentDefinition: DefineMenuAgent(configuration, functions), + agentDescription: "Provides information about the restaurant menu"); + } + + private static PromptAgentDefinition DefineMenuAgent(IConfiguration configuration, AIFunction[] functions) + { + PromptAgentDefinition agentDefinition = + new(configuration.GetValue(Application.Settings.FoundryModelMini)) + { + Instructions = + """ + Answer the users questions on the menu. + For questions or input that do not require searching the documentation, inform the + user that you can only answer questions what's on the menu. + """ + }; + + foreach (AIFunction function in functions) + { + agentDefinition.Tools.Add(function.AsOpenAIResponseTool()); + } + + return agentDefinition; + } +} +// diff --git a/dotnet/samples/03-workflows/human-in-the-loop/HumanInTheLoop.cs b/dotnet/samples/03-workflows/human-in-the-loop/HumanInTheLoop.cs new file mode 100644 index 0000000000..979c3385e7 --- /dev/null +++ b/dotnet/samples/03-workflows/human-in-the-loop/HumanInTheLoop.cs @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Pause workflow for human input using RequestPort and ExternalRequest. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Microsoft.Agents.AI.Workflows; + +namespace WorkflowSamples.HumanInTheLoop; + +// +/// +/// Demonstrates human-in-the-loop interaction using RequestPort and ExternalRequest. +/// Implements a number guessing game where the external user provides guesses +/// and the workflow provides feedback until the correct number is found. +/// +public static class Program +{ + private static async Task Main() + { + // Create the workflow + var workflow = BuildWorkflow(); + + // Execute the workflow + await using StreamingRun handle = await InProcessExecution.StreamAsync(workflow, NumberSignal.Init); + await foreach (WorkflowEvent evt in handle.WatchStreamAsync()) + { + switch (evt) + { + case RequestInfoEvent requestInputEvt: + ExternalResponse response = HandleExternalRequest(requestInputEvt.Request); + await handle.SendResponseAsync(response); + break; + + case WorkflowOutputEvent outputEvt: + Console.WriteLine($"Workflow completed with result: {outputEvt.Data}"); + return; + } + } + } + + private static ExternalResponse HandleExternalRequest(ExternalRequest request) + { + if (request.DataIs()) + { + switch (request.DataAs()) + { + case NumberSignal.Init: + int initialGuess = ReadIntegerFromConsole("Please provide your initial guess: "); + return request.CreateResponse(initialGuess); + case NumberSignal.Above: + int lowerGuess = ReadIntegerFromConsole("You previously guessed too large. Please provide a new guess: "); + return request.CreateResponse(lowerGuess); + case NumberSignal.Below: + int higherGuess = ReadIntegerFromConsole("You previously guessed too small. Please provide a new guess: "); + return request.CreateResponse(higherGuess); + } + } + + throw new NotSupportedException($"Request {request.PortInfo.RequestType} is not supported"); + } + + private static int ReadIntegerFromConsole(string prompt) + { + while (true) + { + Console.Write(prompt); + string? input = Console.ReadLine(); + if (int.TryParse(input, out int value)) + { + return value; + } + Console.WriteLine("Invalid input. Please enter a valid integer."); + } + } +// + +// + internal static Workflow BuildWorkflow() + { + RequestPort numberRequestPort = RequestPort.Create("GuessNumber"); + JudgeExecutor judgeExecutor = new(42); + + return new WorkflowBuilder(numberRequestPort) + .AddEdge(numberRequestPort, judgeExecutor) + .AddEdge(judgeExecutor, numberRequestPort) + .WithOutputFrom(judgeExecutor) + .Build(); + } +} + +internal enum NumberSignal +{ + Init, + Above, + Below, +} + +internal sealed class JudgeExecutor() : Executor("Judge") +{ + private readonly int _targetNumber; + private int _tries; + + public JudgeExecutor(int targetNumber) : this() + { + this._targetNumber = targetNumber; + } + + public override async ValueTask HandleAsync(int message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + this._tries++; + if (message == this._targetNumber) + { + await context.YieldOutputAsync($"{this._targetNumber} found in {this._tries} tries!", cancellationToken); + } + else if (message < this._targetNumber) + { + await context.SendMessageAsync(NumberSignal.Below, cancellationToken: cancellationToken); + } + else + { + await context.SendMessageAsync(NumberSignal.Above, cancellationToken: cancellationToken); + } + } +} +// diff --git a/dotnet/samples/03-workflows/sequential/Sequential.cs b/dotnet/samples/03-workflows/sequential/Sequential.cs new file mode 100644 index 0000000000..d3e91bc27a --- /dev/null +++ b/dotnet/samples/03-workflows/sequential/Sequential.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Linear step-by-step workflow with executors connected sequentially. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Microsoft.Agents.AI.Workflows; + +namespace WorkflowSamples.Sequential; + +// +/// +/// Demonstrates a sequential workflow where executors are connected in a linear chain. +/// Data flows from one executor to the next in order. +/// For input "Hello, World!", the workflow produces "!DLROW ,OLLEH". +/// +public static class Program +{ + private static async Task Main() + { + // Create the executors + Func uppercaseFunc = s => s.ToUpperInvariant(); + var uppercase = uppercaseFunc.BindAsExecutor("UppercaseExecutor"); + + ReverseTextExecutor reverse = new(); + + // Build the workflow by connecting executors sequentially + WorkflowBuilder builder = new(uppercase); + builder.AddEdge(uppercase, reverse).WithOutputFrom(reverse); + var workflow = builder.Build(); + + // Execute the workflow with input data + await using Run run = await InProcessExecution.RunAsync(workflow, "Hello, World!"); + foreach (WorkflowEvent evt in run.NewEvents) + { + if (evt is ExecutorCompletedEvent executorComplete) + { + Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}"); + } + } + } +} +// + +// +/// +/// Executor that reverses the input text. +/// +internal sealed class ReverseTextExecutor() : Executor("ReverseTextExecutor") +{ + public override ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(string.Concat(message.Reverse())); + } +} +// diff --git a/dotnet/samples/03-workflows/state-management/StateManagement.cs b/dotnet/samples/03-workflows/state-management/StateManagement.cs new file mode 100644 index 0000000000..5fa222fcbb --- /dev/null +++ b/dotnet/samples/03-workflows/state-management/StateManagement.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Share state across workflow steps using shared state scopes. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Microsoft.Agents.AI.Workflows; + +namespace WorkflowSamples.StateManagement; + +// +/// +/// Demonstrates shared states within a workflow. +/// Multiple executors read from and write to shared states for data sharing +/// and coordination. Uses fan-out/fan-in for parallel word and paragraph counting. +/// +public static class Program +{ + private static async Task Main() + { + // Create the executors + var fileRead = new FileReadExecutor(); + var wordCount = new WordCountingExecutor(); + var paragraphCount = new ParagraphCountingExecutor(); + var aggregate = new AggregationExecutor(); + + // Build the workflow with fan-out/fan-in for parallel counting + var workflow = new WorkflowBuilder(fileRead) + .AddFanOutEdge(fileRead, [wordCount, paragraphCount]) + .AddFanInEdge([wordCount, paragraphCount], aggregate) + .WithOutputFrom(aggregate) + .Build(); + + // Execute the workflow + await using Run run = await InProcessExecution.RunAsync(workflow, "Lorem_Ipsum.txt"); + foreach (WorkflowEvent evt in run.NewEvents) + { + if (evt is WorkflowOutputEvent outputEvent) + { + Console.WriteLine(outputEvent.Data); + } + } + } +} +// + +// +internal static class FileContentStateConstants +{ + public const string FileContentStateScope = "FileContentState"; +} + +internal sealed class FileReadExecutor() : Executor("FileReadExecutor") +{ + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + string fileContent = Resources.Read(message); + string fileID = Guid.NewGuid().ToString("N"); + await context.QueueStateUpdateAsync(fileID, fileContent, scopeName: FileContentStateConstants.FileContentStateScope, cancellationToken); + return fileID; + } +} + +internal sealed class FileStats +{ + public int ParagraphCount { get; set; } + public int WordCount { get; set; } +} + +internal sealed class WordCountingExecutor() : Executor("WordCountingExecutor") +{ + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + var fileContent = await context.ReadStateAsync(message, scopeName: FileContentStateConstants.FileContentStateScope, cancellationToken) + ?? throw new InvalidOperationException("File content state not found"); + int wordCount = fileContent.Split([' ', '\n', '\r'], StringSplitOptions.RemoveEmptyEntries).Length; + return new FileStats { WordCount = wordCount }; + } +} + +internal sealed class ParagraphCountingExecutor() : Executor("ParagraphCountingExecutor") +{ + public override async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + var fileContent = await context.ReadStateAsync(message, scopeName: FileContentStateConstants.FileContentStateScope, cancellationToken) + ?? throw new InvalidOperationException("File content state not found"); + int paragraphCount = fileContent.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries).Length; + return new FileStats { ParagraphCount = paragraphCount }; + } +} + +internal sealed class AggregationExecutor() : Executor("AggregationExecutor") +{ + private readonly List _messages = []; + + public override async ValueTask HandleAsync(FileStats message, IWorkflowContext context, CancellationToken cancellationToken = default) + { + this._messages.Add(message); + + if (this._messages.Count == 2) + { + var totalParagraphCount = this._messages.Sum(m => m.ParagraphCount); + var totalWordCount = this._messages.Sum(m => m.WordCount); + await context.YieldOutputAsync($"Total Paragraphs: {totalParagraphCount}, Total Words: {totalWordCount}", cancellationToken); + } + } +} +// diff --git a/dotnet/samples/03-workflows/visualization/Visualization.cs b/dotnet/samples/03-workflows/visualization/Visualization.cs new file mode 100644 index 0000000000..4180f49219 --- /dev/null +++ b/dotnet/samples/03-workflows/visualization/Visualization.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft. All rights reserved. +// Description: Visualize workflow execution graphs in Mermaid and DOT formats. +// Docs: https://learn.microsoft.com/agent-framework/workflows/overview + +using Microsoft.Agents.AI.Workflows; + +namespace WorkflowSamples.Visualization; + +// +/// +/// Demonstrates workflow visualization using Mermaid and DOT (Graphviz) formats. +/// Generates visual representations of workflow graphs for documentation and debugging. +/// +internal static class Program +{ + private static void Main(string[] args) + { + // Build a sample workflow to visualize + var fileRead = new Func(s => s).BindAsExecutor("FileRead"); + var wordCount = new Func(s => s).BindAsExecutor("WordCount"); + var paragraphCount = new Func(s => s).BindAsExecutor("ParagraphCount"); + var aggregate = new Func(s => s).BindAsExecutor("Aggregate"); + + Workflow workflow = new WorkflowBuilder(fileRead) + .AddFanOutEdge(fileRead, [wordCount, paragraphCount]) + .AddFanInEdge([wordCount, paragraphCount], aggregate) + .WithOutputFrom(aggregate) + .Build(); + + // Generate Mermaid visualization + Console.WriteLine("Mermaid string: \n======="); + var mermaid = workflow.ToMermaidString(); + Console.WriteLine(mermaid); + Console.WriteLine("======="); + + // Generate DOT (Graphviz) visualization + Console.WriteLine("DiGraph string: \n======="); + var dotString = workflow.ToDotString(); + Console.WriteLine(dotString); + Console.WriteLine("======="); + } +} +// diff --git a/dotnet/samples/04-hosting/README.md b/dotnet/samples/04-hosting/README.md new file mode 100644 index 0000000000..513581cb05 --- /dev/null +++ b/dotnet/samples/04-hosting/README.md @@ -0,0 +1,13 @@ +# Hosting & Protocol Samples (.NET) + +Deploy your agents using different hosting patterns and protocols. +These are multi-project solutions with their own `.csproj` files. + +| Pattern | Sample | Description | +|---------|--------|-------------| +| A2A Protocol | [a2a/](./a2a/) | Agent-to-Agent protocol (client + server) | +| AG-UI Protocol | [ag-ui/](./ag-ui/) | Agentic UI protocol (client + server) | +| Azure Functions | [azure-functions/](./azure-functions/) | Serverless hosting with Durable Functions | +| OpenAI Endpoints | [openai-endpoints/](./openai-endpoints/) | OpenAI-compatible hosted endpoints | + +For docs: https://learn.microsoft.com/agent-framework/integrations/overview diff --git a/dotnet/samples/A2AClientServer/A2AClient/A2AClient.csproj b/dotnet/samples/04-hosting/a2a/A2AClient/A2AClient.csproj similarity index 100% rename from dotnet/samples/A2AClientServer/A2AClient/A2AClient.csproj rename to dotnet/samples/04-hosting/a2a/A2AClient/A2AClient.csproj diff --git a/dotnet/samples/A2AClientServer/A2AClient/HostClientAgent.cs b/dotnet/samples/04-hosting/a2a/A2AClient/HostClientAgent.cs similarity index 100% rename from dotnet/samples/A2AClientServer/A2AClient/HostClientAgent.cs rename to dotnet/samples/04-hosting/a2a/A2AClient/HostClientAgent.cs diff --git a/dotnet/samples/A2AClientServer/A2AClient/Program.cs b/dotnet/samples/04-hosting/a2a/A2AClient/Program.cs similarity index 100% rename from dotnet/samples/A2AClientServer/A2AClient/Program.cs rename to dotnet/samples/04-hosting/a2a/A2AClient/Program.cs diff --git a/dotnet/samples/A2AClientServer/A2AClient/README.md b/dotnet/samples/04-hosting/a2a/A2AClient/README.md similarity index 100% rename from dotnet/samples/A2AClientServer/A2AClient/README.md rename to dotnet/samples/04-hosting/a2a/A2AClient/README.md diff --git a/dotnet/samples/A2AClientServer/A2AServer/A2AServer.csproj b/dotnet/samples/04-hosting/a2a/A2AServer/A2AServer.csproj similarity index 100% rename from dotnet/samples/A2AClientServer/A2AServer/A2AServer.csproj rename to dotnet/samples/04-hosting/a2a/A2AServer/A2AServer.csproj diff --git a/dotnet/samples/A2AClientServer/A2AServer/A2AServer.http b/dotnet/samples/04-hosting/a2a/A2AServer/A2AServer.http similarity index 100% rename from dotnet/samples/A2AClientServer/A2AServer/A2AServer.http rename to dotnet/samples/04-hosting/a2a/A2AServer/A2AServer.http diff --git a/dotnet/samples/A2AClientServer/A2AServer/HostAgentFactory.cs b/dotnet/samples/04-hosting/a2a/A2AServer/HostAgentFactory.cs similarity index 100% rename from dotnet/samples/A2AClientServer/A2AServer/HostAgentFactory.cs rename to dotnet/samples/04-hosting/a2a/A2AServer/HostAgentFactory.cs diff --git a/dotnet/samples/A2AClientServer/A2AServer/Models/InvoiceQuery.cs b/dotnet/samples/04-hosting/a2a/A2AServer/Models/InvoiceQuery.cs similarity index 100% rename from dotnet/samples/A2AClientServer/A2AServer/Models/InvoiceQuery.cs rename to dotnet/samples/04-hosting/a2a/A2AServer/Models/InvoiceQuery.cs diff --git a/dotnet/samples/A2AClientServer/A2AServer/Program.cs b/dotnet/samples/04-hosting/a2a/A2AServer/Program.cs similarity index 100% rename from dotnet/samples/A2AClientServer/A2AServer/Program.cs rename to dotnet/samples/04-hosting/a2a/A2AServer/Program.cs diff --git a/dotnet/samples/A2AClientServer/README.md b/dotnet/samples/04-hosting/a2a/README.md similarity index 100% rename from dotnet/samples/A2AClientServer/README.md rename to dotnet/samples/04-hosting/a2a/README.md diff --git a/dotnet/samples/AGUIClientServer/AGUIClient/AGUIClient.csproj b/dotnet/samples/04-hosting/ag-ui/AGUIClient/AGUIClient.csproj similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIClient/AGUIClient.csproj rename to dotnet/samples/04-hosting/ag-ui/AGUIClient/AGUIClient.csproj diff --git a/dotnet/samples/AGUIClientServer/AGUIClient/AGUIClientSerializerContext.cs b/dotnet/samples/04-hosting/ag-ui/AGUIClient/AGUIClientSerializerContext.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIClient/AGUIClientSerializerContext.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIClient/AGUIClientSerializerContext.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIClient/Program.cs b/dotnet/samples/04-hosting/ag-ui/AGUIClient/Program.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIClient/Program.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIClient/Program.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIClient/README.md b/dotnet/samples/04-hosting/ag-ui/AGUIClient/README.md similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIClient/README.md rename to dotnet/samples/04-hosting/ag-ui/AGUIClient/README.md diff --git a/dotnet/samples/AGUIClientServer/AGUIClient/SensorRequest.cs b/dotnet/samples/04-hosting/ag-ui/AGUIClient/SensorRequest.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIClient/SensorRequest.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIClient/SensorRequest.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIClient/SensorResponse.cs b/dotnet/samples/04-hosting/ag-ui/AGUIClient/SensorResponse.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIClient/SensorResponse.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIClient/SensorResponse.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/AGUIServer.csproj b/dotnet/samples/04-hosting/ag-ui/AGUIServer/AGUIServer.csproj similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/AGUIServer.csproj rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/AGUIServer.csproj diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/AGUIServer.http b/dotnet/samples/04-hosting/ag-ui/AGUIServer/AGUIServer.http similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/AGUIServer.http rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/AGUIServer.http diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/AGUIServerSerializerContext.cs b/dotnet/samples/04-hosting/ag-ui/AGUIServer/AGUIServerSerializerContext.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/AGUIServerSerializerContext.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/AGUIServerSerializerContext.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/Program.cs b/dotnet/samples/04-hosting/ag-ui/AGUIServer/Program.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/Program.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/Program.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/Properties/launchSettings.json b/dotnet/samples/04-hosting/ag-ui/AGUIServer/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/Properties/launchSettings.json rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/Properties/launchSettings.json diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/ServerWeatherForecastRequest.cs b/dotnet/samples/04-hosting/ag-ui/AGUIServer/ServerWeatherForecastRequest.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/ServerWeatherForecastRequest.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/ServerWeatherForecastRequest.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIServer/ServerWeatherForecastResponse.cs b/dotnet/samples/04-hosting/ag-ui/AGUIServer/ServerWeatherForecastResponse.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIServer/ServerWeatherForecastResponse.cs rename to dotnet/samples/04-hosting/ag-ui/AGUIServer/ServerWeatherForecastResponse.cs diff --git a/dotnet/samples/AGUIClientServer/README.md b/dotnet/samples/04-hosting/ag-ui/README.md similarity index 100% rename from dotnet/samples/AGUIClientServer/README.md rename to dotnet/samples/04-hosting/ag-ui/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/01_SingleAgent.csproj b/dotnet/samples/04-hosting/azure-functions/01_SingleAgent/01_SingleAgent.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/01_SingleAgent.csproj rename to dotnet/samples/04-hosting/azure-functions/01_SingleAgent/01_SingleAgent.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/Program.cs b/dotnet/samples/04-hosting/azure-functions/01_SingleAgent/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/Program.cs rename to dotnet/samples/04-hosting/azure-functions/01_SingleAgent/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/README.md b/dotnet/samples/04-hosting/azure-functions/01_SingleAgent/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/README.md rename to dotnet/samples/04-hosting/azure-functions/01_SingleAgent/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/demo.http b/dotnet/samples/04-hosting/azure-functions/01_SingleAgent/demo.http similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/demo.http rename to dotnet/samples/04-hosting/azure-functions/01_SingleAgent/demo.http diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/host.json b/dotnet/samples/04-hosting/azure-functions/01_SingleAgent/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/host.json rename to dotnet/samples/04-hosting/azure-functions/01_SingleAgent/host.json diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj b/dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj rename to dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/FunctionTriggers.cs b/dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/FunctionTriggers.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/FunctionTriggers.cs rename to dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/FunctionTriggers.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/Program.cs b/dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/Program.cs rename to dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/README.md b/dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/README.md rename to dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/demo.http b/dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/demo.http similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/demo.http rename to dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/demo.http diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/host.json b/dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/host.json rename to dotnet/samples/04-hosting/azure-functions/02_AgentOrchestration_Chaining/host.json diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj b/dotnet/samples/04-hosting/azure-functions/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj rename to dotnet/samples/04-hosting/azure-functions/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/01_SingleAgent/Program.cs b/dotnet/samples/04-hosting/azure-functions/ConsoleApps/01_SingleAgent/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/01_SingleAgent/Program.cs rename to dotnet/samples/04-hosting/azure-functions/ConsoleApps/01_SingleAgent/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/01_SingleAgent/README.md b/dotnet/samples/04-hosting/azure-functions/ConsoleApps/01_SingleAgent/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/01_SingleAgent/README.md rename to dotnet/samples/04-hosting/azure-functions/ConsoleApps/01_SingleAgent/README.md diff --git a/dotnet/samples/Durable/Directory.Build.props b/dotnet/samples/04-hosting/azure-functions/Directory.Build.props similarity index 100% rename from dotnet/samples/Durable/Directory.Build.props rename to dotnet/samples/04-hosting/azure-functions/Directory.Build.props diff --git a/dotnet/samples/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj b/dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/AgentWithHostedMCP.csproj similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/AgentWithHostedMCP.csproj diff --git a/dotnet/samples/HostedAgents/AgentWithHostedMCP/Dockerfile b/dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/Dockerfile similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithHostedMCP/Dockerfile rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/Dockerfile diff --git a/dotnet/samples/HostedAgents/AgentWithHostedMCP/Program.cs b/dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/Program.cs similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithHostedMCP/Program.cs rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/Program.cs diff --git a/dotnet/samples/HostedAgents/AgentWithHostedMCP/README.md b/dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/README.md similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithHostedMCP/README.md rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/README.md diff --git a/dotnet/samples/HostedAgents/AgentWithHostedMCP/agent.yaml b/dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/agent.yaml similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithHostedMCP/agent.yaml rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/agent.yaml diff --git a/dotnet/samples/HostedAgents/AgentWithHostedMCP/run-requests.http b/dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/run-requests.http similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithHostedMCP/run-requests.http rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithHostedMCP/run-requests.http diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj b/dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Dockerfile b/dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/Dockerfile similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithTextSearchRag/Dockerfile rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/Dockerfile diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Program.cs b/dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/Program.cs similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithTextSearchRag/Program.cs rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/Program.cs diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/README.md b/dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/README.md similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithTextSearchRag/README.md rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/README.md diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/agent.yaml b/dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/agent.yaml similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithTextSearchRag/agent.yaml rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/agent.yaml diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/run-requests.http b/dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/run-requests.http similarity index 100% rename from dotnet/samples/HostedAgents/AgentWithTextSearchRag/run-requests.http rename to dotnet/samples/04-hosting/openai-endpoints/AgentWithTextSearchRag/run-requests.http diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj b/dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/AgentsInWorkflows.csproj similarity index 100% rename from dotnet/samples/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj rename to dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/AgentsInWorkflows.csproj diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/Dockerfile b/dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/Dockerfile similarity index 100% rename from dotnet/samples/HostedAgents/AgentsInWorkflows/Dockerfile rename to dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/Dockerfile diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/Program.cs b/dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/Program.cs similarity index 100% rename from dotnet/samples/HostedAgents/AgentsInWorkflows/Program.cs rename to dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/Program.cs diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/README.md b/dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/README.md similarity index 100% rename from dotnet/samples/HostedAgents/AgentsInWorkflows/README.md rename to dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/README.md diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/agent.yaml b/dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/agent.yaml similarity index 100% rename from dotnet/samples/HostedAgents/AgentsInWorkflows/agent.yaml rename to dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/agent.yaml diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/run-requests.http b/dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/run-requests.http similarity index 100% rename from dotnet/samples/HostedAgents/AgentsInWorkflows/run-requests.http rename to dotnet/samples/04-hosting/openai-endpoints/AgentsInWorkflows/run-requests.http diff --git a/dotnet/samples/05-end-to-end/README.md b/dotnet/samples/05-end-to-end/README.md new file mode 100644 index 0000000000..91a94384a9 --- /dev/null +++ b/dotnet/samples/05-end-to-end/README.md @@ -0,0 +1,10 @@ +# End-to-End Samples (.NET) + +Full applications demonstrating complete agent solutions. + +| Sample | Description | +|--------|-------------| +| [agent-web-chat/](./agent-web-chat/) | Web chat interface for agents | +| [agui-web-chat/](./agui-web-chat/) | AG-UI web chat interface | +| [m365-agent/](./m365-agent/) | Microsoft 365 agent integration | +| [purview/](./purview/) | Microsoft Purview integration | diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Custom/CustomAITools.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Custom/CustomAITools.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Custom/CustomAITools.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Custom/CustomAITools.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Program.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Program.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Properties/launchSettings.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Properties/launchSettings.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Properties/launchSettings.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/appsettings.Development.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/appsettings.Development.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/appsettings.Development.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/appsettings.Development.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/appsettings.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/appsettings.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/appsettings.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AgentHost/appsettings.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AppHost/ModelExtensions.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/ModelExtensions.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AppHost/ModelExtensions.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/ModelExtensions.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AppHost/Program.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/Program.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AppHost/Program.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/Program.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AppHost/Properties/launchSettings.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AppHost/Properties/launchSettings.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/Properties/launchSettings.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AppHost/appsettings.Development.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/appsettings.Development.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AppHost/appsettings.Development.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/appsettings.Development.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.AppHost/appsettings.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/appsettings.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.AppHost/appsettings.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.AppHost/appsettings.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/A2AAgentClient.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/A2AAgentClient.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/AgentDiscoveryClient.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/AgentDiscoveryClient.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/AgentDiscoveryClient.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/AgentDiscoveryClient.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/AgentWebChat.Web.csproj similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/AgentWebChat.Web.csproj diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/App.razor b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/App.razor similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/App.razor rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/App.razor diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Layout/MainLayout.razor similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Layout/MainLayout.razor diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Pages/Error.razor b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Pages/Error.razor similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Pages/Error.razor rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Pages/Error.razor diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Pages/Home.razor b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Pages/Home.razor similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Pages/Home.razor rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Pages/Home.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Routes.razor b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Routes.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Routes.razor rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/Routes.razor diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/_Imports.razor b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/_Imports.razor similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/_Imports.razor rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Components/_Imports.razor diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/IAgentClient.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/IAgentClient.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/IAgentClient.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/IAgentClient.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Program.cs b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Program.cs similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Program.cs rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Program.cs diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Properties/launchSettings.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Properties/launchSettings.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/Properties/launchSettings.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/appsettings.Development.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/appsettings.Development.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/appsettings.Development.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/appsettings.Development.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/appsettings.json b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/appsettings.json similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/appsettings.json rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/appsettings.json diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/wwwroot/app.css b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/wwwroot/app.css similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/wwwroot/app.css rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/wwwroot/app.css diff --git a/dotnet/samples/AGUIWebChat/Client/wwwroot/favicon.png b/dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/wwwroot/favicon.png similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/wwwroot/favicon.png rename to dotnet/samples/05-end-to-end/agent-web-chat/AgentWebChat.Web/wwwroot/favicon.png diff --git a/dotnet/samples/AGUIWebChat/Client/AGUIWebChatClient.csproj b/dotnet/samples/05-end-to-end/agui-web-chat/Client/AGUIWebChatClient.csproj similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/AGUIWebChatClient.csproj rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/AGUIWebChatClient.csproj diff --git a/dotnet/samples/AGUIWebChat/Client/Components/App.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/App.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/App.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/App.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/LoadingSpinner.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/LoadingSpinner.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/LoadingSpinner.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/LoadingSpinner.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Layout/MainLayout.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/MainLayout.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Layout/MainLayout.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/MainLayout.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Layout/MainLayout.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/MainLayout.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Layout/MainLayout.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Layout/MainLayout.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/Chat.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/Chat.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/Chat.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/Chat.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatCitation.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatCitation.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatCitation.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatCitation.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatHeader.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatHeader.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatHeader.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatHeader.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatInput.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatInput.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatInput.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatInput.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.js b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatInput.razor.js similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.js rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatInput.razor.js diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageItem.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageItem.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageItem.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageItem.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageList.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageList.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageList.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageList.razor.css diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.js b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageList.razor.js similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.js rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatMessageList.razor.js diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatSuggestions.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatSuggestions.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatSuggestions.razor.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Pages/Chat/ChatSuggestions.razor.css diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Routes.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Routes.razor similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/Components/Routes.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/Routes.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Components/_Imports.razor b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/_Imports.razor similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Components/_Imports.razor rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Components/_Imports.razor diff --git a/dotnet/samples/AGUIWebChat/Client/Program.cs b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Program.cs similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Program.cs rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Program.cs diff --git a/dotnet/samples/AGUIWebChat/Client/Properties/launchSettings.json b/dotnet/samples/05-end-to-end/agui-web-chat/Client/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/Properties/launchSettings.json rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/Properties/launchSettings.json diff --git a/dotnet/samples/AGUIWebChat/Client/wwwroot/app.css b/dotnet/samples/05-end-to-end/agui-web-chat/Client/wwwroot/app.css similarity index 100% rename from dotnet/samples/AGUIWebChat/Client/wwwroot/app.css rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/wwwroot/app.css diff --git a/dotnet/samples/AgentWebChat/AgentWebChat.Web/wwwroot/favicon.png b/dotnet/samples/05-end-to-end/agui-web-chat/Client/wwwroot/favicon.png similarity index 100% rename from dotnet/samples/AgentWebChat/AgentWebChat.Web/wwwroot/favicon.png rename to dotnet/samples/05-end-to-end/agui-web-chat/Client/wwwroot/favicon.png diff --git a/dotnet/samples/AGUIWebChat/README.md b/dotnet/samples/05-end-to-end/agui-web-chat/README.md similarity index 100% rename from dotnet/samples/AGUIWebChat/README.md rename to dotnet/samples/05-end-to-end/agui-web-chat/README.md diff --git a/dotnet/samples/AGUIWebChat/Server/AGUIWebChatServer.csproj b/dotnet/samples/05-end-to-end/agui-web-chat/Server/AGUIWebChatServer.csproj similarity index 100% rename from dotnet/samples/AGUIWebChat/Server/AGUIWebChatServer.csproj rename to dotnet/samples/05-end-to-end/agui-web-chat/Server/AGUIWebChatServer.csproj diff --git a/dotnet/samples/AGUIWebChat/Server/Program.cs b/dotnet/samples/05-end-to-end/agui-web-chat/Server/Program.cs similarity index 100% rename from dotnet/samples/AGUIWebChat/Server/Program.cs rename to dotnet/samples/05-end-to-end/agui-web-chat/Server/Program.cs diff --git a/dotnet/samples/AGUIWebChat/Server/Properties/launchSettings.json b/dotnet/samples/05-end-to-end/agui-web-chat/Server/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AGUIWebChat/Server/Properties/launchSettings.json rename to dotnet/samples/05-end-to-end/agui-web-chat/Server/Properties/launchSettings.json diff --git a/dotnet/samples/M365Agent/AFAgentApplication.cs b/dotnet/samples/05-end-to-end/m365-agent/AFAgentApplication.cs similarity index 100% rename from dotnet/samples/M365Agent/AFAgentApplication.cs rename to dotnet/samples/05-end-to-end/m365-agent/AFAgentApplication.cs diff --git a/dotnet/samples/M365Agent/Agents/AdaptiveCardAIContent.cs b/dotnet/samples/05-end-to-end/m365-agent/Agents/AdaptiveCardAIContent.cs similarity index 100% rename from dotnet/samples/M365Agent/Agents/AdaptiveCardAIContent.cs rename to dotnet/samples/05-end-to-end/m365-agent/Agents/AdaptiveCardAIContent.cs diff --git a/dotnet/samples/M365Agent/Agents/WeatherForecastAgent.cs b/dotnet/samples/05-end-to-end/m365-agent/Agents/WeatherForecastAgent.cs similarity index 100% rename from dotnet/samples/M365Agent/Agents/WeatherForecastAgent.cs rename to dotnet/samples/05-end-to-end/m365-agent/Agents/WeatherForecastAgent.cs diff --git a/dotnet/samples/M365Agent/Agents/WeatherForecastAgentResponse.cs b/dotnet/samples/05-end-to-end/m365-agent/Agents/WeatherForecastAgentResponse.cs similarity index 100% rename from dotnet/samples/M365Agent/Agents/WeatherForecastAgentResponse.cs rename to dotnet/samples/05-end-to-end/m365-agent/Agents/WeatherForecastAgentResponse.cs diff --git a/dotnet/samples/M365Agent/Agents/WeatherForecastAgentResponseContentType.cs b/dotnet/samples/05-end-to-end/m365-agent/Agents/WeatherForecastAgentResponseContentType.cs similarity index 100% rename from dotnet/samples/M365Agent/Agents/WeatherForecastAgentResponseContentType.cs rename to dotnet/samples/05-end-to-end/m365-agent/Agents/WeatherForecastAgentResponseContentType.cs diff --git a/dotnet/samples/M365Agent/Auth/AspNetExtensions.cs b/dotnet/samples/05-end-to-end/m365-agent/Auth/AspNetExtensions.cs similarity index 100% rename from dotnet/samples/M365Agent/Auth/AspNetExtensions.cs rename to dotnet/samples/05-end-to-end/m365-agent/Auth/AspNetExtensions.cs diff --git a/dotnet/samples/M365Agent/Auth/TokenValidationOptions.cs b/dotnet/samples/05-end-to-end/m365-agent/Auth/TokenValidationOptions.cs similarity index 100% rename from dotnet/samples/M365Agent/Auth/TokenValidationOptions.cs rename to dotnet/samples/05-end-to-end/m365-agent/Auth/TokenValidationOptions.cs diff --git a/dotnet/samples/M365Agent/JsonUtilities.cs b/dotnet/samples/05-end-to-end/m365-agent/JsonUtilities.cs similarity index 100% rename from dotnet/samples/M365Agent/JsonUtilities.cs rename to dotnet/samples/05-end-to-end/m365-agent/JsonUtilities.cs diff --git a/dotnet/samples/M365Agent/M365Agent.csproj b/dotnet/samples/05-end-to-end/m365-agent/M365Agent.csproj similarity index 100% rename from dotnet/samples/M365Agent/M365Agent.csproj rename to dotnet/samples/05-end-to-end/m365-agent/M365Agent.csproj diff --git a/dotnet/samples/M365Agent/Program.cs b/dotnet/samples/05-end-to-end/m365-agent/Program.cs similarity index 100% rename from dotnet/samples/M365Agent/Program.cs rename to dotnet/samples/05-end-to-end/m365-agent/Program.cs diff --git a/dotnet/samples/M365Agent/Properties/launchSettings.json b/dotnet/samples/05-end-to-end/m365-agent/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/M365Agent/Properties/launchSettings.json rename to dotnet/samples/05-end-to-end/m365-agent/Properties/launchSettings.json diff --git a/dotnet/samples/M365Agent/README.md b/dotnet/samples/05-end-to-end/m365-agent/README.md similarity index 100% rename from dotnet/samples/M365Agent/README.md rename to dotnet/samples/05-end-to-end/m365-agent/README.md diff --git a/dotnet/samples/M365Agent/appManifest/color.png b/dotnet/samples/05-end-to-end/m365-agent/appManifest/color.png similarity index 100% rename from dotnet/samples/M365Agent/appManifest/color.png rename to dotnet/samples/05-end-to-end/m365-agent/appManifest/color.png diff --git a/dotnet/samples/M365Agent/appManifest/manifest.json b/dotnet/samples/05-end-to-end/m365-agent/appManifest/manifest.json similarity index 100% rename from dotnet/samples/M365Agent/appManifest/manifest.json rename to dotnet/samples/05-end-to-end/m365-agent/appManifest/manifest.json diff --git a/dotnet/samples/M365Agent/appManifest/outline.png b/dotnet/samples/05-end-to-end/m365-agent/appManifest/outline.png similarity index 100% rename from dotnet/samples/M365Agent/appManifest/outline.png rename to dotnet/samples/05-end-to-end/m365-agent/appManifest/outline.png diff --git a/dotnet/samples/M365Agent/appsettings.json.template b/dotnet/samples/05-end-to-end/m365-agent/appsettings.json.template similarity index 100% rename from dotnet/samples/M365Agent/appsettings.json.template rename to dotnet/samples/05-end-to-end/m365-agent/appsettings.json.template diff --git a/dotnet/samples/Purview/AgentWithPurview/AgentWithPurview.csproj b/dotnet/samples/05-end-to-end/purview/AgentWithPurview/AgentWithPurview.csproj similarity index 100% rename from dotnet/samples/Purview/AgentWithPurview/AgentWithPurview.csproj rename to dotnet/samples/05-end-to-end/purview/AgentWithPurview/AgentWithPurview.csproj diff --git a/dotnet/samples/Purview/AgentWithPurview/Program.cs b/dotnet/samples/05-end-to-end/purview/AgentWithPurview/Program.cs similarity index 100% rename from dotnet/samples/Purview/AgentWithPurview/Program.cs rename to dotnet/samples/05-end-to-end/purview/AgentWithPurview/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/01_SingleAgent/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/local.settings.json deleted file mode 100644 index 54dfbb5664..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/local.settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "" - } -} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/local.settings.json b/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/local.settings.json deleted file mode 100644 index 5dfdb17999..0000000000 --- a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/local.settings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None", - "AZURE_OPENAI_ENDPOINT": "", - "AZURE_OPENAI_DEPLOYMENT": "", - "REDIS_CONNECTION_STRING": "localhost:6379", - "REDIS_STREAM_TTL_MINUTES": "10" - } -} diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AClient/A2AClient.csproj b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/A2AClient.csproj new file mode 100644 index 0000000000..6b88c5c697 --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/A2AClient.csproj @@ -0,0 +1,23 @@ + + + + Exe + net10.0 + enable + enable + 5ee045b0-aea3-4f08-8d31-32d1a6f8fed0 + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AClient/HostClientAgent.cs b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/HostClientAgent.cs new file mode 100644 index 0000000000..4daf2c542b --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/HostClientAgent.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft. All rights reserved. +using System.ClientModel; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Logging; +using OpenAI; +using OpenAI.Chat; + +namespace A2A; + +internal sealed class HostClientAgent +{ + internal HostClientAgent(ILoggerFactory loggerFactory) + { + this._logger = loggerFactory.CreateLogger("HostClientAgent"); + } + + internal async Task InitializeAgentAsync(string modelId, string apiKey, string[] agentUrls) + { + try + { + this._logger.LogInformation("Initializing Agent Framework agent with model: {ModelId}", modelId); + + // Connect to the remote agents via A2A + var createAgentTasks = agentUrls.Select(CreateAgentAsync); + var agents = await Task.WhenAll(createAgentTasks); + var tools = agents.Select(agent => (AITool)agent.AsAIFunction()).ToList(); + + // Create the agent that uses the remote agents as tools + this.Agent = new OpenAIClient(new ApiKeyCredential(apiKey)) + .GetChatClient(modelId) + .AsAIAgent(instructions: "You specialize in handling queries for users and using your tools to provide answers.", name: "HostClient", tools: tools); + } + catch (Exception ex) + { + this._logger.LogError(ex, "Failed to initialize HostClientAgent"); + throw; + } + } + + /// + /// The associated + /// + public AIAgent? Agent { get; private set; } + + #region private + private readonly ILogger _logger; + + private static async Task CreateAgentAsync(string agentUri) + { + var url = new Uri(agentUri); + var httpClient = new HttpClient + { + Timeout = TimeSpan.FromSeconds(60) + }; + + var agentCardResolver = new A2ACardResolver(url, httpClient); + + return await agentCardResolver.GetAIAgentAsync(); + } + #endregion +} diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AClient/Program.cs b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/Program.cs new file mode 100644 index 0000000000..0b9696e3a1 --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/Program.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.CommandLine; +using System.Reflection; +using Microsoft.Agents.AI; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace A2A; + +public static class Program +{ + public static async Task Main(string[] args) + { + // Create root command with options + var rootCommand = new RootCommand("A2AClient"); + rootCommand.SetAction((_, ct) => HandleCommandsAsync(ct)); + + // Run the command + return await rootCommand.Parse(args).InvokeAsync(); + } + + private static async Task HandleCommandsAsync(CancellationToken cancellationToken) + { + // Set up the logging + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddConsole(); + builder.SetMinimumLevel(LogLevel.Information); + }); + var logger = loggerFactory.CreateLogger("A2AClient"); + + // Retrieve configuration settings + IConfigurationRoot configRoot = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddUserSecrets(Assembly.GetExecutingAssembly()) + .Build(); + var apiKey = configRoot["A2AClient:ApiKey"] ?? throw new ArgumentException("A2AClient:ApiKey must be provided"); + var modelId = configRoot["A2AClient:ModelId"] ?? "gpt-4.1"; + var agentUrls = configRoot["A2AClient:AgentUrls"] ?? "http://localhost:5000/;http://localhost:5001/;http://localhost:5002/"; + + // Create the Host agent + var hostAgent = new HostClientAgent(loggerFactory); + await hostAgent.InitializeAgentAsync(modelId, apiKey, agentUrls!.Split(";")); + AgentSession session = await hostAgent.Agent!.CreateSessionAsync(cancellationToken); + try + { + while (true) + { + // Get user message + Console.Write("\nUser (:q or quit to exit): "); + string? message = Console.ReadLine(); + if (string.IsNullOrWhiteSpace(message)) + { + Console.WriteLine("Request cannot be empty."); + continue; + } + + if (message is ":q" or "quit") + { + break; + } + + var agentResponse = await hostAgent.Agent!.RunAsync(message, session, cancellationToken: cancellationToken); + foreach (var chatMessage in agentResponse.Messages) + { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine($"\nAgent: {chatMessage.Text}"); + Console.ResetColor(); + } + } + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while running the A2AClient"); + return; + } + } +} diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AClient/README.md b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/README.md new file mode 100644 index 0000000000..c542430b22 --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AClient/README.md @@ -0,0 +1,26 @@ + +# A2A Client Sample +Show how to create an A2A Client with a command line interface which invokes agents using the A2A protocol. + +## Run the Sample + +To run the sample, follow these steps: + +1. Run the A2A client: + ```bash + cd A2AClient + dotnet run + ``` +2. Enter your request e.g. "Show me all invoices for Contoso?" + +## Set Environment Variables + +The agent urls are provided as a ` ` delimited list of strings + +```powershell +cd dotnet/samples/A2AClientServer/A2AClient + +$env:OPENAI_MODEL="gpt-4o-mini" +$env:OPENAI_API_KEY="" +$env:AGENT_URLS="http://localhost:5000/policy;http://localhost:5000/invoice;http://localhost:5000/logistics" +``` diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.csproj b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.csproj new file mode 100644 index 0000000000..0a3b170a0b --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.csproj @@ -0,0 +1,30 @@ + + + + Exe + net10.0 + enable + enable + 5ee045b0-aea3-4f08-8d31-32d1a6f8fed0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.http b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.http new file mode 100644 index 0000000000..9e50c67fec --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/A2AServer.http @@ -0,0 +1,85 @@ +### Each A2A agent is available at a different host address +@hostInvoice = http://localhost:5000 +@hostPolicy = http://localhost:5001 +@hostLogistics = http://localhost:5002 + +### Query agent card for the invoice agent +GET {{hostInvoice}}/.well-known/agent-card.json + +### Send a message to the invoice agent +POST {{hostInvoice}} +Content-Type: application/json + +{ + "id": "1", + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "id": "12345", + "message": { + "kind": "message", + "role": "user", + "messageId": "msg_1", + "parts": [ + { + "kind": "text", + "text": "Show me all invoices for Contoso?" + } + ] + } + } +} + +### Query agent card for the policy agent +GET {{hostPolicy}}/.well-known/agent-card.json + +### Send a message to the policy agent +POST {{hostPolicy}} +Content-Type: application/json + +{ + "id": "1", + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "id": "12345", + "message": { + "kind": "message", + "role": "user", + "messageId": "msg_1", + "parts": [ + { + "kind": "text", + "text": "What is the policy for short shipments?" + } + ] + } + } +} + +### Query agent card for the logistics agent +GET {{hostLogistics}}/.well-known/agent-card.json + +### Send a message to the logistics agent +POST {{hostLogistics}} +Content-Type: application/json + +{ + "id": "1", + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "id": "12345", + "message": { + "kind": "message", + "role": "user", + "messageId": "msg_1", + "parts": [ + { + "kind": "text", + "text": "What is the status for SHPMT-SAP-001?" + } + ] + } + } +} \ No newline at end of file diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AServer/HostAgentFactory.cs b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/HostAgentFactory.cs new file mode 100644 index 0000000000..8af2b01daf --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/HostAgentFactory.cs @@ -0,0 +1,148 @@ +// Copyright (c) Microsoft. All rights reserved. + +using A2A; +using Azure.AI.Agents.Persistent; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI; +using OpenAI.Chat; + +namespace A2AServer; + +internal static class HostAgentFactory +{ + internal static async Task<(AIAgent, AgentCard)> CreateFoundryHostAgentAsync(string agentType, string model, string endpoint, string assistantId, IList? tools = null) + { + var persistentAgentsClient = new PersistentAgentsClient(endpoint, new AzureCliCredential()); + PersistentAgent persistentAgent = await persistentAgentsClient.Administration.GetAgentAsync(assistantId); + + AIAgent agent = await persistentAgentsClient + .GetAIAgentAsync(persistentAgent.Id, chatOptions: new() { Tools = tools }); + + AgentCard agentCard = agentType.ToUpperInvariant() switch + { + "INVOICE" => GetInvoiceAgentCard(), + "POLICY" => GetPolicyAgentCard(), + "LOGISTICS" => GetLogisticsAgentCard(), + _ => throw new ArgumentException($"Unsupported agent type: {agentType}"), + }; + + return new(agent, agentCard); + } + + internal static async Task<(AIAgent, AgentCard)> CreateChatCompletionHostAgentAsync(string agentType, string model, string apiKey, string name, string instructions, IList? tools = null) + { + AIAgent agent = new OpenAIClient(apiKey) + .GetChatClient(model) + .AsAIAgent(instructions, name, tools: tools); + + AgentCard agentCard = agentType.ToUpperInvariant() switch + { + "INVOICE" => GetInvoiceAgentCard(), + "POLICY" => GetPolicyAgentCard(), + "LOGISTICS" => GetLogisticsAgentCard(), + _ => throw new ArgumentException($"Unsupported agent type: {agentType}"), + }; + + return new(agent, agentCard); + } + + #region private + private static AgentCard GetInvoiceAgentCard() + { + var capabilities = new AgentCapabilities() + { + Streaming = false, + PushNotifications = false, + }; + + var invoiceQuery = new AgentSkill() + { + Id = "id_invoice_agent", + Name = "InvoiceQuery", + Description = "Handles requests relating to invoices.", + Tags = ["invoice", "semantic-kernel"], + Examples = + [ + "List the latest invoices for Contoso.", + ], + }; + + return new() + { + Name = "InvoiceAgent", + Description = "Handles requests relating to invoices.", + Version = "1.0.0", + DefaultInputModes = ["text"], + DefaultOutputModes = ["text"], + Capabilities = capabilities, + Skills = [invoiceQuery], + }; + } + + private static AgentCard GetPolicyAgentCard() + { + var capabilities = new AgentCapabilities() + { + Streaming = false, + PushNotifications = false, + }; + + var policyQuery = new AgentSkill() + { + Id = "id_policy_agent", + Name = "PolicyAgent", + Description = "Handles requests relating to policies and customer communications.", + Tags = ["policy", "semantic-kernel"], + Examples = + [ + "What is the policy for short shipments?", + ], + }; + + return new AgentCard() + { + Name = "PolicyAgent", + Description = "Handles requests relating to policies and customer communications.", + Version = "1.0.0", + DefaultInputModes = ["text"], + DefaultOutputModes = ["text"], + Capabilities = capabilities, + Skills = [policyQuery], + }; + } + + private static AgentCard GetLogisticsAgentCard() + { + var capabilities = new AgentCapabilities() + { + Streaming = false, + PushNotifications = false, + }; + + var logisticsQuery = new AgentSkill() + { + Id = "id_logistics_agent", + Name = "LogisticsQuery", + Description = "Handles requests relating to logistics.", + Tags = ["logistics", "semantic-kernel"], + Examples = + [ + "What is the status for SHPMT-SAP-001", + ], + }; + + return new AgentCard() + { + Name = "LogisticsAgent", + Description = "Handles requests relating to logistics.", + Version = "1.0.0", + DefaultInputModes = ["text"], + DefaultOutputModes = ["text"], + Capabilities = capabilities, + Skills = [logisticsQuery], + }; + } + #endregion +} diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AServer/Models/InvoiceQuery.cs b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/Models/InvoiceQuery.cs new file mode 100644 index 0000000000..2b2d142c46 --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/Models/InvoiceQuery.cs @@ -0,0 +1,167 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; + +namespace A2A; + +/// +/// A simple invoice plugin that returns mock data. +/// +public class Product +{ + public string Name { get; set; } + public int Quantity { get; set; } + public decimal Price { get; set; } // Price per unit + + public Product(string name, int quantity, decimal price) + { + this.Name = name; + this.Quantity = quantity; + this.Price = price; + } + + public decimal TotalPrice() => this.Quantity * this.Price; // Total price for this product +} + +public class Invoice +{ + public string TransactionId { get; set; } + public string InvoiceId { get; set; } + public string CompanyName { get; set; } + public DateTime InvoiceDate { get; set; } + public List Products { get; set; } // List of products + + public Invoice(string transactionId, string invoiceId, string companyName, DateTime invoiceDate, List products) + { + this.TransactionId = transactionId; + this.InvoiceId = invoiceId; + this.CompanyName = companyName; + this.InvoiceDate = invoiceDate; + this.Products = products; + } + + public decimal TotalInvoicePrice() => this.Products.Sum(product => product.TotalPrice()); // Total price of all products in the invoice +} + +public class InvoiceQuery +{ + private readonly List _invoices; + + public InvoiceQuery() + { + // Extended mock data with quantities and prices + this._invoices = + [ + new("TICKET-XYZ987", "INV789", "Contoso", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 150, 10.00m), + new("Hats", 200, 15.00m), + new("Glasses", 300, 5.00m) + ]), + new("TICKET-XYZ111", "INV111", "XStore", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 2500, 12.00m), + new("Hats", 1500, 8.00m), + new("Glasses", 200, 20.00m) + ]), + new("TICKET-XYZ222", "INV222", "Cymbal Direct", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 1200, 14.00m), + new("Hats", 800, 7.00m), + new("Glasses", 500, 25.00m) + ]), + new("TICKET-XYZ333", "INV333", "Contoso", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 400, 11.00m), + new("Hats", 600, 15.00m), + new("Glasses", 700, 5.00m) + ]), + new("TICKET-XYZ444", "INV444", "XStore", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 800, 10.00m), + new("Hats", 500, 18.00m), + new("Glasses", 300, 22.00m) + ]), + new("TICKET-XYZ555", "INV555", "Cymbal Direct", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 1100, 9.00m), + new("Hats", 900, 12.00m), + new("Glasses", 1200, 15.00m) + ]), + new("TICKET-XYZ666", "INV666", "Contoso", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 2500, 8.00m), + new("Hats", 1200, 10.00m), + new("Glasses", 1000, 6.00m) + ]), + new("TICKET-XYZ777", "INV777", "XStore", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 1900, 13.00m), + new("Hats", 1300, 16.00m), + new("Glasses", 800, 19.00m) + ]), + new("TICKET-XYZ888", "INV888", "Cymbal Direct", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 2200, 11.00m), + new("Hats", 1700, 8.50m), + new("Glasses", 600, 21.00m) + ]), + new("TICKET-XYZ999", "INV999", "Contoso", GetRandomDateWithinLastTwoMonths(), + [ + new("T-Shirts", 1400, 10.50m), + new("Hats", 1100, 9.00m), + new("Glasses", 950, 12.00m) + ]) + ]; + } + + public static DateTime GetRandomDateWithinLastTwoMonths() + { + // Get the current date and time + DateTime endDate = DateTime.UtcNow; + + // Calculate the start date, which is two months before the current date + DateTime startDate = endDate.AddMonths(-2); + + // Generate a random number of days between 0 and the total number of days in the range + int totalDays = (endDate - startDate).Days; + int randomDays = Random.Shared.Next(0, totalDays + 1); // +1 to include the end date + + // Return the random date + return startDate.AddDays(randomDays); + } + + [Description("Retrieves invoices for the specified company and optionally within the specified time range")] + public IEnumerable QueryInvoices(string companyName, DateTime? startDate = null, DateTime? endDate = null) + { + var query = this._invoices.Where(i => i.CompanyName.Equals(companyName, StringComparison.OrdinalIgnoreCase)); + + if (startDate.HasValue) + { + query = query.Where(i => i.InvoiceDate >= startDate.Value); + } + + if (endDate.HasValue) + { + query = query.Where(i => i.InvoiceDate <= endDate.Value); + } + + return query.ToList(); + } + + [Description("Retrieves invoice using the transaction id")] + public IEnumerable QueryByTransactionId(string transactionId) + { + var query = this._invoices.Where(i => i.TransactionId.Equals(transactionId, StringComparison.OrdinalIgnoreCase)); + + return query.ToList(); + } + + [Description("Retrieves invoice using the invoice id")] + public IEnumerable QueryByInvoiceId(string invoiceId) + { + var query = this._invoices.Where(i => i.InvoiceId.Equals(invoiceId, StringComparison.OrdinalIgnoreCase)); + + return query.ToList(); + } +} diff --git a/dotnet/samples/_to_delete/A2AClientServer/A2AServer/Program.cs b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/Program.cs new file mode 100644 index 0000000000..bd344c46c8 --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/A2AServer/Program.cs @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft. All rights reserved. +using A2A; +using A2A.AspNetCore; +using A2AServer; +using Microsoft.Agents.AI; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +string agentId = string.Empty; +string agentType = string.Empty; + +for (var i = 0; i < args.Length; i++) +{ + if (args[i].StartsWith("--agentId", StringComparison.InvariantCultureIgnoreCase) && i + 1 < args.Length) + { + agentId = args[++i]; + } + else if (args[i].StartsWith("--agentType", StringComparison.InvariantCultureIgnoreCase) && i + 1 < args.Length) + { + agentType = args[++i]; + } +} + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddHttpClient().AddLogging(); +var app = builder.Build(); + +var httpClient = app.Services.GetRequiredService().CreateClient(); +var logger = app.Logger; + +IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddUserSecrets() + .Build(); + +string? apiKey = configuration["OPENAI_API_KEY"]; +string model = configuration["OPENAI_MODEL"] ?? "gpt-4o-mini"; +string? endpoint = configuration["AZURE_FOUNDRY_PROJECT_ENDPOINT"]; + +var invoiceQueryPlugin = new InvoiceQuery(); +IList tools = + [ + AIFunctionFactory.Create(invoiceQueryPlugin.QueryInvoices), + AIFunctionFactory.Create(invoiceQueryPlugin.QueryByTransactionId), + AIFunctionFactory.Create(invoiceQueryPlugin.QueryByInvoiceId) + ]; + +AIAgent hostA2AAgent; +AgentCard hostA2AAgentCard; + +if (!string.IsNullOrEmpty(endpoint) && !string.IsNullOrEmpty(agentId)) +{ + (hostA2AAgent, hostA2AAgentCard) = agentType.ToUpperInvariant() switch + { + "INVOICE" => await HostAgentFactory.CreateFoundryHostAgentAsync(agentType, model, endpoint, agentId, tools), + "POLICY" => await HostAgentFactory.CreateFoundryHostAgentAsync(agentType, model, endpoint, agentId), + "LOGISTICS" => await HostAgentFactory.CreateFoundryHostAgentAsync(agentType, model, endpoint, agentId), + _ => throw new ArgumentException($"Unsupported agent type: {agentType}"), + }; +} +else if (!string.IsNullOrEmpty(apiKey)) +{ + (hostA2AAgent, hostA2AAgentCard) = agentType.ToUpperInvariant() switch + { + "INVOICE" => await HostAgentFactory.CreateChatCompletionHostAgentAsync( + agentType, model, apiKey, "InvoiceAgent", + """ + You specialize in handling queries related to invoices. + """, tools), + "POLICY" => await HostAgentFactory.CreateChatCompletionHostAgentAsync( + agentType, model, apiKey, "PolicyAgent", + """ + You specialize in handling queries related to policies and customer communications. + + Always reply with exactly this text: + + Policy: Short Shipment Dispute Handling Policy V2.1 + + Summary: "For short shipments reported by customers, first verify internal shipment records + (SAP) and physical logistics scan data (BigQuery). If discrepancy is confirmed and logistics data + shows fewer items packed than invoiced, issue a credit for the missing items. Document the + resolution in SAP CRM and notify the customer via email within 2 business days, referencing the + original invoice and the credit memo number. Use the 'Formal Credit Notification' email + template." + """), + "LOGISTICS" => await HostAgentFactory.CreateChatCompletionHostAgentAsync( + agentType, model, apiKey, "LogisticsAgent", + """ + You specialize in handling queries related to logistics. + + Always reply with exactly: + + Shipment number: SHPMT-SAP-001 + Item: TSHIRT-RED-L + Quantity: 900 + """), + _ => throw new ArgumentException($"Unsupported agent type: {agentType}"), + }; +} +else +{ + throw new ArgumentException("Either A2AServer:ApiKey or A2AServer:ConnectionString & agentId must be provided"); +} + +var a2aTaskManager = app.MapA2A( + hostA2AAgent, + path: "/", + agentCard: hostA2AAgentCard, + taskManager => app.MapWellKnownAgentCard(taskManager, "/")); + +await app.RunAsync(); diff --git a/dotnet/samples/_to_delete/A2AClientServer/README.md b/dotnet/samples/_to_delete/A2AClientServer/README.md new file mode 100644 index 0000000000..04b9968e76 --- /dev/null +++ b/dotnet/samples/_to_delete/A2AClientServer/README.md @@ -0,0 +1,235 @@ +# A2A Client and Server samples + +> **Warning** +> The [A2A protocol](https://google.github.io/A2A/) is still under development and changing fast. +> We will try to keep these samples updated as the protocol evolves. + +These samples are built with [official A2A C# SDK](https://www.nuget.org/packages/A2A) and demonstrates: + +1. Creating an A2A Server which makes an agent available via the A2A protocol. +2. Creating an A2A Client with a command line interface which invokes agents using the A2A protocol. + +The demonstration has two components: + +1. `A2AServer` - You will run three instances of the server to correspond to three A2A servers each providing a single Agent i.e., the Invoice, Policy and Logistics agents. +2. `A2AClient` - This represents a client application which will connect to the remote A2A servers using the A2A protocol so that it can use those agents when answering questions you will ask. + +Demo Architecture + +## Configuring Environment Variables + +The samples can be configured to use chat completion agents or Azure AI agents. + +### Configuring for use with Chat Completion Agents + +Provide your OpenAI API key via an environment variable + +```powershell +$env:OPENAI_API_KEY="" +``` + +Use the following commands to run each A2A server: + +Execute the following command to build the sample: + +```powershell +cd A2AServer +dotnet build +``` + +```bash +dotnet run --urls "http://localhost:5000;https://localhost:5010" --agentType "invoice" --no-build +``` + +```bash +dotnet run --urls "http://localhost:5001;https://localhost:5011" --agentType "policy" --no-build +``` + +```bash +dotnet run --urls "http://localhost:5002;https://localhost:5012" --agentType "logistics" --no-build +``` + +### Configuring for use with Azure AI Agents + +You must create the agents in an Azure AI Foundry project and then provide the project endpoint and agents ids. The instructions for each agent are as follows: + +- Invoice Agent + ``` + You specialize in handling queries related to invoices. + ``` +- Policy Agent + ``` + You specialize in handling queries related to policies and customer communications. + + Always reply with exactly this text: + + Policy: Short Shipment Dispute Handling Policy V2.1 + + Summary: "For short shipments reported by customers, first verify internal shipment records + (SAP) and physical logistics scan data (BigQuery). If discrepancy is confirmed and logistics data + shows fewer items packed than invoiced, issue a credit for the missing items. Document the + resolution in SAP CRM and notify the customer via email within 2 business days, referencing the + original invoice and the credit memo number. Use the 'Formal Credit Notification' email + template." + ``` +- Logistics Agent + ``` + You specialize in handling queries related to logistics. + + Always reply with exactly: + + Shipment number: SHPMT-SAP-001 + Item: TSHIRT-RED-L + Quantity: 900" + ``` + +```powershell +$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://ai-foundry-your-project.services.ai.azure.com/api/projects/ai-proj-ga-your-project" # Replace with your Foundry Project endpoint +``` + +Use the following commands to run each A2A server + +```bash +dotnet run --urls "http://localhost:5000;https://localhost:5010" --agentId "" --agentType "invoice" --no-build +``` + +```bash +dotnet run --urls "http://localhost:5001;https://localhost:5011" --agentId "" --agentType "policy" --no-build +``` + +```bash +dotnet run --urls "http://localhost:5002;https://localhost:5012" --agentId "" --agentType "logistics" --no-build +``` + +### Testing the Agents using the Rest Client + +This sample contains a [.http file](https://learn.microsoft.com/aspnet/core/test/http-files?view=aspnetcore-10.0) which can be used to test the agent. + +1. In Visual Studio open [./A2AServer/A2AServer.http](./A2AServer/A2AServer.http) +1. There are two sent requests for each agent, e.g., for the invoice agent: + 1. Query agent card for the invoice agent + `GET {{hostInvoice}}/.well-known/agent-card.json` + 1. Send a message to the invoice agent + ``` + POST {{hostInvoice}} + Content-Type: application/json + + { + "id": "1", + "jsonrpc": "2.0", + "method": "message/send", + "params": { + "id": "12345", + "message": { + "kind": "message", + "role": "user", + "messageId": "msg_1", + "parts": [ + { + "kind": "text", + "text": "Show me all invoices for Contoso?" + } + ] + } + } + } + ``` + +Sample output from the request to display the agent card: + +Agent Card + +Sample output from the request to send a message to the agent via A2A protocol: + +Send Message + +### Testing the Agents using the A2A Inspector + +The A2A Inspector is a web-based tool designed to help developers inspect, debug, and validate servers that implement the Google A2A (Agent2Agent) protocol. It provides a user-friendly interface to interact with an A2A agent, view communication, and ensure specification compliance. + +For more information go [here](https://github.com/a2aproject/a2a-inspector). + +Running the [inspector with Docker](https://github.com/a2aproject/a2a-inspector?tab=readme-ov-file#option-two-run-with-docker) is the easiest way to get started. + +1. Navigate to the A2A Inspector in your browser: [http://127.0.0.1:8080/](http://127.0.0.1:8080/) +1. Enter the URL of the Agent you are running e.g., [http://host.docker.internal:5000](http://host.docker.internal:5000) +1. Connect to the agent and the agent card will be displayed and validated. +1. Type a message and send it to the agent using A2A protocol. + 1. The response will be validated automatically and then displayed in the UI. + 1. You can select the response to view the raw json. + +Agent card after connecting to an agent using the A2A protocol: + +Agent Card + +Sample response after sending a message to the agent via A2A protocol: + +Send Message + +Raw JSON response from an A2A agent: + +Response Raw JSON + +### Configuring Agents for the A2A Client + +The A2A client will connect to remote agents using the A2A protocol. + +By default the client will connect to the invoice, policy and logistics agents provided by the sample A2A Server. + +These are available at the following URL's: + +- Invoice Agent: http://localhost:5000/ +- Policy Agent: http://localhost:5001/ +- Logistics Agent: http://localhost:5002/ + +If you want to change which agents are using then set the agents url as a space delimited string as follows: + +```powershell +$env:A2A_AGENT_URLS="http://localhost:5000/;http://localhost:5001/;http://localhost:5002/" +``` + +## Run the Sample + +To run the sample, follow these steps: + +1. Run the A2A server's using the commands shown earlier +2. Run the A2A client: + ```bash + cd A2AClient + dotnet run + ``` +3. Enter your request e.g. "Customer is disputing transaction TICKET-XYZ987 as they claim the received fewer t-shirts than ordered." +4. The host client agent will call the remote agents, these calls will be displayed as console output. The final answer will use information from the remote agents. The sample below includes all three agents but in your case you may only see the policy and invoice agent. + +Sample output from the A2A client: + +``` +A2AClient> dotnet run +info: HostClientAgent[0] + Initializing Agent Framework agent with model: gpt-4o-mini + +User (:q or quit to exit): Customer is disputing transaction TICKET-XYZ987 as they claim the received fewer t-shirts than ordered. + +Agent: + +Agent: + +Agent: The transaction details for **TICKET-XYZ987** are as follows: + +- **Invoice ID:** INV789 +- **Company Name:** Contoso +- **Invoice Date:** September 4, 2025 +- **Products:** + - **T-Shirts:** 150 units at $10.00 each + - **Hats:** 200 units at $15.00 each + - **Glasses:** 300 units at $5.00 each + +To proceed with the dispute regarding the quantity of t-shirts delivered, please specify the exact quantity issue � how many t-shirts were actually received compared to the ordered amount. + +### Customer Service Policy for Handling Disputes +**Short Shipment Dispute Handling Policy V2.1** +- **Summary:** For short shipments reported by customers, first verify internal shipment records and physical logistics scan data. If a discrepancy is confirmed and the logistics data shows fewer items were packed than invoiced, a credit for the missing items will be issued. +- **Follow-up Actions:** Document the resolution in the SAP CRM and notify the customer via email within 2 business days, referencing the original invoice and the credit memo number, using the 'Formal Credit Notification' email template. + +Please provide me with the information regarding the specific quantity issue so I can assist you further. +``` diff --git a/dotnet/samples/A2AClientServer/a2a-inspector-agent-card.png b/dotnet/samples/_to_delete/A2AClientServer/a2a-inspector-agent-card.png similarity index 100% rename from dotnet/samples/A2AClientServer/a2a-inspector-agent-card.png rename to dotnet/samples/_to_delete/A2AClientServer/a2a-inspector-agent-card.png diff --git a/dotnet/samples/A2AClientServer/a2a-inspector-raw-json-response.png b/dotnet/samples/_to_delete/A2AClientServer/a2a-inspector-raw-json-response.png similarity index 100% rename from dotnet/samples/A2AClientServer/a2a-inspector-raw-json-response.png rename to dotnet/samples/_to_delete/A2AClientServer/a2a-inspector-raw-json-response.png diff --git a/dotnet/samples/A2AClientServer/a2a-inspector-send-message.png b/dotnet/samples/_to_delete/A2AClientServer/a2a-inspector-send-message.png similarity index 100% rename from dotnet/samples/A2AClientServer/a2a-inspector-send-message.png rename to dotnet/samples/_to_delete/A2AClientServer/a2a-inspector-send-message.png diff --git a/dotnet/samples/A2AClientServer/demo-architecture.png b/dotnet/samples/_to_delete/A2AClientServer/demo-architecture.png similarity index 100% rename from dotnet/samples/A2AClientServer/demo-architecture.png rename to dotnet/samples/_to_delete/A2AClientServer/demo-architecture.png diff --git a/dotnet/samples/A2AClientServer/rest-client-agent-card.png b/dotnet/samples/_to_delete/A2AClientServer/rest-client-agent-card.png similarity index 100% rename from dotnet/samples/A2AClientServer/rest-client-agent-card.png rename to dotnet/samples/_to_delete/A2AClientServer/rest-client-agent-card.png diff --git a/dotnet/samples/A2AClientServer/rest-client-send-message.png b/dotnet/samples/_to_delete/A2AClientServer/rest-client-send-message.png similarity index 100% rename from dotnet/samples/A2AClientServer/rest-client-send-message.png rename to dotnet/samples/_to_delete/A2AClientServer/rest-client-send-message.png diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClient.csproj b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClient.csproj new file mode 100644 index 0000000000..7d80fa7cda --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClient.csproj @@ -0,0 +1,21 @@ + + + + Exe + net10.0 + enable + enable + a8b2e9f0-1ea3-4f18-9d41-42d1a6f8fe10 + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClientSerializerContext.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClientSerializerContext.cs new file mode 100644 index 0000000000..1cc4fb8f53 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/AGUIClientSerializerContext.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates how to use the AG-UI client to connect to a remote AG-UI server +// and display streaming updates including conversation/response metadata, text content, and errors. + +using System.Text.Json.Serialization; + +namespace AGUIClient; + +[JsonSerializable(typeof(SensorRequest))] +[JsonSerializable(typeof(SensorResponse))] +internal sealed partial class AGUIClientSerializerContext : JsonSerializerContext; diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/Program.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/Program.cs new file mode 100644 index 0000000000..1e5b6d6fee --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/Program.cs @@ -0,0 +1,213 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates how to use the AG-UI client to connect to a remote AG-UI server +// and display streaming updates including conversation/response metadata, text content, and errors. + +using System.CommandLine; +using System.ComponentModel; +using System.Reflection; +using System.Text; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.AGUI; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace AGUIClient; + +public static class Program +{ + public static async Task Main(string[] args) + { + // Create root command with options + RootCommand rootCommand = new("AGUIClient"); + rootCommand.SetAction((_, ct) => HandleCommandsAsync(ct)); + + // Run the command + return await rootCommand.Parse(args).InvokeAsync(); + } + + private static async Task HandleCommandsAsync(CancellationToken cancellationToken) + { + // Set up the logging + using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => + { + builder.AddConsole(); + builder.SetMinimumLevel(LogLevel.Information); + }); + ILogger logger = loggerFactory.CreateLogger("AGUIClient"); + + // Retrieve configuration settings + IConfigurationRoot configRoot = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddUserSecrets(Assembly.GetExecutingAssembly()) + .Build(); + + string serverUrl = configRoot["AGUI_SERVER_URL"] ?? "http://localhost:5100"; + + logger.LogInformation("Connecting to AG-UI server at: {ServerUrl}", serverUrl); + + // Create the AG-UI client agent + using HttpClient httpClient = new() + { + Timeout = TimeSpan.FromSeconds(60) + }; + + var changeBackground = AIFunctionFactory.Create( + () => + { + Console.ForegroundColor = ConsoleColor.DarkBlue; + Console.WriteLine("Changing color to blue"); + }, + name: "change_background_color", + description: "Change the console background color to dark blue." + ); + + var readClientClimateSensors = AIFunctionFactory.Create( + ([Description("The sensors measurements to include in the response")] SensorRequest request) => + { + return new SensorResponse() + { + Temperature = 22.5, + Humidity = 45.0, + AirQualityIndex = 75 + }; + }, + name: "read_client_climate_sensors", + description: "Reads the climate sensor data from the client device.", + serializerOptions: AGUIClientSerializerContext.Default.Options + ); + + var chatClient = new AGUIChatClient( + httpClient, + serverUrl, + jsonSerializerOptions: AGUIClientSerializerContext.Default.Options); + + AIAgent agent = chatClient.AsAIAgent( + name: "agui-client", + description: "AG-UI Client Agent", + tools: [changeBackground, readClientClimateSensors]); + + AgentSession session = await agent.CreateSessionAsync(cancellationToken); + List messages = [new(ChatRole.System, "You are a helpful assistant.")]; + try + { + while (true) + { + // Get user message + Console.Write("\nUser (:q or quit to exit): "); + string? message = Console.ReadLine(); + if (string.IsNullOrWhiteSpace(message)) + { + Console.WriteLine("Request cannot be empty."); + continue; + } + + if (message is ":q" or "quit") + { + break; + } + + messages.Add(new(ChatRole.User, message)); + + // Call RunStreamingAsync to get streaming updates + bool isFirstUpdate = true; + string? sessionId = null; + var updates = new List(); + await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, session, cancellationToken: cancellationToken)) + { + // Use AsChatResponseUpdate to access ChatResponseUpdate properties + ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate(); + updates.Add(chatUpdate); + if (chatUpdate.ConversationId != null) + { + sessionId = chatUpdate.ConversationId; + } + + // Display run started information from the first update + if (isFirstUpdate && sessionId != null && update.ResponseId != null) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"\n[Run Started - Session: {sessionId}, Run: {update.ResponseId}]"); + Console.ResetColor(); + isFirstUpdate = false; + } + + // Display different content types with appropriate formatting + foreach (AIContent content in update.Contents) + { + switch (content) + { + case TextContent textContent: + Console.ForegroundColor = ConsoleColor.Cyan; + Console.Write(textContent.Text); + Console.ResetColor(); + break; + + case FunctionCallContent functionCallContent: + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"\n[Function Call - Name: {functionCallContent.Name}, Arguments: {PrintArguments(functionCallContent.Arguments)}]"); + Console.ResetColor(); + break; + + case FunctionResultContent functionResultContent: + Console.ForegroundColor = ConsoleColor.Magenta; + if (functionResultContent.Exception != null) + { + Console.WriteLine($"\n[Function Result - Exception: {functionResultContent.Exception}]"); + } + else + { + Console.WriteLine($"\n[Function Result - Result: {functionResultContent.Result}]"); + } + Console.ResetColor(); + break; + + case ErrorContent errorContent: + Console.ForegroundColor = ConsoleColor.Red; + string code = errorContent.AdditionalProperties?["Code"] as string ?? "Unknown"; + Console.WriteLine($"\n[Error - Code: {code}, Message: {errorContent.Message}]"); + Console.ResetColor(); + break; + } + } + } + if (updates.Count > 0 && !updates[^1].Contents.Any(c => c is TextContent)) + { + var lastUpdate = updates[^1]; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(); + Console.WriteLine($"[Run Ended - Session: {sessionId}, Run: {lastUpdate.ResponseId}]"); + Console.ResetColor(); + } + messages.Clear(); + Console.WriteLine(); + } + } + catch (OperationCanceledException) + { + logger.LogInformation("AGUIClient operation was canceled."); + } + catch (Exception ex) when (ex is not OutOfMemoryException and not StackOverflowException and not ThreadAbortException and not AccessViolationException) + { + logger.LogError(ex, "An error occurred while running the AGUIClient"); + return; + } + } + + private static string PrintArguments(IDictionary? arguments) + { + if (arguments == null) + { + return ""; + } + var builder = new StringBuilder().AppendLine(); + foreach (var kvp in arguments) + { + builder + .AppendLine($" Name: {kvp.Key}") + .AppendLine($" Value: {kvp.Value}"); + } + return builder.ToString(); + } +} diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/README.md b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/README.md new file mode 100644 index 0000000000..f0f6052159 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/README.md @@ -0,0 +1,34 @@ +# AG-UI Client + +This is a console application that demonstrates how to connect to an AG-UI server and interact with remote agents using the AG-UI protocol. + +## Features + +- Connects to an AG-UI server endpoint +- Displays streaming updates with color-coded output: + - **Yellow**: Run started notifications + - **Cyan**: Agent text responses (streamed) + - **Green**: Run finished notifications + - **Red**: Error messages (if any) +- Interactive prompt loop for sending messages + +## Configuration + +Set the following environment variable to specify the AG-UI server URL: + +```powershell +$env:AGUI_SERVER_URL="http://localhost:5100" +``` + +If not set, the default is `http://localhost:5100`. + +## Running the Client + +1. Make sure the AG-UI server is running +2. Run the client: + ```bash + cd AGUIClient + dotnet run + ``` +3. Enter your messages and observe the streaming updates +4. Type `:q` or `quit` to exit diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorRequest.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorRequest.cs new file mode 100644 index 0000000000..76e6efa8de --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorRequest.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates how to use the AG-UI client to connect to a remote AG-UI server +// and display streaming updates including conversation/response metadata, text content, and errors. + +namespace AGUIClient; + +internal sealed class SensorRequest +{ + public bool IncludeTemperature { get; set; } = true; + public bool IncludeHumidity { get; set; } = true; + public bool IncludeAirQualityIndex { get; set; } = true; +} diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorResponse.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorResponse.cs new file mode 100644 index 0000000000..09ade6a0c7 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIClient/SensorResponse.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates how to use the AG-UI client to connect to a remote AG-UI server +// and display streaming updates including conversation/response metadata, text content, and errors. + +namespace AGUIClient; + +internal sealed class SensorResponse +{ + public double Temperature { get; set; } + public double Humidity { get; set; } + public int AirQualityIndex { get; set; } +} diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AGUIDojoServer.csproj b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AGUIDojoServer.csproj similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AGUIDojoServer.csproj rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AGUIDojoServer.csproj diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AGUIDojoServerSerializerContext.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AGUIDojoServerSerializerContext.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AGUIDojoServerSerializerContext.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AGUIDojoServerSerializerContext.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticPlanningTools.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticPlanningTools.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticPlanningTools.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticPlanningTools.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticUIAgent.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticUIAgent.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticUIAgent.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/AgenticUIAgent.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/JsonPatchOperation.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/JsonPatchOperation.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/JsonPatchOperation.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/JsonPatchOperation.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/Plan.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/Plan.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/Plan.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/Plan.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/Step.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/Step.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/Step.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/Step.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/StepStatus.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/StepStatus.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/AgenticUI/StepStatus.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/AgenticUI/StepStatus.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/BackendToolRendering/WeatherInfo.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/BackendToolRendering/WeatherInfo.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/BackendToolRendering/WeatherInfo.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/BackendToolRendering/WeatherInfo.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/ChatClientAgentFactory.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/ChatClientAgentFactory.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/ChatClientAgentFactory.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/ChatClientAgentFactory.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/DocumentState.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/DocumentState.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/DocumentState.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/DocumentState.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/PredictiveStateUpdatesAgent.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/PredictiveStateUpdatesAgent.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/PredictiveStateUpdatesAgent.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/PredictiveStateUpdates/PredictiveStateUpdatesAgent.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/Program.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/Program.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/Program.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/Program.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/Properties/launchSettings.json b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/Properties/launchSettings.json rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/Properties/launchSettings.json diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/Ingredient.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/Ingredient.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/Ingredient.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/Ingredient.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/Recipe.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/Recipe.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/Recipe.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/Recipe.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/RecipeResponse.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/RecipeResponse.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/RecipeResponse.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/RecipeResponse.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/appsettings.Development.json b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/appsettings.Development.json similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/appsettings.Development.json rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/appsettings.Development.json diff --git a/dotnet/samples/AGUIClientServer/AGUIDojoServer/appsettings.json b/dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/appsettings.json similarity index 100% rename from dotnet/samples/AGUIClientServer/AGUIDojoServer/appsettings.json rename to dotnet/samples/_to_delete/AGUIClientServer/AGUIDojoServer/appsettings.json diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.csproj b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.csproj new file mode 100644 index 0000000000..ccfe22923a --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.csproj @@ -0,0 +1,22 @@ + + + + Exe + net10.0 + enable + enable + a8b2e9f0-1ea3-4f18-9d41-42d1a6f8fe10 + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.http b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.http new file mode 100644 index 0000000000..b3f5831893 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServer.http @@ -0,0 +1,17 @@ +@host = http://localhost:5100 + +### Send a message to the AG-UI agent +POST {{host}}/ +Content-Type: application/json + +{ + "threadId": "thread_123", + "runId": "run_456", + "messages": [ + { + "role": "user", + "content": "What is the capital of France?" + } + ], + "context": {} +} diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServerSerializerContext.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServerSerializerContext.cs new file mode 100644 index 0000000000..1ca6ad7bdc --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/AGUIServerSerializerContext.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json.Serialization; + +namespace AGUIServer; + +[JsonSerializable(typeof(ServerWeatherForecastRequest))] +[JsonSerializable(typeof(ServerWeatherForecastResponse))] +internal sealed partial class AGUIServerSerializerContext : JsonSerializerContext; diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Program.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Program.cs new file mode 100644 index 0000000000..418f72ad43 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Program.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; +using AGUIServer; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore; +using Microsoft.Extensions.AI; +using OpenAI.Chat; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); +builder.Services.AddHttpClient().AddLogging(); +builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.TypeInfoResolverChain.Add(AGUIServerSerializerContext.Default)); +builder.Services.AddAGUI(); + +WebApplication app = builder.Build(); + +string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set."); + +// Create the AI agent with tools +var agent = new AzureOpenAIClient( + new Uri(endpoint), + new DefaultAzureCredential()) + .GetChatClient(deploymentName) + .AsAIAgent( + name: "AGUIAssistant", + tools: [ + AIFunctionFactory.Create( + () => DateTimeOffset.UtcNow, + name: "get_current_time", + description: "Get the current UTC time." + ), + AIFunctionFactory.Create( + ([Description("The weather forecast request")]ServerWeatherForecastRequest request) => { + return new ServerWeatherForecastResponse() + { + Summary = "Sunny", + TemperatureC = 25, + Date = request.Date + }; + }, + name: "get_server_weather_forecast", + description: "Gets the forecast for a specific location and date", + AGUIServerSerializerContext.Default.Options) + ]); + +// Map the AG-UI agent endpoint +app.MapAGUI("/", agent); + +await app.RunAsync(); diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Properties/launchSettings.json b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Properties/launchSettings.json new file mode 100644 index 0000000000..6e38bd9975 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "AGUIServer": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5100;https://localhost:5101" + } + } +} \ No newline at end of file diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastRequest.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastRequest.cs new file mode 100644 index 0000000000..a4e3d983ca --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastRequest.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace AGUIServer; + +internal sealed class ServerWeatherForecastRequest +{ + public DateTime Date { get; set; } + public string Location { get; set; } = "Seattle"; +} diff --git a/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastResponse.cs b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastResponse.cs new file mode 100644 index 0000000000..2bc5d8fbb9 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/AGUIServer/ServerWeatherForecastResponse.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace AGUIServer; + +internal sealed class ServerWeatherForecastResponse +{ + public string Summary { get; set; } = ""; + + public int TemperatureC { get; set; } + + public DateTime Date { get; set; } +} diff --git a/dotnet/samples/_to_delete/AGUIClientServer/README.md b/dotnet/samples/_to_delete/AGUIClientServer/README.md new file mode 100644 index 0000000000..2e4887cde9 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIClientServer/README.md @@ -0,0 +1,208 @@ +# AG-UI Client and Server Sample + +This sample demonstrates how to use the AG-UI (Agent UI) protocol to enable communication between a client application and a remote agent server. The AG-UI protocol provides a standardized way for clients to interact with AI agents. + +## Overview + +The demonstration has two components: + +1. **AGUIServer** - An ASP.NET Core web server that hosts an AI agent and exposes it via the AG-UI protocol +2. **AGUIClient** - A console application that connects to the AG-UI server and displays streaming updates + +> **Warning** +> The AG-UI protocol is still under development and changing. +> We will try to keep these samples updated as the protocol evolves. + +## Configuring Environment Variables + +Configure the required Azure OpenAI environment variables: + +```powershell +$env:AZURE_OPENAI_ENDPOINT="<>" +$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +> **Note:** This sample uses `DefaultAzureCredential` for authentication. Make sure you're authenticated with Azure (e.g., via `az login`, Visual Studio, or environment variables). + +## Running the Sample + +### Step 1: Start the AG-UI Server + +```bash +cd AGUIServer +dotnet build +dotnet run --urls "http://localhost:5100" +``` + +The server will start and listen on `http://localhost:5100`. + +### Step 2: Testing with the REST Client (Optional) + +Before running the client, you can test the server using the included `.http` file: + +1. Open [./AGUIServer/AGUIServer.http](./AGUIServer/AGUIServer.http) in Visual Studio or VS Code with the REST Client extension +2. Send a test request to verify the server is working +3. Observe the server-sent events stream in the response + +Sample request: +```http +POST http://localhost:5100/ +Content-Type: application/json + +{ + "threadId": "thread_123", + "runId": "run_456", + "messages": [ + { + "role": "user", + "content": "What is the capital of France?" + } + ], + "context": {} +} +``` + +### Step 3: Run the AG-UI Client + +In a new terminal window: + +```bash +cd AGUIClient +dotnet run +``` + +Optionally, configure a different server URL: + +```powershell +$env:AGUI_SERVER_URL="http://localhost:5100" +``` + +### Step 4: Interact with the Agent + +1. The client will connect to the AG-UI server +2. Enter your message at the prompt +3. Observe the streaming updates with color-coded output: + - **Yellow**: Run started notification showing thread and run IDs + - **Cyan**: Agent's text response (streamed character by character) + - **Green**: Run finished notification + - **Red**: Error messages (if any occur) +4. Type `:q` or `quit` to exit + +## Sample Output + +``` +AGUIClient> dotnet run +info: AGUIClient[0] + Connecting to AG-UI server at: http://localhost:5100 + +User (:q or quit to exit): What is the capital of France? + +[Run Started - Thread: thread_abc123, Run: run_xyz789] +The capital of France is Paris. It is known for its rich history, culture, and iconic landmarks such as the Eiffel Tower and the Louvre Museum. +[Run Finished - Thread: thread_abc123, Run: run_xyz789] + +User (:q or quit to exit): Tell me a fun fact about space + +[Run Started - Thread: thread_abc123, Run: run_def456] +Here's a fun fact: A day on Venus is longer than its year! Venus takes about 243 Earth days to rotate once on its axis, but only about 225 Earth days to orbit the Sun. +[Run Finished - Thread: thread_abc123, Run: run_def456] + +User (:q or quit to exit): :q +``` + +## How It Works + +### Server Side + +The `AGUIServer` uses the `MapAGUI` extension method to expose an agent through the AG-UI protocol: + +```csharp +AIAgent agent = new OpenAIClient(apiKey) + .GetChatClient(model) + .AsAIAgent( + instructions: "You are a helpful assistant.", + name: "AGUIAssistant"); + +app.MapAGUI("/", agent); +``` + +This automatically handles: +- HTTP POST requests with message payloads +- Converting agent responses to AG-UI event streams +- Server-sent events (SSE) formatting +- Thread and run management + +### Client Side + +The `AGUIClient` uses the `AGUIChatClient` to connect to the remote server: + +```csharp +using HttpClient httpClient = new(); +var chatClient = new AGUIChatClient( + httpClient, + endpoint: serverUrl, + modelId: "agui-client", + jsonSerializerOptions: null); + +AIAgent agent = chatClient.AsAIAgent( + instructions: null, + name: "agui-client", + description: "AG-UI Client Agent", + tools: []); + +bool isFirstUpdate = true; +AgentResponseUpdate? currentUpdate = null; + +await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, thread)) +{ + // First update indicates run started + if (isFirstUpdate) + { + Console.WriteLine($"[Run Started - Thread: {update.ConversationId}, Run: {update.ResponseId}]"); + isFirstUpdate = false; + } + + currentUpdate = update; + + foreach (AIContent content in update.Contents) + { + switch (content) + { + case TextContent textContent: + // Display streaming text + Console.Write(textContent.Text); + break; + case ErrorContent errorContent: + // Display error notification + Console.WriteLine($"[Error: {errorContent.Message}]"); + break; + } + } +} + +// Last update indicates run finished +if (currentUpdate != null) +{ + Console.WriteLine($"\n[Run Finished - Thread: {currentUpdate.ConversationId}, Run: {currentUpdate.ResponseId}]"); +} +``` + +The `RunStreamingAsync` method: +1. Sends messages to the server via HTTP POST +2. Receives server-sent events (SSE) stream +3. Parses events into `AgentResponseUpdate` objects +4. Yields updates as they arrive for real-time display + +## Key Concepts + +- **Thread**: Represents a conversation context that persists across multiple runs (accessed via `ConversationId` property) +- **Run**: A single execution of the agent for a given set of messages (identified by `ResponseId` property) +- **AgentResponseUpdate**: Contains the response data with: + - `ResponseId`: The unique run identifier + - `ConversationId`: The thread/conversation identifier + - `Contents`: Collection of content items (TextContent, ErrorContent, etc.) +- **Run Lifecycle**: + - The **first** `AgentResponseUpdate` in a run indicates the run has started + - Subsequent updates contain streaming content as the agent processes + - The **last** `AgentResponseUpdate` in a run indicates the run has finished + - If an error occurs, the update will contain `ErrorContent` \ No newline at end of file diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/AGUIWebChatClient.csproj b/dotnet/samples/_to_delete/AGUIWebChat/Client/AGUIWebChatClient.csproj new file mode 100644 index 0000000000..b28e53df6e --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/AGUIWebChatClient.csproj @@ -0,0 +1,14 @@ + + + + net10.0 + enable + enable + true + + + + + + + diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/App.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/App.razor new file mode 100644 index 0000000000..a64d576883 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/App.razor @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + +@code { + private readonly IComponentRenderMode renderMode = new InteractiveServerRenderMode(prerender: false); +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor new file mode 100644 index 0000000000..116455ce45 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor @@ -0,0 +1 @@ +
diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor.css new file mode 100644 index 0000000000..e599d27e86 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/LoadingSpinner.razor.css @@ -0,0 +1,89 @@ +/* Used under CC0 license */ + +.lds-ellipsis { + color: #666; + animation: fade-in 1s; +} + +@keyframes fade-in { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + + .lds-ellipsis, + .lds-ellipsis div { + box-sizing: border-box; + } + +.lds-ellipsis { + margin: auto; + display: block; + position: relative; + width: 80px; + height: 80px; +} + + .lds-ellipsis div { + position: absolute; + top: 33.33333px; + width: 10px; + height: 10px; + border-radius: 50%; + background: currentColor; + animation-timing-function: cubic-bezier(0, 1, 1, 0); + } + + .lds-ellipsis div:nth-child(1) { + left: 8px; + animation: lds-ellipsis1 0.6s infinite; + } + + .lds-ellipsis div:nth-child(2) { + left: 8px; + animation: lds-ellipsis2 0.6s infinite; + } + + .lds-ellipsis div:nth-child(3) { + left: 32px; + animation: lds-ellipsis2 0.6s infinite; + } + + .lds-ellipsis div:nth-child(4) { + left: 56px; + animation: lds-ellipsis3 0.6s infinite; + } + +@keyframes lds-ellipsis1 { + 0% { + transform: scale(0); + } + + 100% { + transform: scale(1); + } +} + +@keyframes lds-ellipsis3 { + 0% { + transform: scale(1); + } + + 100% { + transform: scale(0); + } +} + +@keyframes lds-ellipsis2 { + 0% { + transform: translate(0, 0); + } + + 100% { + transform: translate(24px, 0); + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor new file mode 100644 index 0000000000..f3da3cbae5 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor @@ -0,0 +1,9 @@ +@inherits LayoutComponentBase + +@Body + +
+ An unhandled error has occurred. + Reload + 🗙 +
diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor.css new file mode 100644 index 0000000000..60cec92d5e --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Layout/MainLayout.razor.css @@ -0,0 +1,20 @@ +#blazor-error-ui { + color-scheme: light only; + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + box-sizing: border-box; + display: none; + left: 0; + padding: 0.6rem 1.25rem 0.7rem 1.25rem; + position: fixed; + width: 100%; + z-index: 1000; +} + + #blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; + } diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor new file mode 100644 index 0000000000..31eb7e406c --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor @@ -0,0 +1,94 @@ +@page "/" +@using System.ComponentModel +@inject IChatClient ChatClient +@inject NavigationManager Nav +@implements IDisposable + +Chat + + + + + +
Ask the assistant a question to start a conversation.
+
+
+
+ + +
+ +@code { + private const string SystemPrompt = @" + You are a helpful assistant. + "; + + private int statefulMessageCount; + private readonly ChatOptions chatOptions = new(); + private readonly List messages = new(); + private CancellationTokenSource? currentResponseCancellation; + private ChatMessage? currentResponseMessage; + private ChatInput? chatInput; + private ChatSuggestions? chatSuggestions; + + protected override void OnInitialized() + { + statefulMessageCount = 0; + messages.Add(new(ChatRole.System, SystemPrompt)); + } + + private async Task AddUserMessageAsync(ChatMessage userMessage) + { + CancelAnyCurrentResponse(); + + // Add the user message to the conversation + messages.Add(userMessage); + chatSuggestions?.Clear(); + await chatInput!.FocusAsync(); + + // Stream and display a new response from the IChatClient + var responseText = new TextContent(""); + currentResponseMessage = new ChatMessage(ChatRole.Assistant, [responseText]); + StateHasChanged(); + currentResponseCancellation = new(); + await foreach (var update in ChatClient.GetStreamingResponseAsync(messages.Skip(statefulMessageCount), chatOptions, currentResponseCancellation.Token)) + { + messages.AddMessages(update, filter: c => c is not TextContent); + responseText.Text += update.Text; + chatOptions.ConversationId = update.ConversationId; + ChatMessageItem.NotifyChanged(currentResponseMessage); + } + + // Store the final response in the conversation, and begin getting suggestions + messages.Add(currentResponseMessage!); + statefulMessageCount = chatOptions.ConversationId is not null ? messages.Count : 0; + currentResponseMessage = null; + chatSuggestions?.Update(messages); + } + + private void CancelAnyCurrentResponse() + { + // If a response was cancelled while streaming, include it in the conversation so it's not lost + if (currentResponseMessage is not null) + { + messages.Add(currentResponseMessage); + } + + currentResponseCancellation?.Cancel(); + currentResponseMessage = null; + } + + private async Task ResetConversationAsync() + { + CancelAnyCurrentResponse(); + messages.Clear(); + messages.Add(new(ChatRole.System, SystemPrompt)); + chatOptions.ConversationId = null; + statefulMessageCount = 0; + chatSuggestions?.Clear(); + await chatInput!.FocusAsync(); + } + + public void Dispose() + => currentResponseCancellation?.Cancel(); +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor.css new file mode 100644 index 0000000000..08841605f6 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/Chat.razor.css @@ -0,0 +1,11 @@ +.chat-container { + position: sticky; + bottom: 0; + padding-left: 1.5rem; + padding-right: 1.5rem; + padding-top: 0.75rem; + padding-bottom: 1.5rem; + border-top-width: 1px; + background-color: #F3F4F6; + border-color: #E5E7EB; +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor new file mode 100644 index 0000000000..ccb5853cec --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor @@ -0,0 +1,38 @@ +@using System.Web +@if (!string.IsNullOrWhiteSpace(viewerUrl)) +{ + + + + +
+
@File
+
@Quote
+
+
+} + +@code { + [Parameter] + public required string File { get; set; } + + [Parameter] + public int? PageNumber { get; set; } + + [Parameter] + public required string Quote { get; set; } + + private string? viewerUrl; + + protected override void OnParametersSet() + { + viewerUrl = null; + + // If you ingest other types of content besides PDF files, construct a URL to an appropriate viewer here + if (File.EndsWith(".pdf")) + { + var search = Quote?.Trim('.', ',', ' ', '\n', '\r', '\t', '"', '\''); + viewerUrl = $"lib/pdf_viewer/viewer.html?file=/Data/{HttpUtility.UrlEncode(File)}#page={PageNumber}&search={HttpUtility.UrlEncode(search)}&phrase=true"; + } + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor.css new file mode 100644 index 0000000000..763c82aec4 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatCitation.razor.css @@ -0,0 +1,37 @@ +.citation { + display: inline-flex; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + margin-top: 1rem; + margin-right: 1rem; + border-bottom: 2px solid #a770de; + gap: 0.5rem; + border-radius: 0.25rem; + font-size: 0.875rem; + line-height: 1.25rem; + background-color: #ffffff; +} + + .citation[href]:hover { + outline: 1px solid #865cb1; + } + + .citation svg { + width: 1.5rem; + height: 1.5rem; + } + + .citation:active { + background-color: rgba(0,0,0,0.05); + } + +.citation-content { + display: flex; + flex-direction: column; +} + +.citation-file { + font-weight: 600; +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor new file mode 100644 index 0000000000..a339038e2a --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor @@ -0,0 +1,17 @@ +
+
+ +
+ +

AGUI WebChat

+
+ +@code { + [Parameter] + public EventCallback OnNewChat { get; set; } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor.css new file mode 100644 index 0000000000..97f0a8d43a --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatHeader.razor.css @@ -0,0 +1,25 @@ +.chat-header-container { + top: 0; + padding: 1.5rem; +} + +.chat-header-controls { + margin-bottom: 1.5rem; +} + +h1 { + overflow: hidden; + text-overflow: ellipsis; +} + +.new-chat-icon { + width: 1.25rem; + height: 1.25rem; + color: rgb(55, 65, 81); +} + +@media (min-width: 768px) { + .chat-header-container { + position: sticky; + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor new file mode 100644 index 0000000000..e87ac6ccf4 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor @@ -0,0 +1,51 @@ +@inject IJSRuntime JS + + + + + +@code { + private ElementReference textArea; + private string? messageText; + + [Parameter] + public EventCallback OnSend { get; set; } + + public ValueTask FocusAsync() + => textArea.FocusAsync(); + + private async Task SendMessageAsync() + { + if (messageText is { Length: > 0 } text) + { + messageText = null; + await OnSend.InvokeAsync(new ChatMessage(ChatRole.User, text)); + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + try + { + var module = await JS.InvokeAsync("import", "./Components/Pages/Chat/ChatInput.razor.js"); + await module.InvokeVoidAsync("init", textArea); + await module.DisposeAsync(); + } + catch (JSDisconnectedException) + { + } + } + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.css new file mode 100644 index 0000000000..375dd711d9 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.css @@ -0,0 +1,57 @@ +.input-box { + display: flex; + flex-direction: column; + background: white; + border: 1px solid rgb(229, 231, 235); + border-radius: 8px; + padding: 0.5rem 0.75rem; + margin-top: 0.75rem; +} + + .input-box:focus-within { + outline: 2px solid #4152d5; + } + +textarea { + resize: none; + border: none; + outline: none; + flex-grow: 1; +} + + textarea:placeholder-shown + .tools { + --send-button-color: #aaa; + } + +.tools { + display: flex; + margin-top: 1rem; + align-items: center; +} + +.tool-icon { + width: 1.25rem; + height: 1.25rem; +} + +.send-button { + color: var(--send-button-color); + margin-left: auto; +} + + .send-button:hover { + color: black; + } + +.attach { + background-color: white; + border-style: dashed; + color: #888; + border-color: #888; + padding: 3px 8px; +} + + .attach:hover { + background-color: #f0f0f0; + color: black; + } diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.js b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.js new file mode 100644 index 0000000000..e4bd8af20a --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatInput.razor.js @@ -0,0 +1,43 @@ +export function init(elem) { + elem.focus(); + + // Auto-resize whenever the user types or if the value is set programmatically + elem.addEventListener('input', () => resizeToFit(elem)); + afterPropertyWritten(elem, 'value', () => resizeToFit(elem)); + + // Auto-submit the form on 'enter' keypress + elem.addEventListener('keydown', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + elem.dispatchEvent(new CustomEvent('change', { bubbles: true })); + elem.closest('form').dispatchEvent(new CustomEvent('submit', { bubbles: true, cancelable: true })); + } + }); +} + +function resizeToFit(elem) { + const lineHeight = parseFloat(getComputedStyle(elem).lineHeight); + + elem.rows = 1; + const numLines = Math.ceil(elem.scrollHeight / lineHeight); + elem.rows = Math.min(5, Math.max(1, numLines)); +} + +function afterPropertyWritten(target, propName, callback) { + const descriptor = getPropertyDescriptor(target, propName); + Object.defineProperty(target, propName, { + get: function () { + return descriptor.get.apply(this, arguments); + }, + set: function () { + const result = descriptor.set.apply(this, arguments); + callback(); + return result; + } + }); +} + +function getPropertyDescriptor(target, propertyName) { + return Object.getOwnPropertyDescriptor(target, propertyName) + || getPropertyDescriptor(Object.getPrototypeOf(target), propertyName); +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor new file mode 100644 index 0000000000..6f4e1357c9 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor @@ -0,0 +1,73 @@ +@using System.Runtime.CompilerServices +@using System.Text.RegularExpressions +@using System.Linq + +@if (Message.Role == ChatRole.User) +{ +
+ @Message.Text +
+} +else if (Message.Role == ChatRole.Assistant) +{ + foreach (var content in Message.Contents) + { + if (content is TextContent { Text: { Length: > 0 } text }) + { +
+
+
+ + + +
+
+
Assistant
+
+
@((MarkupString)text)
+
+
+ } + else if (content is FunctionCallContent { Name: "Search" } fcc && fcc.Arguments?.TryGetValue("searchPhrase", out var searchPhrase) is true) + { + + } + } +} + +@code { + private static readonly ConditionalWeakTable SubscribersLookup = new(); + + [Parameter, EditorRequired] + public required ChatMessage Message { get; set; } + + [Parameter] + public bool InProgress { get; set;} + + protected override void OnInitialized() + { + SubscribersLookup.AddOrUpdate(Message, this); + } + + public static void NotifyChanged(ChatMessage source) + { + if (SubscribersLookup.TryGetValue(source, out var subscriber)) + { + subscriber.StateHasChanged(); + } + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor.css new file mode 100644 index 0000000000..16443cf657 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageItem.razor.css @@ -0,0 +1,67 @@ +.user-message { + background: rgb(182 215 232); + align-self: flex-end; + min-width: 25%; + max-width: calc(100% - 5rem); + padding: 0.5rem 1.25rem; + border-radius: 0.25rem; + color: #1F2937; + white-space: pre-wrap; +} + +.assistant-message, .assistant-search { + display: grid; + grid-template-rows: min-content; + grid-template-columns: 2rem minmax(0, 1fr); + gap: 0.25rem; +} + +.assistant-message-header { + font-weight: 600; +} + +.assistant-message-text { + grid-column-start: 2; +} + +.assistant-message-icon { + display: flex; + justify-content: center; + align-items: center; + border-radius: 9999px; + width: 1.5rem; + height: 1.5rem; + color: #ffffff; + background: #9b72ce; +} + + .assistant-message-icon svg { + width: 1rem; + height: 1rem; + } + +.assistant-search { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.assistant-search-icon { + display: flex; + justify-content: center; + align-items: center; + width: 1.5rem; + height: 1.5rem; +} + + .assistant-search-icon svg { + width: 1rem; + height: 1rem; + } + +.assistant-search-content { + align-content: center; +} + +.assistant-search-phrase { + font-weight: 600; +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor new file mode 100644 index 0000000000..d245f455f1 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor @@ -0,0 +1,42 @@ +@inject IJSRuntime JS + +
+ + @foreach (var message in Messages) + { + + } + + @if (InProgressMessage is not null) + { + + + } + else if (IsEmpty) + { +
@NoMessagesContent
+ } +
+
+ +@code { + [Parameter] + public required IEnumerable Messages { get; set; } + + [Parameter] + public ChatMessage? InProgressMessage { get; set; } + + [Parameter] + public RenderFragment? NoMessagesContent { get; set; } + + private bool IsEmpty => !Messages.Any(m => (m.Role == ChatRole.User || m.Role == ChatRole.Assistant) && !string.IsNullOrEmpty(m.Text)); + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + // Activates the auto-scrolling behavior + await JS.InvokeVoidAsync("import", "./Components/Pages/Chat/ChatMessageList.razor.js"); + } + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.css new file mode 100644 index 0000000000..4be50ddfc3 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.css @@ -0,0 +1,22 @@ +.message-list-container { + margin: 2rem 1.5rem; + flex-grow: 1; +} + +.message-list { + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +.no-messages { + text-align: center; + font-size: 1.25rem; + color: #999; + margin-top: calc(40vh - 18rem); +} + +chat-messages > ::deep div:last-of-type { + /* Adds some vertical buffer to so that suggestions don't overlap the output when they appear */ + margin-bottom: 2rem; +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.js b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.js new file mode 100644 index 0000000000..9755d47c29 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatMessageList.razor.js @@ -0,0 +1,34 @@ +// The following logic provides auto-scroll behavior for the chat messages list. +// If you don't want that behavior, you can simply not load this module. + +window.customElements.define('chat-messages', class ChatMessages extends HTMLElement { + static _isFirstAutoScroll = true; + + connectedCallback() { + this._observer = new MutationObserver(mutations => this._scheduleAutoScroll(mutations)); + this._observer.observe(this, { childList: true, attributes: true }); + } + + disconnectedCallback() { + this._observer.disconnect(); + } + + _scheduleAutoScroll(mutations) { + // Debounce the calls in case multiple DOM updates occur together + cancelAnimationFrame(this._nextAutoScroll); + this._nextAutoScroll = requestAnimationFrame(() => { + const addedUserMessage = mutations.some(m => Array.from(m.addedNodes).some(n => n.parentElement === this && n.classList?.contains('user-message'))); + const elem = this.lastElementChild; + if (ChatMessages._isFirstAutoScroll || addedUserMessage || this._elemIsNearScrollBoundary(elem, 300)) { + elem.scrollIntoView({ behavior: ChatMessages._isFirstAutoScroll ? 'instant' : 'smooth' }); + ChatMessages._isFirstAutoScroll = false; + } + }); + } + + _elemIsNearScrollBoundary(elem, threshold) { + const maxScrollPos = document.body.scrollHeight - window.innerHeight; + const remainingScrollDistance = maxScrollPos - window.scrollY; + return remainingScrollDistance < elem.offsetHeight + threshold; + } +}); diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor new file mode 100644 index 0000000000..69ca922a8c --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor @@ -0,0 +1,78 @@ +@inject IChatClient ChatClient + +@if (suggestions is not null) +{ +
+ @foreach (var suggestion in suggestions) + { + + } +
+} + +@code { + private static string Prompt = @" + Suggest up to 3 follow-up questions that I could ask you to help me complete my task. + Each suggestion must be a complete sentence, maximum 6 words. + Each suggestion must be phrased as something that I (the user) would ask you (the assistant) in response to your previous message, + for example 'How do I do that?' or 'Explain ...'. + If there are no suggestions, reply with an empty list. + "; + + private string[]? suggestions; + private CancellationTokenSource? cancellation; + + [Parameter] + public EventCallback OnSelected { get; set; } + + public void Clear() + { + suggestions = null; + cancellation?.Cancel(); + } + + public void Update(IReadOnlyList messages) + { + // Runs in the background and handles its own cancellation/errors + _ = UpdateSuggestionsAsync(messages); + } + + private async Task UpdateSuggestionsAsync(IReadOnlyList messages) + { + cancellation?.Cancel(); + cancellation = new CancellationTokenSource(); + + try + { + var response = await ChatClient.GetResponseAsync( + [.. ReduceMessages(messages), new(ChatRole.User, Prompt)], + cancellationToken: cancellation.Token); + if (!response.TryGetResult(out suggestions)) + { + suggestions = null; + } + + StateHasChanged(); + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + await DispatchExceptionAsync(ex); + } + } + + private async Task AddSuggestionAsync(string text) + { + await OnSelected.InvokeAsync(new(ChatRole.User, text)); + } + + private IEnumerable ReduceMessages(IReadOnlyList messages) + { + // Get any leading system messages, plus up to 5 user/assistant messages + // This should be enough context to generate suggestions without unnecessarily resending entire conversations when long + var systemMessages = messages.TakeWhile(m => m.Role == ChatRole.System); + var otherMessages = messages.Where((m, index) => m.Role == ChatRole.User || m.Role == ChatRole.Assistant).Where(m => !string.IsNullOrEmpty(m.Text)).TakeLast(5); + return systemMessages.Concat(otherMessages); + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor.css new file mode 100644 index 0000000000..dcc7ee8bd8 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Pages/Chat/ChatSuggestions.razor.css @@ -0,0 +1,9 @@ +.suggestions { + text-align: right; + white-space: nowrap; + gap: 0.5rem; + justify-content: flex-end; + flex-wrap: wrap; + display: flex; + margin-bottom: 0.75rem; +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Routes.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Routes.razor new file mode 100644 index 0000000000..faa2a8c2d5 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/Routes.razor @@ -0,0 +1,6 @@ + + + + + + diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/_Imports.razor b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/_Imports.razor new file mode 100644 index 0000000000..82be3d448e --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Components/_Imports.razor @@ -0,0 +1,12 @@ +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using AGUIWebChatClient +@using AGUIWebChatClient.Components +@using AGUIWebChatClient.Components.Layout +@using Microsoft.Extensions.AI diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Program.cs b/dotnet/samples/_to_delete/AGUIWebChat/Client/Program.cs new file mode 100644 index 0000000000..c145227062 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Program.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. + +using AGUIWebChatClient.Components; +using Microsoft.Agents.AI.AGUI; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); + +string serverUrl = builder.Configuration["SERVER_URL"] ?? "http://localhost:5100"; + +builder.Services.AddHttpClient("aguiserver", httpClient => httpClient.BaseAddress = new Uri(serverUrl)); + +builder.Services.AddChatClient(sp => new AGUIChatClient( + sp.GetRequiredService().CreateClient("aguiserver"), "ag-ui")); + +WebApplication app = builder.Build(); + +// Configure the HTTP request pipeline. +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error", createScopeForErrors: true); + app.UseHsts(); +} + +app.UseHttpsRedirection(); +app.UseAntiforgery(); +app.MapStaticAssets(); +app.MapRazorComponents() + .AddInteractiveServerRenderMode(); + +app.Run(); diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/Properties/launchSettings.json b/dotnet/samples/_to_delete/AGUIWebChat/Client/Properties/launchSettings.json new file mode 100644 index 0000000000..348e16bc3b --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "SERVER_URL": "http://localhost:5100" + } + } + } +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/app.css b/dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/app.css new file mode 100644 index 0000000000..5fd82f3bb0 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/app.css @@ -0,0 +1,93 @@ +html { + min-height: 100vh; +} + +html, .main-background-gradient { + background: linear-gradient(to bottom, rgb(225 227 233), #f4f4f4 25rem); +} + +body { + display: flex; + flex-direction: column; + min-height: 100vh; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +html::after { + content: ''; + background-image: linear-gradient(to right, #3a4ed5, #3acfd5 15%, #d53abf 85%, red); + width: 100%; + height: 2px; + position: fixed; + top: 0; +} + +h1 { + font-size: 2.25rem; + line-height: 2.5rem; + font-weight: 600; +} + +h1:focus { + outline: none; +} + +.valid.modified:not([type=checkbox]) { + outline: 1px solid #26b050; +} + +.invalid { + outline: 1px solid #e50000; +} + +.validation-message { + color: #e50000; +} + +.blazor-error-boundary { + background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; + padding: 1rem 1rem 1rem 3.7rem; + color: white; +} + + .blazor-error-boundary::after { + content: "An error has occurred." + } + +.btn-default { + display: flex; + padding: 0.25rem 0.75rem; + gap: 0.25rem; + align-items: center; + border-radius: 0.25rem; + border: 1px solid #9CA3AF; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 600; + background-color: #D1D5DB; +} + + .btn-default:hover { + background-color: #E5E7EB; + } + +.btn-subtle { + display: flex; + padding: 0.25rem 0.75rem; + gap: 0.25rem; + align-items: center; + border-radius: 0.25rem; + border: 1px solid #D1D5DB; + font-size: 0.875rem; + line-height: 1.25rem; +} + + .btn-subtle:hover { + border-color: #93C5FD; + background-color: #DBEAFE; + } + +.page-width { + max-width: 1024px; + margin: auto; +} diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/favicon.png b/dotnet/samples/_to_delete/AGUIWebChat/Client/wwwroot/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8422b59695935d180d11d5dbe99653e711097819 GIT binary patch literal 1148 zcmV-?1cUpDP)9h26h2-Cs%i*@Moc3?#6qJID|D#|3|2Hn7gTIYEkr|%Xjp);YgvFmB&0#2E2b=| zkVr)lMv9=KqwN&%obTp-$<51T%rx*NCwceh-E+=&e(oLO`@Z~7gybJ#U|^tB2Pai} zRN@5%1qsZ1e@R(XC8n~)nU1S0QdzEYlWPdUpH{wJ2Pd4V8kI3BM=)sG^IkUXF2-j{ zrPTYA6sxpQ`Q1c6mtar~gG~#;lt=s^6_OccmRd>o{*=>)KS=lM zZ!)iG|8G0-9s3VLm`bsa6e ze*TlRxAjXtm^F8V`M1%s5d@tYS>&+_ga#xKGb|!oUBx3uc@mj1%=MaH4GR0tPBG_& z9OZE;->dO@`Q)nr<%dHAsEZRKl zedN6+3+uGHejJp;Q==pskSAcRcyh@6mjm2z-uG;s%dM-u0*u##7OxI7wwyCGpS?4U zBFAr(%GBv5j$jS@@t@iI8?ZqE36I^4t+P^J9D^ELbS5KMtZ z{Qn#JnSd$15nJ$ggkF%I4yUQC+BjDF^}AtB7w348EL>7#sAsLWs}ndp8^DsAcOIL9 zTOO!!0!k2`9BLk25)NeZp7ev>I1Mn={cWI3Yhx2Q#DnAo4IphoV~R^c0x&nw*MoIV zPthX?{6{u}sMS(MxD*dmd5rU(YazQE59b|TsB5Tm)I4a!VaN@HYOR)DwH1U5y(E)z zQqQU*B%MwtRQ$%x&;1p%ANmc|PkoFJZ%<-uq%PX&C!c-7ypis=eP+FCeuv+B@h#{4 zGx1m0PjS~FJt}3mdt4c!lel`1;4W|03kcZRG+DzkTy|7-F~eDsV2Tx!73dM0H0CTh zl)F-YUkE1zEzEW(;JXc|KR5{ox%YTh{$%F$a36JP6Nb<0%#NbSh$dMYF-{ z1_x(Vx)}fs?5_|!5xBTWiiIQHG<%)*e=45Fhjw_tlnmlixq;mUdC$R8v#j( zhQ$9YR-o%i5Uc`S?6EC51!bTRK=Xkyb<18FkCKnS2;o*qlij1YA@-nRpq#OMTX&RbL<^2q@0qja!uIvI;j$6>~k@IMwD42=8$$!+R^@5o6HX(*n~ httpClient.BaseAddress = new Uri(serverUrl)); + +builder.Services.AddChatClient(sp => new AGUIChatClient( + sp.GetRequiredService().CreateClient("aguiserver"), "ag-ui")); +``` + +The Blazor UI (`Client/Components/Pages/Chat/Chat.razor`) uses the `IChatClient` to: +- Send user messages to the agent +- Stream responses back in real-time +- Maintain conversation history +- Display messages with appropriate styling + +### UI Components + +The chat interface is built from several Blazor components: + +- **Chat.razor** - Main chat page coordinating the conversation flow +- **ChatHeader.razor** - Header with "New chat" button +- **ChatMessageList.razor** - Scrollable list of messages with auto-scroll +- **ChatMessageItem.razor** - Individual message rendering (user vs assistant) +- **ChatInput.razor** - Text input with auto-resize and keyboard shortcuts +- **ChatSuggestions.razor** - AI-generated follow-up question suggestions +- **LoadingSpinner.razor** - Animated loading indicator during streaming + +## Configuration + +### Server Configuration + +The server URL and port are configured in `Server/Properties/launchSettings.json`: + +```json +{ + "profiles": { + "http": { + "applicationUrl": "http://localhost:5100" + } + } +} +``` + +### Client Configuration + +The client connects to the server URL specified in `Client/Properties/launchSettings.json`: + +```json +{ + "profiles": { + "http": { + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "SERVER_URL": "http://localhost:5100" + } + } + } +} +``` + +To change the server URL, modify the `SERVER_URL` environment variable in the client's launch settings or provide it at runtime: + +```powershell +$env:SERVER_URL="http://your-server:5100" +dotnet run +``` + +## Customization + +### Changing the Agent Instructions + +Edit the instructions in `Server/Program.cs`: + +```csharp +ChatClientAgent agent = chatClient.AsIChatClient().AsAIAgent( + name: "ChatAssistant", + instructions: "You are a helpful coding assistant specializing in C# and .NET."); +``` + +### Styling the UI + +The chat interface uses CSS files colocated with each Razor component. Key styles: + +- `wwwroot/app.css` - Global styles, buttons, color scheme +- `Components/Pages/Chat/Chat.razor.css` - Chat container layout +- `Components/Pages/Chat/ChatMessageItem.razor.css` - Message bubbles and icons +- `Components/Pages/Chat/ChatInput.razor.css` - Input box styling + +### Disabling Suggestions + +To disable the AI-generated follow-up suggestions, comment out the suggestions component in `Chat.razor`: + +```razor +@* *@ +``` diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Server/AGUIWebChatServer.csproj b/dotnet/samples/_to_delete/AGUIWebChat/Server/AGUIWebChatServer.csproj new file mode 100644 index 0000000000..c45adfd4a8 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Server/AGUIWebChatServer.csproj @@ -0,0 +1,21 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Server/Program.cs b/dotnet/samples/_to_delete/AGUIWebChat/Server/Program.cs new file mode 100644 index 0000000000..eb5b259016 --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Server/Program.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates a basic AG-UI server hosting a chat agent for the Blazor web client. + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore; +using Microsoft.Extensions.AI; +using OpenAI.Chat; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); +builder.Services.AddHttpClient().AddLogging(); +builder.Services.AddAGUI(); + +WebApplication app = builder.Build(); + +string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set."); + +// Create the AI agent +AzureOpenAIClient azureOpenAIClient = new( + new Uri(endpoint), + new DefaultAzureCredential()); + +ChatClient chatClient = azureOpenAIClient.GetChatClient(deploymentName); + +ChatClientAgent agent = chatClient.AsIChatClient().AsAIAgent( + name: "ChatAssistant", + instructions: "You are a helpful assistant."); + +// Map the AG-UI agent endpoint +app.MapAGUI("/ag-ui", agent); + +await app.RunAsync(); diff --git a/dotnet/samples/_to_delete/AGUIWebChat/Server/Properties/launchSettings.json b/dotnet/samples/_to_delete/AGUIWebChat/Server/Properties/launchSettings.json new file mode 100644 index 0000000000..4d84174f7a --- /dev/null +++ b/dotnet/samples/_to_delete/AGUIWebChat/Server/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5100", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs new file mode 100644 index 0000000000..09e19a82f5 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/ActorFrameworkWebApplicationExtensions.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; +using Microsoft.Agents.AI; + +namespace AgentWebChat.AgentHost; + +internal static class ActorFrameworkWebApplicationExtensions +{ + public static void MapAgentDiscovery(this IEndpointRouteBuilder endpoints, [StringSyntax("Route")] string path) + { + var registeredAIAgents = endpoints.ServiceProvider.GetKeyedServices(KeyedService.AnyKey); + + var routeGroup = endpoints.MapGroup(path); + routeGroup.MapGet("/", async (CancellationToken cancellationToken) => + { + var results = new List(); + foreach (var result in registeredAIAgents) + { + results.Add(new AgentDiscoveryCard + { + Name = result.Name!, + Description = result.Description, + }); + } + + return Results.Ok(results); + }) + .WithName("GetAgents"); + } + + internal sealed class AgentDiscoveryCard + { + public required string Name { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Description { get; set; } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj new file mode 100644 index 0000000000..f71becf5d3 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/AgentWebChat.AgentHost.csproj @@ -0,0 +1,33 @@ + + + + net10.0 + enable + enable + true + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Custom/CustomAITools.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Custom/CustomAITools.cs new file mode 100644 index 0000000000..14f0bcee41 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Custom/CustomAITools.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Extensions.AI; + +namespace AgentWebChat.AgentHost.Custom; + +public class CustomAITool : AITool; + +public class CustomFunctionTool : AIFunction +{ + protected override ValueTask InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken) + { + return new ValueTask(arguments.Context?.Count ?? 0); + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Program.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Program.cs new file mode 100644 index 0000000000..e7262345d7 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Program.cs @@ -0,0 +1,181 @@ +// Copyright (c) Microsoft. All rights reserved. + +using A2A.AspNetCore; +using AgentWebChat.AgentHost; +using AgentWebChat.AgentHost.Custom; +using AgentWebChat.AgentHost.Utilities; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.DevUI; +using Microsoft.Agents.AI.Hosting; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; + +var builder = WebApplication.CreateBuilder(args); + +// Add service defaults & Aspire client integrations. +builder.AddServiceDefaults(); +builder.Services.AddOpenApi(); + +// Add services to the container. +builder.Services.AddProblemDetails(); + +// Configure the chat model and our agent. +builder.AddKeyedChatClient("chat-model"); + +// Add DevUI services +builder.AddDevUI(); + +// Add OpenAI services +builder.AddOpenAIChatCompletions(); +builder.AddOpenAIResponses(); + +var pirateAgentBuilder = builder.AddAIAgent( + "pirate", + instructions: "You are a pirate. Speak like a pirate", + description: "An agent that speaks like a pirate.", + chatClientServiceKey: "chat-model") + .WithAITool(new CustomAITool()) + .WithAITool(new CustomFunctionTool()) + .WithInMemorySessionStore(); + +var knightsKnavesAgentBuilder = builder.AddAIAgent("knights-and-knaves", (sp, key) => +{ + var chatClient = sp.GetRequiredKeyedService("chat-model"); + + ChatClientAgent knight = new( + chatClient, + """ + You are a knight. This means that you must always tell the truth. Your name is Alice. + Bob is standing next to you. Bob is a knave, which means he always lies. + When replying, always start with your name (Alice). Eg, "Alice: I am a knight." + """, "Alice"); + + ChatClientAgent knave = new( + chatClient, + """ + You are a knave. This means that you must always lie. Your name is Bob. + Alice is standing next to you. Alice is a knight, which means she always tells the truth. + When replying, always include your name (Bob). Eg, "Bob: I am a knight." + """, "Bob"); + + ChatClientAgent narrator = new( + chatClient, + """ + You are are the narrator of a puzzle involving knights (who always tell the truth) and knaves (who always lie). + The user is going to ask questions and guess whether Alice or Bob is the knight or knave. + Alice is standing to one side of you. Alice is a knight, which means she always tells the truth. + Bob is standing to the other side of you. Bob is a knave, which means he always lies. + When replying, always include your name (Narrator). + Once the user has deduced what type (knight or knave) both Alice and Bob are, tell them whether they are right or wrong. + If the user asks a general question about their surrounding, make something up which is consistent with the scenario. + """, "Narrator"); + + return AgentWorkflowBuilder.BuildConcurrent([knight, knave, narrator]).AsAgent(name: key); +}); + +// Workflow consisting of multiple specialized agents +var chemistryAgent = builder.AddAIAgent("chemist", + instructions: "You are a chemistry expert. Answer thinking from the chemistry perspective", + description: "An agent that helps with chemistry.", + chatClientServiceKey: "chat-model"); + +var mathsAgent = builder.AddAIAgent("mathematician", + instructions: "You are a mathematics expert. Answer thinking from the maths perspective", + description: "An agent that helps with mathematics.", + chatClientServiceKey: "chat-model"); + +var literatureAgent = builder.AddAIAgent("literator", + instructions: "You are a literature expert. Answer thinking from the literature perspective", + description: "An agent that helps with literature.", + chatClientServiceKey: "chat-model"); + +var scienceSequentialWorkflow = builder.AddWorkflow("science-sequential-workflow", (sp, key) => +{ + List usedAgents = [chemistryAgent, mathsAgent, literatureAgent]; + var agents = usedAgents.Select(ab => sp.GetRequiredKeyedService(ab.Name)); + return AgentWorkflowBuilder.BuildSequential(workflowName: key, agents: agents); +}).AddAsAIAgent(); + +var scienceConcurrentWorkflow = builder.AddWorkflow("science-concurrent-workflow", (sp, key) => +{ + List usedAgents = [chemistryAgent, mathsAgent, literatureAgent]; + var agents = usedAgents.Select(ab => sp.GetRequiredKeyedService(ab.Name)); + return AgentWorkflowBuilder.BuildConcurrent(workflowName: key, agents: agents); +}).AddAsAIAgent(); + +builder.AddWorkflow("nonAgentWorkflow", (sp, key) => +{ + List usedAgents = [pirateAgentBuilder, chemistryAgent]; + var agents = usedAgents.Select(ab => sp.GetRequiredKeyedService(ab.Name)); + return AgentWorkflowBuilder.BuildSequential(workflowName: key, agents: agents); +}); + +builder.Services.AddKeyedSingleton("NonAgentAndNonmatchingDINameWorkflow", (sp, key) => +{ + List usedAgents = [pirateAgentBuilder, chemistryAgent]; + var agents = usedAgents.Select(ab => sp.GetRequiredKeyedService(ab.Name)); + return AgentWorkflowBuilder.BuildSequential(workflowName: "random-name", agents: agents); +}); + +builder.Services.AddSingleton(sp => +{ + var chatClient = sp.GetRequiredKeyedService("chat-model"); + return new ChatClientAgent(chatClient, name: "default-agent", instructions: "you are a default agent."); +}); + +builder.Services.AddKeyedSingleton("my-di-nonmatching-agent", (sp, name) => +{ + var chatClient = sp.GetRequiredKeyedService("chat-model"); + return new ChatClientAgent( + chatClient, + name: "some-random-name", // demonstrating registration can be different for DI and actual agent + instructions: "you are a dependency inject agent. Tell me all about dependency injection."); +}); + +builder.Services.AddKeyedSingleton("my-di-matchingname-agent", (sp, name) => +{ + if (name is not string nameStr) + { + throw new NotSupportedException("Name should be passed as a key"); + } + + var chatClient = sp.GetRequiredKeyedService("chat-model"); + return new ChatClientAgent( + chatClient, + name: nameStr, // demonstrating registration with the same name + instructions: "you are a dependency inject agent. Tell me all about dependency injection."); +}); + +var app = builder.Build(); + +app.MapOpenApi(); +app.UseSwaggerUI(options => options.SwaggerEndpoint("/openapi/v1.json", "Agents API")); + +// Configure the HTTP request pipeline. +app.UseExceptionHandler(); + +// attach a2a with simple message communication +app.MapA2A(pirateAgentBuilder, path: "/a2a/pirate"); +app.MapA2A(knightsKnavesAgentBuilder, path: "/a2a/knights-and-knaves", agentCard: new() +{ + Name = "Knights and Knaves", + Description = "An agent that helps you solve the knights and knaves puzzle.", + Version = "1.0", + + // Url can be not set, and SDK will help assign it. + // Url = "http://localhost:5390/a2a/knights-and-knaves" +}); + +app.MapDevUI(); + +app.MapOpenAIResponses(); +app.MapOpenAIConversations(); + +app.MapOpenAIChatCompletions(pirateAgentBuilder); +app.MapOpenAIChatCompletions(knightsKnavesAgentBuilder); + +// Map the agents HTTP endpoints +app.MapAgentDiscovery("/agents"); + +app.MapDefaultEndpoints(); +app.Run(); diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Properties/launchSettings.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Properties/launchSettings.json new file mode 100644 index 0000000000..2ae820b4a7 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Properties/launchSettings.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5390", + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7373;http://localhost:5390", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs new file mode 100644 index 0000000000..ad1f30021f --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientConnectionInfo.cs @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Data.Common; +using System.Diagnostics.CodeAnalysis; + +namespace AgentWebChat.AgentHost.Utilities; + +public class ChatClientConnectionInfo +{ + public Uri? Endpoint { get; init; } + public required string SelectedModel { get; init; } + + public ClientChatProvider Provider { get; init; } + public string? AccessKey { get; init; } + + // Example connection string: + // Endpoint=https://localhost:4523;Model=phi3.5;AccessKey=1234;Provider=ollama; + public static bool TryParse(string? connectionString, [NotNullWhen(true)] out ChatClientConnectionInfo? settings) + { + if (string.IsNullOrEmpty(connectionString)) + { + settings = null; + return false; + } + + var connectionBuilder = new DbConnectionStringBuilder + { + ConnectionString = connectionString + }; + + Uri? endpoint = null; + if (connectionBuilder.ContainsKey("Endpoint") && Uri.TryCreate(connectionBuilder["Endpoint"].ToString(), UriKind.Absolute, out endpoint)) + { + } + + string? model = null; + if (connectionBuilder.ContainsKey("Model")) + { + model = (string)connectionBuilder["Model"]; + } + + string? accessKey = null; + if (connectionBuilder.ContainsKey("AccessKey")) + { + accessKey = (string)connectionBuilder["AccessKey"]; + } + + var provider = ClientChatProvider.Unknown; + if (connectionBuilder.ContainsKey("Provider")) + { + var providerValue = (string)connectionBuilder["Provider"]; + Enum.TryParse(providerValue, ignoreCase: true, out provider); + } + + if ((endpoint is null && provider != ClientChatProvider.OpenAI) || model is null || provider is ClientChatProvider.Unknown) + { + settings = null; + return false; + } + + settings = new ChatClientConnectionInfo + { + Endpoint = endpoint, + SelectedModel = model, + AccessKey = accessKey, + Provider = provider + }; + + return true; + } +} + +public enum ClientChatProvider +{ + Unknown, + Ollama, + OpenAI, + AzureOpenAI, + AzureAIInference, +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs new file mode 100644 index 0000000000..7b1f2d86b4 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/Utilities/ChatClientExtensions.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft. All rights reserved. + +using AgentWebChat.AgentHost.Utilities; +using Microsoft.Extensions.AI; +using OllamaSharp; + +namespace AgentWebChat.AgentHost.Utilities; + +public static class ChatClientExtensions +{ + public static ChatClientBuilder AddChatClient(this IHostApplicationBuilder builder, string connectionName) + { + var cs = builder.Configuration.GetConnectionString(connectionName); + + if (!ChatClientConnectionInfo.TryParse(cs, out var connectionInfo)) + { + throw new InvalidOperationException($"Invalid connection string: {cs}. Expected format: 'Endpoint=endpoint;AccessKey=your_access_key;Model=model_name;Provider=ollama/openai/azureopenai;'."); + } + + var chatClientBuilder = connectionInfo.Provider switch + { + ClientChatProvider.Ollama => builder.AddOllamaClient(connectionName, connectionInfo), + ClientChatProvider.OpenAI => builder.AddOpenAIClient(connectionName, connectionInfo), + ClientChatProvider.AzureOpenAI => builder.AddAzureOpenAIClient(connectionName).AddChatClient(connectionInfo.SelectedModel), + _ => throw new NotSupportedException($"Unsupported provider: {connectionInfo.Provider}") + }; + + // Add OpenTelemetry tracing for the ChatClient activity source + chatClientBuilder.UseOpenTelemetry().UseLogging(); + + builder.Services.AddOpenTelemetry().WithTracing(t => t.AddSource("Experimental.Microsoft.Extensions.AI")); + + return chatClientBuilder; + } + + private static ChatClientBuilder AddOpenAIClient(this IHostApplicationBuilder builder, string connectionName, ChatClientConnectionInfo connectionInfo) => + builder.AddOpenAIClient(connectionName, settings => + { + settings.Endpoint = connectionInfo.Endpoint; + settings.Key = connectionInfo.AccessKey; + }) + .AddChatClient(connectionInfo.SelectedModel); + + private static ChatClientBuilder AddOllamaClient(this IHostApplicationBuilder builder, string connectionName, ChatClientConnectionInfo connectionInfo) + { + var httpKey = $"{connectionName}_http"; + + builder.Services.AddHttpClient(httpKey, c => c.BaseAddress = connectionInfo.Endpoint); + + return builder.Services.AddChatClient(sp => + { + // Create a client for the Ollama API using the http client factory + var client = sp.GetRequiredService().CreateClient(httpKey); + + return new OllamaApiClient(client, connectionInfo.SelectedModel); + }); + } + + public static ChatClientBuilder AddKeyedChatClient(this IHostApplicationBuilder builder, string connectionName) + { + var cs = builder.Configuration.GetConnectionString(connectionName); + + if (!ChatClientConnectionInfo.TryParse(cs, out var connectionInfo)) + { + throw new InvalidOperationException($"Invalid connection string: {cs}. Expected format: 'Endpoint=endpoint;AccessKey=your_access_key;Model=model_name;Provider=ollama/openai/azureopenai;'."); + } + + var chatClientBuilder = connectionInfo.Provider switch + { + ClientChatProvider.Ollama => builder.AddKeyedOllamaClient(connectionName, connectionInfo), + ClientChatProvider.OpenAI => builder.AddKeyedOpenAIClient(connectionName, connectionInfo), + ClientChatProvider.AzureOpenAI => builder.AddKeyedAzureOpenAIClient(connectionName).AddKeyedChatClient(connectionName, connectionInfo.SelectedModel), + _ => throw new NotSupportedException($"Unsupported provider: {connectionInfo.Provider}") + }; + + // Add OpenTelemetry tracing for the ChatClient activity source + chatClientBuilder.UseOpenTelemetry().UseLogging(); + + builder.Services.AddOpenTelemetry().WithTracing(t => t.AddSource("Experimental.Microsoft.Extensions.AI")); + + return chatClientBuilder; + } + + private static ChatClientBuilder AddKeyedOpenAIClient(this IHostApplicationBuilder builder, string connectionName, ChatClientConnectionInfo connectionInfo) => + builder.AddKeyedOpenAIClient(connectionName, settings => + { + settings.Endpoint = connectionInfo.Endpoint; + settings.Key = connectionInfo.AccessKey; + }) + .AddKeyedChatClient(connectionName, connectionInfo.SelectedModel); + + private static ChatClientBuilder AddKeyedOllamaClient(this IHostApplicationBuilder builder, string connectionName, ChatClientConnectionInfo connectionInfo) + { + var httpKey = $"{connectionName}_http"; + + builder.Services.AddHttpClient(httpKey, c => c.BaseAddress = connectionInfo.Endpoint); + + return builder.Services.AddKeyedChatClient(connectionName, sp => + { + // Create a client for the Ollama API using the http client factory + var client = sp.GetRequiredService().CreateClient(httpKey); + + return new OllamaApiClient(client, connectionInfo.SelectedModel); + }); + } +} diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.Development.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/appsettings.Development.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.Development.json rename to dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/appsettings.Development.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/appsettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.json rename to dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AgentHost/appsettings.json diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj new file mode 100644 index 0000000000..de87c119ec --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/AgentWebChat.AppHost.csproj @@ -0,0 +1,24 @@ + + + + + + Exe + net10.0 + enable + enable + true + 2969a84d-8ee6-4304-8737-6e469a315aa8 + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/ModelExtensions.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/ModelExtensions.cs new file mode 100644 index 0000000000..40237ef360 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/ModelExtensions.cs @@ -0,0 +1,266 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace AgentWebChat.AppHost; + +public static class ModelExtensions +{ + public static IResourceBuilder AddAIModel(this IDistributedApplicationBuilder builder, string name) + { + var model = new AIModel(name); + return builder.CreateResourceBuilder(model); + } + + public static IResourceBuilder RunAsOpenAI(this IResourceBuilder builder, string modelName, IResourceBuilder apiKey) + { + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + return builder.AsOpenAI(modelName, apiKey); + } + + return builder; + } + + public static IResourceBuilder PublishAsOpenAI(this IResourceBuilder builder, string modelName, IResourceBuilder apiKey) + { + if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode) + { + return builder.AsOpenAI(modelName, apiKey); + } + + return builder; + } + + public static IResourceBuilder RunAsAzureOpenAI(this IResourceBuilder builder, string modelName, Action>? configure) + { + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + return builder.AsAzureOpenAI(modelName, configure); + } + + return builder; + } + + public static IResourceBuilder PublishAsAzureOpenAI(this IResourceBuilder builder, string modelName, Action>? configure) + { + if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode) + { + return builder.AsAzureOpenAI(modelName, configure); + } + + return builder; + } + + public static IResourceBuilder AsAzureOpenAI(this IResourceBuilder builder, string modelName, Action>? configure) + { + builder.Reset(); + + var openAIModel = builder.ApplicationBuilder.AddAzureOpenAI(builder.Resource.Name); + + configure?.Invoke(openAIModel); + + builder.Resource.UnderlyingResource = openAIModel.Resource; + // Add the model name to the connection string + builder.Resource.ConnectionString = ReferenceExpression.Create($"{openAIModel.Resource.ConnectionStringExpression};Model={modelName}"); + builder.Resource.Provider = "AzureOpenAI"; + return builder; + } + + public static IResourceBuilder RunAsAzureAIInference(this IResourceBuilder builder, string modelName, IResourceBuilder endpoint, IResourceBuilder apiKey) + { + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + return builder.AsAzureAIInference(modelName, endpoint, apiKey); + } + + return builder; + } + + public static IResourceBuilder PublishAsAzureAIInference(this IResourceBuilder builder, string modelName, IResourceBuilder endpoint, IResourceBuilder apiKey) + { + if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode) + { + return builder.AsAzureAIInference(modelName, endpoint, apiKey); + } + + return builder; + } + + public static IResourceBuilder AsAzureAIInference(this IResourceBuilder builder, string modelName, IResourceBuilder endpoint, IResourceBuilder apiKey) + { + builder.Reset(); + + // See: https://github.com/dotnet/aspire/issues/7641 + var csb = new ReferenceExpressionBuilder(); + csb.Append($"Endpoint={endpoint.Resource};"); + csb.Append($"AccessKey={apiKey.Resource};"); + csb.Append($"Model={modelName}"); + var cs = csb.Build(); + + builder.ApplicationBuilder.AddResource(builder.Resource); + + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + var csTask = cs.GetValueAsync(default).AsTask(); + if (!csTask.IsCompletedSuccessfully) + { + throw new InvalidOperationException("Connection string could not be resolved!"); + } + +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits + builder.WithInitialState(new CustomResourceSnapshot + { + ResourceType = "Azure AI Inference Model", + State = KnownResourceStates.Running, + Properties = [ + new("ConnectionString", csTask.Result ) { IsSensitive = true } + ] + }); +#pragma warning restore VSTHRD002 + } + + builder.Resource.UnderlyingResource = builder.Resource; + builder.Resource.ConnectionString = cs; + builder.Resource.Provider = "AzureAIInference"; + + return builder; + } + + public static IResourceBuilder RunAsAzureAIInference(this IResourceBuilder builder, string modelName, string endpoint, IResourceBuilder apiKey) + { + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + return builder.AsAzureAIInference(modelName, endpoint, apiKey); + } + + return builder; + } + + public static IResourceBuilder PublishAsAzureAIInference(this IResourceBuilder builder, string modelName, string endpoint, IResourceBuilder apiKey) + { + if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode) + { + return builder.AsAzureAIInference(modelName, endpoint, apiKey); + } + + return builder; + } + + public static IResourceBuilder AsAzureAIInference(this IResourceBuilder builder, string modelName, string endpoint, IResourceBuilder apiKey) + { + builder.Reset(); + + // See: https://github.com/dotnet/aspire/issues/7641 + var csb = new ReferenceExpressionBuilder(); + csb.Append($"Endpoint={endpoint};"); + csb.Append($"AccessKey={apiKey.Resource};"); + csb.Append($"Model={modelName}"); + var cs = csb.Build(); + + builder.ApplicationBuilder.AddResource(builder.Resource); + + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + var csTask = cs.GetValueAsync(default).AsTask(); + if (!csTask.IsCompletedSuccessfully) + { + throw new InvalidOperationException("Connection string could not be resolved!"); + } + +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits + builder.WithInitialState(new CustomResourceSnapshot + { + ResourceType = "Azure AI Inference Model", + State = KnownResourceStates.Running, + Properties = [ + new("ConnectionString", csTask.Result ) { IsSensitive = true } + ] + }); +#pragma warning restore VSTHRD002 + } + + builder.Resource.UnderlyingResource = builder.Resource; + builder.Resource.ConnectionString = cs; + builder.Resource.Provider = "AzureAIInference"; + + return builder; + } + + public static IResourceBuilder AsOpenAI(this IResourceBuilder builder, string modelName, IResourceBuilder apiKey) + { + builder.Reset(); + + // See: https://github.com/dotnet/aspire/issues/7641 + var csb = new ReferenceExpressionBuilder(); + csb.Append($"AccessKey={apiKey.Resource};"); + csb.Append($"Model={modelName}"); + var cs = csb.Build(); + + builder.ApplicationBuilder.AddResource(builder.Resource); + + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + var csTask = cs.GetValueAsync(default).AsTask(); + if (!csTask.IsCompletedSuccessfully) + { + throw new InvalidOperationException("Connection string could not be resolved!"); + } + +#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits + builder.WithInitialState(new CustomResourceSnapshot + { + ResourceType = "OpenAI Model", + State = KnownResourceStates.Running, + Properties = [ + new("ConnectionString", csTask.Result ) { IsSensitive = true } + ] + }); +#pragma warning restore VSTHRD002 + } + + builder.Resource.UnderlyingResource = builder.Resource; + builder.Resource.ConnectionString = cs; + builder.Resource.Provider = "OpenAI"; + + return builder; + } + + private static void Reset(this IResourceBuilder builder) + { + // Reset the properties of the AIModel resource + if (builder.Resource.UnderlyingResource is { } underlyingResource) + { + builder.ApplicationBuilder.Resources.Remove(underlyingResource); + + if (underlyingResource is IResourceWithParent resourceWithParent) + { + builder.ApplicationBuilder.Resources.Remove(resourceWithParent.Parent); + } + } + + builder.Resource.ConnectionString = null; + builder.Resource.Provider = null; + } +} + +// A resource representing an AI model. +public class AIModel(string name) : Resource(name), IResourceWithConnectionString +{ + internal string? Provider { get; set; } + internal IResourceWithConnectionString? UnderlyingResource { get; set; } + internal ReferenceExpression? ConnectionString { get; set; } + + public ReferenceExpression ConnectionStringExpression => + this.Build(); + + public ReferenceExpression Build() + { + var connectionString = this.ConnectionString ?? throw new InvalidOperationException("No connection string available."); + + if (this.Provider is null) + { + throw new InvalidOperationException("No provider configured."); + } + + return ReferenceExpression.Create($"{connectionString};Provider={this.Provider}"); + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Program.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Program.cs new file mode 100644 index 0000000000..328e3f5e83 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Program.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft. All rights reserved. + +using AgentWebChat.AppHost; + +var builder = DistributedApplication.CreateBuilder(args); + +var azOpenAiResource = builder.AddParameterFromConfiguration("AzureOpenAIName", "AzureOpenAI:Name"); +var azOpenAiResourceGroup = builder.AddParameterFromConfiguration("AzureOpenAIResourceGroup", "AzureOpenAI:ResourceGroup"); +var chatModel = builder.AddAIModel("chat-model").AsAzureOpenAI("gpt-4o", o => o.AsExisting(azOpenAiResource, azOpenAiResourceGroup)); + +var agentHost = builder.AddProject("agenthost") + .WithHttpEndpoint(name: "devui") + .WithUrlForEndpoint("devui", (url) => new() { Url = "/devui", DisplayText = "Dev UI" }) + .WithReference(chatModel); + +builder.AddProject("webfrontend") + .WithExternalHttpEndpoints() + .WithReference(agentHost) + .WaitFor(agentHost); + +builder.Build().Run(); diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Properties/launchSettings.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Properties/launchSettings.json new file mode 100644 index 0000000000..78978e33cc --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17277;http://localhost:15143", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21000", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22278" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15143", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19242", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20010" + } + } + } +} diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.Development.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/appsettings.Development.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.Development.json rename to dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/appsettings.Development.json diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/appsettings.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/appsettings.json new file mode 100644 index 0000000000..31c092aa45 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj new file mode 100644 index 0000000000..0c5573beac --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/AgentWebChat.ServiceDefaults.csproj @@ -0,0 +1,22 @@ + + + + net10.0 + enable + enable + true + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs new file mode 100644 index 0000000000..00af0166c8 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.ServiceDefaults/ServiceDefaultsExtensions.cs @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace Microsoft.Extensions.Hosting; + +// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// This project should be referenced by each service project in your solution. +// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults +public static class ServiceDefaultsExtensions +{ + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Logging.SetMinimumLevel(LogLevel.Trace); + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + // Uncomment the following to restrict the allowed schemes for service discovery. + // builder.Services.Configure(options => + // { + // options.AllowedSchemes = ["https"]; + // }); + + return builder; + } + + public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + }) + .WithTracing(tracing => + { + tracing.AddSource(builder.Environment.ApplicationName) + .AddSource("*Microsoft.Agents.AI") + .AddSource("Microsoft.Agents.AI.Runtime.InProcess") + .AddSource("Microsoft.Agents.AI.Runtime.Abstractions.InMemoryActorStateStorage") + .AddAspNetCoreInstrumentation() + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + } + + return app; + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs new file mode 100644 index 0000000000..f790ec0daa --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/A2AAgentClient.cs @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Concurrent; +using System.Runtime.CompilerServices; +using System.Text.Json; +using A2A; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Hosting.A2A.Converters; +using Microsoft.Extensions.AI; + +namespace AgentWebChat.Web; + +internal sealed class A2AAgentClient : AgentClientBase +{ + private readonly ILogger _logger; + private readonly Uri _uri; + + // because A2A sdk does not provide a client which can handle multiple agents, we need a client per agent + // for this app the convention is "baseUri/" + private readonly ConcurrentDictionary _clients = []; + + public A2AAgentClient(ILogger logger, Uri baseUri) + { + this._logger = logger; + this._uri = baseUri; + } + + public override async IAsyncEnumerable RunStreamingAsync( + string agentName, + IList messages, + string? sessionId = null, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + this._logger.LogInformation("Running agent {AgentName} with {MessageCount} messages via A2A", agentName, messages.Count); + + var (a2aClient, _) = this.ResolveClient(agentName); + var contextId = sessionId ?? Guid.NewGuid().ToString("N"); + + // Convert and send messages via A2A without try-catch in yield method + var results = new List(); + + try + { + // Convert all messages to A2A parts and create a single message + var parts = messages.ToParts(); + var a2aMessage = new AgentMessage + { + MessageId = Guid.NewGuid().ToString("N"), + ContextId = contextId, + Role = MessageRole.User, + Parts = parts + }; + + var messageSendParams = new MessageSendParams { Message = a2aMessage }; + var a2aResponse = await a2aClient.SendMessageAsync(messageSendParams, cancellationToken); + + // Handle different response types + if (a2aResponse is AgentMessage message) + { + var responseMessage = message.ToChatMessage(); + if (responseMessage is { Contents.Count: > 0 }) + { + results.Add(new AgentResponseUpdate(responseMessage.Role, responseMessage.Contents) + { + MessageId = message.MessageId, + CreatedAt = DateTimeOffset.UtcNow + }); + } + } + else if (a2aResponse is AgentTask agentTask) + { + // Manually convert AgentTask artifacts to ChatMessages since the extension method is internal + if (agentTask.Artifacts is not null) + { + foreach (var artifact in agentTask.Artifacts) + { + List? aiContents = null; + + foreach (var part in artifact.Parts) + { + (aiContents ??= []).Add(part.ToAIContent()); + } + + if (aiContents is not null) + { + var additionalProperties = ConvertMetadataToAdditionalProperties(artifact.Metadata); + var chatMessage = new ChatMessage(ChatRole.Assistant, aiContents) + { + AdditionalProperties = additionalProperties, + RawRepresentation = artifact, + }; + + results.Add(new AgentResponseUpdate(chatMessage.Role, chatMessage.Contents) + { + MessageId = agentTask.Id, + CreatedAt = DateTimeOffset.UtcNow + }); + } + } + } + } + else + { + this._logger.LogWarning("Unsupported A2A response type: {ResponseType}", a2aResponse?.GetType().FullName ?? "null"); + } + } + catch (Exception ex) + { + this._logger.LogError(ex, "Error running agent {AgentName} via A2A", agentName); + + results.Add(new AgentResponseUpdate(ChatRole.Assistant, $"Error: {ex.Message}") + { + MessageId = Guid.NewGuid().ToString("N"), + CreatedAt = DateTimeOffset.UtcNow + }); + } + + // Yield the results + foreach (var result in results) + { + yield return result; + } + } + + public override async Task GetAgentCardAsync(string agentName, CancellationToken cancellationToken = default) + { + this._logger.LogInformation("Retrieving agent card for {Agent}", agentName); + + var (_, a2aCardResolver) = this.ResolveClient(agentName); + try + { + return await a2aCardResolver.GetAgentCardAsync(cancellationToken); + } + catch (Exception ex) + { + this._logger.LogError(ex, "Failed to get agent card for {AgentName}", agentName); + return null; + } + } + + private (A2AClient, A2ACardResolver) ResolveClient(string agentName) => + this._clients.GetOrAdd(agentName, name => + { + var uri = new Uri($"{this._uri}/{name}/"); + var a2aClient = new A2AClient(uri); + + // /v1/card is a default path for A2A agent card discovery + var a2aCardResolver = new A2ACardResolver(uri, agentCardPath: "/v1/card/"); + + this._logger.LogInformation("Built clients for agent {Agent} with baseUri {Uri}", name, uri); + return (a2aClient, a2aCardResolver); + }); + + private static AdditionalPropertiesDictionary? ConvertMetadataToAdditionalProperties(Dictionary? metadata) + { + if (metadata is not { Count: > 0 }) + { + return null; + } + + var additionalProperties = new AdditionalPropertiesDictionary(); + foreach (var kvp in metadata) + { + additionalProperties[kvp.Key] = kvp.Value; + } + return additionalProperties; + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentDiscoveryClient.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentDiscoveryClient.cs new file mode 100644 index 0000000000..bb45e25e92 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentDiscoveryClient.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace AgentWebChat.Web; + +public class AgentDiscoveryClient(HttpClient httpClient, ILogger logger) +{ + public async Task> GetAgentsAsync(CancellationToken cancellationToken = default) + { + var response = await httpClient.GetAsync(new Uri("/agents", UriKind.Relative), cancellationToken); + response.EnsureSuccessStatusCode(); + + var json = await response.Content.ReadAsStringAsync(cancellationToken); + var agents = JsonSerializer.Deserialize>(json) ?? []; + + logger.LogInformation("Retrieved {AgentCount} agents from the API", agents.Count); + return agents; + } + + public class AgentDiscoveryCard + { + [JsonPropertyName("name")] + public required string Name { get; set; } + + [JsonPropertyName("description")] + public string? Description { get; set; } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj new file mode 100644 index 0000000000..fd26f56191 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj @@ -0,0 +1,18 @@ + + + + net10.0 + enable + enable + $(NoWarn);CA1812 + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/App.razor b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/App.razor new file mode 100644 index 0000000000..4a544389d8 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/App.razor @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor new file mode 100644 index 0000000000..8c5e922ff1 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor @@ -0,0 +1,15 @@ +@inherits LayoutComponentBase + +
+
+
+ @Body +
+
+
+ +
+ An unhandled error has occurred. + Reload + 🗙 +
diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css new file mode 100644 index 0000000000..cc4ae8d91d --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Layout/MainLayout.razor.css @@ -0,0 +1,33 @@ +.page { + position: relative; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +main { + flex: 1; +} + +.content { + padding: 0; +} + +#blazor-error-ui { + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + display: none; + left: 0; + padding: 0.6rem 1.25rem 0.7rem 1.25rem; + position: fixed; + width: 100%; + z-index: 1000; +} + + #blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; + } \ No newline at end of file diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Error.razor b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Error.razor new file mode 100644 index 0000000000..5620ef383b --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Error.razor @@ -0,0 +1,35 @@ +@page "/Error" +@using System.Diagnostics + +Error + +

Error.

+

An error occurred while processing your request.

+ +@if (ShowRequestId) +{ +

+ Request ID: @requestId +

+} + +

Development Mode

+

+ Swapping to Development environment will display more detailed information about the error that occurred. +

+

+ The Development environment shouldn't be enabled for deployed applications. + It can result in displaying sensitive information from exceptions to end users. + For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development + and restarting the app. +

+ +@code{ + [CascadingParameter] + public HttpContext? HttpContext { get; set; } + + private string? requestId; + private bool ShowRequestId => !string.IsNullOrEmpty(requestId); + + protected override void OnInitialized() => requestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier; +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Home.razor b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Home.razor new file mode 100644 index 0000000000..5642aa0ff3 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Pages/Home.razor @@ -0,0 +1,1207 @@ +@page "/" +@attribute [StreamRendering(true)] +@inject AgentDiscoveryClient AgentClient +@inject IJSRuntime JSRuntime +@inject ILogger Logger +@inject A2AAgentClient A2AActorClient +@inject OpenAIResponsesAgentClient OpenAIResponsesAgentClient +@inject OpenAIChatCompletionsAgentClient OpenAIChatCompletionsAgentClient +@rendermode InteractiveServer +@using System.Text +@using System.Text.Json +@using Microsoft.Extensions.AI +@using Microsoft.Agents.AI.Hosting +@using A2A + +Agent Web Chat + +
+
+

+ + + + Agent Web Chat +

+

The best hypertext-based chat on the Web!

+
+ +
+ +
+ + @if (!string.IsNullOrEmpty(selectedAgentName) && currentConversation is null) + { + + } +
+
+ +
+ +
+ +
+ @switch (selectedProtocol) + { + case Protocol.OpenAIResponses: + ֎ OpenAI Responses + break; + case Protocol.OpenAIChatCompletions: + ֎ OpenAI ChatCompletions + break; + case Protocol.A2A: + default: + 🔗 A2A protocol supports long-running agentic processes + break; + } +
+
+
+ + @if (selectedProtocol == Protocol.A2A) + { +
+
+

+ + + + A2A Configuration +

+ Discover and configure agent cards +
+ + @if (isA2AExpanded) + { +
+
+ + + @if (!string.IsNullOrEmpty(selectedAgentName)) + { + for agent: @GetAgentDisplayName(selectedAgentName) + } + else + { + Please select an agent first + } +
+ + @if (discoveredAgentCardJson is not null) + { +
+

🔗 Discovered Agent Card

+
+
+
+ Agent Card JSON: +
+
@discoveredAgentCardJson
+
+
+
+ } + + @if (!string.IsNullOrEmpty(discoveryError)) + { +
+ + + + + + @discoveryError +
+ } +
+ } +
+ } + + @if (conversations.Any()) + { +
+
+ @foreach (var conv in conversations) + { +
+ @GetAgentIcon(conv.AgentName) + @GetAgentDisplayName(conv.AgentName) + +
+ } +
+
+ } + + @if (currentConversation is not null) + { +
+
+ @foreach (var message in currentConversation.Messages) + { +
+ @if (message.Role != ChatRole.User) + { +
@GetAgentIcon(currentConversation.AgentName)
+ } +
+
@message.Text
+
+ @(message.Role == ChatRole.User ? "You" : GetAgentDisplayName(currentConversation.AgentName)) +
+
+
+ } + + @if (isStreaming && currentStreamedMessage.Length > 0) + { +
+
@GetAgentIcon(currentConversation.AgentName)
+
+
+ @currentStreamedMessage + +
+
+
+ } +
+ +
+
+ + +
+
+
+ } +
+ + + +@code { + + private string currentMessage = ""; + private bool isStreaming = false; + private bool isLoadingAgents = true; + private string currentStreamedMessage = ""; + private string selectedAgentName = ""; + private List availableAgents = new(); + private List conversations = new(); + private Conversation? currentConversation; + + // protocol + private Protocol selectedProtocol; + + // a2a agent card + private bool isA2AExpanded = false; + private bool isDiscoveringCard = false; + private string? discoveredAgentCardJson = null; + private string? discoveryError = null; + + private enum Protocol + { + A2A, // Agent-to-Agent protocol + OpenAIResponses, + OpenAIChatCompletions + } + + private sealed class Conversation + { + public string SessionId { get; set; } = Guid.NewGuid().ToString("N"); + public string AgentName { get; set; } = ""; + public List Messages { get; set; } = new(); + } + + protected override async Task OnInitializedAsync() + { + Logger.LogDebug("Initializing Agent Chat component"); + + // Load agents + try + { + availableAgents = await AgentClient.GetAgentsAsync(); + Logger.LogInformation("Loaded {AgentCount} agents", availableAgents.Count); + Logger.LogInformation("Loaded Agents info: {AgentData}", JsonSerializer.Serialize(availableAgents, new JsonSerializerOptions() { WriteIndented = true })); + + // Default to first agent and start a conversation + if (availableAgents.Any()) + { + selectedAgentName = availableAgents.First().Name!; + StartNewConversation(); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Failed to load agents"); + } + finally + { + isLoadingAgents = false; + } + + // Conversations start fresh on page load + } + + private string GetAgentIcon(string agentName) => agentName?.ToLower() switch + { + "pirate" => "🏴‍☠️", + "knights-and-knaves" => "⚔️", + _ => "🤖" + }; + + private string GetAgentDisplayName(string agentName) => agentName?.ToLower() switch + { + "pirate" => "Pirate", + "knights-and-knaves" => "Knights & Knaves", + _ => agentName ?? "Agent" + }; + + private void ToggleA2AExpanded() => isA2AExpanded = !isA2AExpanded; + + private async Task DiscoverAgentCard() + { + if (string.IsNullOrEmpty(selectedAgentName) || isDiscoveringCard) + return; + + isDiscoveringCard = true; + discoveryError = null; + discoveredAgentCardJson = null; + StateHasChanged(); + + try + { + Logger.LogInformation("Discovering agent card for agent: {AgentName}", selectedAgentName); + var agentCard = await A2AActorClient.GetAgentCardAsync(selectedAgentName); + if (agentCard is not null) + { + discoveredAgentCardJson = JsonSerializer.Serialize(agentCard, new JsonSerializerOptions() { WriteIndented = true }); + Logger.LogInformation("Successfully discovered agent card for {AgentName}: {CardData}", selectedAgentName, discoveredAgentCardJson); + } + else + { + discoveryError = "No agent card found for this agent."; + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Failed to discover agent card for {AgentName}", selectedAgentName); + discoveryError = $"Failed to discover agent card: {ex.Message}"; + } + finally + { + isDiscoveringCard = false; + StateHasChanged(); + } + } + + private void StartNewConversation() + { + if (string.IsNullOrEmpty(selectedAgentName)) + return; + + var newConversation = new Conversation + { + AgentName = selectedAgentName + }; + + conversations.Add(newConversation); + currentConversation = newConversation; + + Logger.LogInformation("Started new conversation with agent: {AgentName}, session: {SessionId}", + newConversation.AgentName, newConversation.SessionId); + + StateHasChanged(); + } + + private void SelectConversation(string sessionId) + { + currentConversation = conversations.FirstOrDefault(c => c.SessionId == sessionId); + if (currentConversation is not null) + { + selectedAgentName = currentConversation.AgentName; + Logger.LogDebug("Selected conversation with session: {SessionId}", sessionId); + } + StateHasChanged(); + } + + private void CloseConversation(string sessionId) + { + var conversationToRemove = conversations.FirstOrDefault(c => c.SessionId == sessionId); + if (conversationToRemove is not null) + { + conversations.Remove(conversationToRemove); + + if (currentConversation?.SessionId == sessionId) + { + currentConversation = conversations.FirstOrDefault(); + if (currentConversation is not null) + { + selectedAgentName = currentConversation.AgentName; + } + } + + Logger.LogInformation("Closed conversation with session: {SessionId}", sessionId); + } + StateHasChanged(); + } + + private async Task SendMessage() + { + if (string.IsNullOrWhiteSpace(currentMessage) || isStreaming || currentConversation is null) + return; + + var userMessage = currentMessage.Trim(); + currentMessage = ""; + + Logger.LogInformation("User sending message: '{UserMessage}' to agent {AgentName} in session {SessionId}", + userMessage, currentConversation.AgentName, currentConversation.SessionId); + + // Add user message to chat + currentConversation.Messages.Add(new ChatMessage(ChatRole.User, userMessage)); + StateHasChanged(); + await ScrollToBottom(); + + // Start streaming response + isStreaming = true; + currentStreamedMessage = ""; + StateHasChanged(); + + StringBuilder responseContent = new(); + var hasReceivedContent = false; + + using var timeoutCts = new CancellationTokenSource( +#if DEBUG + TimeSpan.FromSeconds(120) +#else + TimeSpan.FromSeconds(20) +#endif + ); + + try + { + // Select the appropriate client based on protocol + AgentClientBase agentClient = selectedProtocol switch + { + Protocol.OpenAIResponses => OpenAIResponsesAgentClient, + Protocol.OpenAIChatCompletions => OpenAIChatCompletionsAgentClient, + Protocol.A2A or _ => A2AActorClient + }; + + var messages = new List { new(ChatRole.User, userMessage) }; + + await foreach (var update in agentClient.RunStreamingAsync( + currentConversation.AgentName, + messages, + currentConversation.SessionId, + cancellationToken: timeoutCts.Token)) + { + var content = update.Text ?? ""; + if (!string.IsNullOrEmpty(content)) + { + hasReceivedContent = true; + responseContent.Append(content); + currentStreamedMessage = responseContent.ToString(); + StateHasChanged(); + await ScrollToBottom(); + + Logger.LogDebug("Received streaming content: {ContentLength} characters", content.Length); + } + } + + Logger.LogInformation("Streaming completed for session {SessionId}, total content length: {ContentLength}", + currentConversation.SessionId, responseContent.Length); + + // Add the complete agent response to chat messages + if (responseContent.Length > 0) + { + currentConversation.Messages.Add(new ChatMessage(ChatRole.Assistant, responseContent.ToString())); + } + else if (!hasReceivedContent) + { + Logger.LogWarning("No content received during streaming for session {SessionId}", currentConversation.SessionId); + currentConversation.Messages.Add(new ChatMessage(ChatRole.Assistant, "No response received from the agent.")); + } + else + { + currentConversation.Messages.Add(new ChatMessage(ChatRole.Assistant, "Sorry, I couldn't generate a response.")); + } + } + catch (OperationCanceledException) when (isStreaming) + { + Logger.LogWarning("Streaming operation timed out for session {SessionId}", currentConversation.SessionId); + currentConversation.Messages.Add(new ChatMessage(ChatRole.Assistant, "Request timed out. Please try again.")); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error occurred while processing message in session {SessionId}: {ErrorMessage}", + currentConversation.SessionId, ex.Message); + currentConversation.Messages.Add(new ChatMessage(ChatRole.Assistant, $"Error: {ex.Message}")); + } + finally + { + isStreaming = false; + currentStreamedMessage = ""; + StateHasChanged(); + await ScrollToBottom(); + } + } + + private bool ShouldPreventDefault = false; + + private async Task HandleKeyPress(KeyboardEventArgs e) + { + if (e.Key == "Enter" && !e.ShiftKey) + { + ShouldPreventDefault = true; + await SendMessage(); + ShouldPreventDefault = false; + } + else if (e.Key == "Escape") + { + currentMessage = ""; // Clear input on Escape + ShouldPreventDefault = true; + StateHasChanged(); + ShouldPreventDefault = false; // Reset after clearing + } + else + { + ShouldPreventDefault = false; + } + } + + private async Task ScrollToBottom() + { + try + { + await JSRuntime.InvokeVoidAsync("scrollToBottom", "chat-messages"); + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Failed to scroll to bottom"); + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await JSRuntime.InvokeVoidAsync("eval", @" + window.scrollToBottom = function(elementId) { + const element = document.getElementById(elementId); + if (element) { + requestAnimationFrame(() => { + element.scrollTop = element.scrollHeight; + }); + } + }; + "); + } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Routes.razor b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Routes.razor new file mode 100644 index 0000000000..faa2a8c2d5 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/Routes.razor @@ -0,0 +1,6 @@ + + + + + + diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/_Imports.razor b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/_Imports.razor new file mode 100644 index 0000000000..b460c12a5c --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Components/_Imports.razor @@ -0,0 +1,11 @@ +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.AspNetCore.OutputCaching +@using Microsoft.JSInterop +@using AgentWebChat.Web +@using AgentWebChat.Web.Components diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/IAgentClient.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/IAgentClient.cs new file mode 100644 index 0000000000..4eda916d01 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/IAgentClient.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft. All rights reserved. + +using A2A; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +namespace AgentWebChat.Web; + +/// +/// Interface for clients that can interact with agents and provide streaming responses. +/// +internal abstract class AgentClientBase +{ + /// + /// Runs an agent with the specified messages and returns a streaming response. + /// + /// The name of the agent to run. + /// The messages to send to the agent. + /// Optional session identifier for conversation continuity. + /// Cancellation token. + /// An asynchronous enumerable of agent response updates. + public abstract IAsyncEnumerable RunStreamingAsync( + string agentName, + IList messages, + string? sessionId = null, + CancellationToken cancellationToken = default); + + /// + /// Gets the agent card for the specified agent (A2A protocol only). + /// + /// The name of the agent. + /// Cancellation token. + /// The agent card if supported, null otherwise. + public virtual Task GetAgentCardAsync(string agentName, CancellationToken cancellationToken = default) + => Task.FromResult(null); +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs new file mode 100644 index 0000000000..8939ca785a --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIChatCompletionsAgentClient.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Runtime.CompilerServices; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI; +using OpenAI.Chat; +using ChatMessage = Microsoft.Extensions.AI.ChatMessage; + +namespace AgentWebChat.Web; + +/// +/// Is a simple frontend client which exercises the ability of exposed agent to communicate via OpenAI ChatCompletions protocol. +/// +internal sealed class OpenAIChatCompletionsAgentClient(HttpClient httpClient) : AgentClientBase +{ + public override async IAsyncEnumerable RunStreamingAsync( + string agentName, + IList messages, + string? sessionId = null, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + OpenAIClientOptions options = new() + { + Endpoint = new Uri(httpClient.BaseAddress!, $"/{agentName}/v1/"), + Transport = new HttpClientPipelineTransport(httpClient) + }; + + var openAiClient = new ChatClient(model: "myModel!", credential: new ApiKeyCredential("dummy-key"), options: options).AsIChatClient(); + await foreach (var update in openAiClient.GetStreamingResponseAsync(messages, cancellationToken: cancellationToken)) + { + yield return new AgentResponseUpdate(update); + } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs new file mode 100644 index 0000000000..0d2470762e --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Runtime.CompilerServices; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI; +using OpenAI.Responses; + +namespace AgentWebChat.Web; + +/// +/// Is a simple frontend client which exercises the ability of exposed agent to communicate via OpenAI Responses protocol. +/// +internal sealed class OpenAIResponsesAgentClient(HttpClient httpClient) : AgentClientBase +{ + public override async IAsyncEnumerable RunStreamingAsync( + string agentName, + IList messages, + string? sessionId = null, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + OpenAIClientOptions options = new() + { + Endpoint = new Uri(httpClient.BaseAddress!, "/v1/"), + Transport = new HttpClientPipelineTransport(httpClient) + }; + + var openAiClient = new ResponsesClient(model: agentName, credential: new ApiKeyCredential("dummy-key"), options: options).AsIChatClient(); + var chatOptions = new ChatOptions() + { + ConversationId = sessionId + }; + + await foreach (var update in openAiClient.GetStreamingResponseAsync(messages, chatOptions, cancellationToken: cancellationToken)) + { + yield return new AgentResponseUpdate(update); + } + } +} diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Program.cs b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Program.cs new file mode 100644 index 0000000000..665aaa1bba --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Program.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft. All rights reserved. + +using AgentWebChat.Web; +using AgentWebChat.Web.Components; + +var builder = WebApplication.CreateBuilder(args); + +// Add service defaults & Aspire client integrations. +builder.AddServiceDefaults(); + +// Add services to the container. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); + +builder.Services.AddOutputCache(); + +// This URL uses "https+http://" to indicate HTTPS is preferred over HTTP. +// Learn more about service discovery scheme resolution at https://aka.ms/dotnet/sdschemes. +Uri baseAddress = new("https+http://agenthost"); + +// for some reason does not resolve with `apiservice` url +Uri a2aAddress = new("http://localhost:5390/a2a"); + +builder.Services.AddHttpClient(client => client.BaseAddress = baseAddress); +builder.Services.AddSingleton(sp => new A2AAgentClient(sp.GetRequiredService>(), a2aAddress)); + +builder.Services.AddHttpClient(client => client.BaseAddress = baseAddress); +builder.Services.AddHttpClient(client => client.BaseAddress = baseAddress); + +var app = builder.Build(); + +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error", createScopeForErrors: true); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseHttpsRedirection(); + +app.UseAntiforgery(); + +app.UseOutputCache(); + +app.MapStaticAssets(); + +app.MapRazorComponents() + .AddInteractiveServerRenderMode(); + +app.MapDefaultEndpoints(); + +app.Run(); diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Properties/launchSettings.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Properties/launchSettings.json new file mode 100644 index 0000000000..f0fb11469c --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5154", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7020;http://localhost:5154", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.Development.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/appsettings.Development.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.Development.json rename to dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/appsettings.Development.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.json b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/appsettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.json rename to dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/appsettings.json diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/app.css b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/app.css new file mode 100644 index 0000000000..6b032e3458 --- /dev/null +++ b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/app.css @@ -0,0 +1,16 @@ +html, body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + margin: 0; + padding: 0; + background-color: #f9fafb; +} + +.blazor-error-boundary { + background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; + padding: 1rem 1rem 1rem 3.7rem; + color: white; +} + +.blazor-error-boundary::after { + content: "An error has occurred." +} \ No newline at end of file diff --git a/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/favicon.png b/dotnet/samples/_to_delete/AgentWebChat/AgentWebChat.Web/wwwroot/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8422b59695935d180d11d5dbe99653e711097819 GIT binary patch literal 1148 zcmV-?1cUpDP)9h26h2-Cs%i*@Moc3?#6qJID|D#|3|2Hn7gTIYEkr|%Xjp);YgvFmB&0#2E2b=| zkVr)lMv9=KqwN&%obTp-$<51T%rx*NCwceh-E+=&e(oLO`@Z~7gybJ#U|^tB2Pai} zRN@5%1qsZ1e@R(XC8n~)nU1S0QdzEYlWPdUpH{wJ2Pd4V8kI3BM=)sG^IkUXF2-j{ zrPTYA6sxpQ`Q1c6mtar~gG~#;lt=s^6_OccmRd>o{*=>)KS=lM zZ!)iG|8G0-9s3VLm`bsa6e ze*TlRxAjXtm^F8V`M1%s5d@tYS>&+_ga#xKGb|!oUBx3uc@mj1%=MaH4GR0tPBG_& z9OZE;->dO@`Q)nr<%dHAsEZRKl zedN6+3+uGHejJp;Q==pskSAcRcyh@6mjm2z-uG;s%dM-u0*u##7OxI7wwyCGpS?4U zBFAr(%GBv5j$jS@@t@iI8?ZqE36I^4t+P^J9D^ELbS5KMtZ z{Qn#JnSd$15nJ$ggkF%I4yUQC+BjDF^}AtB7w348EL>7#sAsLWs}ndp8^DsAcOIL9 zTOO!!0!k2`9BLk25)NeZp7ev>I1Mn={cWI3Yhx2Q#DnAo4IphoV~R^c0x&nw*MoIV zPthX?{6{u}sMS(MxD*dmd5rU(YazQE59b|TsB5Tm)I4a!VaN@HYOR)DwH1U5y(E)z zQqQU*B%MwtRQ$%x&;1p%ANmc|PkoFJZ%<-uq%PX&C!c-7ypis=eP+FCeuv+B@h#{4 zGx1m0PjS~FJt}3mdt4c!lel`1;4W|03kcZRG+DzkTy|7-F~eDsV2Tx!73dM0H0CTh zl)F-YUkE1zEzEW(;JXc|KR5{ox%YTh{$%F$a36JP6Nb<0%#NbSh$dMYF-{ z1_x(Vx)}fs?5_|!5xBTWiiIQHG<%)*e=45Fhjw_tlnmlixq;mUdC$R8v#j( zhQ$9YR-o%i5Uc`S?6EC51!bTRK=Xkyb<18FkCKnS2;o*qlij1YA@-nRpq#OMTX&RbL<^2q@0qja!uIvI;j$6>~k@IMwD42=8$$!+R^@5o6HX(*n~ + + net10.0 + v4 + Exe + enable + enable + + SingleAgent + SingleAgent + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/Program.cs new file mode 100644 index 0000000000..e629f3ee2c --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/Program.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft. All rights reserved. + +#pragma warning disable IDE0002 // Simplify Member Access + +using Azure; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Hosting.AzureFunctions; +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.Hosting; +using OpenAI.Chat; + +// Get the Azure OpenAI endpoint and deployment name from environment variables. +string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") + ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT is not set."); + +// Use Azure Key Credential if provided, otherwise use Azure CLI Credential. +string? azureOpenAiKey = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY"); +AzureOpenAIClient client = !string.IsNullOrEmpty(azureOpenAiKey) + ? new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(azureOpenAiKey)) + : new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()); + +// Set up an AI agent following the standard Microsoft Agent Framework pattern. +const string JokerName = "Joker"; +const string JokerInstructions = "You are good at telling jokes."; + +AIAgent agent = client.GetChatClient(deploymentName).AsAIAgent(JokerInstructions, JokerName); + +// Configure the function app to host the AI agent. +// This will automatically generate HTTP API endpoints for the agent. +using IHost app = FunctionsApplication + .CreateBuilder(args) + .ConfigureFunctionsWebApplication() + .ConfigureDurableAgents(options => options.AddAIAgent(agent, timeToLive: TimeSpan.FromHours(1))) + .Build(); +app.Run(); diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/README.md new file mode 100644 index 0000000000..d4ac968978 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/README.md @@ -0,0 +1,89 @@ +# Single Agent Sample + +This sample demonstrates how to use the Durable Agent Framework (DAFx) to create a simple Azure Functions app that hosts a single AI agent and provides direct HTTP API access for interactive conversations. + +## Key Concepts Demonstrated + +- Using the Microsoft Agent Framework to define a simple AI agent with a name and instructions. +- Registering agents with the Function app and running them using HTTP. +- Conversation management (via session IDs) for isolated interactions. + +## Environment Setup + +See the [README.md](../README.md) file in the parent directory for more information on how to configure the environment, including how to install and run common sample dependencies. + +## Running the Sample + +With the environment setup and function app running, you can test the sample by sending an HTTP request to the agent endpoint. + +You can use the `demo.http` file to send a message to the agent, or a command line tool like `curl` as shown below: + +Bash (Linux/macOS/WSL): + +```bash +curl -X POST http://localhost:7071/api/agents/Joker/run \ + -H "Content-Type: text/plain" \ + -d "Tell me a joke about a pirate." +``` + +PowerShell: + +```powershell +Invoke-RestMethod -Method Post ` + -Uri http://localhost:7071/api/agents/Joker/run ` + -ContentType text/plain ` + -Body "Tell me a joke about a pirate." +``` + +You can also send JSON requests: + +```bash +curl -X POST http://localhost:7071/api/agents/Joker/run \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d '{"message": "Tell me a joke about a pirate."}' +``` + +To continue a conversation, include the `thread_id` in the query string or JSON body: + +```bash +curl -X POST "http://localhost:7071/api/agents/Joker/run?thread_id=your-thread-id" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d '{"message": "Tell me another one."}' +``` + +The response from the agent will be displayed in the terminal where you ran `func start`. The expected `text/plain` output will look something like: + +```text +Why don't pirates ever learn the alphabet? Because they always get stuck at "C"! +``` + +The expected `application/json` output will look something like: + +```json +{ + "status": 200, + "thread_id": "ee6e47a0-f24b-40b1-ade8-16fcebb9eb40", + "response": { + "Messages": [ + { + "AuthorName": "Joker", + "CreatedAt": "2025-11-11T12:00:00.0000000Z", + "Role": "assistant", + "Contents": [ + { + "Type": "text", + "Text": "Why don't pirates ever learn the alphabet? Because they always get stuck at 'C'!" + } + ] + } + ], + "Usage": { + "InputTokenCount": 78, + "OutputTokenCount": 36, + "TotalTokenCount": 114 + } + } +} +``` diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/demo.http b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/demo.http new file mode 100644 index 0000000000..3b741adf31 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/demo.http @@ -0,0 +1,8 @@ +# Default endpoint address for local testing +@authority=http://localhost:7071 + +### Prompt the agent +POST {{authority}}/api/agents/Joker/run +Content-Type: text/plain + +Tell me a joke about a pirate. diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/host.json rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/01_SingleAgent/host.json diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj new file mode 100644 index 0000000000..83032dcfd0 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj @@ -0,0 +1,42 @@ + + + net10.0 + v4 + Exe + enable + enable + + AgentOrchestration_Chaining + AgentOrchestration_Chaining + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/FunctionTriggers.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/FunctionTriggers.cs new file mode 100644 index 0000000000..7f67b8a6df --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/FunctionTriggers.cs @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net; +using System.Text.Json; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.DurableTask; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.DurableTask; +using Microsoft.DurableTask.Client; + +namespace AgentOrchestration_Chaining; + +public static class FunctionTriggers +{ + public sealed record TextResponse(string Text); + + [Function(nameof(RunOrchestrationAsync))] + public static async Task RunOrchestrationAsync([OrchestrationTrigger] TaskOrchestrationContext context) + { + DurableAIAgent writer = context.GetAgent("WriterAgent"); + AgentSession writerSession = await writer.CreateSessionAsync(); + + AgentResponse initial = await writer.RunAsync( + message: "Write a concise inspirational sentence about learning.", + session: writerSession); + + AgentResponse refined = await writer.RunAsync( + message: $"Improve this further while keeping it under 25 words: {initial.Result.Text}", + session: writerSession); + + return refined.Result.Text; + } + + // POST /singleagent/run + [Function(nameof(StartOrchestrationAsync))] + public static async Task StartOrchestrationAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "singleagent/run")] HttpRequestData req, + [DurableClient] DurableTaskClient client) + { + string instanceId = await client.ScheduleNewOrchestrationInstanceAsync( + orchestratorName: nameof(RunOrchestrationAsync)); + + HttpResponseData response = req.CreateResponse(HttpStatusCode.Accepted); + await response.WriteAsJsonAsync(new + { + message = "Single-agent orchestration started.", + instanceId, + statusQueryGetUri = GetStatusQueryGetUri(req, instanceId), + }); + return response; + } + + // GET /singleagent/status/{instanceId} + [Function(nameof(GetOrchestrationStatusAsync))] + public static async Task GetOrchestrationStatusAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "singleagent/status/{instanceId}")] HttpRequestData req, + string instanceId, + [DurableClient] DurableTaskClient client) + { + OrchestrationMetadata? status = await client.GetInstanceAsync( + instanceId, + getInputsAndOutputs: true, + req.FunctionContext.CancellationToken); + + if (status is null) + { + HttpResponseData notFound = req.CreateResponse(HttpStatusCode.NotFound); + await notFound.WriteAsJsonAsync(new { error = "Instance not found" }); + return notFound; + } + + HttpResponseData response = req.CreateResponse(HttpStatusCode.OK); + await response.WriteAsJsonAsync(new + { + instanceId = status.InstanceId, + runtimeStatus = status.RuntimeStatus.ToString(), + input = status.SerializedInput is not null ? (object)status.ReadInputAs() : null, + output = status.SerializedOutput is not null ? (object)status.ReadOutputAs() : null, + failureDetails = status.FailureDetails + }); + return response; + } + + private static string GetStatusQueryGetUri(HttpRequestData req, string instanceId) + { + // NOTE: This can be made more robust by considering the value of + // request headers like "X-Forwarded-Host" and "X-Forwarded-Proto". + string authority = $"{req.Url.Scheme}://{req.Url.Authority}"; + return $"{authority}/api/singleagent/status/{instanceId}"; + } +} diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/Program.cs new file mode 100644 index 0000000000..7ab6a23477 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/Program.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft. All rights reserved. + +#pragma warning disable IDE0002 // Simplify Member Access + +using Azure; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Hosting.AzureFunctions; +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.Hosting; +using OpenAI.Chat; + +// Get the Azure OpenAI endpoint and deployment name from environment variables. +string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") + ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT is not set."); + +// Use Azure Key Credential if provided, otherwise use Azure CLI Credential. +string? azureOpenAiKey = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY"); +AzureOpenAIClient client = !string.IsNullOrEmpty(azureOpenAiKey) + ? new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(azureOpenAiKey)) + : new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()); + +// Single agent used by the orchestration to demonstrate sequential calls on the same session. +const string WriterName = "WriterAgent"; +const string WriterInstructions = + """ + You refine short pieces of text. When given an initial sentence you enhance it; + when given an improved sentence you polish it further. + """; + +AIAgent writerAgent = client.GetChatClient(deploymentName).AsAIAgent(WriterInstructions, WriterName); + +using IHost app = FunctionsApplication + .CreateBuilder(args) + .ConfigureFunctionsWebApplication() + .ConfigureDurableAgents(options => options.AddAIAgent(writerAgent)) + .Build(); + +app.Run(); diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/README.md new file mode 100644 index 0000000000..8fb86a4f52 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/README.md @@ -0,0 +1,59 @@ +# Single Agent Orchestration Sample + +This sample demonstrates how to use the Durable Agent Framework (DAFx) to create a simple Azure Functions app that orchestrates sequential calls to a single AI agent using the same session for context continuity. + +## Key Concepts Demonstrated + +- Orchestrating multiple interactions with the same agent in a deterministic order +- Using the same `AgentSession` across multiple calls to maintain conversational context +- Durable orchestration with automatic checkpointing and resumption from failures +- HTTP API integration for starting and monitoring orchestrations + +## Environment Setup + +See the [README.md](../README.md) file in the parent directory for more information on how to configure the environment, including how to install and run common sample dependencies. + +## Running the Sample + +With the environment setup and function app running, you can test the sample by sending an HTTP request to start the orchestration. + +You can use the `demo.http` file to start the orchestration, or a command line tool like `curl` as shown below: + +Bash (Linux/macOS/WSL): + +```bash +curl -X POST http://localhost:7071/api/singleagent/run +``` + +PowerShell: + +```powershell +Invoke-RestMethod -Method Post -Uri http://localhost:7071/api/singleagent/run +``` + +The response will be a JSON object that looks something like the following, which indicates that the orchestration has started. + +```json +{ + "message": "Single-agent orchestration started.", + "instanceId": "86313f1d45fb42eeb50b1852626bf3ff", + "statusQueryGetUri": "http://localhost:7071/api/singleagent/status/86313f1d45fb42eeb50b1852626bf3ff" +} +``` + +The orchestration will proceed to run the WriterAgent twice in sequence: + +1. First, it writes an inspirational sentence about learning +2. Then, it refines the initial output using the same conversation thread + +Once the orchestration has completed, you can get the status of the orchestration by sending a GET request to the `statusQueryGetUri` URL. The response will be a JSON object that looks something like the following: + +```json +{ + "failureDetails": null, + "input": null, + "instanceId": "86313f1d45fb42eeb50b1852626bf3ff", + "output": "Learning serves as the key, opening doors to boundless opportunities and a brighter future.", + "runtimeStatus": "Completed" +} +``` diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/demo.http b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/demo.http new file mode 100644 index 0000000000..aa4dcc4a16 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/demo.http @@ -0,0 +1,3 @@ +### Start the single-agent orchestration +POST http://localhost:7071/api/singleagent/run + diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/host.json rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/02_AgentOrchestration_Chaining/host.json diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/FunctionTriggers.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/FunctionTriggers.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/FunctionTriggers.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/FunctionTriggers.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/demo.http b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/demo.http similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/demo.http rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/demo.http diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/host.json rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/03_AgentOrchestration_Concurrency/host.json diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/FunctionTriggers.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/FunctionTriggers.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/FunctionTriggers.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/FunctionTriggers.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Models.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/demo.http b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/demo.http similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/demo.http rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/demo.http diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/host.json rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/04_AgentOrchestration_Conditionals/host.json diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/FunctionTriggers.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/FunctionTriggers.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/FunctionTriggers.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/FunctionTriggers.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Models.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/demo.http b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/demo.http similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/demo.http rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/demo.http diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/host.json new file mode 100644 index 0000000000..9384a0a583 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/05_AgentOrchestration_HITL/host.json @@ -0,0 +1,20 @@ +{ + "version": "2.0", + "logging": { + "logLevel": { + "Microsoft.Agents.AI.DurableTask": "Information", + "Microsoft.Agents.AI.Hosting.AzureFunctions": "Information", + "DurableTask": "Information", + "Microsoft.DurableTask": "Information" + } + }, + "extensions": { + "durableTask": { + "hubName": "default", + "storageProvider": { + "type": "AzureManaged", + "connectionStringName": "DURABLE_TASK_SCHEDULER_CONNECTION_STRING" + } + } + } +} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/06_LongRunningTools.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/06_LongRunningTools.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/06_LongRunningTools.csproj rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/06_LongRunningTools.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/FunctionTriggers.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/FunctionTriggers.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/FunctionTriggers.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/FunctionTriggers.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/Models.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/Tools.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/Tools.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/Tools.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/Tools.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/demo.http b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/demo.http similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/06_LongRunningTools/demo.http rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/demo.http diff --git a/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/host.json new file mode 100644 index 0000000000..9384a0a583 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/06_LongRunningTools/host.json @@ -0,0 +1,20 @@ +{ + "version": "2.0", + "logging": { + "logLevel": { + "Microsoft.Agents.AI.DurableTask": "Information", + "Microsoft.Agents.AI.Hosting.AzureFunctions": "Information", + "DurableTask": "Information", + "Microsoft.DurableTask": "Information" + } + }, + "extensions": { + "durableTask": { + "hubName": "default", + "storageProvider": { + "type": "AzureManaged", + "connectionStringName": "DURABLE_TASK_SCHEDULER_CONNECTION_STRING" + } + } + } +} diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/07_AgentAsMcpTool.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/07_AgentAsMcpTool.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/07_AgentAsMcpTool.csproj rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/07_AgentAsMcpTool.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/host.json rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/07_AgentAsMcpTool/host.json diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/08_ReliableStreaming.csproj b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/08_ReliableStreaming.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/08_ReliableStreaming.csproj rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/08_ReliableStreaming.csproj diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/FunctionTriggers.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/FunctionTriggers.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/FunctionTriggers.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/FunctionTriggers.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/Program.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/README.md diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/RedisStreamResponseHandler.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/RedisStreamResponseHandler.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/RedisStreamResponseHandler.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/RedisStreamResponseHandler.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/Tools.cs b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/Tools.cs similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/Tools.cs rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/Tools.cs diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/host.json b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/host.json similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/08_ReliableStreaming/host.json rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/08_ReliableStreaming/host.json diff --git a/dotnet/samples/Durable/Agents/AzureFunctions/README.md b/dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/AzureFunctions/README.md rename to dotnet/samples/_to_delete/Durable/Agents/AzureFunctions/README.md diff --git a/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj new file mode 100644 index 0000000000..c75457546e --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/01_SingleAgent.csproj @@ -0,0 +1,30 @@ + + + net10.0 + Exe + enable + enable + SingleAgent + SingleAgent + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/Program.cs new file mode 100644 index 0000000000..188d29ea46 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/Program.cs @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Azure; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.DurableTask; +using Microsoft.DurableTask.Client.AzureManaged; +using Microsoft.DurableTask.Worker.AzureManaged; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using OpenAI.Chat; + +// Get the Azure OpenAI endpoint and deployment name from environment variables. +string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") + ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT is not set."); + +// Get DTS connection string from environment variable +string dtsConnectionString = Environment.GetEnvironmentVariable("DURABLE_TASK_SCHEDULER_CONNECTION_STRING") + ?? "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None"; + +// Use Azure Key Credential if provided, otherwise use Azure CLI Credential. +string? azureOpenAiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY"); +AzureOpenAIClient client = !string.IsNullOrEmpty(azureOpenAiKey) + ? new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(azureOpenAiKey)) + : new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()); + +// Set up an AI agent following the standard Microsoft Agent Framework pattern. +const string JokerName = "Joker"; +const string JokerInstructions = "You are good at telling jokes."; + +AIAgent agent = client.GetChatClient(deploymentName).AsAIAgent(JokerInstructions, JokerName); + +// Configure the console app to host the AI agent. +IHost host = Host.CreateDefaultBuilder(args) + .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning)) + .ConfigureServices(services => + { + services.ConfigureDurableAgents( + options => options.AddAIAgent(agent, timeToLive: TimeSpan.FromHours(1)), + workerBuilder: builder => builder.UseDurableTaskScheduler(dtsConnectionString), + clientBuilder: builder => builder.UseDurableTaskScheduler(dtsConnectionString)); + }) + .Build(); + +await host.StartAsync(); + +// Get the agent proxy from services +IServiceProvider services = host.Services; +AIAgent agentProxy = services.GetRequiredKeyedService(JokerName); + +// Console colors for better UX +Console.ForegroundColor = ConsoleColor.Cyan; +Console.WriteLine("=== Single Agent Console Sample ==="); +Console.ResetColor(); +Console.WriteLine("Enter a message for the Joker agent (or 'exit' to quit):"); +Console.WriteLine(); + +// Create a session for the conversation +AgentSession session = await agentProxy.CreateSessionAsync(); + +while (true) +{ + // Read input from stdin + Console.ForegroundColor = ConsoleColor.Yellow; + Console.Write("You: "); + Console.ResetColor(); + + string? input = Console.ReadLine(); + if (string.IsNullOrWhiteSpace(input) || input.Equals("exit", StringComparison.OrdinalIgnoreCase)) + { + break; + } + + // Run the agent + Console.ForegroundColor = ConsoleColor.Green; + Console.Write("Joker: "); + Console.ResetColor(); + + try + { + AgentResponse agentResponse = await agentProxy.RunAsync( + message: input, + session: session, + cancellationToken: CancellationToken.None); + + Console.WriteLine(agentResponse.Text); + Console.WriteLine(); + } + catch (Exception ex) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine($"Error: {ex.Message}"); + Console.ResetColor(); + Console.WriteLine(); + } +} + +await host.StopAsync(); diff --git a/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/README.md new file mode 100644 index 0000000000..7c921b0d87 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/01_SingleAgent/README.md @@ -0,0 +1,56 @@ +# Single Agent Sample + +This sample demonstrates how to use the durable agents extension to create a simple console app that hosts a single AI agent and provides interactive conversation via stdin/stdout. + +## Key Concepts Demonstrated + +- Using the Microsoft Agent Framework to define a simple AI agent with a name and instructions. +- Registering durable agents with the console app and running them interactively. +- Conversation management (via threads) for isolated interactions. + +## Environment Setup + +See the [README.md](../README.md) file in the parent directory for more information on how to configure the environment, including how to install and run common sample dependencies. + +## Running the Sample + +With the environment setup, you can run the sample: + +```bash +cd dotnet/samples/DurableAgents/ConsoleApps/01_SingleAgent +dotnet run --framework net10.0 +``` + +The app will prompt you for input. You can interact with the Joker agent: + +```text +=== Single Agent Console Sample === +Enter a message for the Joker agent (or 'exit' to quit): + +You: Tell me a joke about a pirate. +Joker: Why don't pirates ever learn the alphabet? Because they always get stuck at "C"! + +You: Now explain the joke. +Joker: The joke plays on the word "sea" (C), which pirates are famously associated with... + +You: exit +``` + +## Scriptable Usage + +You can also pipe input to the app for scriptable usage: + +```bash +echo "Tell me a joke about a pirate." | dotnet run +``` + +The app will read from stdin, process the input, and write the response to stdout. + +## Viewing Agent State + +You can view the state of the agent in the Durable Task Scheduler dashboard: + +1. Open your browser and navigate to `http://localhost:8082` +2. In the dashboard, you can view the state of the Joker agent, including its conversation history and current state + +The agent maintains conversation state across multiple interactions, and you can inspect this state in the dashboard to understand how the durable agents extension manages conversation context. diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/02_AgentOrchestration_Chaining.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Models.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/02_AgentOrchestration_Chaining/README.md diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/03_AgentOrchestration_Concurrency.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Models.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/03_AgentOrchestration_Concurrency/README.md diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/04_AgentOrchestration_Conditionals.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Models.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/04_AgentOrchestration_Conditionals/README.md diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/05_AgentOrchestration_HITL.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Models.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/05_AgentOrchestration_HITL/README.md diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/06_LongRunningTools.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/06_LongRunningTools.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/06_LongRunningTools.csproj rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/06_LongRunningTools.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/Models.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/Models.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/Models.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/Models.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/06_LongRunningTools/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/06_LongRunningTools/README.md diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/07_ReliableStreaming.csproj b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/07_ReliableStreaming.csproj similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/07_ReliableStreaming.csproj rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/07_ReliableStreaming.csproj diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/Program.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/Program.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/Program.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/Program.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/README.md diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/RedisStreamResponseHandler.cs b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/RedisStreamResponseHandler.cs similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/07_ReliableStreaming/RedisStreamResponseHandler.cs rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/07_ReliableStreaming/RedisStreamResponseHandler.cs diff --git a/dotnet/samples/Durable/Agents/ConsoleApps/README.md b/dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/README.md similarity index 100% rename from dotnet/samples/Durable/Agents/ConsoleApps/README.md rename to dotnet/samples/_to_delete/Durable/Agents/ConsoleApps/README.md diff --git a/dotnet/samples/_to_delete/Durable/Directory.Build.props b/dotnet/samples/_to_delete/Durable/Directory.Build.props new file mode 100644 index 0000000000..7c4cb7dea2 --- /dev/null +++ b/dotnet/samples/_to_delete/Durable/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dotnet/samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj b/dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj similarity index 100% rename from dotnet/samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj rename to dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_AsFunctionTools/A2AAgent_AsFunctionTools.csproj diff --git a/dotnet/samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/Program.cs b/dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_AsFunctionTools/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_AsFunctionTools/Program.cs diff --git a/dotnet/samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/README.md b/dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_AsFunctionTools/README.md similarity index 100% rename from dotnet/samples/GettingStarted/A2A/A2AAgent_AsFunctionTools/README.md rename to dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_AsFunctionTools/README.md diff --git a/dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj b/dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj similarity index 100% rename from dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj rename to dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj diff --git a/dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/Program.cs b/dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/Program.cs diff --git a/dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/README.md b/dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/README.md similarity index 100% rename from dotnet/samples/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/README.md rename to dotnet/samples/_to_delete/GettingStarted/A2A/A2AAgent_PollingForTaskCompletion/README.md diff --git a/dotnet/samples/GettingStarted/A2A/README.md b/dotnet/samples/_to_delete/GettingStarted/A2A/README.md similarity index 100% rename from dotnet/samples/GettingStarted/A2A/README.md rename to dotnet/samples/_to_delete/GettingStarted/A2A/README.md diff --git a/dotnet/samples/GettingStarted/AGUI/README.md b/dotnet/samples/_to_delete/GettingStarted/AGUI/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/README.md rename to dotnet/samples/_to_delete/GettingStarted/AGUI/README.md diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Client/Client.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Client/Client.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Client/Client.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Client/Client.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Client/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Client/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Client/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Client/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/Server.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/Server.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step01_GettingStarted/Server/Server.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/Server.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.Development.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.Development.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.Development.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.Development.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step01_GettingStarted/Server/appsettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Client/Client.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Client/Client.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Client/Client.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Client/Client.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Client/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Client/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Client/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Client/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/Server.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/Server.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step02_BackendTools/Server/Server.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/Server.csproj diff --git a/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.Development.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.Development.json new file mode 100644 index 0000000000..0c208ae918 --- /dev/null +++ b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step02_BackendTools/Server/appsettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Client/Client.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Client/Client.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Client/Client.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Client/Client.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Client/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Client/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Client/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Client/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/Server.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/Server.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step03_FrontendTools/Server/Server.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/Server.csproj diff --git a/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.Development.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.Development.json new file mode 100644 index 0000000000..0c208ae918 --- /dev/null +++ b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step03_FrontendTools/Server/appsettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Client/Client.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Client/Client.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Client/Client.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Client/Client.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Client/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Client/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Client/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Client/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/Server.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/Server.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/Server.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/Server.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.Development.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.Development.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.Development.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.Development.json diff --git a/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.json new file mode 100644 index 0000000000..10f68b8c8b --- /dev/null +++ b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step04_HumanInLoop/Server/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Client/Client.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Client/Client.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Client/Client.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Client/Client.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Client/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Client/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Client/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Client/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Client/StatefulAgent.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Client/StatefulAgent.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Client/StatefulAgent.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Client/StatefulAgent.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/Program.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/RecipeModels.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/RecipeModels.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/RecipeModels.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/RecipeModels.cs diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/Server.csproj b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/Server.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/Server.csproj rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/Server.csproj diff --git a/dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs similarity index 100% rename from dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs rename to dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs diff --git a/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.Development.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.Development.json new file mode 100644 index 0000000000..0c208ae918 --- /dev/null +++ b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.json b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.json new file mode 100644 index 0000000000..10f68b8c8b --- /dev/null +++ b/dotnet/samples/_to_delete/GettingStarted/AGUI/Step05_StateManagement/Server/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/dotnet/samples/GettingStarted/AgentOpenTelemetry/AgentOpenTelemetry.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/AgentOpenTelemetry.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentOpenTelemetry/AgentOpenTelemetry.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/AgentOpenTelemetry.csproj diff --git a/dotnet/samples/GettingStarted/AgentOpenTelemetry/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentOpenTelemetry/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentOpenTelemetry/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentOpenTelemetry/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/README.md diff --git a/dotnet/samples/GettingStarted/AgentOpenTelemetry/start-demo.ps1 b/dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/start-demo.ps1 similarity index 100% rename from dotnet/samples/GettingStarted/AgentOpenTelemetry/start-demo.ps1 rename to dotnet/samples/_to_delete/GettingStarted/AgentOpenTelemetry/start-demo.ps1 diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_A2A/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_A2A/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_A2A/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_A2A/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_A2A/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_A2A/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_A2A/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_A2A/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/Agent_With_Anthropic.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Anthropic/Agent_With_Anthropic.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/Agent_With_Anthropic.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Anthropic/Agent_With_Anthropic.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Anthropic/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Anthropic/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Anthropic/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_Anthropic/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Anthropic/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Agent_With_AzureAIAgentsPersistent.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Agent_With_AzureAIAgentsPersistent.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Agent_With_AzureAIAgentsPersistent.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Agent_With_AzureAIAgentsPersistent.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIAgentsPersistent/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Agent_With_AzureAIProject.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Agent_With_AzureAIProject.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Agent_With_AzureAIProject.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Agent_With_AzureAIProject.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIProject/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIProject/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureAIProject/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureAIProject/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Agent_With_GitHubCopilot.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Agent_With_GitHubCopilot.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Agent_With_GitHubCopilot.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Agent_With_GitHubCopilot.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GitHubCopilot/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Agent_With_GoogleGemini.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Agent_With_GoogleGemini.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Agent_With_GoogleGemini.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Agent_With_GoogleGemini.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GoogleGemini/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GoogleGemini/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_GoogleGemini/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_GoogleGemini/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_ONNX/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_ONNX/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Ollama/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_Ollama/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Agent_With_OpenAIAssistants.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Agent_With_OpenAIAssistants.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Agent_With_OpenAIAssistants.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Agent_With_OpenAIAssistants.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIAssistants/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/README.md diff --git a/dotnet/samples/GettingStarted/AgentProviders/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentProviders/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentProviders/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentProviders/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Agent_Anthropic_Step01_Running.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Agent_Anthropic_Step01_Running.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Agent_Anthropic_Step01_Running.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Agent_Anthropic_Step01_Running.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step01_Running/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Agent_Anthropic_Step02_Reasoning.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Agent_Anthropic_Step02_Reasoning.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Agent_Anthropic_Step02_Reasoning.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Agent_Anthropic_Step02_Reasoning.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step02_Reasoning/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithAnthropic/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithAnthropic/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithAnthropic/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/AgentWithMemory_Step02_MemoryUsingMem0.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/AgentWithMemory_Step02_MemoryUsingMem0.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/AgentWithMemory_Step02_MemoryUsingMem0.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/AgentWithMemory_Step02_MemoryUsingMem0.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step02_MemoryUsingMem0/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/AgentWithMemory_Step03_CustomMemory.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/AgentWithMemory_Step03_CustomMemory.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/AgentWithMemory_Step03_CustomMemory.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/AgentWithMemory_Step03_CustomMemory.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/AgentWithMemory_Step03_CustomMemory/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithMemory/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithMemory/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithMemory/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Agent_OpenAI_Step02_Reasoning.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Agent_OpenAI_Step02_Reasoning.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Agent_OpenAI_Step02_Reasoning.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Agent_OpenAI_Step02_Reasoning.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Agent_OpenAI_Step03_CreateFromChatClient.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Agent_OpenAI_Step03_CreateFromChatClient.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Agent_OpenAI_Step03_CreateFromChatClient.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Agent_OpenAI_Step03_CreateFromChatClient.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/OpenAIChatClientAgent.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/OpenAIChatClientAgent.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/OpenAIChatClientAgent.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/OpenAIChatClientAgent.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step03_CreateFromChatClient/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Agent_OpenAI_Step05_Conversation.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Agent_OpenAI_Step05_Conversation.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Agent_OpenAI_Step05_Conversation.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Agent_OpenAI_Step05_Conversation.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithOpenAI/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithOpenAI/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithOpenAI/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/AgentWithRAG_Step01_BasicTextRAG.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/AgentWithRAG_Step01_BasicTextRAG.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/AgentWithRAG_Step01_BasicTextRAG.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/AgentWithRAG_Step01_BasicTextRAG.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchDocument.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchDocument.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchDocument.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchDocument.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStore.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStore.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStore.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStore.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreOptions.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreOptions.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreOptions.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreOptions.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreUpsertOptions.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreUpsertOptions.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreUpsertOptions.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step01_BasicTextRAG/TextSearchStore/TextSearchStoreUpsertOptions.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/AgentWithRAG_Step02_CustomVectorStoreRAG.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/AgentWithRAG_Step02_CustomVectorStoreRAG.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/AgentWithRAG_Step02_CustomVectorStoreRAG.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/AgentWithRAG_Step02_CustomVectorStoreRAG.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step02_CustomVectorStoreRAG/README.md diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/contoso-outdoors-knowledge-base.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/contoso-outdoors-knowledge-base.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/contoso-outdoors-knowledge-base.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/contoso-outdoors-knowledge-base.md diff --git a/dotnet/samples/GettingStarted/AgentWithRAG/README.md b/dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/README.md similarity index 100% rename from dotnet/samples/GettingStarted/AgentWithRAG/README.md rename to dotnet/samples/_to_delete/GettingStarted/AgentWithRAG/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step01_Running/Agent_Step01_Running.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step01_Running/Agent_Step01_Running.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step01_Running/Agent_Step01_Running.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step01_Running/Agent_Step01_Running.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step01_Running/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step01_Running/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step01_Running/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step01_Running/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Agent_Step02_MultiturnConversation.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Agent_Step02_MultiturnConversation.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Agent_Step02_MultiturnConversation.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Agent_Step02_MultiturnConversation.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step02_MultiturnConversation/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step03_UsingFunctionTools/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step06_PersistedConversations/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step06_PersistedConversations/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step06_PersistedConversations/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step06_PersistedConversations/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Agent_Step07_3rdPartyChatHistoryStorage.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Agent_Step07_3rdPartyChatHistoryStorage.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Agent_Step07_3rdPartyChatHistoryStorage.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Agent_Step07_3rdPartyChatHistoryStorage.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step07_3rdPartyChatHistoryStorage/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step08_Observability/Agent_Step08_Observability.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step08_Observability/Agent_Step08_Observability.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step08_Observability/Agent_Step08_Observability.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step08_Observability/Agent_Step08_Observability.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step08_Observability/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step08_Observability/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step08_Observability/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step08_Observability/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step09_DependencyInjection/Agent_Step09_DependencyInjection.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step09_DependencyInjection/Agent_Step09_DependencyInjection.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step09_DependencyInjection/Agent_Step09_DependencyInjection.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step09_DependencyInjection/Agent_Step09_DependencyInjection.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step09_DependencyInjection/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step09_DependencyInjection/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step09_DependencyInjection/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step09_DependencyInjection/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/Agent_Step10_AsMcpTool.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step10_AsMcpTool/Agent_Step10_AsMcpTool.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/Agent_Step10_AsMcpTool.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step10_AsMcpTool/Agent_Step10_AsMcpTool.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step10_AsMcpTool/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step10_AsMcpTool/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step10_AsMcpTool/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step10_AsMcpTool/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step11_UsingImages/Agent_Step11_UsingImages.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step11_UsingImages/Agent_Step11_UsingImages.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step11_UsingImages/Agent_Step11_UsingImages.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step11_UsingImages/Agent_Step11_UsingImages.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step11_UsingImages/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step11_UsingImages/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step11_UsingImages/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step11_UsingImages/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step11_UsingImages/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step11_UsingImages/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step11_UsingImages/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step11_UsingImages/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Agent_Step12_AsFunctionTool.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Agent_Step12_AsFunctionTool.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Agent_Step12_AsFunctionTool.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Agent_Step12_AsFunctionTool.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step12_AsFunctionTool/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Agent_Step13_BackgroundResponsesWithToolsAndPersistence.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Agent_Step13_BackgroundResponsesWithToolsAndPersistence.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Agent_Step13_BackgroundResponsesWithToolsAndPersistence.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Agent_Step13_BackgroundResponsesWithToolsAndPersistence.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step13_BackgroundResponsesWithToolsAndPersistence/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware/Agent_Step14_Middleware.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step14_Middleware/Agent_Step14_Middleware.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware/Agent_Step14_Middleware.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step14_Middleware/Agent_Step14_Middleware.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step14_Middleware/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step14_Middleware/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step14_Middleware/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step14_Middleware/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Agent_Step15_Plugins.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step15_Plugins/Agent_Step15_Plugins.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Agent_Step15_Plugins.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step15_Plugins/Agent_Step15_Plugins.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step15_Plugins/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step17_BackgroundResponses/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step17_BackgroundResponses/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step18_DeepResearch/Agent_Step18_DeepResearch.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step18_DeepResearch/Agent_Step18_DeepResearch.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step18_DeepResearch/Agent_Step18_DeepResearch.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step18_DeepResearch/Agent_Step18_DeepResearch.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step18_DeepResearch/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step18_DeepResearch/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step18_DeepResearch/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step18_DeepResearch/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step18_DeepResearch/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step18_DeepResearch/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step18_DeepResearch/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step18_DeepResearch/README.md diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step19_Declarative/Agent_Step19_Declarative.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step19_Declarative/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step19_Declarative/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step19_Declarative/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step19_Declarative/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Agent_Step20_AdditionalAIContext.csproj b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Agent_Step20_AdditionalAIContext.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Agent_Step20_AdditionalAIContext.csproj rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Agent_Step20_AdditionalAIContext.csproj diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Agents/Agent_Step20_AdditionalAIContext/Program.cs diff --git a/dotnet/samples/GettingStarted/Agents/README.md b/dotnet/samples/_to_delete/GettingStarted/Agents/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Agents/README.md rename to dotnet/samples/_to_delete/GettingStarted/Agents/README.md diff --git a/dotnet/samples/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj b/dotnet/samples/_to_delete/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj similarity index 100% rename from dotnet/samples/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj rename to dotnet/samples/_to_delete/GettingStarted/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj diff --git a/dotnet/samples/GettingStarted/DeclarativeAgents/ChatClient/Program.cs b/dotnet/samples/_to_delete/GettingStarted/DeclarativeAgents/ChatClient/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/DeclarativeAgents/ChatClient/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/DeclarativeAgents/ChatClient/Program.cs diff --git a/dotnet/samples/GettingStarted/DeclarativeAgents/ChatClient/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/DeclarativeAgents/ChatClient/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/DeclarativeAgents/ChatClient/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/DeclarativeAgents/ChatClient/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj b/dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj similarity index 100% rename from dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj rename to dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj diff --git a/dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Program.cs b/dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Program.cs diff --git a/dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json b/dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json similarity index 100% rename from dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json rename to dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json diff --git a/dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/README.md b/dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/README.md similarity index 100% rename from dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/README.md rename to dotnet/samples/_to_delete/GettingStarted/DevUI/DevUI_Step01_BasicUsage/README.md diff --git a/dotnet/samples/GettingStarted/DevUI/README.md b/dotnet/samples/_to_delete/GettingStarted/DevUI/README.md similarity index 100% rename from dotnet/samples/GettingStarted/DevUI/README.md rename to dotnet/samples/_to_delete/GettingStarted/DevUI/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step01.2_Running/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step07_Observability/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step12_Middleware/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step13_Plugins/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/README.md b/dotnet/samples/_to_delete/GettingStarted/FoundryAgents/README.md similarity index 100% rename from dotnet/samples/GettingStarted/FoundryAgents/README.md rename to dotnet/samples/_to_delete/GettingStarted/FoundryAgents/README.md diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Program.cs b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server/Program.cs diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server/README.md b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server/README.md similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server/README.md rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server/README.md diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Agent_MCP_Server_Auth.csproj b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Agent_MCP_Server_Auth.csproj similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Agent_MCP_Server_Auth.csproj rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Agent_MCP_Server_Auth.csproj diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Program.cs b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/Program.cs diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/README.md b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/README.md similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/README.md rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/Agent_MCP_Server_Auth/README.md diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/FoundryAgent_Hosted_MCP.csproj b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/FoundryAgent_Hosted_MCP.csproj similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/FoundryAgent_Hosted_MCP.csproj rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/FoundryAgent_Hosted_MCP.csproj diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/README.md b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/README.md similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/README.md rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/FoundryAgent_Hosted_MCP/README.md diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/README.md b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/README.md similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/README.md rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/README.md diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/Program.cs b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/Program.cs diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/README.md b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/README.md similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/README.md rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/README.md diff --git a/dotnet/samples/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/ResponseAgent_Hosted_MCP.csproj b/dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/ResponseAgent_Hosted_MCP.csproj similarity index 100% rename from dotnet/samples/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/ResponseAgent_Hosted_MCP.csproj rename to dotnet/samples/_to_delete/GettingStarted/ModelContextProtocol/ResponseAgent_Hosted_MCP/ResponseAgent_Hosted_MCP.csproj diff --git a/dotnet/samples/GettingStarted/README.md b/dotnet/samples/_to_delete/GettingStarted/README.md similarity index 100% rename from dotnet/samples/GettingStarted/README.md rename to dotnet/samples/_to_delete/GettingStarted/README.md diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/CustomAgentExecutors.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/CustomAgentExecutors/CustomAgentExecutors.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/CustomAgentExecutors.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/CustomAgentExecutors/CustomAgentExecutors.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/CustomAgentExecutors/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/FoundryAgent.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/FoundryAgent/FoundryAgent.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/FoundryAgent.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/FoundryAgent/FoundryAgent.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/FoundryAgent/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/DeploymentGroupChatManager.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/DeploymentGroupChatManager.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/DeploymentGroupChatManager.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/DeploymentGroupChatManager.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/GroupChatToolApproval.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/GroupChatToolApproval.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/GroupChatToolApproval.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/GroupChatToolApproval.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/README.md b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/GroupChatToolApproval/README.md rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/GroupChatToolApproval/README.md diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowAsAnAgent.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowAsAnAgent.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowAsAnAgent.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowAsAnAgent.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Agents/WorkflowAsAnAgent/WorkflowFactory.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/CheckpointAndRehydrate.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/CheckpointAndRehydrate.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/CheckpointAndRehydrate.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/CheckpointAndRehydrate.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndRehydrate/WorkflowFactory.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/CheckpointAndResume.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/CheckpointAndResume.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/CheckpointAndResume.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/CheckpointAndResume.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointAndResume/WorkflowFactory.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/CheckpointWithHumanInTheLoop.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/CheckpointWithHumanInTheLoop.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/CheckpointWithHumanInTheLoop.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/CheckpointWithHumanInTheLoop.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Checkpoint/CheckpointWithHumanInTheLoop/WorkflowFactory.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Concurrent.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/Concurrent/Concurrent.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Concurrent.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/Concurrent/Concurrent.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/Concurrent/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/MapReduce.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/MapReduce/MapReduce.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/MapReduce.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/MapReduce/MapReduce.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Concurrent/MapReduce/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/01_EdgeCondition.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/01_EdgeCondition.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/01_EdgeCondition.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/01_EdgeCondition.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Resources.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Resources.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Resources.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/01_EdgeCondition/Resources.cs diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/02_SwitchCase.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/02_SwitchCase.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/02_SwitchCase.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/02_SwitchCase.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Resources.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Resources.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Resources.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/02_SwitchCase/Resources.cs diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/03_MultiSelection.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/03_MultiSelection.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/03_MultiSelection.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/03_MultiSelection.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Resources.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Resources.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Resources.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/ConditionalEdges/03_MultiSelection/Resources.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.yaml b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.yaml similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.yaml rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ConfirmInput/ConfirmInput.yaml diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ConfirmInput/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ConfirmInput/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ConfirmInput/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ConfirmInput/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/CustomerSupport/CustomerSupport.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/CustomerSupport/CustomerSupport.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/CustomerSupport/CustomerSupport.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/CustomerSupport/CustomerSupport.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/CustomerSupport/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/CustomerSupport/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/CustomerSupport/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/CustomerSupport/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/CustomerSupport/TicketingPlugin.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/CustomerSupport/TicketingPlugin.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/CustomerSupport/TicketingPlugin.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/CustomerSupport/TicketingPlugin.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/DeepResearch.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/DeepResearch/DeepResearch.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/DeepResearch.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/DeepResearch/DeepResearch.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/DeepResearch/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/wttr.json b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/DeepResearch/wttr.json similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/DeepResearch/wttr.json rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/DeepResearch/wttr.json diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/ExecuteCode.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteCode/ExecuteCode.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/ExecuteCode.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteCode/ExecuteCode.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteCode/Generated.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteCode/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/ExecuteWorkflow.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteWorkflow/ExecuteWorkflow.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/ExecuteWorkflow.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteWorkflow/ExecuteWorkflow.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ExecuteWorkflow/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.yaml b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.yaml similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.yaml rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/FunctionTools.yaml diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/MenuPlugin.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/MenuPlugin.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/MenuPlugin.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/MenuPlugin.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/FunctionTools/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/FunctionTools/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/GenerateCode/GenerateCode.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/GenerateCode/GenerateCode.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/GenerateCode/GenerateCode.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/GenerateCode/GenerateCode.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/GenerateCode/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/GenerateCode/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/GenerateCode/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/GenerateCode/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/HostedWorkflow/HostedWorkflow.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/HostedWorkflow/HostedWorkflow.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/HostedWorkflow/HostedWorkflow.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/HostedWorkflow/HostedWorkflow.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/HostedWorkflow/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/HostedWorkflow/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/HostedWorkflow/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/HostedWorkflow/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.yaml b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.yaml similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.yaml rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/InputArguments/InputArguments.yaml diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/InputArguments/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/InputArguments/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/InputArguments/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/InputArguments/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/Marketing/Marketing.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/Marketing/Marketing.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/Marketing/Marketing.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/Marketing/Marketing.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/Marketing/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/Marketing/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/Marketing/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/Marketing/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/README.md b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/README.md rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/README.md diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/StudentTeacher/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/StudentTeacher.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/StudentTeacher/StudentTeacher.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/StudentTeacher/StudentTeacher.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/StudentTeacher/StudentTeacher.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ToolApproval/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ToolApproval/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.yaml b/dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.yaml similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.yaml rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Declarative/ToolApproval/ToolApproval.yaml diff --git a/dotnet/samples/GettingStarted/Workflows/Directory.Build.props b/dotnet/samples/_to_delete/GettingStarted/Workflows/Directory.Build.props similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Directory.Build.props rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Directory.Build.props diff --git a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/HumanInTheLoopBasic.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/HumanInTheLoopBasic.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/HumanInTheLoopBasic.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/HumanInTheLoopBasic.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/WorkflowFactory.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Loop/Loop.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Loop/Loop.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Loop/Loop.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Loop/Loop.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Loop/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Loop/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Loop/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Loop/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/ApplicationInsights.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/ApplicationInsights/ApplicationInsights.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/ApplicationInsights.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/ApplicationInsights/ApplicationInsights.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/ApplicationInsights/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/AspireDashboard.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/AspireDashboard/AspireDashboard.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/AspireDashboard.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/AspireDashboard/AspireDashboard.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/AspireDashboard/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowAsAnAgentObservability.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowAsAnAgentObservability.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowAsAnAgentObservability.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowAsAnAgentObservability.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowHelper.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowHelper.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowHelper.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Observability/WorkflowAsAnAgent/WorkflowHelper.cs diff --git a/dotnet/samples/GettingStarted/Workflows/README.md b/dotnet/samples/_to_delete/GettingStarted/Workflows/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/README.md rename to dotnet/samples/_to_delete/GettingStarted/Workflows/README.md diff --git a/dotnet/samples/GettingStarted/Workflows/Resources/Lorem_Ipsum.txt b/dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/Lorem_Ipsum.txt similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Resources/Lorem_Ipsum.txt rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/Lorem_Ipsum.txt diff --git a/dotnet/samples/GettingStarted/Workflows/Resources/ambiguous_email.txt b/dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/ambiguous_email.txt similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Resources/ambiguous_email.txt rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/ambiguous_email.txt diff --git a/dotnet/samples/GettingStarted/Workflows/Resources/email.txt b/dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/email.txt similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Resources/email.txt rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/email.txt diff --git a/dotnet/samples/GettingStarted/Workflows/Resources/spam.txt b/dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/spam.txt similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Resources/spam.txt rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Resources/spam.txt diff --git a/dotnet/samples/GettingStarted/Workflows/SharedStates/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/SharedStates/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/SharedStates/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/SharedStates/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/SharedStates/Resources.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/SharedStates/Resources.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/SharedStates/Resources.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/SharedStates/Resources.cs diff --git a/dotnet/samples/GettingStarted/Workflows/SharedStates/SharedStates.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/SharedStates/SharedStates.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/SharedStates/SharedStates.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/SharedStates/SharedStates.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/Visualization/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Visualization/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/Visualization/README.md b/dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Visualization/README.md rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/README.md diff --git a/dotnet/samples/GettingStarted/Workflows/Visualization/Resources/graphviz_render.png b/dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Resources/graphviz_render.png similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Visualization/Resources/graphviz_render.png rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Resources/graphviz_render.png diff --git a/dotnet/samples/GettingStarted/Workflows/Visualization/Resources/mermaid_render.png b/dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Resources/mermaid_render.png similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Visualization/Resources/mermaid_render.png rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Resources/mermaid_render.png diff --git a/dotnet/samples/GettingStarted/Workflows/Visualization/Visualization.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Visualization.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/Visualization/Visualization.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/Visualization/Visualization.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/01_ExecutorsAndEdges.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/01_ExecutorsAndEdges.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/01_ExecutorsAndEdges.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/01_ExecutorsAndEdges.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/01_ExecutorsAndEdges/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/02_Streaming.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/02_Streaming/02_Streaming.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/02_Streaming.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/02_Streaming/02_Streaming.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/02_Streaming/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/03_AgentsInWorkflows.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/03_AgentsInWorkflows.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/03_AgentsInWorkflows.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/03_AgentsInWorkflows.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/03_AgentsInWorkflows/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/04_AgentWorkflowPatterns.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/04_AgentWorkflowPatterns.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/04_AgentWorkflowPatterns.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/04_AgentWorkflowPatterns.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/04_AgentWorkflowPatterns/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/05_MultiModelService.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/05_MultiModelService/05_MultiModelService.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/05_MultiModelService.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/05_MultiModelService/05_MultiModelService.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/05_MultiModelService/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/06_SubWorkflows/06_SubWorkflows.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/06_SubWorkflows/06_SubWorkflows.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/06_SubWorkflows/06_SubWorkflows.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/06_SubWorkflows/06_SubWorkflows.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/06_SubWorkflows/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/06_SubWorkflows/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/06_SubWorkflows/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/06_SubWorkflows/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/07_MixedWorkflowAgentsAndExecutors.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/07_MixedWorkflowAgentsAndExecutors.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/07_MixedWorkflowAgentsAndExecutors.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/07_MixedWorkflowAgentsAndExecutors.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/Program.cs diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/README.md b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/README.md similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/README.md rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/07_MixedWorkflowAgentsAndExecutors/README.md diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/08_WriterCriticWorkflow.csproj b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/08_WriterCriticWorkflow.csproj similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/08_WriterCriticWorkflow.csproj rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/08_WriterCriticWorkflow.csproj diff --git a/dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs b/dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs similarity index 100% rename from dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs rename to dotnet/samples/_to_delete/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj new file mode 100644 index 0000000000..1244b81542 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj @@ -0,0 +1,70 @@ + + + + Exe + net10.0 + + enable + enable + + + false + $(NoWarn);MEAI001;OPENAI001 + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Dockerfile b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Dockerfile new file mode 100644 index 0000000000..a2590fc112 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app -f net10.0 + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "AgentWithHostedMCP.dll"] diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Program.cs b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Program.cs new file mode 100644 index 0000000000..4dffdf92bd --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/Program.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows how to create and use a simple AI agent with OpenAI Responses as the backend, that uses a Hosted MCP Tool. +// In this case the OpenAI responses service will invoke any MCP tools as required. MCP tools are not invoked by the Agent Framework. +// The sample demonstrates how to use MCP tools with auto approval by setting ApprovalMode to NeverRequire. + +using Azure.AI.AgentServer.AgentFramework.Extensions; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI.Responses; + +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"; + +// Create an MCP tool that can be called without approval. +AITool mcpTool = new HostedMcpServerTool(serverName: "microsoft_learn", serverAddress: "https://learn.microsoft.com/api/mcp") +{ + AllowedTools = ["microsoft_docs_search"], + ApprovalMode = HostedMcpServerToolApprovalMode.NeverRequire +}; + +// Create an agent with the MCP tool using Azure OpenAI Responses. +AIAgent agent = new AzureOpenAIClient( + new Uri(endpoint), + new DefaultAzureCredential()) + .GetResponsesClient(deploymentName) + .CreateAIAgent( + instructions: "You answer questions by searching the Microsoft Learn content only.", + name: "MicrosoftLearnAgent", + tools: [mcpTool]); + +await agent.RunAIAgentAsync(); diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/README.md b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/README.md new file mode 100644 index 0000000000..a5648d7ac9 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/README.md @@ -0,0 +1,43 @@ +# What this sample demonstrates + +This sample demonstrates how to use a Hosted Model Context Protocol (MCP) server with an AI agent. +The agent connects to the Microsoft Learn MCP server to search documentation and answer questions using official Microsoft content. + +Key features: +- Configuring MCP tools with automatic approval (no user confirmation required) +- Filtering available tools from an MCP server +- Using Azure OpenAI Responses with MCP tools + +## Prerequisites + +Before running this sample, ensure you have: + +1. An Azure OpenAI endpoint configured +2. A deployment of a chat model (e.g., gpt-4o-mini) +3. Azure CLI installed and authenticated + +**Note**: This sample uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure OpenAI resource. + +## Environment Variables + +Set the following environment variables: + +```powershell +# Replace with your Azure OpenAI endpoint +$env:AZURE_OPENAI_ENDPOINT="https://your-openai-resource.openai.azure.com/" + +# Optional, defaults to gpt-4o-mini +$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" +``` + +## How It Works + +The sample connects to the Microsoft Learn MCP server and uses its documentation search capabilities: + +1. The agent is configured with a HostedMcpServerTool pointing to `https://learn.microsoft.com/api/mcp` +2. Only the `microsoft_docs_search` tool is enabled from the available MCP tools +3. Approval mode is set to `NeverRequire`, allowing automatic tool execution +4. When you ask questions, Azure OpenAI Responses automatically invokes the MCP tool to search documentation +5. The agent returns answers based on the Microsoft Learn content + +In this configuration, the OpenAI Responses service manages tool invocation directly - the Agent Framework does not handle MCP tool calls. diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/agent.yaml b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/agent.yaml new file mode 100644 index 0000000000..6444f1aad0 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/agent.yaml @@ -0,0 +1,31 @@ +name: AgentWithHostedMCP +displayName: "Microsoft Learn Response Agent with MCP" +description: > + An AI agent that uses Azure OpenAI Responses with a Hosted Model Context Protocol (MCP) server. + The agent answers questions by searching Microsoft Learn documentation using MCP tools. + This demonstrates how MCP tools can be integrated with Azure OpenAI Responses where the service + itself handles tool invocation. +metadata: + authors: + - Microsoft Agent Framework Team + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Model Context Protocol + - MCP + - Tool Call Approval +template: + kind: hosted + name: AgentWithHostedMCP + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: AZURE_OPENAI_ENDPOINT + value: ${AZURE_OPENAI_ENDPOINT} + - name: AZURE_OPENAI_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/run-requests.http b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/run-requests.http new file mode 100644 index 0000000000..cc26f43b90 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithHostedMCP/run-requests.http @@ -0,0 +1,30 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple string input - Ask about MCP Tools +POST {{endpoint}} +Content-Type: application/json +{ + "input": "Please summarize the Azure AI Agent documentation related to MCP Tool calling?" +} + +### Explicit input - Ask about Agent Framework +POST {{endpoint}} +Content-Type: application/json +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "What is the Microsoft Agent Framework?" + } + ] + } + ] +} diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj new file mode 100644 index 0000000000..03ffaf1824 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj @@ -0,0 +1,69 @@ + + + + Exe + net10.0 + + enable + enable + + + false + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Dockerfile b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Dockerfile new file mode 100644 index 0000000000..3d944c9883 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app -f net10.0 + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "AgentWithTextSearchRag.dll"] diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Program.cs b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Program.cs new file mode 100644 index 0000000000..b197ffeefc --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/Program.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows how to use TextSearchProvider to add retrieval augmented generation (RAG) +// capabilities to an AI agent. The provider runs a search against an external knowledge base +// before each model invocation and injects the results into the model context. + +using Azure.AI.AgentServer.AgentFramework.Extensions; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +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"; + +TextSearchProviderOptions textSearchOptions = new() +{ + // Run the search prior to every model invocation and keep a short rolling window of conversation context. + SearchTime = TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke, + RecentMessageMemoryLimit = 6, +}; + +AIAgent agent = new AzureOpenAIClient( + new Uri(endpoint), + new DefaultAzureCredential()) + .GetChatClient(deploymentName) + .CreateAIAgent(new ChatClientAgentOptions + { + ChatOptions = new ChatOptions + { + Instructions = "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available.", + }, + AIContextProviderFactory = ctx => new TextSearchProvider(MockSearchAsync, ctx.SerializedState, ctx.JsonSerializerOptions, textSearchOptions) + }); + +await agent.RunAIAgentAsync(); + +static Task> MockSearchAsync(string query, CancellationToken cancellationToken) +{ + // The mock search inspects the user's question and returns pre-defined snippets + // that resemble documents stored in an external knowledge source. + List results = []; + + if (query.Contains("return", StringComparison.OrdinalIgnoreCase) || query.Contains("refund", StringComparison.OrdinalIgnoreCase)) + { + results.Add(new() + { + SourceName = "Contoso Outdoors Return Policy", + SourceLink = "https://contoso.com/policies/returns", + Text = "Customers may return any item within 30 days of delivery. Items should be unused and include original packaging. Refunds are issued to the original payment method within 5 business days of inspection." + }); + } + + if (query.Contains("shipping", StringComparison.OrdinalIgnoreCase)) + { + results.Add(new() + { + SourceName = "Contoso Outdoors Shipping Guide", + SourceLink = "https://contoso.com/help/shipping", + Text = "Standard shipping is free on orders over $50 and typically arrives in 3-5 business days within the continental United States. Expedited options are available at checkout." + }); + } + + if (query.Contains("tent", StringComparison.OrdinalIgnoreCase) || query.Contains("fabric", StringComparison.OrdinalIgnoreCase)) + { + results.Add(new() + { + SourceName = "TrailRunner Tent Care Instructions", + SourceLink = "https://contoso.com/manuals/trailrunner-tent", + Text = "Clean the tent fabric with lukewarm water and a non-detergent soap. Allow it to air dry completely before storage and avoid prolonged UV exposure to extend the lifespan of the waterproof coating." + }); + } + + return Task.FromResult>(results); +} diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/README.md b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/README.md new file mode 100644 index 0000000000..614597bed9 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/README.md @@ -0,0 +1,41 @@ +# What this sample demonstrates + +This sample demonstrates how to use TextSearchProvider to add retrieval augmented generation (RAG) capabilities to an AI agent. The provider runs a search against an external knowledge base before each model invocation and injects the results into the model context. + +Key features: +- Configuring TextSearchProvider with custom search behavior +- Running searches before AI invocations to provide relevant context +- Managing conversation memory with a rolling window approach +- Citing source documents in AI responses + +## Prerequisites + +Before running this sample, ensure you have: + +1. An Azure OpenAI endpoint configured +2. A deployment of a chat model (e.g., gpt-4o-mini) +3. Azure CLI installed and authenticated + +## Environment Variables + +Set the following environment variables: + +```powershell +# Replace with your Azure OpenAI endpoint +$env:AZURE_OPENAI_ENDPOINT="https://your-openai-resource.openai.azure.com/" + +# Optional, defaults to gpt-4o-mini +$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" +``` + +## How It Works + +The sample uses a mock search function that demonstrates the RAG pattern: + +1. When the user asks a question, the TextSearchProvider intercepts it +2. The search function looks for relevant documents based on the query +3. Retrieved documents are injected into the model's context +4. The AI responds using both its training and the provided context +5. The agent can cite specific source documents in its answers + +The mock search function returns pre-defined snippets for demonstration purposes. In a production scenario, you would replace this with actual searches against your knowledge base (e.g., Azure AI Search, vector database, etc.). diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/agent.yaml b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/agent.yaml new file mode 100644 index 0000000000..1366071b17 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/agent.yaml @@ -0,0 +1,31 @@ +name: AgentWithTextSearchRag +displayName: "Text Search RAG Agent" +description: > + An AI agent that uses TextSearchProvider for retrieval augmented generation (RAG) capabilities. + The agent runs searches against an external knowledge base before each model invocation and + injects the results into the model context. It can answer questions about Contoso Outdoors + policies and products, including return policies, refunds, shipping options, and product care + instructions such as tent maintenance. +metadata: + authors: + - Microsoft Agent Framework Team + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Retrieval-Augmented Generation + - RAG +template: + kind: hosted + name: AgentWithTextSearchRag + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: AZURE_OPENAI_ENDPOINT + value: ${AZURE_OPENAI_ENDPOINT} + - name: AZURE_OPENAI_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/run-requests.http b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/run-requests.http new file mode 100644 index 0000000000..4bfb02d8f8 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentWithTextSearchRag/run-requests.http @@ -0,0 +1,30 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple string input +POST {{endpoint}} +Content-Type: application/json +{ + "input": "Hi! I need help understanding the return policy." +} + +### Explicit input +POST {{endpoint}} +Content-Type: application/json +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "How long does standard shipping usually take?" + } + ] + } + ] +} diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj new file mode 100644 index 0000000000..a434e07d33 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj @@ -0,0 +1,69 @@ + + + + Exe + net10.0 + + enable + enable + + + false + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Dockerfile b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Dockerfile new file mode 100644 index 0000000000..86b6c156f3 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app -f net10.0 + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "AgentsInWorkflows.dll"] diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Program.cs b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Program.cs new file mode 100644 index 0000000000..b1d8a922fd --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/Program.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates how to integrate AI agents into a workflow pipeline. +// Three translation agents are connected sequentially to create a translation chain: +// English → French → Spanish → English, showing how agents can be composed as workflow executors. + +using Azure.AI.AgentServer.AgentFramework.Extensions; +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; + +// Set up the Azure OpenAI client +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"; + +IChatClient chatClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()) + .GetChatClient(deploymentName) + .AsIChatClient(); + +// Create agents +AIAgent frenchAgent = GetTranslationAgent("French", chatClient); +AIAgent spanishAgent = GetTranslationAgent("Spanish", chatClient); +AIAgent englishAgent = GetTranslationAgent("English", chatClient); + +// Build the workflow and turn it into an agent +AIAgent agent = new WorkflowBuilder(frenchAgent) + .AddEdge(frenchAgent, spanishAgent) + .AddEdge(spanishAgent, englishAgent) + .Build() + .AsAgent(); + +await agent.RunAIAgentAsync(); + +static ChatClientAgent GetTranslationAgent(string targetLanguage, IChatClient chatClient) => + new(chatClient, $"You are a translation assistant that translates the provided text to {targetLanguage}."); diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/README.md b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/README.md new file mode 100644 index 0000000000..5f6babc755 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/README.md @@ -0,0 +1,26 @@ +# What this sample demonstrates + +This sample demonstrates the use of AI agents as executors within a workflow. + +This workflow uses three translation agents: +1. French Agent - translates input text to French +2. Spanish Agent - translates French text to Spanish +3. English Agent - translates Spanish text back to English + +The agents are connected sequentially, creating a translation chain that demonstrates how AI-powered components can be seamlessly integrated into workflow pipelines. + +## Prerequisites + +Before you begin, ensure you have the following prerequisites: + +- .NET 10 SDK or later +- Azure OpenAI service endpoint and deployment configured +- Azure CLI installed and authenticated (for Azure credential authentication) + +**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure OpenAI resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively). + +Set the following environment variables: + +```powershell +$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" # Replace with your Azure OpenAI resource endpoint +$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini \ No newline at end of file diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/agent.yaml b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/agent.yaml new file mode 100644 index 0000000000..900f05d513 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/agent.yaml @@ -0,0 +1,28 @@ +name: AgentsInWorkflows +displayName: "Translation Chain Workflow Agent" +description: > + A workflow agent that performs sequential translation through multiple languages. + The agent translates text from English to French, then to Spanish, and finally back + to English, leveraging AI-powered translation capabilities in a pipeline workflow. +metadata: + authors: + - Microsoft Agent Framework Team + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Workflows +template: + kind: hosted + name: AgentsInWorkflows + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: AZURE_OPENAI_ENDPOINT + value: ${AZURE_OPENAI_ENDPOINT} + - name: AZURE_OPENAI_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/run-requests.http b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/run-requests.http new file mode 100644 index 0000000000..5c33700a93 --- /dev/null +++ b/dotnet/samples/_to_delete/HostedAgents/AgentsInWorkflows/run-requests.http @@ -0,0 +1,30 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple string input +POST {{endpoint}} +Content-Type: application/json +{ + "input": "Hello, how are you today?" +} + +### Explicit input +POST {{endpoint}} +Content-Type: application/json +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "Hello, how are you today?" + } + ] + } + ] +} diff --git a/dotnet/samples/_to_delete/M365Agent/AFAgentApplication.cs b/dotnet/samples/_to_delete/M365Agent/AFAgentApplication.cs new file mode 100644 index 0000000000..6ebfa81897 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/AFAgentApplication.cs @@ -0,0 +1,184 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json; +using AdaptiveCards; +using M365Agent.Agents; +using Microsoft.Agents.AI; +using Microsoft.Agents.Builder; +using Microsoft.Agents.Builder.App; +using Microsoft.Agents.Builder.State; +using Microsoft.Agents.Core.Models; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; + +namespace M365Agent; + +/// +/// An adapter class that exposes a Microsoft Agent Framework as a M365 Agent SDK . +/// +internal sealed class AFAgentApplication : AgentApplication +{ + private readonly AIAgent _agent; + private readonly string? _welcomeMessage; + + public AFAgentApplication(AIAgent agent, AgentApplicationOptions options, [FromKeyedServices("AFAgentApplicationWelcomeMessage")] string? welcomeMessage = null) : base(options) + { + this._agent = agent; + this._welcomeMessage = welcomeMessage; + + this.OnConversationUpdate(ConversationUpdateEvents.MembersAdded, this.WelcomeMessageAsync); + this.OnActivity(ActivityTypes.Message, this.MessageActivityAsync, rank: RouteRank.Last); + } + + /// + /// The main agent invocation method, where each user message triggers a call to the underlying . + /// + private async Task MessageActivityAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken) + { + // Start a Streaming Process + await turnContext.StreamingResponse.QueueInformativeUpdateAsync("Working on a response for you", cancellationToken); + + // Get the conversation history from turn state. + JsonElement sessionElementStart = turnState.GetValue("conversation.chatHistory"); + + // Deserialize the conversation history into an AgentSession, or create a new one if none exists. + AgentSession agentSession = sessionElementStart.ValueKind is not JsonValueKind.Undefined and not JsonValueKind.Null + ? await this._agent.DeserializeSessionAsync(sessionElementStart, JsonUtilities.DefaultOptions, cancellationToken) + : await this._agent.CreateSessionAsync(cancellationToken); + + ChatMessage chatMessage = HandleUserInput(turnContext); + + // Invoke the WeatherForecastAgent to process the message + AgentResponse agentResponse = await this._agent.RunAsync(chatMessage, agentSession, cancellationToken: cancellationToken); + + // Check for any user input requests in the response + // and turn them into adaptive cards in the streaming response. + List? attachments = null; + HandleUserInputRequests(agentResponse, ref attachments); + + // Check for Adaptive Card content in the response messages + // and return them appropriately in the response. + var adaptiveCards = agentResponse.Messages.SelectMany(x => x.Contents).OfType().ToList(); + if (adaptiveCards.Count > 0) + { + attachments ??= []; + attachments.Add(new Attachment() + { + ContentType = "application/vnd.microsoft.card.adaptive", + Content = adaptiveCards.First().AdaptiveCardJson, + }); + } + else + { + turnContext.StreamingResponse.QueueTextChunk(agentResponse.Text); + } + + // If created any adaptive cards, add them to the final message. + if (attachments is not null) + { + turnContext.StreamingResponse.FinalMessage = MessageFactory.Attachment(attachments); + } + + // Serialize and save the updated conversation history back to turn state. + JsonElement sessionElementEnd = this._agent.SerializeSession(agentSession, JsonUtilities.DefaultOptions); + turnState.SetValue("conversation.chatHistory", sessionElementEnd); + + // End the streaming response + await turnContext.StreamingResponse.EndStreamAsync(cancellationToken); + } + + /// + /// A method to show a welcome message when a new user joins the conversation. + /// + private async Task WelcomeMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(this._welcomeMessage)) + { + return; + } + + foreach (ChannelAccount member in turnContext.Activity.MembersAdded) + { + if (member.Id != turnContext.Activity.Recipient.Id) + { + await turnContext.SendActivityAsync(MessageFactory.Text(this._welcomeMessage), cancellationToken); + } + } + } + + /// + /// When a user responds to a function approval request by clicking on a card, this method converts the response + /// into the appropriate approval or rejection . + /// + /// The for the current turn. + /// The to pass to the . + private static ChatMessage HandleUserInput(ITurnContext turnContext) + { + // Check if this contains the function approval Adaptive Card response. + if (turnContext.Activity.Value is JsonElement valueElement + && valueElement.GetProperty("type").GetString() == "functionApproval" + && valueElement.GetProperty("approved") is JsonElement approvedJsonElement + && approvedJsonElement.ValueKind is JsonValueKind.True or JsonValueKind.False + && valueElement.GetProperty("requestJson") is JsonElement requestJsonElement + && requestJsonElement.ValueKind == JsonValueKind.String) + { + var requestContent = JsonSerializer.Deserialize(requestJsonElement.GetString()!, JsonUtilities.DefaultOptions); + + return new ChatMessage(ChatRole.User, [requestContent!.CreateResponse(approvedJsonElement.ValueKind == JsonValueKind.True)]); + } + + return new ChatMessage(ChatRole.User, turnContext.Activity.Text); + } + + /// + /// When the agent returns any function approval requests, this method converts them into adaptive cards that + /// asks the user to approve or deny the requests. + /// + /// The that may contain the function approval requests. + /// The list of to which the adaptive cards will be added. + private static void HandleUserInputRequests(AgentResponse response, ref List? attachments) + { + foreach (FunctionApprovalRequestContent functionApprovalRequest in response.Messages.SelectMany(m => m.Contents).OfType()) + { + var functionApprovalRequestJson = JsonSerializer.Serialize(functionApprovalRequest, JsonUtilities.DefaultOptions); + + var card = new AdaptiveCard("1.5"); + card.Body.Add(new AdaptiveTextBlock + { + Text = "Function Call Approval Required", + Size = AdaptiveTextSize.Large, + Weight = AdaptiveTextWeight.Bolder, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center + }); + card.Body.Add(new AdaptiveTextBlock + { + Text = $"Function: {functionApprovalRequest.FunctionCall.Name}" + }); + card.Body.Add(new AdaptiveActionSet() + { + Actions = + [ + new AdaptiveSubmitAction + { + Id = "Approve", + Title = "Approve", + Data = new { type = "functionApproval", approved = true, requestJson = functionApprovalRequestJson } + }, + new AdaptiveSubmitAction + { + Id = "Deny", + Title = "Deny", + Data = new { type = "functionApproval", approved = false, requestJson = functionApprovalRequestJson } + } + ] + }); + + attachments ??= []; + attachments.Add(new Attachment() + { + ContentType = "application/vnd.microsoft.card.adaptive", + Content = card.ToJson(), + }); + } + } +} diff --git a/dotnet/samples/_to_delete/M365Agent/Agents/AdaptiveCardAIContent.cs b/dotnet/samples/_to_delete/M365Agent/Agents/AdaptiveCardAIContent.cs new file mode 100644 index 0000000000..9b1ebee662 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Agents/AdaptiveCardAIContent.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json.Serialization; +using AdaptiveCards; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +namespace M365Agent.Agents; + +/// +/// An type allows an to return adaptive cards as part of its response messages. +/// +internal sealed class AdaptiveCardAIContent : AIContent +{ + public AdaptiveCardAIContent(AdaptiveCard adaptiveCard) + { + this.AdaptiveCard = adaptiveCard ?? throw new ArgumentNullException(nameof(adaptiveCard)); + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + [JsonConstructor] + public AdaptiveCardAIContent(string adaptiveCardJson) + { + this.AdaptiveCardJson = adaptiveCardJson; + } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + + [JsonIgnore] + public AdaptiveCard AdaptiveCard { get; private set; } + + public string AdaptiveCardJson + { + get => this.AdaptiveCard.ToJson(); + set => this.AdaptiveCard = AdaptiveCard.FromJson(value).Card; + } +} diff --git a/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgent.cs b/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgent.cs new file mode 100644 index 0000000000..5968e4eb28 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgent.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; +using System.Text.Json; +using AdaptiveCards; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +namespace M365Agent.Agents; + +/// +/// A weather forecasting agent. This agent wraps a and adds custom logic +/// to generate adaptive cards for weather forecasts and add these to the agent's response. +/// +public class WeatherForecastAgent : DelegatingAIAgent +{ + private const string AgentName = "WeatherForecastAgent"; + private const string AgentInstructions = """ + You are a friendly assistant that helps people find a weather forecast for a given location. + You may ask follow up questions until you have enough information to answer the customers question. + When answering with a weather forecast, fill out the weatherCard property with an adaptive card containing the weather information and + add some emojis to indicate the type of weather. + When answering with just text, fill out the context property with a friendly response. + """; + + /// + /// Initializes a new instance of the class. + /// + /// An instance of for interacting with an LLM. + public WeatherForecastAgent(IChatClient chatClient) + : base(new ChatClientAgent( + chatClient: chatClient, + new ChatClientAgentOptions() + { + Name = AgentName, + ChatOptions = new ChatOptions() + { + Instructions = AgentInstructions, + Tools = [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather))], + // We want the agent to return structured output in a known format + // so that we can easily create adaptive cards from the response. + ResponseFormat = ChatResponseFormat.ForJsonSchema( + schema: AIJsonUtilities.CreateJsonSchema(typeof(WeatherForecastAgentResponse)), + schemaName: "WeatherForecastAgentResponse", + schemaDescription: "Response to a query about the weather in a specified location"), + } + })) + { + } + + protected override async Task RunCoreAsync(IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default) + { + var response = await base.RunCoreAsync(messages, session, options, cancellationToken); + + // If the agent returned a valid structured output response + // we might be able to enhance the response with an adaptive card. + if (response.TryDeserialize(JsonSerializerOptions.Web, out var structuredOutput)) + { + var textContentMessage = response.Messages.FirstOrDefault(x => x.Contents.OfType().Any()); + if (textContentMessage is not null) + { + // If the response contains weather information, create an adaptive card. + if (structuredOutput.ContentType == WeatherForecastAgentResponseContentType.WeatherForecastAgentResponse) + { + var card = CreateWeatherCard(structuredOutput.Location, structuredOutput.MeteorologicalCondition, structuredOutput.TemperatureInCelsius); + textContentMessage.Contents.Add(new AdaptiveCardAIContent(card)); + } + + // If the response is just text, replace the structured output with the text response. + if (structuredOutput.ContentType == WeatherForecastAgentResponseContentType.OtherAgentResponse) + { + var textContent = textContentMessage.Contents.OfType().First(); + textContent.Text = structuredOutput.OtherResponse; + } + } + } + + return response; + } + + /// + /// A mock weather tool, to get weather information for a given location. + /// + [Description("Get the weather for a given location.")] + private 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."; + + /// + /// Create an adaptive card to display weather information. + /// + private static AdaptiveCard CreateWeatherCard(string? location, string? condition, string? temperature) + { + var card = new AdaptiveCard("1.5"); + card.Body.Add(new AdaptiveTextBlock + { + Text = "🌤️ Weather Forecast 🌤️", + Size = AdaptiveTextSize.Large, + Weight = AdaptiveTextWeight.Bolder, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center + }); + card.Body.Add(new AdaptiveTextBlock + { + Text = "Location: " + location, + }); + card.Body.Add(new AdaptiveTextBlock + { + Text = "Condition: " + condition, + }); + card.Body.Add(new AdaptiveTextBlock + { + Text = "Temperature: " + temperature, + }); + return card; + } +} diff --git a/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponse.cs b/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponse.cs new file mode 100644 index 0000000000..e5e15dffd4 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponse.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; +using System.Text.Json.Serialization; + +namespace M365Agent.Agents; + +/// +/// The structured output type for the . +/// +internal sealed class WeatherForecastAgentResponse +{ + /// + /// A value indicating whether the response contains a weather forecast or some other type of response. + /// + [JsonPropertyName("contentType")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public WeatherForecastAgentResponseContentType ContentType { get; set; } + + /// + /// If the agent could not provide a weather forecast this should contain a textual response. + /// + [Description("If the answer is other agent response, contains the textual agent response.")] + [JsonPropertyName("otherResponse")] + public string? OtherResponse { get; set; } + + /// + /// The location for which the weather forecast is given. + /// + [Description("If the answer is a weather forecast, contains the location for which the forecast is given.")] + [JsonPropertyName("location")] + public string? Location { get; set; } + + /// + /// The temperature in Celsius for the given location. + /// + [Description("If the answer is a weather forecast, contains the temperature in Celsius.")] + [JsonPropertyName("temperatureInCelsius")] + public string? TemperatureInCelsius { get; set; } + + /// + /// The meteorological condition for the given location. + /// + [Description("If the answer is a weather forecast, contains the meteorological condition (e.g., Sunny, Rainy).")] + [JsonPropertyName("meteorologicalCondition")] + public string? MeteorologicalCondition { get; set; } +} diff --git a/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponseContentType.cs b/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponseContentType.cs new file mode 100644 index 0000000000..cd888d0a0c --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Agents/WeatherForecastAgentResponseContentType.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json.Serialization; + +namespace M365Agent.Agents; + +/// +/// The type of content contained in a . +/// +internal enum WeatherForecastAgentResponseContentType +{ + [JsonPropertyName("otherAgentResponse")] + OtherAgentResponse, + + [JsonPropertyName("weatherForecastAgentResponse")] + WeatherForecastAgentResponse +} diff --git a/dotnet/samples/_to_delete/M365Agent/Auth/AspNetExtensions.cs b/dotnet/samples/_to_delete/M365Agent/Auth/AspNetExtensions.cs new file mode 100644 index 0000000000..1452c5f05e --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Auth/AspNetExtensions.cs @@ -0,0 +1,206 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Collections.Concurrent; +using System.Globalization; +using System.IdentityModel.Tokens.Jwt; +using System.Text; +using Microsoft.Agents.Authentication; +using Microsoft.Agents.Core; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Protocols; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Validators; + +namespace M365Agent; + +internal static class AspNetExtensions +{ + private static readonly CompositeFormat s_cachedValidTokenIssuerUrlTemplateV1Format = CompositeFormat.Parse(AuthenticationConstants.ValidTokenIssuerUrlTemplateV1); + private static readonly CompositeFormat s_cachedValidTokenIssuerUrlTemplateV2Format = CompositeFormat.Parse(AuthenticationConstants.ValidTokenIssuerUrlTemplateV2); + + private static readonly ConcurrentDictionary> s_openIdMetadataCache = new(); + + /// + /// Adds AspNet token validation typical for ABS/SMBA and agent-to-agent using settings in configuration. + /// + /// The service collection to resolve dependencies. + /// Used to read configuration settings. + /// Name of the config section to read. + /// + /// This extension reads settings from configuration. If configuration is missing JWT token + /// is not enabled. + ///

The minimum, but typical, configuration is:

+ /// + /// "TokenValidation": { + /// "Enabled": boolean, + /// "Audiences": [ + /// "{{ClientId}}" // this is the Client ID used for the Azure Bot + /// ], + /// "TenantId": "{{TenantId}}" + /// } + /// + /// The full options are: + /// + /// "TokenValidation": { + /// "Enabled": boolean, + /// "Audiences": [ + /// "{required:agent-appid}" + /// ], + /// "TenantId": "{recommended:tenant-id}", + /// "ValidIssuers": [ + /// "{default:Public-AzureBotService}" + /// ], + /// "IsGov": {optional:false}, + /// "AzureBotServiceOpenIdMetadataUrl": optional, + /// "OpenIdMetadataUrl": optional, + /// "AzureBotServiceTokenHandling": "{optional:true}" + /// "OpenIdMetadataRefresh": "optional-12:00:00" + /// } + /// + ///
+ public static void AddAgentAspNetAuthentication(this IServiceCollection services, IConfiguration configuration, string tokenValidationSectionName = "TokenValidation") + { + IConfigurationSection tokenValidationSection = configuration.GetSection(tokenValidationSectionName); + + if (!tokenValidationSection.Exists() || !tokenValidationSection.GetValue("Enabled", true)) + { + // Noop if TokenValidation section missing or disabled. + System.Diagnostics.Trace.WriteLine("AddAgentAspNetAuthentication: Auth disabled"); + return; + } + + services.AddAgentAspNetAuthentication(tokenValidationSection.Get()!); + } + + /// + /// Adds AspNet token validation typical for ABS/SMBA and agent-to-agent. + /// + public static void AddAgentAspNetAuthentication(this IServiceCollection services, TokenValidationOptions validationOptions) + { + AssertionHelpers.ThrowIfNull(validationOptions, nameof(validationOptions)); + + // Must have at least one Audience. + if (validationOptions.Audiences == null || validationOptions.Audiences.Count == 0) + { + throw new ArgumentException($"{nameof(TokenValidationOptions)}:Audiences requires at least one ClientId"); + } + + // Audience values must be GUID's + foreach (var audience in validationOptions.Audiences) + { + if (!Guid.TryParse(audience, out _)) + { + throw new ArgumentException($"{nameof(TokenValidationOptions)}:Audiences values must be a GUID"); + } + } + + // If ValidIssuers is empty, default for ABS Public Cloud + if (validationOptions.ValidIssuers == null || validationOptions.ValidIssuers.Count == 0) + { + validationOptions.ValidIssuers = + [ + "https://api.botframework.com", + "https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/", + "https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0", + "https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/", + "https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0", + "https://sts.windows.net/69e9b82d-4842-4902-8d1e-abc5b98a55e8/", + "https://login.microsoftonline.com/69e9b82d-4842-4902-8d1e-abc5b98a55e8/v2.0", + ]; + + if (!string.IsNullOrEmpty(validationOptions.TenantId) && Guid.TryParse(validationOptions.TenantId, out _)) + { + validationOptions.ValidIssuers.Add(string.Format(CultureInfo.InvariantCulture, s_cachedValidTokenIssuerUrlTemplateV1Format, validationOptions.TenantId)); + validationOptions.ValidIssuers.Add(string.Format(CultureInfo.InvariantCulture, s_cachedValidTokenIssuerUrlTemplateV2Format, validationOptions.TenantId)); + } + } + + // If the `AzureBotServiceOpenIdMetadataUrl` setting is not specified, use the default based on `IsGov`. This is what is used to authenticate ABS tokens. + if (string.IsNullOrEmpty(validationOptions.AzureBotServiceOpenIdMetadataUrl)) + { + validationOptions.AzureBotServiceOpenIdMetadataUrl = validationOptions.IsGov ? AuthenticationConstants.GovAzureBotServiceOpenIdMetadataUrl : AuthenticationConstants.PublicAzureBotServiceOpenIdMetadataUrl; + } + + // If the `OpenIdMetadataUrl` setting is not specified, use the default based on `IsGov`. This is what is used to authenticate Entra ID tokens. + if (string.IsNullOrEmpty(validationOptions.OpenIdMetadataUrl)) + { + validationOptions.OpenIdMetadataUrl = validationOptions.IsGov ? AuthenticationConstants.GovOpenIdMetadataUrl : AuthenticationConstants.PublicOpenIdMetadataUrl; + } + + var openIdMetadataRefresh = validationOptions.OpenIdMetadataRefresh ?? BaseConfigurationManager.DefaultAutomaticRefreshInterval; + + _ = services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ClockSkew = TimeSpan.FromMinutes(5), + ValidIssuers = validationOptions.ValidIssuers, + ValidAudiences = validationOptions.Audiences, + ValidateIssuerSigningKey = true, + RequireSignedTokens = true, + }; + + // Using Microsoft.IdentityModel.Validators + options.TokenValidationParameters.EnableAadSigningKeyIssuerValidation(); + + options.Events = new JwtBearerEvents + { + // Create a ConfigurationManager based on the requestor. This is to handle ABS non-Entra tokens. + OnMessageReceived = async context => + { + string authorizationHeader = context.Request.Headers.Authorization.ToString(); + + if (string.IsNullOrWhiteSpace(authorizationHeader)) + { + // Default to AadTokenValidation handling + context.Options.TokenValidationParameters.ConfigurationManager ??= options.ConfigurationManager as BaseConfigurationManager; + await Task.CompletedTask.ConfigureAwait(false); + return; + } + + string[] parts = authorizationHeader.Split(' ')!; + if (parts.Length != 2 || parts[0] != "Bearer") + { + // Default to AadTokenValidation handling + context.Options.TokenValidationParameters.ConfigurationManager ??= options.ConfigurationManager as BaseConfigurationManager; + await Task.CompletedTask.ConfigureAwait(false); + return; + } + + JwtSecurityToken token = new(parts[1]); + string issuer = token.Claims.FirstOrDefault(claim => claim.Type == AuthenticationConstants.IssuerClaim)?.Value!; + + string openIdMetadataUrl = (validationOptions.AzureBotServiceTokenHandling && AuthenticationConstants.BotFrameworkTokenIssuer.Equals(issuer, StringComparison.Ordinal)) + ? validationOptions.AzureBotServiceOpenIdMetadataUrl + : validationOptions.OpenIdMetadataUrl; + + context.Options.TokenValidationParameters.ConfigurationManager = s_openIdMetadataCache.GetOrAdd(openIdMetadataUrl, key => + { + return new ConfigurationManager(openIdMetadataUrl, new OpenIdConnectConfigurationRetriever(), new HttpClient()) + { + AutomaticRefreshInterval = openIdMetadataRefresh + }; + }); + + await Task.CompletedTask.ConfigureAwait(false); + }, + + OnTokenValidated = context => Task.CompletedTask, + OnForbidden = context => Task.CompletedTask, + OnAuthenticationFailed = context => Task.CompletedTask + }; + }); + } +} diff --git a/dotnet/samples/_to_delete/M365Agent/Auth/TokenValidationOptions.cs b/dotnet/samples/_to_delete/M365Agent/Auth/TokenValidationOptions.cs new file mode 100644 index 0000000000..f8f2fa2e08 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Auth/TokenValidationOptions.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Agents.Authentication; + +namespace M365Agent; + +internal sealed class TokenValidationOptions +{ + /// + /// The list of audiences to validate against. + /// + public IList? Audiences { get; set; } + + /// + /// TenantId of the Azure Bot. Optional but recommended. + /// + public string? TenantId { get; set; } + + /// + /// Additional valid issuers. Optional, in which case the Public Azure Bot Service issuers are used. + /// + public IList? ValidIssuers { get; set; } + + /// + /// Can be omitted, in which case public Azure Bot Service and Azure Cloud metadata urls are used. + /// + public bool IsGov { get; set; } + + /// + /// Azure Bot Service OpenIdMetadataUrl. Optional, in which case default value depends on IsGov. + /// + /// + /// + public string? AzureBotServiceOpenIdMetadataUrl { get; set; } + + /// + /// Entra OpenIdMetadataUrl. Optional, in which case default value depends on IsGov. + /// + /// + /// + public string? OpenIdMetadataUrl { get; set; } + + /// + /// Determines if Azure Bot Service tokens are handled. Defaults to true and should always be true until Azure Bot Service sends Entra ID token. + /// + public bool AzureBotServiceTokenHandling { get; set; } = true; + + /// + /// OpenIdMetadata refresh interval. Defaults to 12 hours. + /// + public TimeSpan? OpenIdMetadataRefresh { get; set; } +} diff --git a/dotnet/samples/_to_delete/M365Agent/JsonUtilities.cs b/dotnet/samples/_to_delete/M365Agent/JsonUtilities.cs new file mode 100644 index 0000000000..c87367e65b --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/JsonUtilities.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using M365Agent.Agents; +using Microsoft.Extensions.AI; + +namespace M365Agent; + +/// Provides a collection of utility methods for working with JSON data in the context of the application. +internal static partial class JsonUtilities +{ + /// + /// Gets the singleton used as the default in JSON serialization operations. + /// + /// + /// + /// For Native AOT or applications disabling , this instance + /// includes source generated contracts for all common exchange types contained in this library. + /// + /// + /// It additionally turns on the following settings: + /// + /// Enables defaults. + /// Enables as the default ignore condition for properties. + /// Enables as the default number handling for number types. + /// + /// + /// + public static JsonSerializerOptions DefaultOptions { get; } = CreateDefaultOptions(); + + /// + /// Creates default options to use for agents-related serialization. + /// + /// The configured options. + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", Justification = "Converter is guarded by IsReflectionEnabledByDefault check.")] + [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access", Justification = "Converter is guarded by IsReflectionEnabledByDefault check.")] + private static JsonSerializerOptions CreateDefaultOptions() + { + // Copy the configuration from the source generated context. + JsonSerializerOptions options = new(JsonContext.Default.Options) + { + // Chain in the resolvers from both AgentAbstractionsJsonUtilities and our source generated context. + // We want AgentAbstractionsJsonUtilities first to ensure any M.E.AI types are handled via its resolver. + TypeInfoResolver = JsonTypeInfoResolver.Combine(AIJsonUtilities.DefaultOptions.TypeInfoResolver, JsonContext.Default), + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // same as in AgentAbstractionsJsonUtilities and AIJsonUtilities + }; + options.AddAIContentType(typeDiscriminatorId: "adaptiveCard"); + + if (JsonSerializer.IsReflectionEnabledByDefault) + { + options.Converters.Add(new JsonStringEnumConverter()); + } + + options.MakeReadOnly(); + return options; + } + + // Keep in sync with CreateDefaultOptions above. + [JsonSourceGenerationOptions(JsonSerializerDefaults.Web, + UseStringEnumConverter = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowReadingFromString)] + + // M365Agent specific types + [JsonSerializable(typeof(AdaptiveCardAIContent))] + + [ExcludeFromCodeCoverage] + internal sealed partial class JsonContext : JsonSerializerContext; +} diff --git a/dotnet/samples/_to_delete/M365Agent/M365Agent.csproj b/dotnet/samples/_to_delete/M365Agent/M365Agent.csproj new file mode 100644 index 0000000000..f40d404204 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/M365Agent.csproj @@ -0,0 +1,29 @@ + + + + Exe + net10.0 + enable + enable + b842df34-390f-490d-9dc0-73909363ad16 + $(NoWarn);CA1812 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/samples/_to_delete/M365Agent/Program.cs b/dotnet/samples/_to_delete/M365Agent/Program.cs new file mode 100644 index 0000000000..834ac2180a --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Program.cs @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Sample that shows how to create an Agent Framework agent that is hosted using the M365 Agent SDK. +// The agent can then be consumed from various M365 channels. +// See the README.md for more information. + +using Azure.AI.OpenAI; +using Azure.Identity; +using M365Agent; +using M365Agent.Agents; +using Microsoft.Agents.AI; +using Microsoft.Agents.Builder; +using Microsoft.Agents.Hosting.AspNetCore; +using Microsoft.Agents.Storage; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using OpenAI; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +if (builder.Environment.IsDevelopment()) +{ + builder.Configuration.AddUserSecrets(); +} + +builder.Services.AddHttpClient(); + +// Register the inference service of your choice. AzureOpenAI and OpenAI are demonstrated... +IChatClient chatClient; +if (builder.Configuration.GetSection("AIServices").GetValue("UseAzureOpenAI")) +{ + var deploymentName = builder.Configuration.GetSection("AIServices:AzureOpenAI").GetValue("DeploymentName")!; + var endpoint = builder.Configuration.GetSection("AIServices:AzureOpenAI").GetValue("Endpoint")!; + + chatClient = new AzureOpenAIClient( + new Uri(endpoint), + new AzureCliCredential()) + .GetChatClient(deploymentName) + .AsIChatClient(); +} +else +{ + var modelId = builder.Configuration.GetSection("AIServices:OpenAI").GetValue("ModelId")!; + var apiKey = builder.Configuration.GetSection("AIServices:OpenAI").GetValue("ApiKey")!; + + chatClient = new OpenAIClient( + apiKey) + .GetChatClient(modelId) + .AsIChatClient(); +} +builder.Services.AddSingleton(chatClient); + +// Add AgentApplicationOptions from appsettings section "AgentApplication". +builder.AddAgentApplicationOptions(); + +// Add the WeatherForecastAgent plus a welcome message. +// These will be consumed by the AFAgentApplication and exposed as an Agent SDK AgentApplication. +builder.Services.AddSingleton(); +builder.Services.AddKeyedSingleton("AFAgentApplicationWelcomeMessage", "Hello and Welcome! I'm here to help with all your weather forecast needs!"); + +// Add the AgentApplication, which contains the logic for responding to +// user messages via the Agent SDK. +builder.AddAgent(); + +// Register IStorage. For development, MemoryStorage is suitable. +// For production Agents, persisted storage should be used so +// that state survives Agent restarts, and operates correctly +// in a cluster of Agent instances. +builder.Services.AddSingleton(); + +// Configure the HTTP request pipeline. + +// Add AspNet token validation for Azure Bot Service and Entra. Authentication is +// configured in the appsettings.json "TokenValidation" section. +builder.Services.AddControllers(); +builder.Services.AddAgentAspNetAuthentication(builder.Configuration); + +WebApplication app = builder.Build(); + +// Enable AspNet authentication and authorization +app.UseAuthentication(); +app.UseAuthorization(); + +app.MapGet("/", () => "Microsoft Agents SDK Sample"); + +// This receives incoming messages and routes them to the registered AgentApplication. +var incomingRoute = app.MapPost("/api/messages", async (HttpRequest request, HttpResponse response, IAgentHttpAdapter adapter, IAgent agent, CancellationToken cancellationToken) => await adapter.ProcessAsync(request, response, agent, cancellationToken)); + +if (!app.Environment.IsDevelopment()) +{ + incomingRoute.RequireAuthorization(); +} +else +{ + // Hardcoded for brevity and ease of testing. + // In production, this should be set in configuration. + app.Urls.Add("http://localhost:3978"); +} + +app.Run(); diff --git a/dotnet/samples/_to_delete/M365Agent/Properties/launchSettings.json b/dotnet/samples/_to_delete/M365Agent/Properties/launchSettings.json new file mode 100644 index 0000000000..14d89c0bab --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "M365Agent": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:49692;http://localhost:49693" + } + } +} \ No newline at end of file diff --git a/dotnet/samples/_to_delete/M365Agent/README.md b/dotnet/samples/_to_delete/M365Agent/README.md new file mode 100644 index 0000000000..e61fa438f5 --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/README.md @@ -0,0 +1,119 @@ +# Microsoft Agent Framework agents with the M365 Agents SDK Weather Agent sample + +This is a sample of a simple Weather Forecast Agent that is hosted on an Asp.Net core web service and is exposed via the M365 Agent SDK. This Agent is configured to accept a request asking for information about a weather forecast and respond to the caller with an Adaptive Card. This agent will handle multiple "turns" to get the required information from the user. + +This Agent Sample is intended to introduce you the basics of integrating Agent Framework with the Microsoft 365 Agents SDK in order to use Agent Framework agents in various M365 services and applications. It can also be used as the base for a custom Agent that you choose to develop. + +***Note:*** This sample requires JSON structured output from the model which works best from newer versions of the model such as gpt-4o-mini. + +## Prerequisites + +- [.NET 10.0 SDK or later](https://dotnet.microsoft.com/download) +- [devtunnel](https://learn.microsoft.com/azure/developer/dev-tunnels/get-started?tabs=windows) +- [Microsoft 365 Agents Toolkit](https://github.com/OfficeDev/microsoft-365-agents-toolkit) + +- You will need an Azure OpenAI or OpenAI resource using `gpt-4o-mini` + +- Configure OpenAI in appsettings + + ```json + "AIServices": { + "AzureOpenAI": { + "DeploymentName": "", // This is the Deployment (as opposed to model) Name of the Azure OpenAI model + "Endpoint": "", // This is the Endpoint of the Azure OpenAI resource + "ApiKey": "" // This is the API Key of the Azure OpenAI resource. Optional, uses AzureCliCredential if not provided + }, + "OpenAI": { + "ModelId": "", // This is the Model ID of the OpenAI model + "ApiKey": "" // This is your API Key for the OpenAI service + }, + "UseAzureOpenAI": false // This is a flag to determine whether to use the Azure OpenAI or the OpenAI service + } + ``` + +## QuickStart using Agent Toolkit +1. If you haven't done so already, install the Agents Playground + + ``` + winget install agentsplayground + ``` +1. Start the sample application. +1. Start Agents Playground. At a command prompt: `agentsplayground` + - The tool will open a web browser showing the Microsoft 365 Agents Playground, ready to send messages to your agent. +1. Interact with the Agent via the browser + +## QuickStart using WebChat or Teams + +- Overview of running and testing an Agent + - Provision an Azure Bot in your Azure Subscription + - Configure your Agent settings to use to desired authentication type + - Running an instance of the Agent app (either locally or deployed to Azure) + - Test in a client + +1. Create an Azure Bot with one of these authentication types + - [SingleTenant, Client Secret](https://learn.microsoft.com/en-us/microsoft-365/agents-sdk/azure-bot-create-single-secret) + - [SingleTenant, Federated Credentials](https://learn.microsoft.com/en-us/microsoft-365/agents-sdk/azure-bot-create-federated-credentials) + - [User Assigned Managed Identity](https://learn.microsoft.com/en-us/microsoft-365/agents-sdk/azure-bot-create-managed-identity) + + > Be sure to follow the **Next Steps** at the end of these docs to configure your agent settings. + + > **IMPORTANT:** If you want to run your agent locally via devtunnels, the only support auth type is ClientSecret and Certificates + +1. Running the Agent + 1. Running the Agent locally + - Requires a tunneling tool to allow for local development and debugging should you wish to do local development whilst connected to a external client such as Microsoft Teams. + - **For ClientSecret or Certificate authentication types only.** Federated Credentials and Managed Identity will not work via a tunnel to a local agent and must be deployed to an App Service or container. + + 1. Run `devtunnel`. Please follow [Create and host a dev tunnel](https://learn.microsoft.com/azure/developer/dev-tunnels/get-started?tabs=windows) and host the tunnel with anonymous user access command as shown below: + + ```bash + devtunnel host -p 3978 --allow-anonymous + ``` + + 1. On the Azure Bot, select **Settings**, then **Configuration**, and update the **Messaging endpoint** to `{tunnel-url}/api/messages` + + 1. Start the Agent in Visual Studio + + 1. Deploy Agent code to Azure + 1. VS Publish works well for this. But any tools used to deploy a web application will also work. + 1. On the Azure Bot, select **Settings**, then **Configuration**, and update the **Messaging endpoint** to `https://{{appServiceDomain}}/api/messages` + +## Testing this agent with WebChat + + 1. Select **Test in WebChat** under **Settings** on the Azure Bot in the Azure Portal + +## Testing this Agent in Teams or M365 + +1. Update the manifest.json + - Edit the `manifest.json` contained in the `/appManifest` folder + - Replace with your AppId (that was created above) *everywhere* you see the place holder string `<>` + - Replace `<>` with your Agent url. For example, the tunnel host name. + - Zip up the contents of the `/appManifest` folder to create a `manifest.zip` + - `manifest.json` + - `outline.png` + - `color.png` + +1. Your Azure Bot should have the **Microsoft Teams** channel added under **Channels**. + +1. Navigate to the Microsoft Admin Portal (MAC). Under **Settings** and **Integrated Apps,** select **Upload Custom App**. + +1. Select the `manifest.zip` created in the previous step. + +1. After a short period of time, the agent shows up in Microsoft Teams and Microsoft 365 Copilot. + +## Enabling JWT token validation +1. By default, the AspNet token validation is disabled in order to support local debugging. +1. Enable by updating appsettings + ```json + "TokenValidation": { + "Enabled": true, + "Audiences": [ + "{{ClientId}}" // this is the Client ID used for the Azure Bot + ], + "TenantId": "{{TenantId}}" + }, + ``` + +## Further reading + +To learn more about using the M365 Agent SDK, see [Microsoft 365 Agents SDK](https://learn.microsoft.com/en-us/microsoft-365/agents-sdk/). diff --git a/dotnet/samples/_to_delete/M365Agent/appManifest/color.png b/dotnet/samples/_to_delete/M365Agent/appManifest/color.png new file mode 100644 index 0000000000000000000000000000000000000000..b8cf81afbe2f5bafd8563920edfadb78b7b71be6 GIT binary patch literal 3415 zcmb_f_cz=97yl$yB&9JzRh6h2tH#4qGlGguP@5VZ)TmuMREiEYsmAqpTZ7ZnE>F-ih-`S z)jiPabibc~4T5Do@MgZ}C5dq?7H{rvYr!LtVV;haHWm>H5pk+~G>pJtSPwz9!%QIL z?J6p?*$Q$^sbaC}3#mquX(;945bnpoc+%>4bmj2j*4KG@ZlhvIK1EKveQp-tp;sflS z4}SX;$jwoVae}M%3TBb@f-(BCG-m~}LW z311k8hKz8Ecm+M)P%mwS`Qda^pus{!e?Y+KDQD2B zWjuLo3{6=k`fmQI5d@(}*Q181Mj`he_jbr58C>@^+LzKri!pF}V7#<_PpQz&%C;U{ zmw+W{t0J1#nQ=&npU~H@5560!cFBrXbr9|2B0^~cU|iuMlNCdQc=W{4l5?D+6VaEh zTMw4Le|CpisEssdz5I_WB6-(_;8BOb0Ov8s8pGkEy3dRw%({?pOI-F=klY?eZ? zUVhJNclMhOiaUeo1=K6XJM&%_W3cuMl0&!|dZ*m;OnJ@X0hcbckvNZBg(+D^|Ij*W z^k!?ARMd55LmON%i4$H$oX@f6BX!4A;^vP8 z8cz4BuYM-<o;D&UDP5xiVZj*vOwL(Xgi^WuW~qbXAKq2Luow#G(c({?o;I6o^aPh zY8-5*rVevAtn+kvbMgF0e2aRCg<-9As)UjYZ6KflvEXw~s4oA9`rIcL$EwC#Nl4!Y z{Ra>{I}!nf;fS&)z+jL655PntETI$6U8Y}Ig2{rj%v@0jcn*%`A)a!{%}s7NBl@YZ zF=5*reV$RHd3{o<&n#+Q@`qDF353xaQpB`4xV}riJ9I9)n@3Z)XG}5(V{Q&3aR3@U zfvScEs@b=w&t&>>-{+3xqK!b>z!qBbNS|r5c*fsepeyv}`T2T3^Rl^VEuDJ791>m# z2v4z4^&I6;*?N?Y>{&QA68>t1^-&FL3ENmAhPS{0r|=(*lqbEP>9cOMLGp_HYhQZg z5|nV2{_Izd_;#CdtTqsobR}=S-qFTrJ-x;iS2#i#z#&uT!%~by2H7SHE59gi?MRJ@ z&uPeey)XN;6>?uj&+koIuhrru!~8?iOjP)pOk zZS*!=6WN?lHJ?`i{nB-e%fBUOPJ{yj=4Qw0yy+VSJ~h!ic41=jIWl86;2wQpJ$|c; zR^8lfv6@E+Ml{RZa7=y6$Fm2e{S_LC&C&1z_6HAE5R)AY98`77m2}Wv?2u>t#n znVG&}p_ND4RUXyAe0eXPm~gRFy97$f;5uNp5E%g15TTUE!!9}f9|!fPptQ}hXUJ-Lf~U%GJe zsq^FU`Ls)2UH98$x8x$=Tx0Fa`MacR@Y*8VNB4KDI$rXuP3tLT~d$yTUmB8m)7qg;fcbUj22v9YhPg)l!VIN8UIm#P<%(f!Xxw-=tty8Y31-^i)60)F`@KU!EX(mkf zQ)GeUGN)evp^?tyIxI4pQA!m=31izfrrvagzaMa~$#cu04I6IB;GGvc4WT-%YB+-dV^gTZZh%XO`b}DECWpOoZjqt9 zqktOLcvhMktKKW=LeH#wDjj)gZTsybRlro)>};szu4ZDya*m$j46iaD|7AtPR&)iG z*~&F{db|zcArblJB^#hfDfNHcBoXPrl|fJ_nY6|4PZvm8y%nhrBrMds%ST0DAoy9= zfGS2J3)T=H-9zf)Va%IxUrlHoa+k}BTWY5cQm5cg1m;kyx6jIVo} zncTNdzEOT^iXh`mZlRk{pWp?fwB`;UK8j^m!oH0&482 zLtYN=)+aYNZ4sk7|&V_eX z>Q)oVz#n+pJ})Bur(co;;PZGpQTW%-s;*VNl8sfFGp0FfZcJIui)lqu)fus9RW8x5>XRi#eKcG&_};xJr8+Kr5*T z`xf#w6!*t}>W)r?K}`cUBF1xChxm1CeQ~Iv!hpZ*aAfA2Oj+4dO7$ZY#HUkTBv7VZ z9{ummlF5yEz#3Q3qr@tUyEH39^e^h#n-ossc?E}3wwVM06<*ub6=g#PU8^A^X*rp* zHdbNBWv)qo)pwXWCP(eOSERnk<+Lwz$c=q_b{Oy9D-rhbvBhiC9BkT4BP$o|ked-g z13lVezZV!hdr*Cp&gcWv1m>P7>o8p1rPUe)cvFI#EF&G+lUbFSDxq3w?&ORaa)Y!@?0&a>GT8psQ{JX#@_+az{5K+M YJx2difYK9bhlEpZpl7Q49&>", + "developer": { + "name": "Microsoft, Inc.", + "websiteUrl": "https://example.azurewebsites.net", + "privacyUrl": "https://example.azurewebsites.net/privacy", + "termsOfUseUrl": "https://example.azurewebsites.net/termsofuse" + }, + "icons": { + "color": "color.png", + "outline": "outline.png" + }, + "name": { + "short": "AF Sample Agent", + "full": "M365 AgentSDK and Microsoft Agent Framework Sample" + }, + "description": { + "short": "Sample demonstrating M365 AgentSDK, Teams, and Microsoft Agent Framework", + "full": "Sample demonstrating M365 AgentSDK, Teams, and Microsoft Agent Framework" + }, + "accentColor": "#FFFFFF", + "copilotAgents": { + "customEngineAgents": [ + { + "id": "<>", + "type": "bot" + } + ] + }, + "bots": [ + { + "botId": "<>", + "scopes": [ + "personal" + ], + "supportsFiles": false, + "isNotificationOnly": false + } + ], + "permissions": [ + "identity", + "messageTeamMembers" + ], + "validDomains": [ + "<>" + ] +} \ No newline at end of file diff --git a/dotnet/samples/_to_delete/M365Agent/appManifest/outline.png b/dotnet/samples/_to_delete/M365Agent/appManifest/outline.png new file mode 100644 index 0000000000000000000000000000000000000000..2c3bf6fa65f152de0cb50056effd5aea7d287ec1 GIT binary patch literal 407 zcmV;I0cie-P)GP9wA4-6No2JPavK^y+J&IdIIqnt|)iz#;q%0#|~})uPXtHpGg|3DT=Cm zRbOQmZzjp~Oa~|w3J0d4$UMjUP`eo9-%ZEed<9c*o{#frSUWpe$h)9<7f||JElr8%Q+a+LHNJ~kNO5B zlRv;1hxJ`;YEbQ%GiTGTR{shYbEe%;Xrq2t9*a`EVNoJ89P+!W;^dkhG3QK~lh@uy z_@!DknGSuYuSg%;OK8pl!P9F+PR@yY6bgl7VhU4=M!!cg{}TWJ002ovPDHLkV1nXO Bp2+|J literal 0 HcmV?d00001 diff --git a/dotnet/samples/_to_delete/M365Agent/appsettings.json.template b/dotnet/samples/_to_delete/M365Agent/appsettings.json.template new file mode 100644 index 0000000000..7268acf39b --- /dev/null +++ b/dotnet/samples/_to_delete/M365Agent/appsettings.json.template @@ -0,0 +1,54 @@ +{ + "TokenValidation": { + "Enabled": false, + "Audiences": [ + "{{ClientId}}" // this is the Client ID used for the Azure Bot + ], + "TenantId": "{{TenantId}}" + }, + + "AgentApplication": { + "StartTypingTimer": true, + "RemoveRecipientMention": false, + "NormalizeMentions": false + }, + + "Connections": { + "ServiceConnection": { + "Settings": { + // this is the AuthType for the connection, valid values can be found in Microsoft.Agents.Authentication.Msal.Model.AuthTypes. The default is ClientSecret. + "AuthType": "" + + // Other properties dependent on the authorization type the Azure Bot uses. + } + } + }, + "ConnectionsMap": [ + { + "ServiceUrl": "*", + "Connection": "ServiceConnection" + } + ], + + // This is the configuration for the AI services, use environment variables or user secrets to store sensitive information. + // Do not store sensitive information in this file + "AIServices": { + "AzureOpenAI": { + "DeploymentName": "", // This is the Deployment (as opposed to model) Name of the Azure OpenAI model + "Endpoint": "", // This is the Endpoint of the Azure OpenAI resource + "ApiKey": "" // This is the API Key of the Azure OpenAI resource. Optional, uses AzureCliCredential if not provided + }, + "OpenAI": { + "ModelId": "", // This is the Model ID of the OpenAI model + "ApiKey": "" // This is your API Key for the OpenAI service + }, + "UseAzureOpenAI": false // This is a flag to determine whether to use the Azure OpenAI or the OpenAI service + }, + + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} \ No newline at end of file diff --git a/dotnet/samples/_to_delete/Purview/AgentWithPurview/AgentWithPurview.csproj b/dotnet/samples/_to_delete/Purview/AgentWithPurview/AgentWithPurview.csproj new file mode 100644 index 0000000000..0a79857d64 --- /dev/null +++ b/dotnet/samples/_to_delete/Purview/AgentWithPurview/AgentWithPurview.csproj @@ -0,0 +1,21 @@ + + + + Exe + net10.0 + + enable + enable + + + + + + + + + + + + + diff --git a/dotnet/samples/_to_delete/Purview/AgentWithPurview/Program.cs b/dotnet/samples/_to_delete/Purview/AgentWithPurview/Program.cs new file mode 100644 index 0000000000..a4b27c47cd --- /dev/null +++ b/dotnet/samples/_to_delete/Purview/AgentWithPurview/Program.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows how to create and use a simple AI agent with Purview integration. +// It uses Azure OpenAI as the backend, but any IChatClient can be used. +// Authentication to Purview is done using an InteractiveBrowserCredential. +// Any TokenCredential with Purview API permissions can be used here. + +using Azure.AI.OpenAI; +using Azure.Core; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Purview; +using Microsoft.Extensions.AI; + +var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; +var purviewClientAppId = Environment.GetEnvironmentVariable("PURVIEW_CLIENT_APP_ID") ?? throw new InvalidOperationException("PURVIEW_CLIENT_APP_ID is not set."); + +// This will get a user token for an entra app configured to call the Purview API. +// Any TokenCredential with permissions to call the Purview API can be used here. +TokenCredential browserCredential = new InteractiveBrowserCredential( + new InteractiveBrowserCredentialOptions + { + ClientId = purviewClientAppId + }); + +using IChatClient client = new AzureOpenAIClient( + new Uri(endpoint), + new AzureCliCredential()) + .GetResponsesClient(deploymentName) + .AsIChatClient() + .AsBuilder() + .WithPurview(browserCredential, new PurviewSettings("Agent Framework Test App")) + .Build(); + +Console.WriteLine("Enter a prompt to send to the client:"); +string? promptText = Console.ReadLine(); + +if (!string.IsNullOrEmpty(promptText)) +{ + // Invoke the agent and output the text result. + Console.WriteLine(await client.GetResponseAsync(promptText)); +} From 5aa9f397513e1b6a9062541149042200522c5d99 Mon Sep 17 00:00:00 2001 From: eavanvalkenburg Date: Mon, 9 Feb 2026 16:50:43 +0100 Subject: [PATCH 2/2] docs: add AGENTS.md with structure & design choices for AI/human maintainers --- dotnet/samples/AGENTS.md | 156 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 dotnet/samples/AGENTS.md diff --git a/dotnet/samples/AGENTS.md b/dotnet/samples/AGENTS.md new file mode 100644 index 0000000000..cffdd5dbda --- /dev/null +++ b/dotnet/samples/AGENTS.md @@ -0,0 +1,156 @@ +# Samples Structure & Design Choices — .NET + +> This file documents the structure and conventions of the .NET samples so that +> agents (AI or human) can maintain them without rediscovering decisions. + +## Directory layout + +``` +dotnet/samples/ +├── 01-get-started/ # Progressive tutorial (steps 01–06) +├── 02-agents/ # Deep-dive concept samples +│ ├── tools/ # One file per tool type +│ ├── middleware/ # One file per middleware concept +│ ├── conversations/ # Storage, persistence +│ └── providers/ # One file per provider +├── 03-workflows/ # One sub-folder per workflow pattern +├── 04-hosting/ # Multi-project solutions +│ ├── a2a/ # Client + Server projects +│ ├── ag-ui/ # Client + Server projects +│ ├── azure-functions/ # Function projects + console apps +│ └── openai-endpoints/ # Hosted agent projects +├── 05-end-to-end/ # Complete applications +│ ├── agent-web-chat/ # .NET Aspire solution +│ ├── agui-web-chat/ # AG-UI full-stack demo +│ ├── m365-agent/ # Teams/M365 integration +│ └── purview/ # Governance integration +├── _to_delete/ # Deprecated samples awaiting review +└── Directory.Build.props # Shared MSBuild properties +``` + +## Design principles + +1. **Progressive complexity**: Sections 01→05 build from "hello world" to + production deployment. Within 01-get-started, files are numbered 01–06 and + each step adds exactly one concept. + +2. **One concept per file**: Each `.cs` in 02-agents/ demonstrates a single + topic (e.g. `FunctionTools.cs`, `ChatClientMiddleware.cs`). Don't combine + multiple unrelated concepts. + +3. **Single-file for 01–03**: Sections 01-get-started, 02-agents, and + 03-workflows use single `.cs` top-level-statement files runnable with + `dotnet run`. Sections 04 and 05 are multi-project solutions. + +4. **Flat tools/middleware/providers**: Each sub-folder under 02-agents/ is flat + (no nesting). File names match the concept they demonstrate. + +## Default provider + +All canonical samples use **Azure AI Foundry** via `AIProjectClient`: + +```csharp +using Azure.AI.Projects; +using Azure.Identity; + +string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); +string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( + name: "...", + model: deploymentName, + instructions: "..."); +``` + +Environment variables should always be **explicit**. Provider-specific samples +(02-agents/providers/) show other providers. + +## Snippet tags for docs integration + +Every sample embeds named snippet regions that the docs repo references via +`:::code` directives. Tags use C# XML comment style: + +```csharp +// +code here +// +``` + +Common tag names and their meaning: + +| Tag | Used in | Purpose | +|-----|---------|---------| +| `create_agent` | 01-get-started/01_HelloAgent.cs | Agent instantiation | +| `run_agent` | 01-get-started/01_HelloAgent.cs | Non-streaming run | +| `run_agent_streaming` | 01-get-started/01_HelloAgent.cs | Streaming run | +| `define_tool` | 01-get-started/02_AddTools.cs | Tool definition | +| `create_agent_with_tools` | 01-get-started/02_AddTools.cs | Agent + tools | +| `multi_turn` | 01-get-started/03_MultiTurn.cs | Thread-based conversation | + +When adding a new sample or modifying an existing one: +- **Keep existing snippet tags** — the docs repo depends on them +- Use `snake_case` for tag names (even in C# files) +- If you add new tags, update the corresponding docs `.md` file to reference them + +## Docs integration + +The docs repo at `semantic-kernel-pr/agent-framework/` references samples via: + +```markdown +:::code language="csharp" source="~/agent-framework/dotnet/samples/01-get-started/01_HelloAgent.cs" id="create_agent" highlight="4-6"::: +``` + +- `source=` paths use `~/agent-framework/` as the docset root +- `id=` matches a `// ` / `// ` region in the sample +- `highlight=` line numbers are **relative to the displayed snippet** (not the file) +- `id=` and `range=` cannot coexist in the same directive +- Docs pages use `zone_pivot_groups: programming-languages` to show C#/Python side by side + +**If you rename or move a sample file**, you must also update the corresponding +docs page. See the mapping below. + +## File → docs page mapping + +| Sample path | Docs page | +|-------------|-----------| +| `01-get-started/01_HelloAgent.cs` | `get-started/your-first-agent.md` | +| `01-get-started/02_AddTools.cs` | `get-started/add-tools.md` | +| `01-get-started/03_MultiTurn.cs` | `get-started/multi-turn.md` | +| `01-get-started/04_Memory.cs` | `get-started/memory.md` | +| `01-get-started/05_FirstWorkflow.cs` | `get-started/workflows.md` | +| `01-get-started/06_HostYourAgent.cs` | `get-started/hosting.md` | +| `02-agents/tools/*.cs` | `agents/tools/.md` | +| `02-agents/middleware/*.cs` | `agents/middleware/.md` | +| `02-agents/providers/*.cs` | `agents/providers/.md` | +| `02-agents/conversations/*.cs` | `agents/conversations/.md` | +| `03-workflows//*.cs` | `workflows/.md` | +| `04-hosting/*` | `integrations/.md` | + +## Naming conventions + +- **C# files**: `PascalCase.cs` (e.g. `FunctionTools.cs`, `01_HelloAgent.cs`) +- **Folders**: `kebab-case` (e.g. `human-in-the-loop`, `azure-functions`) +- **Getting started numbering**: `01_` through `06_` prefix +- **README.md**: Required in every section folder and every multi-project folder + +## NuGet packages + +```bash +dotnet add package Microsoft.Agents.AI +``` + +For Azure AI Foundry provider: +```bash +dotnet add package Azure.AI.Projects +``` + +## When adding a new sample + +1. Put it in the correct section folder based on complexity +2. Add snippet tags for any code that should appear in docs +3. Use single-file top-level statements for 01–03; multi-project for 04–05 +4. Use explicit env vars via `Environment.GetEnvironmentVariable()` +5. Add a corresponding docs page (or update the existing one) with `:::code` refs +6. Update this file's mapping table if adding a new file