AutoGen Deep Dive
The Chat Room That Does Work
Imagine a Slack channel where a research analyst, a developer, a code reviewer, and a project manager are collaborating on a task. They exchange messages. The analyst provides findings. The developer writes code based on those findings. The reviewer critiques the code. The project manager decides when the task is complete and summarizes the outcome.
Now make all of them AI agents. That is Microsoft AutoGen.
AutoGen pioneered the "conversational" approach to multi-agent systems. Instead of designing explicit task orchestration pipelines, you define agents with roles and let them converse until a task is complete. The conversation itself is the coordination mechanism.
The approach is natural, powerful, and surprisingly robust. It works especially well for tasks that benefit from dialogue: research synthesis, code generation with critique, multi-perspective analysis, debate-style problem solving.
AutoGen v0.4 (released late 2024) rewrote the framework from scratch with an async-first actor model architecture, significantly improving reliability and scalability over the original v0.2. This lesson covers v0.4 in depth: the new architecture, agent types, conversation patterns, code execution, GroupChat, and the MagenticOne system.
:::tip 🎮 Interactive Playground Visualize this concept: Try the Agent Frameworks demo on the EngineersOfAI Playground - no code required. :::
Why AutoGen Exists
Before AutoGen (pre-2023), multi-agent systems required explicit orchestration: you wrote code specifying which agent called which other agent, in what order, with what data. This was powerful but rigid - changing the coordination pattern required changing the code.
AutoGen's insight: conversational coordination is more natural and more flexible than explicit orchestration. If agents know how to have a conversation, the coordination emerges from the conversation itself. You add a new agent type to the conversation, and the dynamics adjust automatically.
The original AutoGen paper (Wu et al., 2023) from Microsoft Research showed that two-agent conversations (AssistantAgent + UserProxyAgent) could solve complex tasks more reliably than single agents alone. The key insight was that the UserProxyAgent could execute code locally and feed results back into the conversation - creating a tight loop between generation and verification.
AutoGen v0.2 (2023): The original release. Conversational agents, GroupChat, code execution. Synchronous. Widely adopted but had reliability issues with long conversations and complex GroupChats.
AutoGen v0.4 (2024): Complete rewrite. Async-first actor model. New Teams API. Improved GroupChat with better speaker selection. MagenticOne integration. Much better reliability for production use.
The AutoGen v0.4 Architecture
v0.4 is built on the actor model: each agent is an independent actor that processes messages from its mailbox asynchronously. Agents communicate by sending typed messages. The runtime manages message routing, concurrency, and error handling.
Key v0.4 changes from v0.2:
- All agents are async by default (
async def) - Actor model replaces sequential function calls
TeamsAPI provides high-level multi-agent coordinationRoundRobinGroupChatandSelectorGroupChatreplace the olderGroupChat- Better termination condition handling
- Built-in observability via event hooks
Core Agent Types
AssistantAgent
The workhorse. An LLM-backed agent that reasons, plans, and responds to messages.
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.anthropic import AnthropicChatCompletionClient
# Create Anthropic client for AutoGen
model_client = AnthropicChatCompletionClient(
model="claude-opus-4-6",
api_key="your-anthropic-api-key",
)
researcher = AssistantAgent(
name="researcher",
model_client=model_client,
system_message="""You are a research analyst specializing in AI and technology trends.
Your role:
- Gather and synthesize information from your training data
- Identify key trends, statistics, and expert opinions
- Present findings in structured, evidence-based format
- Explicitly state when information may be outdated or uncertain
When you complete your research, end your message with 'RESEARCH COMPLETE'.""",
)
UserProxyAgent
Represents the human user - but more importantly, serves as the code execution environment. When an AssistantAgent produces Python code, the UserProxyAgent executes it and feeds results back into the conversation.
from autogen_agentchat.agents import UserProxyAgent
# Code-executing proxy (most common pattern)
executor = UserProxyAgent(
name="executor",
description="Executes Python code and returns results to the conversation.",
# In production: use DockerCommandLineCodeExecutor for sandboxing
code_execution_config={
"work_dir": "/tmp/autogen_workspace",
"use_docker": False, # True for production
"timeout": 60,
},
)
ConversableAgent
The base class both AssistantAgent and UserProxyAgent inherit from. Use it when you need custom conversation logic.
Conversation Patterns
Two-Agent Chat (Simplest Pattern)
Two agents talk to each other until a termination condition is met.
"""
Two-agent AutoGen: research + code execution pattern.
Install: pip install autogen-agentchat autogen-ext
"""
import asyncio
from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_ext.models.anthropic import AnthropicChatCompletionClient
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
async def two_agent_demo():
# Model client
model_client = AnthropicChatCompletionClient(
model="claude-opus-4-6",
)
# Agent 1: Writes the code
coder = AssistantAgent(
name="coder",
model_client=model_client,
system_message="""You are an expert Python programmer.
Write clean, well-commented Python code to solve the task.
Always wrap your code in ```python ... ``` code blocks.
When the task is done and verified, say TASK_COMPLETE.""",
)
# Agent 2: Executes the code and reports results
executor = CodeExecutorAgent(
name="executor",
code_executor=LocalCommandLineCodeExecutor(work_dir="/tmp"),
)
# Termination: stop when coder says TASK_COMPLETE or after 15 messages
termination = (
TextMentionTermination("TASK_COMPLETE")
| MaxMessageTermination(15)
)
# Two-agent team using round robin (coder → executor → coder → ...)
team = RoundRobinGroupChat(
participants=[coder, executor],
termination_condition=termination,
)
# Run the conversation
task = """Write a Python function that:
1. Takes a list of numbers
2. Returns the top-3 numbers and their indices
3. Handles edge cases (empty list, list with fewer than 3 elements)
4. Includes a brief test demonstrating it works."""
print("Starting two-agent conversation...")
async for message in team.run_stream(task=task):
if hasattr(message, "content"):
print(f"\n[{message.source}]:\n{message.content[:500]}")
await model_client.close()
if __name__ == "__main__":
asyncio.run(two_agent_demo())
RoundRobinGroupChat
Agents take turns in a fixed order. Simple and predictable.
async def round_robin_demo():
"""Research pipeline: analyst → writer → critic (repeating)."""
model_client = AnthropicChatCompletionClient(model="claude-opus-4-6")
analyst = AssistantAgent(
name="analyst",
model_client=model_client,
system_message="""You are a market research analyst.
Provide data-driven analysis with specific statistics and examples.
Structure your analysis with clear sections.""",
)
writer = AssistantAgent(
name="writer",
model_client=model_client,
system_message="""You are a technical writer.
Transform the analyst's research into a polished, readable report section.
Use clear language appropriate for a business audience.""",
)
critic = AssistantAgent(
name="critic",
model_client=model_client,
system_message="""You are a quality reviewer.
Evaluate the current draft for accuracy, clarity, and completeness.
List specific improvements needed. If the draft is publication-ready, say APPROVED.""",
)
termination = TextMentionTermination("APPROVED") | MaxMessageTermination(12)
team = RoundRobinGroupChat(
participants=[analyst, writer, critic],
termination_condition=termination,
)
result = await team.run(
task="Write a 300-word analysis of how LLMs are changing software development workflows in 2025."
)
print(f"Conversation completed in {len(result.messages)} messages")
print(f"Final message from: {result.messages[-1].source}")
await model_client.close()
SelectorGroupChat
A "director" agent decides which participant should speak next, based on context. More flexible than round robin.
async def selector_group_chat_demo():
"""
Customer support routing: different specialists handle different issues.
The selector (GroupChatManager) picks the right specialist based on the conversation.
"""
model_client = AnthropicChatCompletionClient(model="claude-opus-4-6")
billing_agent = AssistantAgent(
name="billing_specialist",
model_client=model_client,
description="Handles billing, payment, and subscription questions.",
system_message="You are a billing specialist. Help with payment and subscription issues. Say RESOLVED when done.",
)
technical_agent = AssistantAgent(
name="technical_specialist",
model_client=model_client,
description="Handles technical issues, bugs, and API questions.",
system_message="You are a technical support specialist. Diagnose and resolve technical issues. Say RESOLVED when done.",
)
account_agent = AssistantAgent(
name="account_specialist",
model_client=model_client,
description="Handles account management, access, and settings.",
system_message="You are an account specialist. Handle account access and settings questions. Say RESOLVED when done.",
)
termination = TextMentionTermination("RESOLVED") | MaxMessageTermination(10)
# SelectorGroupChat uses an LLM to pick the next speaker
team = SelectorGroupChat(
participants=[billing_agent, technical_agent, account_agent],
model_client=model_client, # Used for speaker selection
termination_condition=termination,
selector_prompt=(
"You are a customer support router. Based on the conversation history, "
"select the most appropriate specialist for the next message. "
"Available specialists: {participants}\n"
"Conversation: {history}\n"
"Next speaker:"
),
)
await team.run(task="I was charged twice for my subscription this month and now I can't log in.")
await model_client.close()
Termination Conditions
Knowing when to stop is as important as knowing what to do. AutoGen v0.4 has a clean termination condition API.
from autogen_agentchat.conditions import (
TextMentionTermination, # Stop when specific text appears
MaxMessageTermination, # Stop after N messages
StopMessageTermination, # Stop when an agent sends StopMessage
TimeoutTermination, # Stop after N seconds
ExternalTermination, # Trigger from outside the conversation
SourceMatchTermination, # Stop when specific agent speaks
)
# Combine with | (OR) and & (AND)
termination = (
TextMentionTermination("TASK_COMPLETE") # Done signal
| MaxMessageTermination(20) # Safety limit
| TimeoutTermination(300) # 5-minute timeout
)
# AND: require both conditions (e.g., approval from two agents)
strict_termination = (
TextMentionTermination("APPROVED")
& SourceMatchTermination(["critic", "reviewer"]) # Must come from specific agents
)
Code Execution: The UserProxyAgent Pattern
Code execution is what makes AutoGen especially powerful. The loop is:
- AssistantAgent generates Python code in a code block
- UserProxyAgent (or CodeExecutorAgent) detects the code block, executes it
- Execution output (stdout, stderr, return value) is fed back into the conversation
- AssistantAgent sees the output and can iterate
"""
Safe code execution with Docker sandbox.
Docker prevents code from accessing host filesystem, network, or system resources.
"""
import asyncio
from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_ext.models.anthropic import AnthropicChatCompletionClient
from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor
async def safe_code_execution_demo():
"""
Data analysis agent with sandboxed code execution.
Uses Docker for safety - code runs in isolated container.
"""
model_client = AnthropicChatCompletionClient(model="claude-opus-4-6")
data_analyst = AssistantAgent(
name="data_analyst",
model_client=model_client,
system_message="""You are an expert data analyst.
Write Python code to analyze data and produce insights.
Always:
- Import required libraries at the top
- Include error handling
- Print clear output with labels
- End with a summary of findings
When analysis is complete, say ANALYSIS_COMPLETE.""",
)
# Docker executor - runs code in an isolated container
# Container is automatically created and destroyed
code_executor = DockerCommandLineCodeExecutor(
image="python:3.12-slim",
timeout=60,
work_dir="/tmp/analysis",
auto_remove=True, # Remove container when done
)
executor_agent = CodeExecutorAgent(
name="code_executor",
code_executor=code_executor,
)
termination = (
TextMentionTermination("ANALYSIS_COMPLETE")
| MaxMessageTermination(10)
)
team = RoundRobinGroupChat(
participants=[data_analyst, executor_agent],
termination_condition=termination,
)
task = """Analyze this dataset of website traffic data and identify trends:
Monthly visitors (Jan-Dec 2024):
12400, 13100, 15200, 14800, 16500, 18200, 17900, 19100, 21300, 22000, 24500, 28100
Tasks:
1. Calculate month-over-month growth rates
2. Find the best and worst performing months
3. Calculate the average growth rate
4. Project Q1 2025 visitors based on the trend"""
async for message in team.run_stream(task=task):
if hasattr(message, "content") and message.content:
print(f"\n[{message.source}]: {str(message.content)[:600]}")
await model_client.close()
asyncio.run(safe_code_execution_demo())
Full Production Example: Research + Writing + Critique Pipeline
"""
Production-grade three-agent AutoGen pipeline:
1. Researcher: gathers information and analysis
2. Writer: produces polished written content
3. Critic: reviews and approves or requests revisions
Uses Anthropic Claude via AutoGen's Anthropic extension.
Install: pip install autogen-agentchat autogen-ext[anthropic]
"""
import asyncio
import json
from dataclasses import dataclass
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.messages import TextMessage
from autogen_ext.models.anthropic import AnthropicChatCompletionClient
@dataclass
class PipelineResult:
topic: str
final_content: str
message_count: int
approved: bool
summary: str
async def research_write_critique_pipeline(
topic: str,
target_word_count: int = 400,
max_rounds: int = 6,
) -> PipelineResult:
"""
Three-agent pipeline for researched, reviewed content.
Agents:
- Researcher: domain analysis and evidence gathering
- Writer: converts research into polished prose
- Critic: quality gates with specific improvement criteria
"""
model_client = AnthropicChatCompletionClient(model="claude-opus-4-6")
# ── Researcher ──────────────────────────────────────────────
researcher = AssistantAgent(
name="researcher",
model_client=model_client,
system_message=f"""You are an expert research analyst.
For the topic you receive:
1. Identify 4-6 key aspects worth covering
2. Provide specific data points, examples, and statistics where available
3. Note any important nuances, counterarguments, or limitations
4. Highlight what makes this topic important right now
5. Identify the target audience and their primary concerns
Format your research as structured notes with headers.
Be specific - avoid vague generalities.
End your research with: RESEARCH READY""",
)
# ── Writer ───────────────────────────────────────────────────
writer = AssistantAgent(
name="writer",
model_client=model_client,
system_message=f"""You are a senior technical writer.
Using the research provided:
1. Write approximately {target_word_count} words of polished, engaging prose
2. Use a clear structure: introduction, key points, implications
3. Make technical concepts accessible without losing accuracy
4. Include specific examples and data points from the research
5. Write for a senior engineer audience - assume technical competence
6. Do not use filler phrases like "In conclusion" or "It is worth noting"
After writing, end with: DRAFT COMPLETE""",
)
# ── Critic ───────────────────────────────────────────────────
critic = AssistantAgent(
name="critic",
model_client=model_client,
system_message=f"""You are a demanding quality reviewer.
Evaluate the draft against these criteria:
- Accuracy: Are all claims correct and well-supported?
- Specificity: Are there concrete examples and data, not vague statements?
- Clarity: Is the prose clear and accessible to the target audience?
- Completeness: Does it cover the most important aspects?
- Length: Is it approximately {target_word_count} words?
If revisions are needed: list 2-4 specific, actionable improvements.
If the draft meets all criteria: say APPROVED
Be demanding but constructive. Do not approve mediocre work.""",
)
# Termination: approved or hit limits
termination = (
TextMentionTermination("APPROVED")
| MaxMessageTermination(max_rounds * 3 + 1)
)
# Round robin: researcher → writer → critic (repeating)
team = RoundRobinGroupChat(
participants=[researcher, writer, critic],
termination_condition=termination,
)
# ── Run the pipeline ─────────────────────────────────────────
print(f"Starting pipeline for: {topic}")
print("─" * 60)
all_messages = []
final_draft = ""
approved = False
async for message in team.run_stream(task=f"Topic: {topic}"):
if hasattr(message, "content") and message.content:
content_str = str(message.content)
all_messages.append({
"source": getattr(message, "source", "unknown"),
"content": content_str,
})
# Track the latest writer output as current draft
if getattr(message, "source", "") == "writer":
final_draft = content_str
if "APPROVED" in content_str:
approved = True
# Display progress
source = getattr(message, "source", "unknown")
preview = content_str[:200].replace("\n", " ")
print(f"[{source}]: {preview}...")
print()
# Extract a summary from the critic's last message
critic_messages = [
m for m in all_messages if m["source"] == "critic"
]
summary = (
critic_messages[-1]["content"][:300]
if critic_messages
else "Pipeline completed"
)
await model_client.close()
return PipelineResult(
topic=topic,
final_content=final_draft,
message_count=len(all_messages),
approved=approved,
summary=summary,
)
async def main():
result = await research_write_critique_pipeline(
topic="How retrieval-augmented generation (RAG) is changing enterprise AI deployments in 2025",
target_word_count=400,
max_rounds=4,
)
print("\n" + "=" * 60)
print("PIPELINE COMPLETE")
print("=" * 60)
print(f"Topic: {result.topic}")
print(f"Messages exchanged: {result.message_count}")
print(f"Approved: {result.approved}")
print(f"\nFinal content ({len(result.final_content.split())} words):")
print("─" * 60)
print(result.final_content)
if __name__ == "__main__":
asyncio.run(main())
MagenticOne: AutoGen's Most Capable System
MagenticOne (Fourney et al., 2024) is Microsoft Research's most advanced multi-agent system, built on AutoGen. It is designed for general-purpose agentic tasks - web browsing, file manipulation, code execution, and complex multi-step reasoning.
Architecture:
- Orchestrator: Maintains a task plan, tracks progress, decides what to do next
- WebSurfer: Browses the web using a browser automation tool
- FileSurfer: Reads and manages files on the local filesystem
- Coder: Writes and executes Python code
- ComputerTerminal: Executes shell commands
Key design decisions:
- Orchestrator maintains "task ledger": Records what has been tried, what worked, what failed. Prevents repeated attempts of failed approaches.
- Explicit progress tracking: Orchestrator explicitly checks whether the task is making progress. If stuck, it changes strategy.
- No fixed turn order: Orchestrator selects the right specialist for each step dynamically.
"""
MagenticOne-style orchestrated multi-agent system.
This demonstrates the orchestrator + specialists pattern.
Install: pip install autogen-ext[magentic-one]
"""
import asyncio
from autogen_ext.agents.magentic_one import MagenticOne
from autogen_ext.models.anthropic import AnthropicChatCompletionClient
async def magentic_one_demo():
"""
MagenticOne handles complex multi-step tasks autonomously.
Best for tasks requiring web research + code + file operations.
"""
model_client = AnthropicChatCompletionClient(model="claude-opus-4-6")
# MagenticOne creates all specialists automatically
magentic = MagenticOne(client=model_client)
task = """Research the top 5 open-source LLM frameworks by GitHub stars as of early 2025.
For each:
1. Name and GitHub URL
2. Primary use case
3. Notable features that differentiate it
4. Current star count (approximate)
Then write a Python script that creates a ranked comparison table and prints it.
Execute the script and show the output."""
print("Running MagenticOne on complex multi-step task...")
result = await magentic.run(task=task)
print(f"\nResult: {result}")
await model_client.close()
# asyncio.run(magentic_one_demo())
AutoGen v0.4 vs v0.2: Key Differences
| Feature | v0.2 | v0.4 |
|---|---|---|
| Execution model | Synchronous | Async-first |
| Architecture | Function calls | Actor model |
| Group chat API | GroupChat + GroupChatManager | RoundRobinGroupChat, SelectorGroupChat |
| Termination | Simple string matching | Composable condition objects |
| Observability | Limited | Event hooks, structured logging |
| Code execution | CodeExecutionConfig dict | CodeExecutorAgent + executor objects |
| Nested chats | Manual | Built-in sub-conversation support |
| Model clients | OpenAI-centric | Pluggable (Anthropic, Gemini, etc.) |
When AutoGen Fits vs When It's Overkill
AutoGen is the right choice when:
- Tasks benefit from dialogue and back-and-forth critique (research → write → review)
- Code generation needs execution validation in a loop
- Different expertise domains need to collaborate on a single task
- You want the simplest possible multi-agent setup that works
AutoGen is overkill when:
- Tasks are purely sequential with no benefit from dialogue (just use a single agent with well-designed prompts)
- You need fine-grained control over state and transitions (use LangGraph)
- You need hierarchical team structures with nested delegation (use CrewAI hierarchical process)
- You need hundreds of agents with complex routing logic (use custom orchestration)
:::danger Code Execution Security
AutoGen's UserProxyAgent and CodeExecutorAgent execute Python code that LLMs generate. A malicious or manipulated conversation could cause the agent to generate and execute harmful code: deleting files, exfiltrating data, making network requests. Always use Docker sandboxing in production: DockerCommandLineCodeExecutor. Never use local execution (LocalCommandLineCodeExecutor) for user-facing production systems. Configure Docker containers with minimal permissions, no external network access, and read-only filesystem mounts where possible.
:::
:::warning GroupChat Speaker Selection Reliability
SelectorGroupChat uses an LLM to select the next speaker - which means speaker selection can fail, loop, or select the wrong agent. Always set a MaxMessageTermination as a safety backstop. Monitor conversations in production for infinite loops (the same two agents repeating the same exchange). Consider using RoundRobinGroupChat for predictable tasks and SelectorGroupChat only when the task genuinely benefits from dynamic routing. Log all speaker selections for debugging.
:::
Interview Questions and Answers
Q: What is the actor model in AutoGen v0.4 and why is it better than the synchronous v0.2 approach?
A: The actor model treats each agent as an independent process (actor) with its own mailbox. Agents receive messages, process them asynchronously, and send messages to other agents via the runtime's message router. They never call each other directly. In v0.2, agents were called synchronously in a chain - agent A would call agent B which would call agent C. This created tight coupling and made it impossible to run agents concurrently. With the actor model in v0.4, multiple agents can process messages simultaneously (true concurrency), agents are decoupled from each other (they only know about message types, not specific agents), the runtime handles failures gracefully (an actor crash doesn't crash the whole system), and adding new agent types is a matter of implementing the actor interface without modifying existing agents. The practical benefits are better reliability, easier testing (actors can be mocked independently), and support for more complex topologies.
Q: How does AutoGen's code execution loop work and what makes it effective for coding tasks?
A: The loop is: (1) AssistantAgent generates a plan and writes Python code in a fenced code block. (2) CodeExecutorAgent detects the code block using regex matching on the message content. (3) The executor runs the code in a sandboxed environment (Docker in production, local subprocess for development). (4) Stdout, stderr, and the return value are captured and returned as a new message from the executor. (5) The AssistantAgent receives the execution output in its context and can see whether the code worked, what errors occurred, and what output was produced. (6) The AssistantAgent then writes new or corrected code based on the feedback. This tight loop is effective because it grounds code generation in empirical feedback - the agent cannot hallucinate the output of its code. It has to look at what the code actually produced. This dramatically reduces code generation errors compared to single-pass code generation with no execution feedback.
Q: When would you choose SelectorGroupChat over RoundRobinGroupChat?
A: RoundRobinGroupChat gives each agent a turn in fixed rotation. It is predictable, cheap (no LLM call for turn selection), and appropriate for pipelines with a natural sequential workflow (research → write → critique). SelectorGroupChat uses an LLM (the selector) to dynamically choose the next speaker based on the conversation so far. It is more expensive (extra LLM call per turn) but handles tasks where the right next agent depends on context. Use SelectorGroupChat when: different user requests need different specialists (customer support routing), the task is exploratory and the right next step is not predetermined (the conversation content determines what kind of expertise is needed next), or when some agents should speak rarely and only when specifically relevant. Use RoundRobinGroupChat for clear sequential pipelines, cost-sensitive applications, and when you want predictable conversation structure.
Q: How does MagenticOne differ from a standard AutoGen GroupChat?
A: MagenticOne introduces a deliberate orchestrator that maintains explicit task state and strategy. In a standard GroupChat, agents communicate and the manager picks the next speaker. There is no global task plan - the plan is implicit in the conversation. MagenticOne's Orchestrator maintains a "task ledger" that records: what the overall task is, what steps have been completed, what has been tried and failed, and what the current plan is. This explicit state prevents common GroupChat failure modes: getting stuck repeating failed approaches, losing track of the overall task in long conversations, and failing to recognize when the task is actually complete. The Orchestrator also performs periodic progress checks - it explicitly asks "are we making progress?" and changes strategy if the answer is no. For complex multi-step tasks involving multiple modalities (web browsing, code execution, file operations), MagenticOne significantly outperforms standard GroupChat because it never loses sight of the overall goal.
Q: How would you handle a conversation that gets stuck in an infinite loop in AutoGen?
A: Multiple safeguards working together. (1) MaxMessageTermination as an absolute backstop - always set this, regardless of other termination conditions. No conversation should run more than 30–50 messages without human review. (2) Detect repetition: monitor for the same content appearing multiple times from the same agent. If agent A says the same thing three times in a row, something is wrong. (3) TimeoutTermination: set a wall-clock time limit. A conversation should not run longer than 10 minutes for most tasks. (4) Progress detection: for tasks with clear milestones, write a custom termination condition that checks whether expected artifacts (code, documents, decisions) have been produced within the last N messages. If not, terminate. (5) Human escalation: when a conversation terminates without reaching the goal condition (approved, resolved, complete), flag it for human review rather than silently failing. (6) MagenticOne's explicit progress checking is the most robust approach for complex tasks - build in explicit "is this making progress?" evaluation every 5–7 turns.
