← Back to Learning Hub

AutoGen

LangChainLangGraphIntermediate11 min

By: Anacodic Team

TL;DR

AutoGen (Microsoft) is a framework for building multi-agent systems as conversations. Instead of a fixed pipeline, you create conversable agents — each with a role and an LLM — and they solve tasks by messaging each other. Two core roles: AssistantAgent (LLM that reasons/writes code) and UserProxyAgent (executes code / relays human input). For more than two agents, a GroupChat + GroupChatManager orchestrates a room where the manager picks the next speaker each turn, collects the reply, and broadcasts it. AutoGen shines for open-ended, iterative tasks — research, code-gen-and-fix, debate/critique loops — where the number of steps isn't known in advance. It trades predictability for flexibility, and its native code-execution loop makes it strong at agentic coding.


Simple explanation + analogy

AutoGen is a group chat of specialists in a Slack channel. You don't script every message. You define who's in the room (a coder, a reviewer, a product manager), give each a persona, and post the task. They then talk it out: the coder proposes code, a proxy agent runs it, the error comes back into the chat, the coder fixes it, the reviewer approves. The conversation is the program.

A GroupChatManager is the moderator: each turn it (1) chooses who speaks next, (2) gets that agent's message, (3) broadcasts it to everyone. The loop ends when a termination condition fires ("the message says TERMINATE", or max rounds hit).

Compare to LangChain (a scripted assembly line) or LangGraph (a subway map you drew): AutoGen lets the agents draw the route themselves through dialogue.


Diagram

   Two-agent chat (the primitive):

   ┌──────────────────┐   proposes code / answer   ┌──────────────────┐
   │  AssistantAgent  │ ─────────────────────────▶ │  UserProxyAgent  │
   │  (LLM: reason,   │ ◀───────────────────────── │  (execute code / │
   │   write code)    │   returns result / feedback│   human relay)   │
   └──────────────────┘                            └──────────────────┘
          loops until TERMINATE or max_turns

   Group chat (N agents):

                    ┌───────────────────────┐
        ┌──────────▶│  GroupChatManager     │◀───────────┐
        │           │  1. select speaker    │            │
        │           │  2. get reply         │            │
        │  broadcast│  3. broadcast to all  │  broadcast │
        │           └───────────────────────┘            │
        ▼                     ▼                           ▼
   ┌─────────┐         ┌────────────┐              ┌────────────┐
   │ Planner │         │  Coder     │              │  Reviewer  │
   └─────────┘         └────────────┘              └────────────┘

How it works (deep)

1. Conversable agents

Everything is a ConversableAgent with a receive → generate_reply → send loop. Two subclasses do most work:

  • AssistantAgent — an LLM with a system prompt/persona. It reasons, answers, and can write code blocks.
  • UserProxyAgent — represents the human and the execution environment. It can auto-execute code the assistant writes (in Docker or locally), request human input, and decide when to terminate. This "proxy that runs code" is AutoGen's signature: it closes the write-code → run-code → read-error → fix loop automatically.

2. The two-agent chat is the building block

user_proxy.initiate_chat(assistant, message=task) starts a back-and-forth. Each turn, the receiver generates a reply (LLM call, code execution, or human input) and sends it back. This alone solves a lot: "write and debug a script" becomes assistant-proposes / proxy-executes / assistant-fixes until tests pass.

3. Group chat and speaker selection

