
Microsoft Agent Framework is the successor to the agent capabilities in Semantic Kernel and AutoGen. That statement is easy to misread as “replace the package and rename a few classes.” The migration is more architectural than that.
Semantic Kernel made Kernel the center of model access, plugins, functions, filters, prompt execution, and agent behavior. Agent Framework separates those responsibilities:
| Responsibility | Agent Framework abstraction |
|---|---|
| Model connection | Provider client or IChatClient |
| Agent behavior | AIAgent |
| Callable capability | AIFunction |
| Conversation continuity | AgentSession |
| Cross-cutting execution | Middleware |
| Multi-step orchestration | Workflow graph |
This separation provides the primary reason to migrate. A new namespace alone has no value. Clear ownership for tools, state, model calls, and control flow does.
Should every Semantic Kernel application migrate?
No. The relevant distinction is between an application that uses Semantic Kernel and an application built around Semantic Kernel agents.
A bounded prompt-processing service using IChatCompletionService can remain exactly where it is when it is stable and supported. The migration signal becomes stronger when an application has persistent agents, several tool sets, multi-agent coordination, approvals, or custom orchestration hidden around one large Kernel.
Agent Framework is the recommended default for new agentic systems. An existing system should migrate only when one of its explicit abstractions replaces custom infrastructure or reduces operational risk.
The new composition model
The core packages are independent and do not share one version number:
1dotnet add package Microsoft.Agents.AI
2dotnet add package Microsoft.Agents.AI.Workflows
3dotnet add package Microsoft.Agents.AI.Foundry
4dotnet add package Azure.AI.Projects
5dotnet add package Azure.Identity
Compatible versions should be pinned through Central Package Management rather than forced onto the same version. Provider integrations have their own release cadence.
The smallest Foundry-backed agent needs a provider client and an AIAgent:
1using Azure.AI.Projects;
2using Azure.Identity;
3using Microsoft.Agents.AI;
4
5string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT")
6 ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
7string model = Environment.GetEnvironmentVariable("FOUNDRY_MODEL")
8 ?? "gpt-5.4-mini";
9
10AIProjectClient projectClient = new AIProjectClient(
11 new Uri(endpoint),
12 new DefaultAzureCredential());
13
14AIAgent agent = projectClient.AsAIAgent(
15 model: model,
16 name: "SupportTriageAgent",
17 instructions: "Classify support requests and produce a concise routing recommendation.");
18
19AgentResponse response = await agent.RunAsync(
20 "The checkout API returns HTTP 503 for customers in West Europe.");
21
22Console.WriteLine(response.Text);
In Semantic Kernel, the provider was commonly registered on a Kernel, which was then assigned to ChatCompletionAgent. Agent Framework creates the agent from a provider client or IChatClient and composes behavior on that agent directly.
This removes ambient capabilities. A shared kernel can accidentally expose every plugin to every agent. Each AIAgent should receive only the tools required for its job.
DefaultAzureCredential is useful during local development. A deployed Azure workload should use an explicit ManagedIdentityCredential so that the production identity is obvious from code and configuration.
Kernel functions become AIFunction tools
The tool model survives the migration, but it moves to Microsoft.Extensions.AI. A normal typed method becomes an AIFunction without depending on Kernel.
1using System.ComponentModel;
2
3public sealed record IncidentStatus(
4 string IncidentId,
5 string Status,
6 string Owner,
7 DateTimeOffset UpdatedAtUtc);
8
9public static class IncidentTools
10{
11 [Description("Gets the current status and owner of an incident.")]
12 public static Task<IncidentStatus> GetIncidentStatusAsync(
13 [Description("Incident identifier in the INC-1234 format.")]
14 string incidentId,
15 CancellationToken cancellationToken)
16 {
17 cancellationToken.ThrowIfCancellationRequested();
18
19 IncidentStatus status = new IncidentStatus(
20 incidentId,
21 "investigating",
22 "platform-operations",
23 DateTimeOffset.UtcNow);
24
25 return Task.FromResult(status);
26 }
27}
The adapter is small:
1using Microsoft.Agents.AI;
2using Microsoft.Extensions.AI;
3
4AIFunction getIncidentStatus = AIFunctionFactory.Create(
5 IncidentTools.GetIncidentStatusAsync);
6
7AIAgent agent = projectClient.AsAIAgent(
8 model: model,
9 name: "IncidentAgent",
10 instructions: "Use incident tools to answer operational status questions.",
11 tools: new[] { getIncidentStatus });
12
13AgentResponse response = await agent.RunAsync(
14 "Who owns incident INC-1042 and what is its current state?");
A safe migration rule is to extract the business operation before converting the tool. A former KernelFunction should call a normal application service with typed input, typed output, cancellation, validation, and authorization. The old and new AI adapters can then use the same service during a staged rollout.
Descriptions help a model select a function. They do not authorize it. Write tools still need resource-level authorization, idempotency, audit records, and bounded results.
AgentSession is conversation state
AgentSession replaces the thread abstraction used by Semantic Kernel agents:
1AgentSession session = await agent.CreateSessionAsync();
2
3AgentResponse firstResponse = await agent.RunAsync(
4 "Incident INC-1042 affects the checkout API.",
5 session);
6
7AgentResponse secondResponse = await agent.RunAsync(
8 "Summarize the affected component and incident identifier.",
9 session);
The session may contain local history, reference provider-side state, or be serialized by the application. It does not automatically provide durable, distributed persistence.
An in-memory dictionary of live AgentSession instances is not a session store. A production design needs an owner, tenant boundary, expiry, serialization format, concurrency rule, and shared storage when subsequent requests can reach another replica.
It is equally important not to turn the session into a business database. Orders, incidents, approvals, and customer records remain in application-owned storage. Conversation history is context, not the source of truth.
When old thread data has no lossless representation in the new provider, existing conversations can remain on the old path while new conversations use sessions. A risky historical-state conversion usually provides less value than a clean cutover boundary.
Responses retain more than text
RunAsync returns an AgentResponse; streaming returns AgentResponseUpdate values:
1IAsyncEnumerable<AgentResponseUpdate> updates = agent.RunStreamingAsync(
2 "Summarize incident INC-1042.");
3
4await foreach (AgentResponseUpdate update in updates)
5{
6 if (!string.IsNullOrEmpty(update.Text))
7 {
8 Console.Write(update.Text);
9 }
10}
Console samples normally print response.Text. Production infrastructure should not flatten the response that early. Tool calls, usage, finish reasons, citations, provider metadata, and structured output may be required for validation and telemetry.
Middleware has a narrower job than filters
Semantic Kernel filters intercepted operations around a shared kernel. Agent Framework middleware runs around agent requests and function calls. Existing filters should be mapped according to their actual responsibility:
| Existing behavior | New owner |
|---|---|
| Provider retries | AI client pipeline |
| Run timing and correlation | Agent middleware |
| Function policy | Function middleware and application service |
| Retrieved run context | AIContextProvider |
| Domain authorization | Application service |
This classification prevents a generic middleware component from becoming the next Kernel. Cross-cutting telemetry belongs there; resource-level authorization usually does not.
Agent Framework also separates conversation continuity from retrieved context. AgentSession carries the conversation. An AIContextProvider contributes additional context. Tools load or change business data. A vector index remains an external data system. Semantic Kernel applications often called all four concepts “memory”; preserving that ambiguity during migration would waste the new architecture.
Workflows make control flow visible
The strongest reason for migrating a multi-agent application is the workflow model. Free-running agent conversations are easy to start and difficult to operate. Routing, retries, approvals, loops, and termination become prompt conventions instead of visible application control flow.
Agent Framework uses a graph of agents and deterministic executors:
1using Microsoft.Agents.AI;
2using Microsoft.Agents.AI.Workflows;
3using Microsoft.Extensions.AI;
4
5AIAgent triageAgent = projectClient.AsAIAgent(
6 model: model,
7 name: "TriageAgent",
8 instructions: "Classify the incident and propose a responsible team.");
9
10AIAgent reviewAgent = projectClient.AsAIAgent(
11 model: model,
12 name: "ReviewAgent",
13 instructions: "Review the classification and return the final routing decision.");
14
15Workflow workflow = new WorkflowBuilder(triageAgent)
16 .AddEdge(triageAgent, reviewAgent)
17 .WithOutputFrom(reviewAgent)
18 .Build();
19
20ChatMessage input = new ChatMessage(
21 ChatRole.User,
22 "Checkout requests fail with HTTP 503 in West Europe.");
23
24await using StreamingRun run = await InProcessExecution.RunStreamingAsync(
25 workflow,
26 input);
27
28await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
29
30await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
31{
32 if (workflowEvent is WorkflowOutputEvent outputEvent)
33 {
34 Console.WriteLine(outputEvent.Data);
35 }
36}
The two-agent sample is intentionally basic. The useful production pattern mixes probabilistic and deterministic nodes:
1load incident -> triage agent -> confidence decision
2 |
3 +--------------+--------------+
4 | |
5 low confidence high confidence
6 | |
7 v v
8 human approval policy validator
9 | |
10 +--------------+--------------+
11 |
12 v
13 persist assignment
The model reasons where ambiguity exists. Deterministic code owns validation, authorization, persistence, and terminal conditions. Every loop gets a hard limit. Every resumable approval gets durable state. Every write remains idempotent.
Migration sequence
Migration should not proceed by searching for old type names. One large Kernel often hides several responsibilities, so those responsibilities should be separated first.
- Inventory model connectors, functions, plugins, filters, memory, threads, and orchestration.
- Move business operations behind normal application interfaces.
- Convert one narrow tool to
AIFunctionand compare its schema and behavior. - Put one agent behind an application-owned interface with old and new adapters.
- Define session ownership, persistence, expiry, and concurrency.
- Draw the existing orchestration and replace it with explicit workflow edges.
- Compare traces, tool calls, cost, latency, and outcome quality before cutover.
The application-owned interface is important:
1Application -> IIncidentAgent -> application services
2 |
3 +-- Semantic Kernel adapter
4 +-- Agent Framework adapter
It keeps framework types out of the domain layer and allows side-by-side evaluation or rollback.
Exact text equality is a poor migration test because model output is probabilistic. Tests should verify required fields, valid structured output, allowed tool selection, authorization, token budgets, reachable terminal states, and task-quality thresholds over a representative dataset.
Dependency injection without captured request state
Thread-safe provider clients and agents with immutable configuration are natural singleton candidates:
1using Azure.AI.Projects;
2using Azure.Identity;
3using Microsoft.Agents.AI;
4
5WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
6
7string endpoint = builder.Configuration["Foundry:ProjectEndpoint"]
8 ?? throw new InvalidOperationException("Foundry project endpoint is missing.");
9string model = builder.Configuration["Foundry:Model"]
10 ?? throw new InvalidOperationException("Foundry model deployment is missing.");
11
12builder.Services.AddSingleton<AIProjectClient>(serviceProvider =>
13{
14 ManagedIdentityCredential credential = new ManagedIdentityCredential();
15 return new AIProjectClient(new Uri(endpoint), credential);
16});
17
18builder.Services.AddSingleton<AIAgent>(serviceProvider =>
19{
20 AIProjectClient projectClient =
21 serviceProvider.GetRequiredService<AIProjectClient>();
22
23 return projectClient.AsAIAgent(
24 model: model,
25 name: "IncidentAgent",
26 instructions: "Classify incidents and recommend the responsible team.");
27});
Request identity, tenant context, and authorization data must not be captured in the singleton. They belong in run context, tool calls, or scoped application services.
An agent is also not automatically an HTTP endpoint. The hosting boundary still needs authentication, authorization, request limits, validation, cancellation, and telemetry. MCP, A2A, or a Foundry adapter changes the transport, not those responsibilities.
Migration measurements
Agent Framework emits OpenTelemetry data for agent and workflow execution. Old and new traces should be compared rather than copying the old dashboard under a new namespace.
Useful dimensions are agent name, provider, model, tool name, workflow node, bounded outcome, latency, token usage, and retry count. Prompts, full responses, credentials, personal data, and unrestricted identifiers stay out of telemetry by default.
The production checks cover three different layers:
- Unit tests for tools and deterministic workflow executors.
- Integration tests for provider adapters, session persistence, and workflow recovery.
- Evaluations for task success, groundedness, tool selection, safety, latency, and cost.
Telemetry does not replace an audit trail. A trace explains execution. An audit record proves which authenticated actor caused a business change.
Patterns to remove during migration
The migration is an opportunity to remove five patterns instead of translating them:
- One shared kernel exposing unrelated plugins to every agent.
- Unbounded chat history without a context and retention budget.
- Generic SQL, shell, filesystem, or HTTP tools with broad authority.
- Group chats that terminate when an agent emits a magic phrase.
- Agent-session state used as authoritative business state.
Each pattern makes a demo flexible and a production system difficult to secure or recover.
The decision
Microsoft Agent Framework matters because it removes Kernel as the mandatory center of an agent application. AIAgent owns behavior, AIFunction exposes narrow capabilities, AgentSession represents conversation continuity, and workflows make control flow inspectable.
A stable Semantic Kernel prompt service should not migrate solely for a new package. An agent system benefits from migration when the new boundaries replace shared ambient state, implicit orchestration, or custom recovery code. That is a measurable engineering benefit, not a version-chasing exercise.
Further details are available in the Microsoft Agent Framework documentation , the official Semantic Kernel migration guide , and the Microsoft Agent Framework repository . The protocol boundary for exposing capabilities to external AI clients is covered separately in Building Production MCP Servers with ASP.NET Core .
Related articles

Aug 31, 2026 - 22 min read
Building Production MCP Servers with ASP.NET Core
An MCP server can look deceptively small. A package is installed, a method receives an attribute, and ASP.NET Core maps an endpoint. That is …

Aug 24, 2026 - 18 min read
Telemetry, Logging, and Auditing in .NET: Designing the Right Data Path
Telemetry, logging and auditing are often implemented through the same API because all three produce timestamped records. That similarity is …

Aug 17, 2026 - 17 min read
Automatic TTL in Azure Cosmos DB with .NET
Temporary data is easy to create and surprisingly difficult to remove reliably. Sessions, idempotency keys, import buffers, transient …
Let's Work Together
Looking for an experienced Platform Architect or Engineer for your next project? Whether it's cloud migration, platform modernization or building new solutions from scratch - I'm here to help you succeed.
