Microsoft Agent Framework.NETAI AgentsSemantic Kernel

The Microsoft Agent Framework for .NET: A Developer's Guide

Microsoft Agent Framework 1.0 unifies Semantic Kernel and AutoGen into one .NET SDK for building AI agents. Here is what it is, why it exists, and how to build your first agent in C#.

The Microsoft Agent Framework for .NET: A Developer's Guide

If you have built AI features on .NET over the last two years, you have probably faced a confusing choice: Semantic Kernel or AutoGen? Both came from Microsoft, both built AI agents, and both pulled in slightly different directions. As of the 1.0 GA release on 2 April 2026, that choice is gone — the two have merged into a single, production-ready SDK called the Microsoft Agent Framework.

This guide explains what the framework is, why Microsoft converged the two libraries, and the core concepts you need to build your first agent in C#.

What is the Microsoft Agent Framework?

The Microsoft Agent Framework is an open-source (MIT-licensed) SDK for building, orchestrating, and deploying AI agents, with a unified programming model across .NET and Python. It is the official successor to both Semantic Kernel and AutoGen, and it is designed from the start for enterprise use.

The short version of its lineage:

  • AutoGen was Microsoft Research’s project for multi-agent experimentation. Its strength was simple, elegant agent abstractions and multi-agent conversations.
  • Semantic Kernel was the enterprise-grade SDK: session state, dependency injection, type safety, middleware, telemetry, and broad model support.
  • Microsoft Agent Framework takes AutoGen’s clean agent model and fuses it with Semantic Kernel’s enterprise plumbing — then adds graph-based workflows for explicit, deterministic multi-agent orchestration.

In other words: the research ergonomics and the production hardening, in one place.

Why the merge matters

Two competing SDKs from the same vendor is a tax on everyone. Teams had to bet on one, tutorials contradicted each other, and moving between them meant rewrites. Consolidating into a single framework means:

  1. One mental model. You learn agents, tools, threads, and workflows once.
  2. A clear upgrade path. Both Semantic Kernel and AutoGen projects have documented migration routes to the framework.
  3. Standards built in. The framework speaks the Model Context Protocol (MCP) for tool/data integration and Agent2Agent (A2A) for agent-to-agent communication — so your agents interoperate beyond the Microsoft ecosystem.

The core concepts

Before writing code, it helps to hold four ideas in your head:

  • Agent — an LLM-backed component with instructions, tools it can call, and (optionally) memory. It takes input and produces a response, potentially invoking tools along the way. AIAgent is the abstraction everything else hangs off.
  • Tools (functions) — plain C# methods you expose to the agent. The model decides when to call them; the framework handles the wiring.
  • Sessions — the conversation state that lets an agent remember earlier turns. Earlier previews called this a thread; in the 1.x .NET SDK the type is AgentSession.
  • Workflows — graph-based orchestration for connecting multiple agents with explicit, inspectable control flow, rather than hoping a prompt coordinates them.

Underneath all four sits Microsoft.Extensions.AI, which is why the framework is not tied to one vendor. The same agent code runs against Microsoft Foundry, Azure OpenAI, OpenAI, Anthropic or a local Ollama model — you swap the client, not the agent. The core Microsoft.Agents.AI package targets .NET 8, .NET Standard 2.0 and .NET Framework 4.7.2, so an agent can be dropped into an older service without a runtime upgrade first.

Conversation state, and the mistake everyone makes with it

A stateless agent is easy. The moment you want a second turn, you need somewhere to keep the history:

AgentSession session = await agent.CreateSessionAsync();

var first  = await agent.RunAsync("My name is Alice.", session);
var second = await agent.RunAsync("What is my name?", session);

That works in a console app and falls apart in a web app, because your process handles thousands of concurrent conversations and restarts whenever you deploy. Sessions are serialisable for exactly this reason:

var serialized = agent.SerializeSession(session);
// persist against your own conversation ID
AgentSession resumed = await agent.DeserializeSessionAsync(serialized);

Two things go wrong here, and neither produces a helpful error.

The first is drift. A session is tied to the agent and service that created it. Deserialise a session against an agent with different instructions, a different tool set or a different provider, and you get context the model was never meant to see — not an exception, just answers that quietly stop making sense. Version your agent configuration and refuse to resume a session that does not match.

The second is an authorisation hole. When you use service-managed history, the session can carry a service-issued identifier — an OpenAI resp_* response ID, or a conv_* conversation ID. Those IDs are scoped to the backing API key or project, not to your end user. In a hosted application where one key serves many customers, echoing that ID to the browser and accepting it back is a straight path to one tenant resuming another tenant’s conversation. Keep service-side IDs in your own storage, hand clients an opaque ID of your own, and check ownership before resuming.

The third, less dramatic problem is growth. Session state accumulates every turn, and every turn is resent to the model. A long-running assistant will eventually cost more per message than it did on day one purely through history. Cap it or summarise it — see cost control for the mechanics.

Your first agent in C#

At its simplest, creating an agent means pointing the framework at a chat model, giving it a name and instructions, and running it. Conceptually, the flow looks like this:

using Microsoft.Agents.AI;
using Azure.AI.OpenAI;
using Azure.Identity;

