Complete guide for migrating from AutoGen to Microsoft Agent Framework
This guide helps AutoGen developers move to the Microsoft Agent Framework (AF) with minimal guesswork. The frameworks share similar multi-agent primitives but differ in default behaviors, tool handling, and orchestration patterns.
from autogen_agentchat.agents import AssistantAgentfrom autogen_ext.models.openai import OpenAIChatCompletionClientclient = OpenAIChatCompletionClient(model="gpt-4.1-mini")agent = AssistantAgent( name="assistant", model_client=client, system_message="You are a helpful assistant. Answer in one sentence.",)# Run agent (AutoGen maintains state internally)result = await agent.run(task="What is the capital of France?")print(result.messages[-1].to_text())
Critical Default Behavior Difference: AutoGen’s AssistantAgent is single-turn by default (max_tool_iterations=1), while AF’s Agent is multi-turn and continues tool execution automatically until completion.
from autogen_core.tools import FunctionTooldef get_weather(location: str) -> str: """Get the weather for a location. Args: location: The city name or location. Returns: A weather description. """ return f"The weather in {location} is sunny and 72°F."# Wrap function in FunctionToolweather_tool = FunctionTool( func=get_weather, description="Get weather information for a location",)agent = AssistantAgent( name="assistant", model_client=client, tools=[weather_tool], system_message="Use available tools to answer questions.",)
AutoGen uses FunctionTool wrappers; AF uses @tool decorators with automatic schema inference from Python type hints and docstrings.
# AutoGen maintains conversation state automaticallyresult1 = await agent.run(task="What's the weather in Seattle?")result2 = await agent.run(task="How about Portland?")# History persists across callsprint(f"Total messages: {len(result2.messages)}")
# AutoGen streaming via run_streamasync for message in agent.run_stream(task="Tell me about AI agents"): if hasattr(message, "content"): print(message.content, end="")
AutoGen’s RoundRobinGroupChat executes agents in order. AF provides SequentialBuilder for the same pattern.
AutoGen
Agent Framework
from autogen_agentchat.teams import RoundRobinGroupChatfrom autogen_agentchat.conditions import TextMentionTerminationresearcher = AssistantAgent( name="researcher", model_client=client, system_message="Provide facts and data about the topic.",)writer = AssistantAgent( name="writer", model_client=client, system_message="Turn research into engaging content.",)editor = AssistantAgent( name="editor", model_client=client, system_message="Review and finalize. End with APPROVED if satisfied.",)team = RoundRobinGroupChat( participants=[researcher, writer, editor], termination_condition=TextMentionTermination("APPROVED"),)result = await team.run(task="Create a summary about electric vehicles")
from agent_framework.orchestrations import SequentialBuilderresearcher = client.as_agent( name="researcher", instructions="Provide facts and data about the topic.",)writer = client.as_agent( name="writer", instructions="Turn research into engaging content.",)editor = client.as_agent( name="editor", instructions="Review and finalize the content.",)workflow = SequentialBuilder( participants=[researcher, writer, editor]).build()async for event in workflow.run( "Create a summary about electric vehicles", stream=True): if event.type == "output": for message in event.data: print(f"{message.author_name}: {message.text}")
Advanced: Sequential with Cycles
For AutoGen patterns with multiple rounds, use AF’s WorkflowBuilder with cyclic edges:
from agent_framework import WorkflowBuilder, executor, AgentExecutorRequest@executorasync def check_approval(response, context): last_message = response.full_conversation[-1] if "APPROVED" in last_message.text: await context.yield_output("Content approved.") else: # Loop back to researcher for another round await context.send_message( AgentExecutorRequest( messages=response.full_conversation, should_respond=True ) )workflow = ( WorkflowBuilder(start_executor=researcher) .add_edge(researcher, writer) .add_edge(writer, editor) .add_edge(editor, check_approval) .add_edge(check_approval, researcher) # Cycle for multiple rounds .build())
Run both implementations side-by-side during migration. Each sample script runs AutoGen first, then AF, so you can compare outputs in a single execution.
Start with single-agent patterns before multi-agent orchestrations
Test default behavior early — AF’s multi-turn default can produce different results than AutoGen’s single-turn default
Use explicit sessions liberally during development; optimize session management after achieving parity
For group chats, AF’s GroupChatBuilder simplifies speaker selection — no need to manually track turn order
Handoff patterns are more structured in AF; use HandoffBuilder for clearer coordination logic
Tool approval is explicit in AF via approval_mode; always use "always_require" in production for actions