What AutoGen Actually Is
AutoGen is an open-source Python framework from Microsoft Research that lets you build applications where multiple LLM-powered agents collaborate on tasks through structured conversation. Strip away the demo videos and you have three concrete pieces.
First, there is the agent abstraction. An agent in AutoGen is a Python class with three ingredients. A system message that sets the role and behavior. A model configuration pointing at OpenAI, Azure OpenAI, or another provider. An optional list of functions or tools the agent can call. The current version lets you build AssistantAgent, UserProxyAgent, and several specialist variants out of the box.
Second, there is the conversation primitive. Agents do not call each other directly. They send messages through a group chat manager or a simple reply chain. Each message is typed (text, code, function call, tool result), and the manager decides who speaks next based on rules you configure.
Third, there is the runtime. The current version ships an actor-model runtime in autogen-core and a higher-level conversation layer in autogen-agentchat. The split matters because the lower runtime handles message delivery, state, and subscriptions, while the upper layer gives you ready-made conversation patterns like two-agent chat, sequential chat, and group chat.
In practice this means AutoGen is less a framework for AI agents and more a Python library for orchestrating turn-taking between LLM calls, tool calls, and human inputs. That framing is useful because it tells you what AutoGen is good at and where it is the wrong tool.
Setup and Authentication
AutoGen runs on Python 3.10 or newer in most setups. The install has shifted across versions, so the right command depends on which release line you target.
For the v0.2 line, still widely used in production, you install the meta package:
pip install pyautogen
For the v0.4 line the package was split. The install is:
pip install autogen-agentchat autogen-core autogen-ext
Both pulls in the OpenAI client, an asyncio runtime, and the agent classes. Expect a moderately heavy dependency tree, on the order of dozens of transitive packages for a typical install.
Authentication is handled through a config_list, which is a list of dictionaries the framework scans for a matching model. The simplest shape uses OpenAI:
config_list = [ {“model”: “gpt-4o”, “api_key”: os.environ[“OPENAI_API_KEY”]} ]
You would normally read the key from the environment rather than hard-coding it. The config_list also accepts a filter dict so you can mix models by tag, cost, or capability.
For Azure OpenAI the entries look slightly different. Each entry needs the endpoint, deployment name, api_version, and key. A typical Azure config_list contains two or three deployments so you can route cheaper work to a smaller model and harder work to a flagship.
A common gotcha is forgetting api_version. Azure rejects requests without it and the error message is unhelpful. Another is model name mismatch. If the model string does not match a deployment you actually provisioned, AutoGen will retry silently with high latency before failing.
If you want a UI on top of the library, AutoGen Studio is installable as a separate package and gives you a web interface for designing agent flows without writing all the Python by hand. It is fine for prototyping and less suited to production wiring.
First Working Example
Here is a runnable two-agent loop. The AssistantAgent writes Python. The UserProxyAgent executes the code and feeds the output back. This pattern is the closest thing AutoGen has to a hello world.
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
llm_config = {“config_list”: config_list_from_json(env_or_file=“OAI_CONFIG_LIST”)}
assistant = AssistantAgent( name=“coder”, llm_config=llm_config, system_message=“You write short Python scripts. Reply TERMINATE when done.” )
user_proxy = UserProxyAgent( name=“executor”, human_input_mode=“NEVER”, code_execution_config={“work_dir”: “coding”, “use_docker”: False} )
user_proxy.initiate_chat( assistant, message=“Fetch the current BTC-USD price from the public CoinGecko API and print it.” )
The two config items doing the real work are human_input_mode=“NEVER” on the user proxy, which removes you from the loop, and use_docker=False, which executes generated code directly in a local subfolder rather than inside a container. The first is what lets the agents run unattended. The second is the fastest path to a demo and the worst path to production, since the assistant can write code that touches your filesystem.
The conversation usually goes like this. The user proxy sends the task. The assistant responds with a Python snippet using requests. The user proxy runs it, sees the output, and forwards it. The assistant summarises and replies with TERMINATE. The conversation halts.
To see it run, save the snippet to a file called first_chat.py, export OPENAI_API_KEY, create an OAI_CONFIG_LIST file with the same key, and run python first_chat.py. You should see a transcript of the exchange in your terminal within a few seconds.
Key Settings That Matter
The dials most people ignore are the ones that decide whether your AutoGen build is a tidy demo or a runaway token burner.
max_consecutive_auto_reply is the most important one. It caps how many turns one agent can produce before the framework forces a stop. Default is unlimited, which is a footgun. Without a cap, an agent that misunderstands the task can loop until your bill spikes. Setting it to 8 or 10 is reasonable for most flows.
human_input_mode takes three values: ALWAYS, NEVER, and TERMINATE. ALWAYS pauses for every reply. NEVER removes the human. TERMINATE only asks for input when an agent emits a special token, which is what production flows usually use so a human can sign off at the end.
code_execution_config has four knobs that matter. work_dir controls where generated files land. use_docker controls whether code runs in a container (safer) or directly (faster, riskier). last_n_messages determines how much conversation history the executor sees when interpreting a code block. timeout bounds how long any single execution can run.
temperature is set inside llm_config and is per-agent. A common pattern is to keep coding agents at low temperature for determinism and let research or critique agents run warmer.
For group chats the controls shift. GroupChat has a speaker_selection_method that defaults to auto, where a manager LLM picks the next speaker. You can switch to round_robin, random, or a custom callable. Each has trade-offs. Auto is flexible but adds cost and latency. round_robin is cheap but rigid. Custom callables let you encode business logic, such as always sending tool results back to the planner.
Termination in group chats uses TerminationCondition classes in the v0.4 line. You compose MaxMessageTermination, TextMentionTermination, and TokenUsageTermination into a list and pass it to the run. This is the cleanest part of the v0.4 API and worth the upgrade if you build multi-agent flows at all.
Caching is another quiet dial. Setting cache_seed to a fixed integer in llm_config caches identical requests, which is useful during development and painful during evaluation. Toggle it off when you actually want fresh responses.
Where It Shines
AutoGen is strongest in flows that need back-and-forth between reasoning and execution. Code generation and execution is the canonical win. The assistant proposes code, the executor runs it, the assistant reads the output and iterates. That loop is exactly what AutoGen was designed around and you can get a working research-to-code agent in under fifty lines.
Multi-agent debate and consensus is another strong fit. Two or three AssistantAgents with opposing system messages can critique each other’s drafts. The framework handles the turn-taking and you can read the full transcript afterwards.
Tool-heavy research workflows also work well. A planner agent can dispatch subtasks to specialist agents, each with its own tools (web search, SQL, calculator, file lookup), and the group chat manager keeps the conversation coherent. The pattern resembles a small specialist team and is a fair description of what the library models.
Sequential workflows where each stage hands off to the next are also straightforward