Start Debugging

Microsoft Agent Framework vs Semantic Kernel for a Greenfield .NET Agent

For a new .NET agent in 2026, start on Microsoft Agent Framework 1.0. Semantic Kernel is in maintenance mode. Here is the side-by-side and the one case where SK still wins.

If you are starting a brand-new .NET agent today and want the one-line answer: build it on Microsoft Agent Framework 1.0 (Microsoft.Agents.AI, currently 1.7.0 on NuGet, GA’d April 3, 2026), not Semantic Kernel. Microsoft’s own product team says the same thing in plain words: “If you are starting a new project and can wait until Microsoft Agent Framework reaches General Availability before shipping, we recommend starting with Microsoft Agent Framework.” That release happened, so the qualifier is gone. Semantic Kernel (Microsoft.SemanticKernel 1.77.0 as of late May 2026) is still shipping and still supported, but it is now the legacy track: critical bugs and security fixes only, with the majority of new features going to Agent Framework. The rest of this post is why that is the right call for greenfield, the exact code differences you will hit on day one, and the one scenario where reaching for Semantic Kernel is still defensible.

Why this is even a question

The confusing part is that both libraries come from the same team at Microsoft, both target .NET 10 and Python, and both let you build a tool-calling agent over OpenAI, Azure OpenAI, Anthropic, Bedrock, Gemini, or Ollama. They are not competitors in the usual sense. Microsoft’s framing is blunt: “Think of Microsoft Agent Framework as Semantic Kernel v2.0 (it’s built by the same team!).” Agent Framework folds in the enterprise plumbing that made Semantic Kernel useful and the multi-agent orchestration patterns that came out of AutoGen, then drops the Kernel god-object that every Semantic Kernel agent had to be wired through. If you have followed what shipped in Agent Framework 1.0, the headline is that the AutoGen/Semantic Kernel split is over and there is now one SDK.

So the real question is not “which is better” in the abstract. For a greenfield project, it is “is there any reason to start on the framework Microsoft has explicitly put into maintenance mode?” Usually the answer is no.

The matrix that decides it

DimensionMicrosoft Agent Framework 1.0Semantic Kernel 1.77
NuGet packageMicrosoft.Agents.AI (1.7.0)Microsoft.SemanticKernel (1.77.0)
Status (June 2026)active, all new featuresmaintenance: critical bugs + security only
Core abstractionAIAgent over IChatClientKernel + ChatCompletionAgent
Agent creationone extension call, no container objectrequires a built Kernel instance
Agent typesone ChatClientAgent for all providersChatCompletionAgent, AzureAIAgent, OpenAIAssistantAgent, …
Tool registrationpass a method to tools:, no attribute[KernelFunction] + plugin + add to Kernel
InvocationRunAsync returns one AgentResponseInvokeAsync returns an IAsyncEnumerable
Thread/sessionagent.CreateSessionAsync()caller picks the thread subclass manually
Message typesMicrosoft.Extensions.AI (shared)Semantic Kernel’s own ChatMessageContent
Multi-agentsequential, concurrent, handoff, group chat, Magentic-Onehandoff via experimental agent orchestration
Long-term supportyes, GA stability commitmentat least 1 year past Agent Framework GA

Read it top to bottom and the decision makes itself on the status row. You do not start a multi-year project on the library whose own maintainers are routing new work elsewhere. Everything below the status row is just Agent Framework removing boilerplate that Semantic Kernel made mandatory.

The same agent, written both ways

The fastest way to feel the difference is to write a trivial tool-calling agent in each. Here is Semantic Kernel. Notice how much of the code is ceremony around the Kernel:

// Semantic Kernel 1.77, .NET 10, Microsoft.SemanticKernel + .Agents.Core
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;

// A tool has to be a [KernelFunction] inside a plugin class.
public class WeatherTools
{
    [KernelFunction, System.ComponentModel.Description("Get the weather for a city")]
    public static string GetWeather(string city) => $"It is 21C and clear in {city}.";
}

// You cannot make an agent without a Kernel, even for one call.
Kernel kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4o-mini", "your-api-key")
    .Build();
kernel.Plugins.AddFromType<WeatherTools>();

ChatCompletionAgent agent = new()
{
    Name = "Concierge",
    Instructions = "You are a concise travel concierge.",
    Kernel = kernel,
    Arguments = new(new OpenAIPromptExecutionSettings
    {
        FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
    })
};