For N agents, wrap them in a GroupChat and drive it with a GroupChatManager. The manager's job each round:

  1. Select the next speaker — strategies: auto (an LLM decides who's most relevant given the conversation), round_robin, random, or a custom function.
  2. Collect that agent's message.
  3. Broadcast it to all members so everyone shares context.

Speaker selection is the heart of AutoGen orchestration and a favorite interview topic. auto is flexible but can misroute; round_robin is predictable; a custom selector gives you a state-machine-like structure while keeping the conversational substrate.

4. Termination

Loops need brakes. Termination fires on: a message matching a condition (e.g. contains "TERMINATE"), max_consecutive_auto_reply reached, max_round in a group chat, or a human typing exit. Getting termination right is essential — otherwise agents chat forever and burn tokens.

5. Human-in-the-loop is first-class

UserProxyAgent(human_input_mode=...):

  • ALWAYS — ask the human every turn,
  • TERMINATE — ask only when the agent wants to end,
  • NEVER — fully autonomous. The same abstraction spans "copilot with a human in the seat" and "fully autonomous crew".

6. Versions (know this for interviews)

  • v0.2 — the classic ConversableAgent / GroupChat API most tutorials use.
  • v0.4+ (AgentChat) — a rewrite: async, event-driven, actor-model core, AssistantAgent + teams like RoundRobinGroupChat / SelectorGroupChat, with model_client objects. Microsoft has since consolidated some of this direction into the Microsoft Agent Framework. If asked "is AutoGen current?", mention the v0.4 rewrite and the Agent Framework consolidation.

The math

AutoGen has no bespoke math, but two quantitative points matter in interviews.

Conversation cost grows with broadcast. In a group chat, every agent typically sees the full transcript. If the conversation has t turns and average message length m tokens, the running context at turn t is ~Σ mᵢ, so the token cost of turn t is roughly proportional to the cumulative history:

$$\text{cost}(t) \approx c \cdot \sum_{i=1}^{t-1} m_i ;;\Rightarrow;; \text{total} \approx O(T^2 \cdot \bar m)$$

for T total turns. This quadratic blow-up is why unbounded group chats get expensive fast — and why max_round, summarization, and tight termination conditions matter.

Speaker selection as a policy. With auto selection, choosing the next speaker is itself an LLM decision π(speaker | transcript). More agents = larger action space = more chance of a misroute. Empirically, keeping the roster small and roles distinct improves the routing hit-rate — a concrete design lever, not just style.


Real code

A minimal two-agent code-writing loop (v0.2 style) — the assistant writes, the proxy runs, the loop self-corrects:

from autogen import AssistantAgent, UserProxyAgent

llm_config = {"model": "gpt-4o", "api_key": "..."}   # any provider via a model client

assistant = AssistantAgent(
    name="coder",
    system_message="You are an expert Python engineer. Write code, fix errors, reply TERMINATE when done.",
    llm_config=llm_config,
)

# UserProxy executes code the assistant writes and relays results back
user_proxy = UserProxyAgent(
    name="runner",
    human_input_mode="NEVER",
    max_consecutive_auto_reply=6,
    is_termination_msg=lambda m: "TERMINATE" in (m.get("content") or ""),
    code_execution_config={"work_dir": "sandbox", "use_docker": True},
)

user_proxy.initiate_chat(
    assistant,
    message="Fetch BTC price from a public API and plot the last 7 days. Save chart.png.",
)
# → assistant writes code → runner executes → error/output returns → assistant fixes → ... → TERMINATE

A group chat with a manager selecting speakers:

from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager

planner  = AssistantAgent("planner",  system_message="Break the task into steps.",   llm_config=llm_config)
coder    = AssistantAgent("coder",    system_message="Implement each step in Python.", llm_config=llm_config)
reviewer = AssistantAgent("reviewer", system_message="Critique code; approve or request changes.", llm_config=llm_config)
proxy    = UserProxyAgent("proxy", human_input_mode="NEVER", code_execution_config={"work_dir": "out"})

group = GroupChat(
    agents=[proxy, planner, coder, reviewer],
    messages=[],
    max_round=12,
    speaker_selection_method="auto",   # manager LLM picks who talks next each turn
)
manager = GroupChatManager(groupchat=group, llm_config=llm_config)

proxy.initiate_chat(manager, message="Build and test a CLI to-do app with add/list/done commands.")

The v0.4 AgentChat equivalent (async, teams):

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination

team = RoundRobinGroupChat(
    [planner, coder, reviewer],
    termination_condition=TextMentionTermination("APPROVED"),
)
await team.run(task="Build and test a CLI to-do app.")

Real-world example (relating to a real stack)

A trip-planning assistant built with Strands + Bedrock uses an orchestrator-as-tools pattern: one orchestrator agent calls specialist agents (budget, flights, hotels, activities) as tools, then synthesizes. That's hierarchical tool-calling — the orchestrator is always in charge.

An AutoGen version of the same trip-planning task would look different in shape: put the specialists in a GroupChat and let a GroupChatManager run a conversation — the budget agent posts a price cap, the flights agent replies with options, the hotels agent critiques against preferences/dates, and they iterate until consensus. Same specialists, but peer-to-peer dialogue instead of a single boss issuing tool calls. That contrast — orchestrator calling tools (Strands) vs agents conversing (AutoGen) — is exactly what an interviewer wants you to articulate. AutoGen's strength here is emergent back-and-forth (an agent can push back on another's suggestion); its risk is the conversation meandering, which is why max_round and clear termination matter.


Interview questions companies actually ask

