Migration Guide: From Semantic Kernel & AutoGen to Microsoft Agent Framework – Part 10

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

FromEffortKey Changes
Semantic KernelLow-MediumKernel → Agent client; Plugins → Tools
AutoGenLowTeams → Workflows; FunctionTool → @ai_function
📝
NOTE

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 KernelAutoGenAgent Framework
KernelAgent Client
PluginFunctionTool@ai_function
ChatHistoryMessagesThread
GroupChatWorkflow / Orchestrator
FilterMiddleware
ConnectorMCP 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

AspectSemantic KernelAgent Framework
AuthenticationAPI KeysAzure AD / Managed Identity
ContextChatHistory (manual)Thread (automatic)
Tools[KernelFunction] + Plugin[Description] only
Multi-AgentLimitedBuilt-in Orchestrators
MCPNot supportedNative support

Complete Series Navigation


References


Discover more from C4: Container, Code, Cloud & Context

Subscribe to get the latest posts sent to your email.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.