AgentThread thread = new ChatHistoryAgentThread();
await foreach (var item in agent.InvokeAsync("What should I pack for Lisbon?", thread))
{
    Console.WriteLine(item.Message);
}

Four things are mandatory here that have nothing to do with your agent: building a Kernel, decorating the tool with [KernelFunction], registering the plugin type on the kernel, and knowing that ChatHistoryAgentThread is the thread subclass you want. The same agent in Agent Framework drops all four:

// Microsoft Agent Framework 1.0, .NET 10, Microsoft.Agents.AI
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;

// A tool is just a method. Description is optional.
[System.ComponentModel.Description("Get the weather for a city")]
static string GetWeather(string city) => $"It is 21C and clear in {city}.";

AIAgent agent = new OpenAIClient("your-api-key")
    .GetChatClient("gpt-4o-mini")
    .AsIChatClient()
    .CreateAIAgent(
        instructions: "You are a concise travel concierge.",
        tools: [AIFunctionFactory.Create(GetWeather)]);

AgentResponse response = await agent.RunAsync("What should I pack for Lisbon?");
Console.WriteLine(response.Text);

There is no Kernel. The tool is a plain static method wrapped by AIFunctionFactory.Create, the same factory you would use when adding tool calling to a raw Microsoft.Extensions.AI chat client. RunAsync returns a single AgentResponse whose .Text is the answer and whose .Messages holds the full transcript including tool calls. If you want to manage conversation history across turns, await agent.CreateSessionAsync() gives you a session and you pass it to RunAsync. The framework picks the right session implementation for the provider so you never new-up a thread subclass by hand.

When to pick Microsoft Agent Framework

For a greenfield .NET agent in 2026, this is the default, and these are the concrete reasons:

When Semantic Kernel is still the right call

Not never. There is one honest scenario and a couple of soft ones:

None of these apply to a true greenfield project with no deadline gun to your head. That is exactly the case Microsoft points at Agent Framework.

The gotcha that quietly picks for you

The decision often gets made by a detail nobody puts in the comparison table: message and content types. Semantic Kernel uses its own ChatMessageContent and StreamingChatMessageContent hierarchy. Agent Framework uses the ChatMessage and AIContent types from Microsoft.Extensions.AI, the same abstraction layer that the rest of the modern .NET AI stack standardized on. If your service already calls IChatClient anywhere, returns Microsoft.Extensions.AI types from a RAG pipeline, or shares DTOs with a non-agent code path, Agent Framework slots in with zero adapter code and Semantic Kernel forces a translation boundary at every seam.

Dependency injection makes the same point. Semantic Kernel needs a Kernel registered in the container before any agent can be constructed:

// Semantic Kernel: the Kernel registration is mandatory.
services.AddKernel().AddOpenAIChatCompletion("gpt-4o-mini", apiKey);
services.AddKeyedSingleton<Agent>("concierge", (sp, _) =>
    new ChatCompletionAgent { Kernel = sp.GetRequiredService<Kernel>() });

Agent Framework registers the agent directly, because there is no intermediate object it has to hang off:

// Agent Framework: register the AIAgent itself.
services.AddKeyedSingleton<AIAgent>("concierge", (sp, _) =>
    sp.GetRequiredService<IChatClient>()
      .CreateAIAgent(instructions: "You are a concise travel concierge."));

Across a real app those small removals compound. The plugin-versus-method difference alone is the subject of a whole post on function tools in Agent Framework, and the pattern there, a plain method with an optional [Description], is the one you will reach for ninety percent of the time.

Restating the call

For a greenfield .NET agent in 2026, build on Microsoft Agent Framework 1.0. It is GA, it is where every new feature lands, it removes the Kernel ceremony Semantic Kernel required, and it shares the Microsoft.Extensions.AI type system with the rest of your stack so the agent is not an island. Reach for Semantic Kernel only when you are extending an existing SK app, when you need a feature that has not crossed to Agent Framework GA yet, or when a deadline makes “the API my team already knows” the pragmatic choice. In all three cases you are choosing SK as a temporary measure and planning the migration, which is itself the strongest argument for not starting there. If you already have Semantic Kernel plugins, the smoothest first step is often turning one into an MCP server so it works from either framework while you move.

Sources

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Back