Part 10 of the Microsoft Agent Framework Series — Final Chapter
If you’re currently using Semantic Kernel or AutoGen, migrating to Microsoft Agent Framework is straightforward. Both frameworks contributed to MAF’s design, so many concepts translate directly.
This final article in our series provides practical migration guidance with before/after code examples.
Migration Overview
| From | Effort | Key Changes |
|---|---|---|
| Semantic Kernel | Low-Medium | Kernel → Agent client; Plugins → Tools |
| AutoGen | Low | Teams → Workflows; FunctionTool → @ai_function |
Both Semantic Kernel and AutoGen will remain supported, but most Microsoft investment is now focused on Agent Framework.
Migrating from Semantic Kernel
Agent Creation
# Semantic Kernel - Agent creation pattern
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
import os
# Create kernel
kernel = Kernel()
# Add AI service
kernel.add_service(AzureChatCompletion(
deployment_name="gpt-4o",
endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
service_id="chat"
))
# Simple prompt invocation
result = await kernel.invoke_prompt(
"Summarize the following text: {{$input}}",
input="Microsoft released Agent Framework..."
)
print(result)
# Using chat history
from semantic_kernel.contents import ChatHistory
chat_history = ChatHistory()
chat_history.add_user_message("Hello!")
chat_function = kernel.get_function("chat")
result = await kernel.invoke(chat_function, chat_history=chat_history)
chat_history.add_assistant_message(str(result)).NET / C# Implementation
using Azure.Identity;
using OpenAI;
using Microsoft.Agents.AI;
namespace MAF.Part10.Migration;
///
/// Part 10: Migration from Semantic Kernel - BEFORE (SK Pattern)
///
public class BeforeSemanticKernel
{
/*
// Semantic Kernel - Agent creation pattern
using Microsoft.SemanticKernel;
var kernel = new KernelBuilder()
.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"),
apiKey: Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"))
.Build();
// Using chat history
var chatHistory = new ChatHistory();
chatHistory.AddUserMessage("Hello!");
var chatService = kernel.GetRequiredService();
var result = await chatService.GetChatMessageContentsAsync(chatHistory);
chatHistory.AddAssistantMessage(result[0].Content);
*/
}
///
/// Part 10: Migration to Agent Framework - AFTER (MAF Pattern)
///
public class AfterAgentFramework
{
public static async Task Main(string[] args)
{
// Agent Framework - Simplified pattern
var agent = new AzureOpenAIClient(
new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
new DefaultAzureCredential()) // Uses Azure AD instead of API keys
.GetOpenAIResponseClient("gpt-4o")
.CreateAIAgent(
name: "MyAgent",
instructions: "You are a helpful assistant.");
// Thread replaces ChatHistory
var thread = agent.GetNewThread();
var result1 = await agent.RunAsync("Hello!", thread);
Console.WriteLine(result1);
// Thread maintains context automatically
var result2 = await agent.RunAsync("What did I just say?", thread);
Console.WriteLine(result2);
}
}
# Agent Framework - Equivalent agent creation
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
import asyncio
# Create client and agent
agent = AzureOpenAIResponsesClient(
credential=AzureCliCredential(), # Use Azure AD instead of API keys
endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
).create_agent(
name="MyAgent",
instructions="You are a helpful assistant that summarizes text."
)
# Simple invocation
result = await agent.run("Summarize the following: Microsoft released Agent Framework...")
print(result.text)
# Multi-turn conversation with thread (replaces ChatHistory)
thread = agent.get_new_thread()
result1 = await agent.run("Hello!", thread)
print(result1.text)
result2 = await agent.run("What did I just say?", thread) # Has context
print(result2.text).NET / C# Implementation
using Azure.Identity;
using OpenAI;
using Microsoft.Agents.AI;
namespace MAF.Part10.Migration;
///
/// Part 10: Migration from Semantic Kernel - BEFORE (SK Pattern)
///
public class BeforeSemanticKernel
{
/*
// Semantic Kernel - Agent creation pattern
using Microsoft.SemanticKernel;
var kernel = new KernelBuilder()
.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"),
apiKey: Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"))
.Build();
// Using chat history
var chatHistory = new ChatHistory();
chatHistory.AddUserMessage("Hello!");
var chatService = kernel.GetRequiredService();
var result = await chatService.GetChatMessageContentsAsync(chatHistory);
chatHistory.AddAssistantMessage(result[0].Content);
*/
}
///
/// Part 10: Migration to Agent Framework - AFTER (MAF Pattern)
///
public class AfterAgentFramework
{
public static async Task Main(string[] args)
{
// Agent Framework - Simplified pattern
var agent = new AzureOpenAIClient(
new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
new DefaultAzureCredential()) // Uses Azure AD instead of API keys
.GetOpenAIResponseClient("gpt-4o")
.CreateAIAgent(
name: "MyAgent",
instructions: "You are a helpful assistant.");
// Thread replaces ChatHistory
var thread = agent.GetNewThread();
var result1 = await agent.RunAsync("Hello!", thread);
Console.WriteLine(result1);
// Thread maintains context automatically
var result2 = await agent.RunAsync("What did I just say?", thread);
Console.WriteLine(result2);
}
}
Tool Registration
# Semantic Kernel - Plugin/Function pattern
from semantic_kernel.functions import kernel_function
from semantic_kernel import Kernel
class WeatherPlugin:
"""Semantic Kernel plugin with @kernel_function decorators."""
@kernel_function(
name="get_weather",
description="Get current weather for a city"
)
def get_weather(self, city: str) -> str:
# Mock weather data
weather = {"new york": "72°F Sunny", "london": "58°F Cloudy"}
return weather.get(city.lower(), "Weather data not available")
@kernel_function(
name="get_forecast",
description="Get 5-day weather forecast"
)
def get_forecast(self, city: str, days: int = 5) -> str:
return f"{days}-day forecast for {city}: Partly cloudy, highs in 70s"
class MathPlugin:
"""Another SK plugin example."""
@kernel_function(description="Add two numbers")
def add(self, a: float, b: float) -> float:
return a + b
@kernel_function(description="Multiply two numbers")
def multiply(self, a: float, b: float) -> float:
return a * b
# Register plugins with kernel
kernel = Kernel()
kernel.add_plugin(WeatherPlugin(), plugin_name="weather")
kernel.add_plugin(MathPlugin(), plugin_name="math")
# Use via function calling
result = await kernel.invoke_prompt(
"What's the weather in New York?",
function_choice_behavior=FunctionChoiceBehavior.Auto()
).NET / C# Implementation
using System.ComponentModel;
using Microsoft.Agents.AI;
namespace MAF.Part10.Migration;
///
/// Part 10: Plugin/Tool Migration - BEFORE (SK Pattern)
///
public class BeforeSemanticKernelPlugins
{
/*
// Semantic Kernel plugins with [KernelFunction]
public class WeatherPlugin
{
[KernelFunction]
[Description("Get current weather for a city")]
public string GetWeather(
[Description("City name")] string city,
[Description("Units: celsius or fahrenheit")] string units = "celsius")
{
return $"Weather in {city}: 72°F Sunny";
}
}
// Registration
kernel.Plugins.AddFromType();
*/
}
///
/// Part 10: Tool Migration - AFTER (MAF Pattern)
///
public static class AfterAgentFrameworkTools
{
// Agent Framework uses [Description] attributes directly on methods
[Description("Get current weather for a city")]
public static string GetWeather(
[Description("City name")] string city,
[Description("Units: celsius or fahrenheit")] string units = "celsius")
{
var weatherData = new Dictionary
{
["new york"] = (72, "Sunny"),
["london"] = (58, "Cloudy"),
};
var data = weatherData.GetValueOrDefault(city.ToLower(), (70, "Unknown"));
var temp = units == "fahrenheit" ? data.Temp : (data.Temp - 32) * 5 / 9;
return $"Weather in {city}: {temp}°{(units == "fahrenheit" ? "F" : "C")}, {data.Condition}";
}
[Description("Get multi-day weather forecast")]
public static string GetForecast(
[Description("City name")] string city,
[Description("Number of days (1-10)")] int days = 5)
{
return $"{days}-day forecast for {city}: Partly cloudy, highs in 70s";
}
// Usage - tools are passed directly to CreateAIAgent
public static void Demo()
{
/*
var agent = client.CreateAIAgent(
name: "WeatherAgent",
instructions: "Help with weather questions.",
tools: new object[]
{
GetWeather,
GetForecast
});
*/
}
}
# Agent Framework - @ai_function pattern
from agent_framework import ai_function
from typing import Annotated
from pydantic import Field
# Weather tools with @ai_function decorator
@ai_function
def get_weather(
city: Annotated[str, Field(description="City name to get weather for")]
) -> str:
"""Get current weather for a city."""
weather = {"new york": "72°F Sunny", "london": "58°F Cloudy"}
return weather.get(city.lower(), "Weather data not available")
@ai_function
def get_forecast(
city: Annotated[str, Field(description="City name")],
days: Annotated[int, Field(description="Number of days", ge=1, le=10)] = 5
) -> str:
"""Get multi-day weather forecast."""
return f"{days}-day forecast for {city}: Partly cloudy, highs in 70s"
# Math tools
@ai_function
def add(
a: Annotated[float, Field(description="First number")],
b: Annotated[float, Field(description="Second number")]
) -> float:
"""Add two numbers together."""
return a + b
@ai_function
def multiply(
a: Annotated[float, Field(description="First number")],
b: Annotated[float, Field(description="Second number")]
) -> float:
"""Multiply two numbers."""
return a * b
# Create agent with tools (no plugins needed)
agent = client.create_agent(
name="ToolAgent",
instructions="You help with weather and math questions.",
tools=[get_weather, get_forecast, add, multiply] # Direct tool registration
)
# Use the agent
result = await agent.run("What's the weather in New York?")
print(result.text) # Automatically calls get_weather tool.NET / C# Implementation
using System.ComponentModel;
using Microsoft.Agents.AI;
namespace MAF.Part10.Migration;
///
/// Part 10: Plugin/Tool Migration - BEFORE (SK Pattern)
///
public class BeforeSemanticKernelPlugins
{
/*
// Semantic Kernel plugins with [KernelFunction]
public class WeatherPlugin
{
[KernelFunction]
[Description("Get current weather for a city")]
public string GetWeather(
[Description("City name")] string city,
[Description("Units: celsius or fahrenheit")] string units = "celsius")
{
return $"Weather in {city}: 72°F Sunny";
}
}
// Registration
kernel.Plugins.AddFromType();
*/
}
///
/// Part 10: Tool Migration - AFTER (MAF Pattern)
///
public static class AfterAgentFrameworkTools
{
// Agent Framework uses [Description] attributes directly on methods
[Description("Get current weather for a city")]
public static string GetWeather(
[Description("City name")] string city,
[Description("Units: celsius or fahrenheit")] string units = "celsius")
{
var weatherData = new Dictionary
{
["new york"] = (72, "Sunny"),
["london"] = (58, "Cloudy"),
};
var data = weatherData.GetValueOrDefault(city.ToLower(), (70, "Unknown"));
var temp = units == "fahrenheit" ? data.Temp : (data.Temp - 32) * 5 / 9;
return $"Weather in {city}: {temp}°{(units == "fahrenheit" ? "F" : "C")}, {data.Condition}";
}
[Description("Get multi-day weather forecast")]
public static string GetForecast(
[Description("City name")] string city,
[Description("Number of days (1-10)")] int days = 5)
{
return $"{days}-day forecast for {city}: Partly cloudy, highs in 70s";
}
// Usage - tools are passed directly to CreateAIAgent
public static void Demo()
{
/*
var agent = client.CreateAIAgent(
name: "WeatherAgent",
instructions: "Help with weather questions.",
tools: new object[]
{
GetWeather,
GetForecast
});
*/
}
}
Migrating from AutoGen
Agent Creation
# AutoGen - Assistant agent pattern
from autogen import AssistantAgent, UserProxyAgent
import os
# Configuration for LLM
config_list = [
{
"model": "gpt-4o",
"api_key": os.getenv("OPENAI_API_KEY"),
}
]
llm_config = {
"config_list": config_list,
"temperature": 0.7,
}
# Create assistant
assistant = AssistantAgent(
name="assistant",
system_message="You are a helpful AI assistant.",
llm_config=llm_config,
)
# Create user proxy for interactions
user_proxy = UserProxyAgent(
name="user",
human_input_mode="NEVER", # Auto-respond
max_consecutive_auto_reply=5,
code_execution_config=False
)
# Start conversation
user_proxy.initiate_chat(
assistant,
message="Explain the benefits of microservices architecture"
)
# Get last response
last_message = assistant.last_message()
print(last_message["content"]).NET / C# Implementation
// AutoGen agents can be migrated to MagenticOrchestrator.
# Agent Framework - Equivalent agent creation
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
import asyncio
# Create client and agent
agent = AzureOpenAIResponsesClient(
credential=AzureCliCredential(), # Use Azure AD instead of API keys
endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
).create_agent(
name="MyAgent",
instructions="You are a helpful assistant that summarizes text."
)
# Simple invocation
result = await agent.run("Summarize the following: Microsoft released Agent Framework...")
print(result.text)
# Multi-turn conversation with thread (replaces ChatHistory)
thread = agent.get_new_thread()
result1 = await agent.run("Hello!", thread)
print(result1.text)
result2 = await agent.run("What did I just say?", thread) # Has context
print(result2.text).NET / C# Implementation
using Azure.Identity;
using OpenAI;
using Microsoft.Agents.AI;
namespace MAF.Part10.Migration;
///
/// Part 10: Migration from Semantic Kernel - BEFORE (SK Pattern)
///
public class BeforeSemanticKernel
{
/*
// Semantic Kernel - Agent creation pattern
using Microsoft.SemanticKernel;
var kernel = new KernelBuilder()
.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4o",
endpoint: Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"),
apiKey: Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"))
.Build();
// Using chat history
var chatHistory = new ChatHistory();
chatHistory.AddUserMessage("Hello!");
var chatService = kernel.GetRequiredService();
var result = await chatService.GetChatMessageContentsAsync(chatHistory);
chatHistory.AddAssistantMessage(result[0].Content);
*/
}
///
/// Part 10: Migration to Agent Framework - AFTER (MAF Pattern)
///
public class AfterAgentFramework
{
public static async Task Main(string[] args)
{
// Agent Framework - Simplified pattern
var agent = new AzureOpenAIClient(
new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
new DefaultAzureCredential()) // Uses Azure AD instead of API keys
.GetOpenAIResponseClient("gpt-4o")
.CreateAIAgent(
name: "MyAgent",
instructions: "You are a helpful assistant.");
// Thread replaces ChatHistory
var thread = agent.GetNewThread();
var result1 = await agent.RunAsync("Hello!", thread);
Console.WriteLine(result1);
// Thread maintains context automatically
var result2 = await agent.RunAsync("What did I just say?", thread);
Console.WriteLine(result2);
}
}
Multi-Agent Teams → Workflows
# AutoGen - Assistant agent pattern
from autogen import AssistantAgent, UserProxyAgent
import os
# Configuration for LLM
config_list = [
{
"model": "gpt-4o",
"api_key": os.getenv("OPENAI_API_KEY"),
}
]
llm_config = {
"config_list": config_list,
"temperature": 0.7,
}
# Create assistant
assistant = AssistantAgent(
name="assistant",
system_message="You are a helpful AI assistant.",
llm_config=llm_config,
)
# Create user proxy for interactions
user_proxy = UserProxyAgent(
name="user",
human_input_mode="NEVER", # Auto-respond
max_consecutive_auto_reply=5,
code_execution_config=False
)
# Start conversation
user_proxy.initiate_chat(
assistant,
message="Explain the benefits of microservices architecture"
)
# Get last response
last_message = assistant.last_message()
print(last_message["content"]) Teams.NET / C# Implementation
// Group Chat -> GroupChatOrchestrator
# Agent Framework - Workflow orchestration (replaces GroupChat)
from agent_framework import WorkflowBuilder
from agent_framework.orchestration import SequentialOrchestrator
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
import asyncio
async def create_content_workflow():
client = AzureOpenAIResponsesClient(credential=AzureCliCredential())
# Create specialized agents
researcher = client.create_agent(
name="Researcher",
instructions="You are a research specialist. Find and present facts."
)
writer = client.create_agent(
name="Writer",
instructions="You are a content writer. Create engaging articles."
)
editor = client.create_agent(
name="Editor",
instructions="You are an editor. Review and improve content."
)
# Option 1: Sequential orchestration (linear pipeline)
sequential = SequentialOrchestrator(agents=[researcher, writer, editor])
result = await sequential.run("Write a blog post about AI agents")
# Option 2: Graph-based workflow for complex flows
builder = WorkflowBuilder()
builder.add_executor(researcher)
builder.add_executor(writer)
builder.add_executor(editor)
builder.add_edge(researcher, writer)
builder.add_edge(writer, editor)
builder.set_start_executor(researcher)
workflow = builder.build()
result = await workflow.run("Write a blog post about AI agents")
return result
# Run the workflow
asyncio.run(create_content_workflow()).NET / C# Implementation
// Workflows -> WorkflowBuilder
Key Mapping Reference
| Semantic Kernel | AutoGen | Agent Framework |
|---|---|---|
| Kernel | — | Agent Client |
| Plugin | FunctionTool | @ai_function |
| ChatHistory | Messages | Thread |
| — | GroupChat | Workflow / Orchestrator |
| Filter | — | Middleware |
| Connector | — | MCP Client |
Migration Checklist
- ☐ Update package dependencies
- ☐ Replace Kernel/AssistantAgent with Agent client
- ☐ Convert plugins/FunctionTools to @ai_function
- ☐ Replace ChatHistory with Thread
- ☐ Update multi-agent patterns to Workflows
- ☐ Test tool invocations
- ☐ Verify conversation state management
- ☐ Update deployment configurations
Series Complete! 🎉
Congratulations on completing the Microsoft Agent Framework series! You’ve learned:
- ✅ Core concepts and architecture
- ✅ Building agents in .NET and Python
- ✅ Tools and function calling
- ✅ Multi-turn conversations with threads
- ✅ Graph-based workflows
- ✅ Multi-agent orchestration patterns
- ✅ Production deployment with observability
- ✅ MCP integration for extensibility
- ✅ Migration from existing frameworks
You’re now equipped to build sophisticated, production-ready AI agents with Microsoft Agent Framework!
📦 Source Code
All code examples from this article series are available on GitHub:
👉 https://github.com/nithinmohantk/microsoft-agent-framework-series-examples
Clone the repository to follow along:
git clone https://github.com/nithinmohantk/microsoft-agent-framework-series-examples.git
cd microsoft-agent-framework-series-examples
.NET Migration Examples
Agent Creation: Before vs After
Tool/Plugin Migration
Key Migration Benefits
| Aspect | Semantic Kernel | Agent Framework |
|---|---|---|
| Authentication | API Keys | Azure AD / Managed Identity |
| Context | ChatHistory (manual) | Thread (automatic) |
| Tools | [KernelFunction] + Plugin | [Description] only |
| Multi-Agent | Limited | Built-in Orchestrators |
| MCP | Not supported | Native support |
Complete Series Navigation
- Part 1: Introduction
- Part 2: First Agent (.NET)
- Part 3: First Agent (Python)
- Part 4: Tools & Function Calling
- Part 5: Multi-Turn Conversations
- Part 6: Workflows
- Part 7: Multi-Agent Patterns
- Part 8: Production-Ready Agents
- Part 9: MCP Integration
- Part 10: Migration Guide ← You are here (Final)
References
- Microsoft Agent Framework GitHub
- MAF Documentation
- Migration from Semantic Kernel
- Migration from AutoGen
- Introducing Microsoft Agent Framework (DevBlog)
- AI Agents for Beginners – MAF Chapter
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.