// 1. Point at a chat model (Azure OpenAI shown here)
var chatClient = new AzureOpenAIClient(
        new Uri("https://<your-resource>.openai.azure.com"),
        new DefaultAzureCredential())
    .GetChatClient("gpt-4o-mini");

// 2. Create an agent with a name + instructions
AIAgent agent = chatClient.CreateAIAgent(
    name: "TravelAssistant",
    instructions: "You are a concise travel assistant. Prefer bullet points.");

// 3. Run it
var reply = await agent.RunAsync("Suggest 3 things to do in Bangalore.");
Console.WriteLine(reply);

The value shows up when you give the agent tools. You annotate ordinary methods and hand them to the agent; the model chooses when to call them:

[Description("Gets the current weather for a city.")]
static string GetWeather(
    [Description("The city name")] string city) =>
    $"The weather in {city} is 28°C and sunny.";

AIAgent agent = chatClient.CreateAIAgent(
    name: "WeatherAssistant",
    instructions: "Answer questions using the tools available to you.",
    tools: [AIFunctionFactory.Create(GetWeather)]);

var reply = await agent.RunAsync("Should I carry an umbrella in Chennai today?");

Once an agent can do something irreversible, it needs a stop button: human-in-the-loop approvals in Agent Framework covers tool approval and workflow request ports, and which one survives a restart.

Note: APIs evolve across releases. Treat the snippets above as a conceptual map, and always check the official samples (linked below) against the exact package version you install. The concepts — agent, tools, threads, workflows — are stable even as method names get refined.

From one agent to many

A single agent answering questions is useful. The framework’s real ambition is multi-agent workflows: a planner agent that delegates to specialist agents, a reviewer that checks another agent’s output, or a graph of steps where each node is an agent with a specific job. Because these workflows are graph-based rather than prompt-based, you can reason about, test, and observe them like real software — which is exactly what you need before putting agents in front of customers.

In .NET this is the WorkflowBuilder API. You connect typed executors with edges and conditions; the runtime handles fan-out and fan-in, emits events per executor, and checkpoints progress at superstep boundaries. A finished workflow can itself be exposed through the ordinary agent interface with AsAIAgent(), so a caller cannot tell whether it is talking to one agent or a graph of nine.

The difference between this and the prompt-orchestration approach shows up the first time something fails halfway. With a prompt telling one model to coordinate others, a failure at step four means starting again from step one and paying for it. With checkpoints at superstep boundaries, you resume from where it broke. That distinction stops being academic when a single workflow run costs real money and takes ninety seconds.

Typed executors also give you the thing prompt orchestration never does: a compile error. If step three emits a DraftReport and step four expects a ReviewRequest, you find out at build time rather than watching the model improvise a conversion at runtime.

When an agent is the wrong tool

Microsoft’s own documentation contains the sharpest line on this: if you can write a function to handle the task, write the function. It is worth taking literally, because the failure mode of ignoring it is expensive rather than obvious.

Reach for an agent when the task is open-ended or conversational, when you genuinely need autonomous tool selection, or when the shape of the work is not known until you see the input. Reach for a workflow when the process has defined steps, when execution order matters, or when several agents and functions must coordinate. Reach for neither when the logic is deterministic — routing a support ticket by category is a switch statement, and wrapping it in a model call buys you latency, a per-request bill, and a component that returns a different answer on Tuesday.

The tempting middle case is “mostly deterministic with one fuzzy bit”. The right structure there is a workflow with one agent node, not an agent asked to do the whole job. Keep the model confined to the part that actually needs judgement, and the rest of your system stays testable.

What breaks first in production

Three things, in roughly this order.

Runaway tool loops. An agent that cannot satisfy its instructions will keep calling tools trying. Without a cap on turns, a single request can make dozens of model calls before someone notices the bill. Set a limit and treat hitting it as a failure to alert on, not a state to retry from.

Tool descriptions that lie. The model chooses tools from their descriptions, so a vague or stale [Description] produces a confidently wrong tool call. When an agent picks the wrong function, suspect the description before the model. The fix is usually a sentence naming what the tool does not do.

Unbounded schema growth. Every tool definition is serialised into every request, whether or not the model calls it. An agent with thirty registered tools pays for thirty schemas on every turn, and the model’s selection accuracy drops as the list grows. Expose only the tools a given flow needs.

One governance point worth raising before it becomes a procurement problem: the framework talks to third-party model providers, MCP servers and remote agents, and Microsoft is explicit that anything you connect outside Azure is your responsibility — including where the data goes and whose retention policy applies. Work out which of your agent’s tool calls cross an organisational boundary while it is still a prototype.

Where to go next

  • Official docs: Microsoft Agent Framework on Microsoft Learn
  • Source & samples: the framework is on GitHub under the MIT license, with .NET and Python samples and Learn modules.
  • Migrating? If you have an existing Semantic Kernel or AutoGen project, start with Microsoft’s migration guides rather than a rewrite.

From here, build a complete tool-using agent end to end, connect it to MCP servers, and deploy one to Azure Container Apps or GKE.

Next: 30 .NET AI and agent interview questions if you are being interviewed on this material.


Have a correction or a topic you want covered? Email mani.bc72@gmail.com.