If you have agents built on AutoGen, it is time to plan a move. Microsoft has archived the project and points users to Microsoft Agent Framework. This guide is for teams with AutoGen code in production or close to it. It explains AutoGen's status and what it means for you, compares your migration options, maps AutoGen's agents, group chats, tools and termination conditions to their equivalents, and ports one small AutoGen team to Microsoft Agent Framework and to Promptise Foundry.
Should you migrate from AutoGen?
Yes, if the code will keep running. The AutoGen README now says the project is archived, that Microsoft provides no bug fixes, security fixes, new features or support, and that it advises against production use. The last release, 0.7.5, shipped on 30 September 2025. Microsoft's recommended path is Microsoft Agent Framework, which has an official migration guide. Other good targets are AG2 (the community fork), Promptise Foundry, LangGraph, the OpenAI Agents SDK, Pydantic AI and CrewAI.
The risk is security, not features. Unpatched dependencies and model client code age quickly.
Microsoft Agent Framework is the closest match. It comes from the AutoGen and Semantic Kernel teams and keeps the group chat, handoff and Magentic patterns.
Most AutoGen teams are simpler than they look. A two-agent round-robin chat is often a loop you can write in ten lines.
Termination conditions become explicit limits. Every target has a step limit; check what it does when reached.
Write evals before you port, so you can prove the new version behaves the same.
[02]
What happened to AutoGen?
AutoGen started at Microsoft Research as a framework for multi-agent conversations. Version 0.4 rewrote it into layers: autogen-core for an event-driven actor runtime, autogen-agentchat for high-level agents and teams, and autogen-ext for model clients and tools. In October 2025 Microsoft announced Microsoft Agent Framework as the successor to both AutoGen and Semantic Kernel, and version 1.0 shipped in April 2026 for Python and .NET.
The AutoGen repository now carries an archived banner. It says new users should start with Microsoft Agent Framework and existing users should follow the AutoGen migration guide. The contributing section further down still describes "maintenance mode" with only bug fixes and security patches, so the README contradicts itself, but the top-level message is clear. On PyPI, autogen-agentchat, autogen-core and autogen-ext have had no release since 0.7.5.
Two other names cause confusion:
`pyautogen` on PyPI now belongs to Microsoft again and installs autogen-agentchat. Pin pyautogen~=0.2.0 only if you still run the old 0.2 API.
AG2 (ag2ai/ag2) is a community fork led by some of AutoGen's original creators, published as ag2. Its 1.0 release (July 2026) is a rewrite with a new API. The old 0.2-style API lives on as "AG2 Classic".
[03]
How AutoGen works, and what a migration must replace
AutoGen AgentChat has four concepts you will need to map:
Agents. AssistantAgent wraps a model client, a system message and tools. By default it makes one round of tool calls per turn (max_tool_iterations=1) and returns the tool result unless reflect_on_tool_use is on. It keeps its own conversation history.
Tools. Plain Python functions, or FunctionTool, with the schema taken from type hints and the docstring. MCP servers connect through McpWorkbench.
Teams. RoundRobinGroupChat lets agents speak in turn. SelectorGroupChat asks a model who speaks next. Swarm routes by handoffs. MagenticOneGroupChat adds a planning orchestrator, and GraphFlow runs a directed graph.
Termination. Conditions such as TextMentionTermination("APPROVE") and MaxMessageTermination(8) decide when a team stops. They combine with | and &.
team.run(task)
│
▼
┌─────────────── RoundRobinGroupChat ────────────────┐
│ [support] ──tool call──▶ get_order ──▶ draft │
│ ▲ │ │
│ └──────── feedback ── [reviewer] ◀────┘ │
│ │
│ after every message: termination condition? │
│ "APPROVE" mentioned | 8 messages → stop │
└────────────────────────────────────────────────────┘
│
▼
TaskResult(messages, stop_reason)A migration replaces each of these: an agent with instructions and tools, the way agents take turns, the stop rule and the history each agent keeps.
[04]
Your AutoGen migration options
Versions checked on 18 October 2026, from each project's docs and PyPI.
Target | Version | Why choose it | Watch out for |
|---|---|---|---|
Microsoft Agent Framework | 1.22.0 | Official successor; group chat, handoff, Magentic and graph workflows; Python and .NET | New API names; several packages to install |
AG2 | 1.1.2 | Community continuation by AutoGen's original authors | 1.0 is a rewrite; AG2 Classic keeps the old API |
Promptise Foundry | 1.4.1 | MCP-first agents with approvals, budgets, guardrails and a runtime in one package | No group chat abstraction; teams become code or a coordinator |
LangGraph | 1.2.16 | Explicit graphs with checkpoints and durable interrupts | More code for simple teams |
OpenAI Agents SDK | 0.24.0 | Handoffs, the closest thing to Swarm, with very little code | Tracing goes to OpenAI by default |
Pydantic AI | 2.57.0 | Typed agents, usage limits, delegation through tools | Multi-agent patterns are code you write |
CrewAI | 1.15.28 | Role-based crews and Flows | Different mental model from conversations |
Microsoft Agent Framework
Choose it when you want the shortest conceptual distance from AutoGen, when you also use Semantic Kernel, or when you build on Azure AI Foundry. Its Agent replaces AssistantAgent, @tool replaces FunctionTool, and orchestration builders replace teams: GroupChatBuilder for round-robin and selector chats, HandoffBuilder for swarms, MagenticBuilder for Magentic-One and WorkflowBuilder for graphs. Its tools have a built-in approval_mode, which AutoGen's AssistantAgent never had. Parts of the official migration guide lag behind the code, for example its AutoGen samples use a StopAfterNMessages class that AutoGen 0.7.5 doesn't have (the real one is MaxMessageTermination), so check names against the API reference.
AG2
Choose it if you want to stay with the people and ideas behind AutoGen. If your code uses the 0.2 API, AG2 Classic is the smallest change. If it uses AgentChat 0.4 or later, there is no drop-in path: AG2 1.0 has its own new API, so treat it like any other port.
Promptise Foundry
Choose it when your agents are mostly tool users that need guard rails: approvals before risky tools, step and time limits, MCP servers, tracing you host yourself and a way to run and deploy the project. A two-agent team becomes two agents and a loop, as Step 3 shows, and a selector or swarm becomes a coordinator that calls other agents as tools.
The others
LangGraph fits when you need explicit, durable graphs; the framework comparison shows the same agent in it. The OpenAI Agents SDK fits swarm-style handoffs on OpenAI models. Pydantic AI fits typed, validated agents. CrewAI fits teams you describe by role.
[05]
When to choose Microsoft Agent Framework (and when not to)
Choose Microsoft Agent Framework if you rely on AutoGen's orchestration patterns (selector chats, Magentic-One, graphs), if you need .NET as well as Python, or if your organization standardizes on Microsoft's stack and support. It is the path Microsoft documents and maintains.
Look elsewhere if your AutoGen code is mostly one or two agents with tools, where a lighter framework or plain code is easier to read; if you want MCP servers, approvals and budgets in the same package; or if you want to avoid a large dependency tree for a small agent. In those cases, porting to Promptise, Pydantic AI or the OpenAI Agents SDK is usually less code.
[06]
What you need to run the examples
Python 3.10 or later and an OpenAI API key. All three versions use gpt-5-mini.
One virtual environment per framework:
pip install "autogen-agentchat==0.7.5" "autogen-ext[openai]==0.7.5" # AutoGen (archived)
pip install "agent-framework-core==1.22.0" "agent-framework-openai==1.17.0" \
"agent-framework-orchestrations==1.3.2" # Agent Framework
pip install "promptise==1.4.1" # Promptisepip install agent-framework installs everything at once, including integrations you may not need. The example is a support team: a support agent looks up the order with a tool and drafts a reply, and a reviewer approves it or asks for changes.
[07]
Step 1: Start from the AutoGen team
This is the AutoGen version, written with AgentChat 0.7.5's documented API.
"""AutoGen AgentChat 0.7: a support agent with a tool and a reviewer, in a round-robin team."""
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_ext.models.openai import OpenAIChatCompletionClient
ORDERS = {"O-1002": {"item": "Office chair", "amount": 219.00, "status": "delivered"}}
async def get_order(order_id: str) -> dict:
"""Look up an order by ID: item, amount in USD and status."""
return ORDERS.get(order_id.strip().upper(), {"error": f"No order {order_id}"})
async def main():
client = OpenAIChatCompletionClient(model="gpt-5-mini")
support = AssistantAgent(
"support", model_client=client, tools=[get_order], reflect_on_tool_use=True,
system_message="You are an order-support agent. Look the order up, then draft a reply "
"under 60 words. Refunds over 100 USD need a manager.")
reviewer = AssistantAgent(
"reviewer", model_client=client,
system_message="Review the support agent's draft. If it is correct, polite and under "
"60 words, answer APPROVE. Otherwise say briefly what to fix.")
team = RoundRobinGroupChat(
[support, reviewer],
termination_condition=TextMentionTermination("APPROVE") | MaxMessageTermination(8))
result = await team.run(task="My chair (order O-1002) arrived broken. I want my money back.")
for m in result.messages:
print(f"[{m.source}] {m.content if isinstance(m.content, str) else type(m).__name__}")
print("stop:", result.stop_reason)
await client.close()
asyncio.run(main())[user] My chair (order O-1002) arrived broken. I want my money back.
[support] ToolCallRequestEvent
[support] ToolCallExecutionEvent
[support] Sorry your Office chair (order O-1002, $219) arrived broken. Refunds over $100 require manager approval. Please send a photo of the damage and tell me whether you want a full refund or a replacement. I will escalate immediately once I receive that.
[reviewer] APPROVE
stop: Text 'APPROVE' mentionedThe support agent called get_order (the two event lines), then wrote a draft because reflect_on_tool_use=True. The reviewer said APPROVE, and TextMentionTermination stopped the team. If the reviewer had kept asking for changes, MaxMessageTermination(8) would have stopped it after eight messages. gpt-5-mini is in AutoGen 0.7.5's model list, so no model_info is needed.
[08]
Step 2: Port it to Microsoft Agent Framework
The official path keeps the same shape. AssistantAgent becomes Agent, the function becomes a @tool, and the round-robin team becomes a GroupChatBuilder with a selection function and a termination function.
"""Microsoft Agent Framework 1.x: the same support + reviewer team as a group chat."""
import asyncio
from agent_framework import Agent, tool
from agent_framework.openai import OpenAIChatClient
from agent_framework.orchestrations import GroupChatBuilder, GroupChatState
ORDERS = {"O-1002": {"item": "Office chair", "amount": 219.00, "status": "delivered"}}
@tool(approval_mode="never_require") # read-only lookup; use "always_require" for tools that change data
def get_order(order_id: str) -> dict:
"""Look up an order by ID: item, amount in USD and status."""
return ORDERS.get(order_id.strip().upper(), {"error": f"No order {order_id}"})
def round_robin(state: GroupChatState) -> str: # RoundRobinGroupChat
names = list(state.participants.keys())
return names[state.current_round % len(names)]
def done(conversation) -> bool: # TextMentionTermination("APPROVE") | MaxMessageTermination(8)
return len(conversation) >= 8 or "APPROVE" in (conversation[-1].text or "")
async def main():
client = OpenAIChatClient(model="gpt-5-mini")
support = Agent(
name="support", client=client, tools=[get_order],
instructions="You are an order-support agent. Look the order up, then draft a reply "
"under 60 words. Refunds over 100 USD need a manager.")
reviewer = Agent(
name="reviewer", client=client,
instructions="Review the support agent's draft. If it is correct, polite and under "
"60 words, answer APPROVE. Otherwise say briefly what to fix.")
workflow = GroupChatBuilder(participants=[support, reviewer], selection_func=round_robin,
termination_condition=done,
intermediate_output_from=[support, reviewer]).build()
result = await workflow.run("My chair (order O-1002) arrived broken. I want my money back.")
for response in result.get_intermediate_outputs(): # each agent's turn
for message in response.messages:
if message.text:
print(f"[{message.author_name}] {message.text}")
asyncio.run(main())[support] Sorry your Office chair (order O-1002) arrived broken. The order amount ($219) requires manager approval for refunds, so I’ve escalated this. Please send a photo of the damage; we’ll review and reply with next steps within 48 hours.
[reviewer] APPROVEThree differences to note. Termination is a plain function over the conversation instead of composable condition objects, so TextMentionTermination | MaxMessageTermination becomes one or. Speaker selection is explicit: round_robin reproduces RoundRobinGroupChat, and passing an orchestrator_agent instead gives you SelectorGroupChat behavior. And every tool declares an approval_mode. The read-only lookup uses never_require; for a refund tool, always_require makes the workflow pause for a decision.
[09]
Step 3: Port it to Promptise
In Promptise the team is two agents and a loop. The loop is the termination condition, written in code you can read and test.
"""The same team in Promptise: two agents and a loop you can read."""
import asyncio
from langchain_core.tools import tool
from promptise import build_agent
from promptise.conversations import InMemoryConversationStore
ORDERS = {"O-1002": {"item": "Office chair", "amount": 219.00, "status": "delivered"}}
MAX_ROUNDS = 3 # MaxMessageTermination(8) allowed about 3 draft/review rounds
@tool
async def get_order(order_id: str) -> dict:
"""Look up an order by ID: item, amount in USD and status."""
return ORDERS.get(order_id.strip().upper(), {"error": f"No order {order_id}"})
async def main():
support = await build_agent(
model="openai:gpt-5-mini", extra_tools=[get_order], max_agent_iterations=5,
conversation_store=InMemoryConversationStore(), # keeps the agent's history, like AssistantAgent
instructions="You are an order-support agent. Look the order up, then draft a reply "
"under 60 words. Refunds over 100 USD need a manager.")
reviewer = await build_agent(
model="openai:gpt-5-mini",
instructions="Review the support agent's draft. If it is correct, polite and under "
"60 words, answer APPROVE. Otherwise say briefly what to fix.")
try:
draft = await support.chat("My chair (order O-1002) arrived broken. I want my money back.",
session_id="ticket-42")
for round_no in range(1, MAX_ROUNDS + 1):
print(f"[support] {draft}")
review = await reviewer.ainvoke({"messages": [{"role": "user", "content": draft}]})
verdict = review["messages"][-1].content
print(f"[reviewer] {verdict}")
if "APPROVE" in verdict: # TextMentionTermination("APPROVE")
print(f"stop: approved in round {round_no}")
break
draft = await support.chat(f"Reviewer feedback: {verdict}\nRewrite the reply.",
session_id="ticket-42")
else:
print(f"stop: no approval after {MAX_ROUNDS} rounds")
finally:
await support.shutdown()
await reviewer.shutdown()
asyncio.run(main())[support] Sorry, I see order O-1002 (Office chair, $219) was delivered. Because the refund exceeds $100, I’ll escalate to a manager for approval. Please reply with photos of the damage and your preferred refund method. A manager will review within 48 hours and I’ll update you then.
[reviewer] APPROVE
stop: approved in round 1How the pieces map:
`AssistantAgent` → `build_agent()`. The system message becomes instructions. The tool becomes a LangChain @tool. Promptise always continues after tool results until the model answers, so there is no reflect_on_tool_use to set.
Agent history → a conversation store. AutoGen agents remember their own conversation. support.chat(..., session_id="ticket-42") gives the support agent the same memory, so the rewrite request in round two sees round one.
`RoundRobinGroupChat` → the `for` loop. Each round is draft, then review.
`TextMentionTermination("APPROVE")` → `if "APPROVE" in verdict`. `MaxMessageTermination(8)` → `MAX_ROUNDS`. The else branch reports when the team ran out of rounds, like stop_reason.
Inside each agent, `max_agent_iterations=5` caps the model calls per turn, which AutoGen's max_tool_iterations only partly covered.
Look at the drafts in all three versions. Each says the agent "escalated" the case or will reply within a set time, and each reviewer approved. No tool escalates anything, and no prompt gave a response time. That is the model filling gaps, in every framework. Give the support agent a real escalation tool, and give the reviewer the tool calls as well as the draft, so it can't approve a claim nothing backs up.
[10]
How do AutoGen concepts map to Microsoft Agent Framework and Promptise?
AutoGen (AgentChat 0.7) | Microsoft Agent Framework 1.x | Promptise Foundry |
|---|---|---|
|
| build_agent(model=, instructions=, extra_tools=) |
OpenAIChatCompletionClient(model=...) | OpenAIChatClient (Responses) or OpenAIChatCompletionClient | model="openai:gpt-5-mini" or any LangChain chat model |
Python function or FunctionTool | @tool with approval_mode | LangChain @tool in extra_tools, or an MCP server in servers= |
McpWorkbench | MCPStdioTool, MCPStreamableHTTPTool | |
reflect_on_tool_use, max_tool_iterations | Continues until a final answer by default | Continues until a final answer; max_agent_iterations caps model calls |
Agent keeps its history; save_state() | AgentSession | conversation_store= + agent.chat(..., session_id=...) |
RoundRobinGroupChat | GroupChatBuilder with a round-robin selection_func | A loop over the agents |
SelectorGroupChat | GroupChatBuilder(orchestrator_agent=...) | A coordinator with cross_agents= |
Swarm, handoffs | HandoffBuilder | A coordinator with cross_agents= (the coordinator keeps control) |
MagenticOneGroupChat | MagenticBuilder | No direct equivalent |
GraphFlow, DiGraphBuilder | WorkflowBuilder | PromptGraph (Reasoning Graph) |
TextMentionTermination, MaxMessageTermination | termination_condition= function | A condition and a bound in your loop; max_agent_iterations |
TimeoutTermination | Your own timeout | max_invocation_time= |
UserProxyAgent | request_info and response handlers | ApprovalPolicy for tool calls; your own input step |
CodeExecutorAgent(approval_func=...) | A sandboxed tool of your own, with approval_mode | agent_pattern="code-action" in a Docker sandbox |
AgentTool | agent.as_tool() | CrossAgent(agent=..., description=...) |
run_stream() + Console | workflow.run(..., stream=True) | agent.astream() |
[11]
How do you migrate from AutoGen step by step?
1. Inventory. List every AutoGen agent, team, tool and termination condition, and which AutoGen API each uses (0.2, or AgentChat 0.4+). 2. Freeze behavior. Write eval cases from real tasks: tools that must be called, actions that must never happen, facts the result must contain. How to evaluate AI agents in Python shows how. 3. Move tools out. Put them on an MCP server, so the tools work in any target. Build a production MCP server in Python shows how. 4. Port single agents first. An AssistantAgent without a team is one Agent or one build_agent() call. 5. Port teams. Round-robin teams become a builder or a loop; selector teams and swarms become an orchestrator or a coordinator. 6. Replace termination with limits that fail loudly. Decide what the caller sees when a team runs out of turns. 7. Add what AutoGen lacked. Approval before risky tools, cost limits, tracing. 8. Run both versions on the evals, then switch traffic.
[12]
Running it in production
Approvals
AutoGen's AssistantAgent had no approval step for tool calls. Add one as you migrate. In Microsoft Agent Framework, set approval_mode="always_require" on tools that change data. In Promptise, use an ApprovalPolicy with a handler that asks a person. Human-in-the-loop approval for AI agents covers the patterns.
Limits and cost
A group chat multiplies model calls: every message is a call, and every tool round adds more. Cap rounds in the team and model calls in each agent. Promptise's max_agent_iterations and max_invocation_time cover each agent; AI agent cost control adds budgets.
Code execution
If you used CodeExecutorAgent or Docker executors, keep the sandbox when you move. Promptise's code-action pattern runs the generated program in a Docker sandbox with no network by default. AI agent code execution sandbox explains the risks.
Dependencies
Remove the autogen-* packages once the port is done, so an archived dependency doesn't stay in your lock file. Pin the new framework and its mcp version, and run your evals on every upgrade.
[13]
Common problems and fixes
Symptom | Cause | Fix |
|---|---|---|
| agent-framework-core doesn't include provider clients | Install agent-framework-openai, or the full agent-framework package |
ModuleNotFoundError: agent-framework-orchestrations | Orchestration builders are a separate package | Install agent-framework-orchestrations |
| The final output is one completion message | Pass intermediate_output_from= and read get_intermediate_outputs() |
The ported agent returns raw tool output | AutoGen's reflect_on_tool_use was off, and code depended on it | Ask for the format you need in the instructions |
The ported agent forgets earlier turns | AutoGen agents kept history, and the new agent is stateless | Use AgentSession (Agent Framework) or a conversation store (Promptise) |
A team never stops | The termination text is never produced | Always pair a text condition with a hard bound |
Code from the migration guide fails | Some guide examples use names that differ from the current API | Check against the API reference of the version you install |
pip install pyautogen installs AgentChat | Microsoft reclaimed the package name | Pin pyautogen~=0.2.0 for the old API, or move to AG2 Classic |
[14]
Limitations
This is not a benchmark. It ports one small team and compares documented features. With the same model and tools, answers depend mostly on the model.
Promptise has no group chat class. Round-robin and selector teams become code or a coordinator. If you rely on Magentic-One style planning, Microsoft Agent Framework's MagenticBuilder is the closer fit.
Promptise approvals wait in-process. A pending approval doesn't survive a restart. Microsoft Agent Framework workflows and LangGraph support checkpointed pauses.
AutoGen's status may change. The README calls the project archived while its contributing section says maintenance mode. Check the repository before you decide on timing.
We make Promptise. We checked competitor claims against their docs, source and PyPI, ran every example once and recommend Microsoft Agent Framework where it fits better.
[15]
Frequently asked questions
Is AutoGen deprecated?
Effectively, yes. The AutoGen README says the project is archived and no longer maintained by Microsoft, with no bug fixes, security fixes or new features, and it advises against production use. The last release, 0.7.5, came out on 30 September 2025. Microsoft points new and existing users to Microsoft Agent Framework and publishes a migration guide.
What replaces AutoGen?
Microsoft Agent Framework is Microsoft's official successor to AutoGen and Semantic Kernel, with version 1.0 released in April 2026 for Python and .NET. The community fork AG2 continues AutoGen's ideas with a new API. Other frameworks, such as Promptise Foundry, LangGraph, the OpenAI Agents SDK, Pydantic AI and CrewAI, are also common migration targets, depending on how your agents work.
Is AG2 the same as AutoGen?
No. AG2 is a community fork led by some of AutoGen's original creators. Its 1.0 release is a rewrite with its own API, so AgentChat code doesn't run on it unchanged. AG2 Classic keeps the older AutoGen 0.2-style API. The pyautogen package name now belongs to Microsoft again and installs autogen-agentchat.
How do I migrate an AutoGen group chat?
Map the team type first. A RoundRobinGroupChat becomes Microsoft Agent Framework's GroupChatBuilder with a round-robin selection function, or a simple loop over two agents in Promptise. A SelectorGroupChat becomes an orchestrator agent or a coordinator that calls other agents as tools. Then turn each termination condition into a termination function or a loop condition with a hard bound.
What replaces AutoGen termination conditions?
In Microsoft Agent Framework, GroupChatBuilder takes a termination_condition function that receives the conversation and returns True to stop. In Promptise, the loop that runs your agents is the condition: check the reviewer's text and bound the number of rounds, and use max_agent_iterations and max_invocation_time to cap each agent. Always pair a text-based stop with a hard limit.
Can I keep using AutoGen?
You can, since the code and packages remain available, but you take on the risk yourself. Microsoft no longer provides security fixes, and its README advises against production use. If you must stay for a while, pin every dependency, keep the agent away from sensitive data and untrusted input where you can, and plan the migration.
[16]
Next steps
Compare seven frameworks feature by feature: Python AI agent frameworks compared.
Design the new team: multi-agent systems in Python.
Test before and after the port: how to evaluate AI agents in Python.
Add the approval step AutoGen didn't have: human-in-the-loop approval for AI agents.
Keep generated code contained: AI agent code execution sandbox.
Reference: cross-agent delegation and conversation persistence in the Promptise docs.