-
Notifications
You must be signed in to change notification settings - Fork 1.3k
.Net: Add additional Hosted Agent Samples #4325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rogerbarreto
merged 7 commits into
microsoft:main
from
rogerbarreto:samples/hosted-agents
Mar 2, 2026
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
1bca731
Add 3 new hosted agent samples: AgentWithTools, AgentWithLocalTools, …
rogerbarreto fff6cea
Add root HostedAgents README, replace test_requests.py with .http, up…
rogerbarreto 76e5f9d
Merge branch 'main' into samples/hosted-agents
rogerbarreto f56897e
Fix dotnet format issues in AgentWithLocalTools/Program.cs
rogerbarreto 1585ff5
Address PR review: align model names and package versions
rogerbarreto f171e68
Upgrade new samples to latest package versions
rogerbarreto 794a2ec
Pin AgentThreadAndHITL to Microsoft.Extensions.AI.OpenAI 10.1.1
rogerbarreto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
70 changes: 70 additions & 0 deletions
70
dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/AgentThreadAndHITL.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworks>net10.0</TargetFrameworks> | ||
|
|
||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <NoWarn>$(NoWarn);MEAI001</NoWarn> | ||
|
|
||
| <!-- | ||
| Disable central package management for this project. | ||
| This project requires explicit package references with versions specified inline rather than | ||
| inheriting them from Directory.Packages.props. This is necessary because a Docker image will | ||
| be created from this project, and the Docker build process only has access to this folder | ||
| and cannot access parent folders where Directory.Packages.props resides. | ||
| --> | ||
| <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally> | ||
| </PropertyGroup> | ||
|
|
||
| <!-- | ||
| Remove analyzer PackageReference items inherited from Directory.Packages.props. | ||
| Note: ManagePackageVersionsCentrally only controls PackageVersion items, not PackageReference items. | ||
| Directory.Packages.props contains both PackageVersion and PackageReference entries for analyzers, | ||
| and the PackageReference items are always inherited through MSBuild imports regardless of the | ||
| ManagePackageVersionsCentrally setting. We must explicitly remove them before adding our own versions. | ||
| --> | ||
| <ItemGroup> | ||
| <PackageReference Remove="Microsoft.CodeAnalysis.NetAnalyzers" /> | ||
| <PackageReference Remove="Microsoft.VisualStudio.Threading.Analyzers" /> | ||
| <PackageReference Remove="xunit.analyzers" /> | ||
| <PackageReference Remove="Moq.Analyzers" /> | ||
| <PackageReference Remove="Roslynator.Analyzers" /> | ||
| <PackageReference Remove="Roslynator.CodeAnalysis.Analyzers" /> | ||
| <PackageReference Remove="Roslynator.Formatting.Analyzers" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Azure.AI.AgentServer.AgentFramework" Version="1.0.0-beta.8" /> | ||
| <PackageReference Include="Azure.AI.OpenAI" Version="2.8.0-beta.1" /> | ||
| <PackageReference Include="Azure.Identity" Version="1.17.1" /> | ||
| <PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.251219.1" /> | ||
| <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="10.1.1-preview.1.25612.2" /> | ||
| </ItemGroup> | ||
|
|
||
| <!-- Add analyzers with compatible versions --> | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Roslynator.Analyzers" Version="4.14.1"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| </ItemGroup> | ||
|
|
||
| </Project> | ||
20 changes: 20 additions & 0 deletions
20
dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/Dockerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 . | ||
|
|
||
rogerbarreto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| EXPOSE 8088 | ||
| ENTRYPOINT ["dotnet", "AgentThreadAndHITL.dll"] | ||
38 changes: 38 additions & 0 deletions
38
dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| // This sample demonstrates Human-in-the-Loop (HITL) capabilities with thread persistence. | ||
| // The agent wraps function tools with ApprovalRequiredAIFunction to require user approval | ||
| // before invoking them. Users respond with 'approve' or 'reject' when prompted. | ||
|
|
||
| using System.ComponentModel; | ||
| using Azure.AI.AgentServer.AgentFramework.Extensions; | ||
| using Azure.AI.AgentServer.AgentFramework.Persistence; | ||
| 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"; | ||
|
|
||
| [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."; | ||
|
|
||
| // Create the chat client and agent. | ||
| // Note: ApprovalRequiredAIFunction wraps the tool to require user approval before invocation. | ||
| // User should reply with 'approve' or 'reject' when prompted. | ||
| #pragma warning disable MEAI001 // Type is for evaluation purposes only | ||
| AIAgent agent = new AzureOpenAIClient( | ||
| new Uri(endpoint), | ||
| new AzureCliCredential()) | ||
| .GetChatClient(deploymentName) | ||
| .AsIChatClient() | ||
| .CreateAIAgent( | ||
| instructions: "You are a helpful assistant", | ||
| tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather))] | ||
| ); | ||
| #pragma warning restore MEAI001 | ||
|
|
||
| var threadRepository = new InMemoryAgentThreadRepository(agent); | ||
| await agent.RunAIAgentAsync(telemetrySourceName: "Agents", threadRepository: threadRepository); |
46 changes: 46 additions & 0 deletions
46
dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # What this sample demonstrates | ||
|
|
||
| This sample demonstrates Human-in-the-Loop (HITL) capabilities with thread persistence. The agent wraps function tools with `ApprovalRequiredAIFunction` so that every tool invocation requires explicit user approval before execution. Thread state is maintained across requests using `InMemoryAgentThreadRepository`. | ||
|
|
||
| Key features: | ||
| - Requiring human approval before executing function calls | ||
| - Persisting conversation threads across multiple requests | ||
| - Approving or rejecting tool invocations at runtime | ||
|
|
||
| > For common prerequisites and setup instructions, see the [Hosted Agent Samples README](../README.md). | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before running this sample, ensure you have: | ||
|
|
||
| 1. .NET 10 SDK installed | ||
| 2. An Azure OpenAI endpoint configured | ||
| 3. A deployment of a chat model (e.g., gpt-4o-mini) | ||
| 4. Azure CLI installed and authenticated (`az login`) | ||
|
|
||
| ## 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 `ApprovalRequiredAIFunction` to wrap standard AI function tools. When the model decides to call a tool, the wrapper intercepts the invocation and returns a HITL approval request to the caller instead of executing the function immediately. | ||
|
|
||
| 1. The user sends a message (e.g., "What is the weather in Vancouver?") | ||
| 2. The model determines a function call is needed and selects the `GetWeather` tool | ||
| 3. `ApprovalRequiredAIFunction` intercepts the call and returns an approval request containing the function name and arguments | ||
| 4. The user responds with `approve` or `reject` | ||
| 5. If approved, the function executes and the model generates a response using the result | ||
| 6. If rejected, the model generates a response without the function result | ||
|
|
||
| Thread persistence is handled by `InMemoryAgentThreadRepository`, which stores conversation history keyed by `conversation.id`. This means the HITL flow works across multiple HTTP requests as long as each request includes the same `conversation.id`. | ||
|
|
||
| > **Note:** HITL requires a stable `conversation.id` in every request so the agent can correlate the approval response with the original function call. Use the `run-requests.http` file in this directory to test the full approval flow. |
28 changes: 28 additions & 0 deletions
28
dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/agent.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| name: AgentThreadAndHITL | ||
| displayName: "Weather Assistant Agent" | ||
| description: > | ||
| A Weather Assistant Agent that provides weather information and forecasts. It | ||
| demonstrates how to use Azure AI AgentServer with Human-in-the-Loop (HITL) | ||
| capabilities to get human approval for functional calls. | ||
| metadata: | ||
| authors: | ||
| - Microsoft Agent Framework Team | ||
| tags: | ||
| - Azure AI AgentServer | ||
| - Microsoft Agent Framework | ||
| - Human-in-the-Loop | ||
| template: | ||
| kind: hosted | ||
| name: AgentThreadAndHITL | ||
| 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 |
70 changes: 70 additions & 0 deletions
70
dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/run-requests.http
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| @host = http://localhost:8088 | ||
| @endpoint = {{host}}/responses | ||
|
|
||
| ### Health Check | ||
| GET {{host}}/readiness | ||
|
|
||
| ### | ||
| # HITL (Human-in-the-Loop) Flow | ||
| # | ||
| # This sample requires a multi-turn conversation to demonstrate the approval flow: | ||
| # 1. Send a request that triggers a tool call (e.g., asking about the weather) | ||
| # 2. The agent responds with a function_call named "__hosted_agent_adapter_hitl__" | ||
| # containing the call_id and the tool details | ||
| # 3. Send a follow-up request with a function_call_output to approve or reject | ||
| # | ||
| # IMPORTANT: You must use the same conversation.id across all requests in a flow, | ||
| # and update the call_id from step 2 into step 3. | ||
| ### | ||
|
|
||
| ### Step 1: Send initial request (triggers HITL approval) | ||
| # @name initialRequest | ||
| POST {{endpoint}} | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "input": "What is the weather like in Vancouver?", | ||
| "stream": false, | ||
| "conversation": { | ||
| "id": "conv_test0000000000000000000000000000000000000000000000" | ||
| } | ||
| } | ||
|
|
||
| ### Step 2: Approve the function call | ||
| # Copy the call_id from the Step 1 response output and replace below. | ||
| # The response will contain: "name": "__hosted_agent_adapter_hitl__" with a "call_id" value. | ||
| POST {{endpoint}} | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "input": [ | ||
| { | ||
| "type": "function_call_output", | ||
| "call_id": "REPLACE_WITH_CALL_ID_FROM_STEP_1", | ||
| "output": "approve" | ||
| } | ||
| ], | ||
| "stream": false, | ||
| "conversation": { | ||
| "id": "conv_test0000000000000000000000000000000000000000000000" | ||
| } | ||
| } | ||
|
|
||
| ### Step 3 (alternative): Reject the function call | ||
| # Use this instead of Step 2 to deny the tool execution. | ||
| POST {{endpoint}} | ||
| Content-Type: application/json | ||
|
|
||
| { | ||
| "input": [ | ||
| { | ||
| "type": "function_call_output", | ||
| "call_id": "REPLACE_WITH_CALL_ID_FROM_STEP_1", | ||
| "output": "reject" | ||
| } | ||
| ], | ||
| "stream": false, | ||
| "conversation": { | ||
| "id": "conv_test0000000000000000000000000000000000000000000000" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
dotnet/samples/05-end-to-end/HostedAgents/AgentWithLocalTools/.dockerignore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| **/.dockerignore | ||
| **/.env | ||
| **/.git | ||
| **/.gitignore | ||
| **/.project | ||
| **/.settings | ||
| **/.toolstarget | ||
| **/.vs | ||
| **/.vscode | ||
| **/*.*proj.user | ||
| **/*.dbmdl | ||
| **/*.jfm | ||
| **/azds.yaml | ||
| **/bin | ||
| **/charts | ||
| **/docker-compose* | ||
| **/Dockerfile* | ||
| **/node_modules | ||
| **/npm-debug.log | ||
| **/obj | ||
| **/secrets.dev.yaml | ||
| **/values.dev.yaml | ||
| LICENSE | ||
| README.md |
70 changes: 70 additions & 0 deletions
70
dotnet/samples/05-end-to-end/HostedAgents/AgentWithLocalTools/AgentWithLocalTools.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworks>net10.0</TargetFrameworks> | ||
|
|
||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <EnablePreviewFeatures>true</EnablePreviewFeatures> | ||
|
|
||
| <!-- | ||
| Disable central package management for this project. | ||
| This project requires explicit package references with versions specified inline rather than | ||
| inheriting them from Directory.Packages.props. This is necessary because a Docker image will | ||
| be created from this project, and the Docker build process only has access to this folder | ||
| and cannot access parent folders where Directory.Packages.props resides. | ||
| --> | ||
| <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally> | ||
| </PropertyGroup> | ||
|
|
||
| <!-- | ||
| Remove analyzer PackageReference items inherited from Directory.Packages.props. | ||
| Note: ManagePackageVersionsCentrally only controls PackageVersion items, not PackageReference items. | ||
| Directory.Packages.props contains both PackageVersion and PackageReference entries for analyzers, | ||
| and the PackageReference items are always inherited through MSBuild imports regardless of the | ||
| ManagePackageVersionsCentrally setting. We must explicitly remove them before adding our own versions. | ||
| --> | ||
| <ItemGroup> | ||
| <PackageReference Remove="Microsoft.CodeAnalysis.NetAnalyzers" /> | ||
| <PackageReference Remove="Microsoft.VisualStudio.Threading.Analyzers" /> | ||
| <PackageReference Remove="xunit.analyzers" /> | ||
| <PackageReference Remove="Moq.Analyzers" /> | ||
| <PackageReference Remove="Roslynator.Analyzers" /> | ||
| <PackageReference Remove="Roslynator.CodeAnalysis.Analyzers" /> | ||
| <PackageReference Remove="Roslynator.Formatting.Analyzers" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Azure.AI.AgentServer.AgentFramework" Version="1.0.0-beta.8" /> | ||
| <PackageReference Include="Azure.AI.Projects" Version="1.2.0-beta.5" /> | ||
| <PackageReference Include="Azure.AI.OpenAI" Version="2.8.0-beta.1" /> | ||
| <PackageReference Include="Azure.Identity" Version="1.17.1" /> | ||
| <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="10.3.0" /> | ||
| </ItemGroup> | ||
|
|
||
| <!-- Add analyzers with compatible versions --> | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Roslynator.Analyzers" Version="4.14.1"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1"> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| </PackageReference> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.