-
Notifications
You must be signed in to change notification settings - Fork 1.8k
.NET: Add Hosted-ToolboxMcpSkills sample #6175
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
semenshi
merged 6 commits into
microsoft:main
from
semenshi:feature/hosted-toolbox-mcp-skills-sample
Jun 2, 2026
+358
−0
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
dd09623
.NET: Add Hosted-ToolboxMcpSkills sample
semenshi 4fa19c3
Align README and Program.cs default model to gpt-5
semenshi 0b3792d
Clarify MCP skills provider log to avoid implying eager discovery
semenshi c906f23
Drop redundant skills provider configured log
semenshi a9a3444
Add Foundry Toolbox Skills tag to manifest
semenshi 651de9e
Simplify BearerTokenHandler by deriving from HttpClientHandler
semenshi 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
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
6 changes: 6 additions & 0 deletions
6
dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/.env.example
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,6 @@ | ||
| AZURE_AI_PROJECT_ENDPOINT=<your-azure-ai-project-endpoint> | ||
| ASPNETCORE_URLS=http://+:8088 | ||
| ASPNETCORE_ENVIRONMENT=Development | ||
| AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-5 | ||
| FOUNDRY_TOOLBOX_NAME=<your-toolbox-name> | ||
| AZURE_BEARER_TOKEN=DefaultAzureCredential | ||
26 changes: 26 additions & 0 deletions
26
dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/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,26 @@ | ||
| # Dockerfile for end-users consuming the Agent Framework via NuGet packages. | ||
| # | ||
| # This Dockerfile performs a full `dotnet restore` and `dotnet publish` inside the container, | ||
| # which only succeeds when the project references its dependencies via PackageReference (see the | ||
| # commented-out section in HostedToolboxMcpSkills.csproj). Contributors building from the | ||
| # agent-framework repository source must use Dockerfile.contributor instead because | ||
| # ProjectReference dependencies live outside this folder and cannot be restored from inside | ||
| # this build context. | ||
| # | ||
| # Use the official .NET 10.0 ASP.NET runtime as a parent image | ||
| FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base | ||
| WORKDIR /app | ||
|
|
||
| FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build | ||
| WORKDIR /src | ||
| COPY . . | ||
| RUN dotnet restore | ||
| RUN dotnet publish -c Release -o /app/publish | ||
|
|
||
| # Final stage | ||
| FROM base AS final | ||
| WORKDIR /app | ||
| COPY --from=build /app/publish . | ||
| EXPOSE 8088 | ||
| ENV ASPNETCORE_URLS=http://+:8088 | ||
| ENTRYPOINT ["dotnet", "HostedToolboxMcpSkills.dll"] |
18 changes: 18 additions & 0 deletions
18
...s/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/Dockerfile.contributor
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,18 @@ | ||
| # Dockerfile for contributors building from the agent-framework repository source. | ||
| # | ||
| # This project uses ProjectReference to the local source, which means a standard | ||
| # multi-stage Docker build cannot resolve dependencies outside this folder. | ||
| # Pre-publish the app targeting the container runtime and copy the output: | ||
| # | ||
| # dotnet publish -c Debug -f net10.0 -r linux-musl-x64 --self-contained false -o out | ||
| # docker build -f Dockerfile.contributor -t hosted-toolbox-mcp-skills . | ||
| # docker run --rm -p 8088:8088 -e AGENT_NAME=hosted-toolbox-mcp-skills -e AZURE_BEARER_TOKEN=$AZURE_BEARER_TOKEN --env-file .env hosted-toolbox-mcp-skills | ||
| # | ||
| # For end-users consuming the NuGet package (not ProjectReference), use the standard | ||
| # Dockerfile which performs a full dotnet restore + publish inside the container. | ||
| FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final | ||
| WORKDIR /app | ||
| COPY out/ . | ||
| EXPOSE 8088 | ||
| ENV ASPNETCORE_URLS=http://+:8088 | ||
| ENTRYPOINT ["dotnet", "HostedToolboxMcpSkills.dll"] |
36 changes: 36 additions & 0 deletions
36
...sting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/HostedToolboxMcpSkills.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,36 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFrameworks>net10.0</TargetFrameworks> | ||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled> | ||
| <RootNamespace>HostedToolboxMcpSkills</RootNamespace> | ||
| <AssemblyName>HostedToolboxMcpSkills</AssemblyName> | ||
| <NoWarn>$(NoWarn);</NoWarn> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Azure.AI.Projects" /> | ||
| <PackageReference Include="Azure.Identity" /> | ||
| <PackageReference Include="ModelContextProtocol" VersionOverride="1.2.0" /> | ||
| <PackageReference Include="DotNetEnv" /> | ||
| </ItemGroup> | ||
|
|
||
| <!-- For contributors: uses ProjectReference to build against local source --> | ||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.Foundry\Microsoft.Agents.AI.Foundry.csproj" /> | ||
| <ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.Foundry.Hosting\Microsoft.Agents.AI.Foundry.Hosting.csproj" /> | ||
| <ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.Mcp\Microsoft.Agents.AI.Mcp.csproj" /> | ||
| <ProjectReference Include="..\Hosted_Shared_Contributor_Setup\Hosted_Shared_Contributor_Setup.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| <!-- For end-users: uncomment the PackageReference below and remove the ProjectReference above | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Agents.AI.Foundry" Version="1.6.1-preview.260514.1" /> | ||
| <PackageReference Include="Microsoft.Agents.AI.Foundry.Hosting" Version="1.6.1-preview.260514.1" /> | ||
| <PackageReference Include="Microsoft.Agents.AI.Mcp" Version="1.6.1-preview.260514.1" /> | ||
| </ItemGroup> | ||
| --> | ||
|
|
||
| </Project> |
109 changes: 109 additions & 0 deletions
109
dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/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,109 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| // Hosted Toolbox MCP Skills Agent | ||
| // | ||
| // Demonstrates how to host an agent that discovers MCP-based skills from a | ||
| // Foundry Toolbox MCP endpoint and injects them as AIContextProviders using | ||
| // AgentSkillsProviderBuilder.UseMcpSkills(). | ||
| // | ||
| // Required environment variables: | ||
| // AZURE_AI_PROJECT_ENDPOINT - Azure AI Foundry project endpoint | ||
| // FOUNDRY_TOOLBOX_NAME - Name of the Foundry Toolbox to connect to | ||
| // AZURE_AI_MODEL_DEPLOYMENT_NAME - Model deployment name (default: gpt-5) | ||
|
|
||
| using System.Net.Http.Headers; | ||
| using Azure.AI.Projects; | ||
| using Azure.Core; | ||
| using Azure.Identity; | ||
| using DotNetEnv; | ||
| using Hosted_Shared_Contributor_Setup; | ||
| using Microsoft.Agents.AI; | ||
| using Microsoft.Agents.AI.Foundry.Hosting; | ||
| using ModelContextProtocol.Client; | ||
|
|
||
| // Load .env file if present (for local development) | ||
| Env.TraversePath().Load(); | ||
|
|
||
| var projectEndpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") | ||
| ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set."); | ||
| var deployment = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-5"; | ||
| var toolboxName = Environment.GetEnvironmentVariable("FOUNDRY_TOOLBOX_NAME") | ||
| ?? throw new InvalidOperationException("FOUNDRY_TOOLBOX_NAME is not set."); | ||
|
|
||
| // Build the Toolbox MCP URL from the project endpoint and toolbox name. | ||
| var toolboxMcpServerUrl = $"{projectEndpoint.TrimEnd('/')}/toolboxes/{toolboxName}/mcp?api-version=v1"; | ||
|
|
||
| // Use a chained credential: try a temporary dev token first (for local Docker debugging), | ||
| // then fall back to DefaultAzureCredential (for local dev via dotnet run / managed identity in production). | ||
| TokenCredential credential = new ChainedTokenCredential( | ||
| new DevTemporaryTokenCredential(), | ||
| new DefaultAzureCredential()); | ||
|
|
||
| // ── Connect to the Foundry Toolbox MCP endpoint ───────────────────────────── | ||
| // Create an HttpClient that attaches a fresh Foundry bearer token to every request. | ||
| using var httpClient = new HttpClient(new BearerTokenHandler(credential, "https://ai.azure.com/.default") { CheckCertificateRevocationList = true }); | ||
|
|
||
| Console.WriteLine($"Connecting to Foundry Toolbox '{toolboxName}' MCP server..."); | ||
|
|
||
| await using var mcpClient = await McpClient.CreateAsync( | ||
| new HttpClientTransport( | ||
| new HttpClientTransportOptions | ||
| { | ||
| Endpoint = new Uri(toolboxMcpServerUrl), | ||
| Name = toolboxName, | ||
| TransportMode = HttpTransportMode.StreamableHttp, | ||
| AdditionalHeaders = new Dictionary<string, string> | ||
| { | ||
| ["Foundry-Features"] = "Toolboxes=V1Preview", | ||
| }, | ||
| }, | ||
| httpClient)); | ||
|
|
||
| // ── Configure MCP-based skills provider ────────────────────────────────────── | ||
| var skillsProvider = new AgentSkillsProviderBuilder() | ||
| .UseMcpSkills(mcpClient) | ||
| .Build(); | ||
|
|
||
| // ── Create the agent ───────────────────────────────────────────────────────── | ||
| AIAgent agent = new AIProjectClient(new Uri(projectEndpoint), credential) | ||
| .AsAIAgent(new ChatClientAgentOptions | ||
| { | ||
| Name = Environment.GetEnvironmentVariable("AGENT_NAME") ?? "hosted-toolbox-mcp-skills", | ||
| Description = "Hosted agent with MCP skills discovered from a Foundry Toolbox", | ||
| ChatOptions = new() | ||
| { | ||
| ModelId = deployment, | ||
| Instructions = "You are a helpful assistant.", | ||
| }, | ||
| AIContextProviders = [skillsProvider], | ||
| }); | ||
|
|
||
| // ── Build the host ─────────────────────────────────────────────────────────── | ||
| var builder = WebApplication.CreateBuilder(args); | ||
| builder.Services.AddFoundryResponses(agent); | ||
| builder.Services.AddDevTemporaryLocalContributorSetup(); // Local Docker debugging only - must not be used in production. | ||
|
|
||
| var app = builder.Build(); | ||
| app.MapFoundryResponses(); | ||
|
|
||
| // Contributor-only: in Development, also map the per-agent OpenAI route shape that live Foundry uses | ||
| // so a local REPL client can target this server via AIProjectClient.AsAIAgent(Uri agentEndpoint). | ||
| // Do not use this in production. Hosted Foundry agents only support the agent-endpoint path. | ||
| app.MapDevTemporaryLocalAgentEndpoint(); | ||
|
|
||
| app.Run(); | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // HttpClientHandler: attaches a fresh Foundry bearer token to every request | ||
| // --------------------------------------------------------------------------- | ||
| internal sealed class BearerTokenHandler(TokenCredential credential, string scope) : HttpClientHandler | ||
| { | ||
| private readonly TokenRequestContext _tokenContext = new([scope]); | ||
|
|
||
| protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
| { | ||
| AccessToken token = await credential.GetTokenAsync(this._tokenContext, cancellationToken).ConfigureAwait(false); | ||
| request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token); | ||
| return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); | ||
| } | ||
| } |
103 changes: 103 additions & 0 deletions
103
...ples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/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,103 @@ | ||
| # Hosted-ToolboxMcpSkills | ||
|
|
||
| A hosted agent that discovers **MCP-based skills from a Foundry Toolbox** and makes them available to the agent using `AgentSkillsProviderBuilder.UseMcpSkills(mcpClient)`. | ||
|
|
||
| The `AgentSkillsProvider` is attached to the agent as a context provider and implements the [Agent Skills](https://agentskills.io/) progressive-disclosure pattern. When the agent is prompted, it discovers available skills in the Foundry Toolbox via the provider: | ||
|
|
||
| 1. **Advertise** - skill names and descriptions are injected into the system prompt so the agent knows what is available. | ||
| 2. **Load** - when the agent decides a skill is relevant, it retrieves the full skill body with detailed instructions via the provider. | ||
| 3. **Read resources** - if a skill includes supplementary content (reference documents, assets), the agent reads them on demand via the provider. | ||
|
|
||
| This way the full skill body and resources are only loaded when the agent actually needs them, reducing token usage. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) | ||
| - An Azure AI Foundry project with a deployed model (e.g., `gpt-5`) | ||
| - A Foundry Toolbox already configured with skills provisioned | ||
| - Azure CLI logged in (`az login`) | ||
|
|
||
| ## Configuration | ||
|
|
||
| Copy the template and fill in your values: | ||
|
|
||
| ```bash | ||
| cp .env.example .env | ||
| ``` | ||
|
|
||
| Edit `.env` and set your Azure AI Foundry project endpoint and toolbox name: | ||
|
|
||
| ```env | ||
| AZURE_AI_PROJECT_ENDPOINT=https://<your-account>.services.ai.azure.com/api/projects/<your-project> | ||
| ASPNETCORE_URLS=http://+:8088 | ||
| ASPNETCORE_ENVIRONMENT=Development | ||
| AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-5 | ||
| FOUNDRY_TOOLBOX_NAME=my-toolbox | ||
| ``` | ||
|
|
||
| > **Note:** `.env` is gitignored. The `.env.example` template is checked in as a reference. | ||
|
|
||
| ## Running directly (contributors) | ||
|
|
||
| This project uses `ProjectReference` to build against the local Agent Framework source. | ||
|
|
||
| ```bash | ||
| cd dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills | ||
| dotnet run | ||
| ``` | ||
|
|
||
| The agent will start on `http://localhost:8088`. | ||
|
|
||
| ### Test it | ||
|
|
||
| Using the Azure Developer CLI: | ||
|
|
||
| ```bash | ||
| azd ai agent invoke --local "What skills do you have available?" | ||
| ``` | ||
|
|
||
| ## Running with Docker | ||
|
|
||
| Since this project uses `ProjectReference`, use `Dockerfile.contributor` which takes a pre-published output. | ||
|
|
||
| ### 1. Publish for the container runtime (Linux Alpine) | ||
|
|
||
| ```bash | ||
| dotnet publish -c Debug -f net10.0 -r linux-musl-x64 --self-contained false -o out | ||
| ``` | ||
|
|
||
| ### 2. Build the Docker image | ||
|
|
||
| ```bash | ||
| docker build -f Dockerfile.contributor -t hosted-toolbox-mcp-skills . | ||
| ``` | ||
|
|
||
| ### 3. Run the container | ||
|
|
||
| Generate a bearer token on your host and pass it to the container: | ||
|
|
||
| ```bash | ||
| # Generate token (expires in ~1 hour) | ||
| export AZURE_BEARER_TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv) | ||
|
|
||
| # Run with token | ||
| docker run --rm -p 8088:8088 \ | ||
| -e AGENT_NAME=hosted-toolbox-mcp-skills \ | ||
| -e AZURE_BEARER_TOKEN=$AZURE_BEARER_TOKEN \ | ||
| --env-file .env \ | ||
| hosted-toolbox-mcp-skills | ||
| ``` | ||
|
|
||
| > **Note:** `AGENT_NAME` is passed via `-e` to simulate the platform injection. `AZURE_BEARER_TOKEN` provides Azure credentials to the container (tokens expire after ~1 hour). The `.env` file provides the remaining configuration. | ||
|
|
||
| ### 4. Test it | ||
|
|
||
| Using the Azure Developer CLI: | ||
|
|
||
| ```bash | ||
| azd ai agent invoke --local "What skills do you have available?" | ||
| ``` | ||
|
|
||
| ## NuGet package users | ||
|
|
||
| If you are consuming the Agent Framework as a NuGet package (not building from source), use the standard `Dockerfile` instead of `Dockerfile.contributor`. See the commented section in `HostedToolboxMcpSkills.csproj` for the `PackageReference` alternative. |
43 changes: 43 additions & 0 deletions
43
...ples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/agent.manifest.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,43 @@ | ||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/AgentManifest.yaml | ||
| name: hosted-toolbox-mcp-skills | ||
| displayName: "Hosted Toolbox MCP Skills Agent" | ||
|
|
||
| description: > | ||
| A hosted agent that discovers MCP-based skills from a Foundry Toolbox | ||
| and makes them available to the agent via the agent skills provider. | ||
|
|
||
| metadata: | ||
| tags: | ||
| - AI Agent Hosting | ||
| - Azure AI AgentServer | ||
| - Responses Protocol | ||
| - Agent Framework | ||
| - MCP | ||
| - Model Context Protocol | ||
| - Agent Skills | ||
| - Foundry Toolbox | ||
| - Foundry Toolbox Skills | ||
|
|
||
| template: | ||
| name: hosted-toolbox-mcp-skills | ||
| kind: hosted | ||
| protocols: | ||
| - protocol: responses | ||
| version: 1.0.0 | ||
| resources: | ||
| cpu: "0.25" | ||
| memory: 0.5Gi | ||
| environment_variables: | ||
| - name: AZURE_AI_MODEL_DEPLOYMENT_NAME | ||
| value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}" | ||
| - name: FOUNDRY_TOOLBOX_NAME | ||
| value: "{{FOUNDRY_TOOLBOX_NAME}}" | ||
| parameters: | ||
| properties: | ||
| - name: FOUNDRY_TOOLBOX_NAME | ||
| secret: false | ||
| description: Name of the Foundry Toolbox to connect to for MCP skill discovery | ||
| resources: | ||
| - kind: model | ||
| id: gpt-5 | ||
| name: AZURE_AI_MODEL_DEPLOYMENT_NAME |
14 changes: 14 additions & 0 deletions
14
dotnet/samples/04-hosting/FoundryHostedAgents/responses/Hosted-ToolboxMcpSkills/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,14 @@ | ||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml | ||
| kind: hosted | ||
| name: hosted-toolbox-mcp-skills | ||
| protocols: | ||
| - protocol: responses | ||
| version: 1.0.0 | ||
| resources: | ||
| cpu: "0.25" | ||
| memory: 0.5Gi | ||
| environment_variables: | ||
| - name: AZURE_AI_MODEL_DEPLOYMENT_NAME | ||
| value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME} | ||
| - name: FOUNDRY_TOOLBOX_NAME | ||
| value: ${FOUNDRY_TOOLBOX_NAME} |
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.