1. What is AutoGen and what's its core abstraction? [easy] A Microsoft framework for multi-agent LLM apps built on conversable agents that solve tasks by messaging each other. The unit is a conversation between agents (and optionally humans/tools), not a fixed pipeline. (Multi-agent Conversation Framework)

2. Difference between AssistantAgent and UserProxyAgent? [easy] AssistantAgent is an LLM persona that reasons and writes code. UserProxyAgent represents the human and the execution environment — it runs the assistant's code, relays human input, and decides termination. Together they form the write-code/run-code/fix loop.

3. How does group chat work, and what does the GroupChatManager do? [medium] Multiple agents share a GroupChat; the GroupChatManager moderates. Each round it (1) selects the next speaker, (2) collects that agent's reply, (3) broadcasts it to all members so context is shared. (Group chat research example)

4. What speaker-selection strategies exist and what are their tradeoffs? [medium] auto (an LLM picks the most relevant next speaker — flexible but can misroute), round_robin (predictable, no LLM cost), random, and custom functions (impose structure while staying conversational). Smaller rosters with distinct roles improve auto accuracy.

5. How do you prevent a group chat from running forever? [medium] Set max_round/max_consecutive_auto_reply, define is_termination_msg (e.g. a message containing TERMINATE/APPROVED), and choose a human_input_mode that can end the loop. Without these, agents chat until tokens run out.

6. How does AutoGen differ from LangChain and LangGraph? [medium] LangChain composes linear chains; LangGraph adds explicit state/branching/loops via a graph you define. AutoGen frames the whole system as an agent conversation — control flow emerges from dialogue and speaker selection rather than a graph you wire. AutoGen is stronger for open-ended, code-executing, debate-style tasks.

7. Why is AutoGen good at agentic coding specifically? [hard] The UserProxyAgent executes code (often in Docker) and feeds stdout/stderr back into the conversation, so the assistant sees real failures and self-corrects — a closed generate/run/debug loop out of the box, no glue code.

8. Why do group-chat costs blow up, and how do you control them? [hard] Every agent sees the full transcript, so per-turn token cost grows with cumulative history — roughly O(T²) over T turns. Control it with tight max_round, transcript summarization/compaction, fewer agents, and terse termination conditions.

9. What changed in AutoGen v0.4 (AgentChat) and where is it heading? [hard] v0.4 rewrote AutoGen on an async, event-driven, actor-model core with AssistantAgent and team abstractions (RoundRobinGroupChat, SelectorGroupChat) and model_client objects. Microsoft has been consolidating this direction into the Microsoft Agent Framework. (microsoft/autogen)

10. When would you not use AutoGen? [medium] When you need deterministic, auditable control flow (use LangGraph workflows), a simple linear pipeline (use an LCEL chain), or the leanest possible agent — Anthropic's guidance is to prefer simple, composable patterns over conversational frameworks unless the open-endedness truly warrants it.


When to use / tradeoffs

Use AutoGen when:

  • The task is open-ended and iterative (research, code-gen-and-debug, critique/debate loops).
  • You want emergent collaboration between specialist agents rather than a fixed script.
  • You need built-in code execution with automatic error-feedback loops.
  • Human-in-the-loop with flexible autonomy levels is a requirement.

Avoid when:

  • You need deterministic, auditable control flow (LangGraph workflow instead).
  • The flow is linear (an LCEL chain is simpler and cheaper).
  • Cost/latency predictability is paramount — conversational loops are hard to bound tightly.

Tradeoffs: flexibility and emergent problem-solving vs. predictability, cost control, and debuggability. The O(T²) transcript growth and free-form routing are the main operational risks — mitigate with small rosters, tight termination, and summarization.


AutoGen turns a multi-agent system into a conversation: conversable agents (AssistantAgent, UserProxyAgent) message each other, and for teams a GroupChatManager selects speakers, collects replies, and broadcasts. It excels at open-ended, code-executing, iterative work and first-class human-in-the-loop — at the cost of predictability and quadratic token growth. Contrast it with an orchestrator-calls-tools (Strands) approach to see conversation-driven vs hierarchical control.

Related articles:

  • CrewAI — role-based multi-agent with explicit tasks and processes (more structured than AutoGen).
  • Framework Comparison — AutoGen vs Strands vs CrewAI vs LangGraph vs OpenAI Agents SDK.
  • Multi-Agent Orchestration Patterns — orchestrator-worker, debate, hierarchical.
  • LangGraph — when you want the deterministic, auditable alternative to conversation.

Runnable notebook

Run it end to end — the mock model needs no API key; add your own key for the real Claude section.

Open In Colab