-
Notifications
You must be signed in to change notification settings - Fork 1k
Python: ADR for create/get agent API #2618
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
dmytrostruk
merged 32 commits into
microsoft:main
from
dmytrostruk:create-agent-updates
Jan 13, 2026
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
00f733c
ADR for create/get agent API
dmytrostruk cd815aa
Merge branch 'main' into create-agent-updates
dmytrostruk 9095e18
Merge branch 'main' into create-agent-updates
dmytrostruk 4a97abe
Merge branch 'main' into create-agent-updates
dmytrostruk 8212dd6
Merge branch 'main' into create-agent-updates
dmytrostruk 8dfb988
Merge branch 'main' into create-agent-updates
dmytrostruk 29faa12
Merge branch 'main' into create-agent-updates
dmytrostruk 5cada6e
Updated ADR with implementation options
dmytrostruk e8907b0
Merge branch 'main' into create-agent-updates
dmytrostruk 0b9bef4
Merge branch 'main' into create-agent-updates
dmytrostruk a50bbbf
Merge branch 'main' into create-agent-updates
dmytrostruk 21bb03f
Merge branch 'main' into create-agent-updates
dmytrostruk 9f97e4e
Merge branch 'main' into create-agent-updates
dmytrostruk bda731f
Small updates
dmytrostruk 238b631
Merge branch 'create-agent-updates' of https://github.com/dmytrostruk…
dmytrostruk 7fbcc08
Merge branch 'main' into create-agent-updates
dmytrostruk 950fc37
Updated decision outcome section
dmytrostruk f87fcc6
Updated broken links
dmytrostruk 933ab5b
Merge branch 'main' into create-agent-updates
dmytrostruk 7da1a6b
Merge branch 'main' into create-agent-updates
dmytrostruk 2a78424
Small updates
dmytrostruk ee9d4d1
Fixed merge conflicts
dmytrostruk 02ae9d6
Small fix
dmytrostruk 4413b6e
Merge branch 'main' into create-agent-updates
dmytrostruk 86efe5b
Merge branch 'main' into create-agent-updates
dmytrostruk de31d11
Updated decision outcome section
dmytrostruk d1fa6f6
Small fixes
dmytrostruk 0d0636c
Merge branch 'main' into create-agent-updates
dmytrostruk cf7f96c
Merge branch 'main' into create-agent-updates
dmytrostruk c020b78
Updated provider naming based on client SDK
dmytrostruk a985c59
Merge branch 'main' into create-agent-updates
dmytrostruk 58d6a6c
Merge branch 'main' into create-agent-updates
dmytrostruk 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,368 @@ | ||
| --- | ||
| status: proposed | ||
| contact: dmytrostruk | ||
| date: 2025-12-12 | ||
| deciders: dmytrostruk, markwallace-microsoft, eavanvalkenburg, giles17 | ||
| --- | ||
|
|
||
| # Create/Get Agent API | ||
|
|
||
| ## Context and Problem Statement | ||
|
|
||
| There is a misalignment between the create/get agent API in the .NET and Python implementations. | ||
|
|
||
| In .NET, the `CreateAIAgent` method can create either a local instance of an agent or a remote instance if the backend provider supports it. For remote agents, once the agent is created, you can retrieve an existing remote agent by using the `GetAIAgent` method. If a backend provider doesn't support remote agents, `CreateAIAgent` just initializes a new local agent instance and `GetAIAgent` is not available. There is also a `BuildAIAgent` method, which is an extension for the `ChatClientBuilder` class from `Microsoft.Extensions.AI`. It builds pipelines of `IChatClient` instances with an `IServiceProvider`. This functionality does not exist in Python, so `BuildAIAgent` is out of scope. | ||
|
|
||
| In Python, there is only one `create_agent` method, which always creates a local instance of the agent. If the backend provider supports remote agents, the remote agent is created only on the first `agent.run()` invocation. | ||
|
|
||
| Below is a short summary of different providers and their APIs in .NET: | ||
|
|
||
| | Package | Method | Behavior | Python support | | ||
| |---|---|---|---| | ||
| | Microsoft.Agents.AI | `CreateAIAgent` (based on `IChatClient`) | Creates a local instance of `ChatClientAgent`. | Yes (`create_agent` in `BaseChatClient`). | | ||
| | Microsoft.Agents.AI.Anthropic | `CreateAIAgent` (based on `IBetaService` and `IAnthropicClient`) | Creates a local instance of `ChatClientAgent`. | Yes (`AnthropicClient` inherits `BaseChatClient`, which exposes `create_agent`). | | ||
| | Microsoft.Agents.AI.AzureAI (V2) | `GetAIAgent` (based on `AIProjectClient` with `AgentReference`) | Creates a local instance of `ChatClientAgent`. | Partial (Python uses `create_agent` from `BaseChatClient`). | | ||
| | Microsoft.Agents.AI.AzureAI (V2) | `GetAIAgent`/`GetAIAgentAsync` (with `Name`/`ChatClientAgentOptions`) | Fetches `AgentRecord` via HTTP, then creates a local `ChatClientAgent` instance. | No | | ||
| | Microsoft.Agents.AI.AzureAI (V2) | `CreateAIAgent`/`CreateAIAgentAsync` (based on `AIProjectClient`) | Creates a remote agent first, then wraps it into a local `ChatClientAgent` instance. | No | | ||
| | Microsoft.Agents.AI.AzureAI.Persistent (V1) | `GetAIAgent` (based on `PersistentAgentsClient` with `PersistentAgent`) | Creates a local instance of `ChatClientAgent`. | Partial (Python uses `create_agent` from `BaseChatClient`). | | ||
| | Microsoft.Agents.AI.AzureAI.Persistent (V1) | `GetAIAgent`/`GetAIAgentAsync` (with `AgentId`) | Fetches `PersistentAgent` via HTTP, then creates a local `ChatClientAgent` instance. | No | | ||
| | Microsoft.Agents.AI.AzureAI.Persistent (V1) | `CreateAIAgent`/`CreateAIAgentAsync` | Creates a remote agent first, then wraps it into a local `ChatClientAgent` instance. | No | | ||
| | Microsoft.Agents.AI.OpenAI | `GetAIAgent` (based on `AssistantClient` with `Assistant`) | Creates a local instance of `ChatClientAgent`. | Partial (Python uses `create_agent` from `BaseChatClient`). | | ||
| | Microsoft.Agents.AI.OpenAI | `GetAIAgent`/`GetAIAgentAsync` (with `AgentId`) | Fetches `Assistant` via HTTP, then creates a local `ChatClientAgent` instance. | No | | ||
| | Microsoft.Agents.AI.OpenAI | `CreateAIAgent`/`CreateAIAgentAsync` (based on `AssistantClient`) | Creates a remote agent first, then wraps it into a local `ChatClientAgent` instance. | No | | ||
| | Microsoft.Agents.AI.OpenAI | `CreateAIAgent` (based on `ChatClient`) | Creates a local instance of `ChatClientAgent`. | Yes (`create_agent` in `BaseChatClient`). | | ||
| | Microsoft.Agents.AI.OpenAI | `CreateAIAgent` (based on `OpenAIResponseClient`) | Creates a local instance of `ChatClientAgent`. | Yes (`create_agent` in `BaseChatClient`). | | ||
|
|
||
| Another difference between Python and .NET implementation is that in .NET `CreateAIAgent`/`GetAIAgent` methods are implemented as extension methods based on underlying SDK client, like `AIProjectClient` from Azure AI or `AssistantClient` from OpenAI: | ||
|
|
||
| ```csharp | ||
| // Definition | ||
| public static ChatClientAgent CreateAIAgent( | ||
| this AIProjectClient aiProjectClient, | ||
| string name, | ||
| string model, | ||
| string instructions, | ||
| string? description = null, | ||
| IList<AITool>? tools = null, | ||
| Func<IChatClient, IChatClient>? clientFactory = null, | ||
| IServiceProvider? services = null, | ||
| CancellationToken cancellationToken = default) | ||
| { } | ||
|
|
||
| // Usage | ||
| AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); // Initialization of underlying SDK client | ||
|
|
||
| var newAgent = await aiProjectClient.CreateAIAgentAsync(name: AgentName, model: deploymentName, instructions: AgentInstructions, tools: [tool]); // ChatClientAgent creation from underlying SDK client | ||
|
|
||
| // Alternative usage (same as extension method, just explicit syntax) | ||
| var newAgent = await AzureAIProjectChatClientExtensions.CreateAIAgentAsync( | ||
| aiProjectClient, | ||
| name: AgentName, | ||
| model: deploymentName, | ||
| instructions: AgentInstructions, | ||
| tools: [tool]); | ||
| ``` | ||
|
|
||
| Python doesn't support extension methods. Currently `create_agent` method is defined on `BaseChatClient`, but this method only creates a local instance of `ChatAgent` and it can't create remote agents for providers that support it for a couple of reasons: | ||
|
|
||
| - It's defined as non-async. | ||
| - `BaseChatClient` implementation is stateful for providers like Azure AI or OpenAI Assistants. The implementation stores agent/assistant metadata like `AgentId` and `AgentName`, so currently it's not possible to create different instances of `ChatAgent` from a single `BaseChatClient` in case if the implementation is stateful. | ||
|
|
||
| ## Decision Drivers | ||
|
|
||
| - API should be aligned between .NET and Python. | ||
| - API should be intuitive and consistent between backend providers in .NET and Python. | ||
|
|
||
| ## Considered Options | ||
|
|
||
| Add missing implementations on the Python side. This should include the following: | ||
|
|
||
| ### agent-framework-azure-ai (both V1 and V2) | ||
|
|
||
| - Add a `get_agent` method that accepts an underlying SDK agent instance and creates a local instance of `ChatAgent`. | ||
dmytrostruk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - Add a `get_agent` method that accepts an agent identifier, performs an additional HTTP request to fetch agent data, and then creates a local instance of `ChatAgent`. | ||
| - Override the `create_agent` method from `BaseChatClient` to create a remote agent instance and wrap it into a local `ChatAgent`. | ||
|
|
||
| .NET: | ||
|
|
||
| ```csharp | ||
| var agent1 = new AIProjectClient(...).GetAIAgent(agentInstanceFromSdkType); // Creates a local ChatClientAgent instance from Azure.AI.Projects.OpenAI.AgentReference | ||
| var agent2 = new AIProjectClient(...).GetAIAgent(agentName); // Fetches agent data, creates a local ChatClientAgent instance | ||
| var agent3 = new AIProjectClient(...).CreateAIAgent(...); // Creates a remote agent, returns a local ChatClientAgent instance | ||
| ``` | ||
|
|
||
| ### agent-framework-core (OpenAI Assistants) | ||
|
|
||
| - Add a `get_agent` method that accepts an underlying SDK agent instance and creates a local instance of `ChatAgent`. | ||
| - Add a `get_agent` method that accepts an agent name, performs an additional HTTP request to fetch agent data, and then creates a local instance of `ChatAgent`. | ||
| - Override the `create_agent` method from `BaseChatClient` to create a remote agent instance and wrap it into a local `ChatAgent`. | ||
|
|
||
| .NET: | ||
|
|
||
| ```csharp | ||
| var agent1 = new AssistantClient(...).GetAIAgent(agentInstanceFromSdkType); // Creates a local ChatClientAgent instance from OpenAI.Assistants.Assistant | ||
| var agent2 = new AssistantClient(...).GetAIAgent(agentId); // Fetches agent data, creates a local ChatClientAgent instance | ||
| var agent3 = new AssistantClient(...).CreateAIAgent(...); // Creates a remote agent, returns a local ChatClientAgent instance | ||
| ``` | ||
|
|
||
| ### Possible Python implementations | ||
dmytrostruk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Methods like `create_agent` and `get_agent` should be implemented separately or defined on some stateless component that will allow to create multiple agents from the same instance/place. | ||
|
|
||
| Possible options: | ||
|
|
||
| #### Option 1: Module-level functions | ||
|
|
||
| Implement free functions in the provider package that accept the underlying SDK client as the first argument (similar to .NET extension methods, but expressed in Python). | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| from agent_framework.azure import create_agent, get_agent | ||
|
|
||
| ai_project_client = AIProjectClient(...) | ||
|
|
||
| # Creates a remote agent first, then returns a local ChatAgent wrapper | ||
| created_agent = await create_agent( | ||
| ai_project_client, | ||
| name="", | ||
| instructions="", | ||
| tools=[tool], | ||
| ) | ||
dmytrostruk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Gets an existing remote agent and returns a local ChatAgent wrapper | ||
| first_agent = await get_agent(ai_project_client, agent_id=agent_id) | ||
|
|
||
| # Wraps an SDK agent instance (no extra HTTP call) | ||
| second_agent = get_agent(ai_project_client, agent_reference) | ||
| ``` | ||
|
|
||
| Pros: | ||
|
|
||
| - Naturally supports async `create_agent` / `get_agent`. | ||
| - Supports multiple agents per SDK client. | ||
| - Closest conceptual match to .NET extension methods while staying Pythonic. | ||
|
|
||
| Cons: | ||
|
|
||
| - Discoverability is lower (users need to know where the functions live). | ||
dmytrostruk marked this conversation as resolved.
Show resolved
Hide resolved
dmytrostruk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - Verbose when creating multiple agents (client must be passed every time): | ||
|
|
||
| ```python | ||
| agent1 = await azure_agents.create_agent(client, name="Agent1", ...) | ||
| agent2 = await azure_agents.create_agent(client, name="Agent2", ...) | ||
| ``` | ||
|
|
||
| #### Option 2: Provider object | ||
|
|
||
| Introduce a dedicated provider type that is constructed from the underlying SDK client, and exposes async `create_agent` / `get_agent` methods. | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| from agent_framework.azure import AzureAIAgentProvider | ||
|
|
||
| ai_project_client = AIProjectClient(...) | ||
| provider = AzureAIAgentProvider(ai_project_client) | ||
|
|
||
| agent = await provider.create_agent( | ||
| name="", | ||
| instructions="", | ||
| tools=[tool], | ||
| ) | ||
|
|
||
| agent = await provider.get_agent(agent_id=agent_id) | ||
| agent = provider.get_agent(agent_reference=agent_reference) | ||
| ``` | ||
|
|
||
| Pros: | ||
|
|
||
| - High discoverability and clear grouping of related behavior. | ||
| - Keeps SDK clients unchanged and supports multiple agents per SDK client. | ||
| - Concise when creating multiple agents (client passed once): | ||
|
|
||
| ```python | ||
| provider = AzureAIAgentProvider(ai_project_client) | ||
| agent1 = await provider.create_agent(name="Agent1", ...) | ||
| agent2 = await provider.create_agent(name="Agent2", ...) | ||
| ``` | ||
|
|
||
| Cons: | ||
|
|
||
| - Adds a new public concept/type for users to learn. | ||
|
|
||
| #### Option 3: Inheritance (SDK client subclass) | ||
|
|
||
| Create a subclass of the underlying SDK client and add `create_agent` / `get_agent` methods. | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| class ExtendedAIProjectClient(AIProjectClient): | ||
| async def create_agent(self, *, name: str, model: str, instructions: str, **kwargs) -> ChatAgent: | ||
| ... | ||
|
|
||
| async def get_agent(self, *, agent_id: str | None = None, sdk_agent=None, **kwargs) -> ChatAgent: | ||
| ... | ||
|
|
||
| client = ExtendedAIProjectClient(...) | ||
| agent = await client.create_agent(name="", instructions="") | ||
| ``` | ||
|
|
||
| Pros: | ||
|
|
||
| - Discoverable and ergonomic call sites. | ||
| - Mirrors the .NET “methods on the client” feeling. | ||
|
|
||
| Cons: | ||
|
|
||
| - Many SDK clients are not designed for inheritance; SDK upgrades can break subclasses. | ||
| - Users must opt into subclass everywhere. | ||
| - Typing/initialization can be tricky if the SDK client has non-trivial constructors. | ||
|
|
||
| #### Option 4: Monkey patching | ||
dmytrostruk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Attach `create_agent` / `get_agent` methods to an SDK client class (or instance) at runtime. | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| def _create_agent(self, *, name: str, model: str, instructions: str, **kwargs) -> ChatAgent: | ||
| ... | ||
|
|
||
| AIProjectClient.create_agent = _create_agent # monkey patch | ||
| ``` | ||
|
|
||
| Pros: | ||
|
|
||
| - Produces “extension method-like” call sites without wrappers or subclasses. | ||
|
|
||
| Cons: | ||
|
|
||
| - Fragile across SDK updates and difficult to type-check. | ||
| - Surprising behavior (global side effects), potential conflicts across packages. | ||
| - Harder to support/debug, especially in larger apps and test suites. | ||
|
|
||
| ## Decision Outcome | ||
|
|
||
| Implement `create_agent`/`get_agent`/`as_agent` API via **Option 2: Provider object**. | ||
|
|
||
| ### Rationale | ||
|
|
||
| | Aspect | Option 1 (Functions) | Option 2 (Provider) | | ||
| |--------|----------------------|---------------------| | ||
| | Multiple implementations | One package may contain V1, V2, and other agent types. Function names like `create_agent` become ambiguous - which agent type does it create? | Each provider class is explicit: `AzureAIAgentsProvider` vs `AzureAIProjectAgentProvider` | | ||
| | Discoverability | Users must know to import specific functions from the package | IDE autocomplete on provider instance shows all available methods | | ||
| | Client reuse | SDK client must be passed to every function call: `create_agent(client, ...)`, `get_agent(client, ...)` | SDK client passed once at construction: `provider = Provider(client)` | | ||
|
|
||
| **Option 1 example:** | ||
| ```python | ||
| from agent_framework.azure import create_agent, get_agent | ||
| agent1 = await create_agent(client, name="Agent1", ...) # Which agent type, V1 or V2? | ||
| agent2 = await create_agent(client, name="Agent2", ...) # Repetitive client passing | ||
| ``` | ||
|
|
||
| **Option 2 example:** | ||
| ```python | ||
| from agent_framework.azure import AzureAIProjectAgentProvider | ||
| provider = AzureAIProjectAgentProvider(client) # Clear which service, client passed once | ||
| agent1 = await provider.create_agent(name="Agent1", ...) | ||
| agent2 = await provider.create_agent(name="Agent2", ...) | ||
| ``` | ||
|
|
||
| ### Method Naming | ||
|
|
||
| | Operation | Python | .NET | Async | | ||
| |-----------|--------|------|-------| | ||
| | Create on service | `create_agent()` | `CreateAIAgent()` | Yes | | ||
| | Get from service | `get_agent(id=...)` | `GetAIAgent(agentId)` | Yes | | ||
| | Wrap SDK object | `as_agent(reference)` | `AsAIAgent(agentInstance)` | No | | ||
|
|
||
| The method names (`create_agent`, `get_agent`) do not explicitly mention "service" or "remote" because: | ||
| - In Python, the provider class name explicitly identifies the service (`AzureAIAgentsProvider`, `OpenAIAssistantProvider`), making additional qualifiers in method names redundant. | ||
| - In .NET, these are extension methods on `AIProjectClient` or `AssistantClient`, which already imply service operations. | ||
|
|
||
| ### Provider Class Naming | ||
|
|
||
| | Package | Provider Class | SDK Client | Service | | ||
| |---------|---------------|------------|---------| | ||
| | `agent_framework.azure` | `AzureAIProjectAgentProvider` | `AIProjectClient` | Azure AI Agent Service, based on Responses API (V2) | | ||
| | `agent_framework.azure` | `AzureAIAgentsProvider` | `AgentsClient` | Azure AI Agent Service (V1) | | ||
| | `agent_framework.openai` | `OpenAIAssistantProvider` | `AsyncOpenAI` | OpenAI Assistants API | | ||
|
|
||
| > **Note:** Azure AI naming is temporary. Final naming will be updated according to Azure AI / Microsoft Foundry renaming decisions. | ||
|
|
||
| ### Usage Examples | ||
|
|
||
| #### Azure AI Agent Service V2 (based on Responses API) | ||
|
|
||
| ```python | ||
| from agent_framework.azure import AzureAIProjectAgentProvider | ||
| from azure.ai.projects import AIProjectClient | ||
|
|
||
| client = AIProjectClient(endpoint, credential) | ||
| provider = AzureAIProjectAgentProvider(client) | ||
|
|
||
| # Create new agent on service | ||
| agent = await provider.create_agent(name="MyAgent", model="gpt-4", instructions="...") | ||
|
|
||
| # Get existing agent by name | ||
| agent = await provider.get_agent(agent_name="MyAgent") | ||
|
|
||
| # Wrap already-fetched SDK object (no HTTP calls) | ||
| agent_ref = await client.agents.get("MyAgent") | ||
| agent = provider.as_agent(agent_ref) | ||
| ``` | ||
|
|
||
| #### Azure AI Persistent Agents V1 | ||
|
|
||
| ```python | ||
| from agent_framework.azure import AzureAIAgentsProvider | ||
| from azure.ai.agents import AgentsClient | ||
|
|
||
| client = AgentsClient(endpoint, credential) | ||
| provider = AzureAIAgentsProvider(client) | ||
|
|
||
| agent = await provider.create_agent(name="MyAgent", model="gpt-4", instructions="...") | ||
| agent = await provider.get_agent(agent_id="persistent-agent-456") | ||
| agent = provider.as_agent(persistent_agent) | ||
| ``` | ||
|
|
||
| #### OpenAI Assistants | ||
|
|
||
| ```python | ||
| from agent_framework.openai import OpenAIAssistantProvider | ||
| from openai import OpenAI | ||
|
|
||
| client = OpenAI() | ||
| provider = OpenAIAssistantProvider(client) | ||
|
|
||
| agent = await provider.create_agent(name="MyAssistant", model="gpt-4", instructions="...") | ||
| agent = await provider.get_agent(assistant_id="asst_123") | ||
| agent = provider.as_agent(assistant) | ||
| ``` | ||
|
|
||
| #### Local-Only Agents (No Provider) | ||
|
|
||
| Current method `create_agent` (python) / `CreateAIAgent` (.NET) can be renamed to `as_agent` (python) / `AsAIAgent` (.NET) to emphasize the conversion logic rather than creation/initialization logic and to avoid collision with `create_agent` method for remote calls. | ||
|
|
||
| ```python | ||
| from agent_framework import ChatAgent | ||
| from agent_framework.openai import OpenAIChatClient | ||
|
|
||
| # Convert chat client to ChatAgent (no remote service involved) | ||
| client = OpenAIChatClient(model="gpt-4") | ||
| agent = client.as_agent(name="LocalAgent", instructions="...") # instead of create_agent | ||
| ``` | ||
|
|
||
| ### Adding New Agent Types | ||
|
|
||
| Python: | ||
|
|
||
| 1. Create provider class in appropriate package. | ||
| 2. Implement `create_agent`, `get_agent`, `as_agent` as applicable. | ||
|
|
||
| .NET: | ||
|
|
||
| 1. Create static class for extension methods. | ||
| 2. Implement `CreateAIAgentAsync`, `GetAIAgentAsync`, `AsAIAgent` as applicable. | ||
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.