n4nAI

Getting started with AutoGen for multi-agent systems

Hands-on AutoGen tutorial for beginners: build multi-agent systems with Microsoft AutoGen, run code-executing agents, and route models via one endpoint.

n4n Team4 min read823 words

Audio narration

Coming soon — every post will get a voice note here.

This AutoGen tutorial for beginners cuts through the hype and shows you how to stand up a working multi-agent system with Microsoft’s AutoGen in under 30 minutes. We’ll define conversable agents, run a coded task with local execution, then scale to a group chat with a reviewer. Along the way, you’ll see how to point AutoGen at an OpenAI-compatible endpoint to avoid vendor lock-in.

Prerequisites

  • Python 3.10 or newer. AutoGen relies on async features and modern type hints that older runtimes lack.
  • pip install pyautogen==0.2.32 (or any stable 0.2.x). The 0.2 line exposes the ConversableAgent and GroupChat APIs used below.
  • An API key for an OpenAI-compatible LLM service. You can use OpenAI directly, or a gateway such as n4n.ai that exposes one OpenAI-compatible endpoint for 240+ models with automatic fallback when a provider is rate-limited.
  • Basic comfort with Python, shell, and reading JSON transcripts.

Project setup

Create an isolated environment and install the dependencies:

python -m venv .venv
source .venv/bin/activate
pip install pyautogen==0.2.32 python-dotenv

Create a .env file to keep secrets out of source control:

OPENAI_API_KEY=sk-...
# If using a unified gateway instead:
# N4N_API_KEY=your-key

Load it explicitly in your script. AutoGen does not read .env for you.

Two-agent baseline

AutoGen’s core primitive is ConversableAgent. Each agent holds a system message, an LLM config, and a communication policy. The simplest useful pair is a coding assistant and a user proxy that executes code locally.

import os
from dotenv import load_dotenv
from autogen import ConversableAgent

load_dotenv()

llm_config = {
    "model": "gpt-4o-mini",
    "api_key": os.environ["OPENAI_API_KEY"],
    "temperature": 0.1,
}

assistant = ConversableAgent(
    name="assistant",
    system_message="You are a pragmatic Python engineer. Output only runnable code and brief explanations.",
    llm_config=llm_config,
)

user_proxy = ConversableAgent(
    name="user_proxy",
    human_input_mode="NEVER",
    code_execution_config={"work_dir": "agent_workspace"},
    default_auto_reply="",
)

human_input_mode="NEVER" lets the agent run unattended. code_execution_config tells the proxy to write generated code to agent_workspace and run it via the local Python interpreter. Treat this directory as untrusted—point it at a scratch path, never your home directory.

Kick off the chat:

user_proxy.initiate_chat(
    assistant,
    message="Write a function fib(n) that returns the first n Fibonacci numbers. Include a test that prints the first 10.",
)

Expected output (abridged)

user_proxy (to assistant):

Write a function fib(n) that returns the first n Fibonacci numbers. Include a test that prints the first 10.

assistant (to user_proxy):

def fib(n):
    seq = []
    a, b = 0, 1
    for _ in range(n):
        seq.append(a)
        a, b = b, a + b
    return seq

if __name__ == "__main__":
    print(fib(10))

user_proxy (to assistant):

***** Suggested code *****
...
***** Code executed *****
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

The proxy executed the block and returned stdout to the assistant. That request-response-execute loop is the entire interaction model. No orchestration server required.

Adding a critic agent

A two-agent loop works for trivial tasks, but real engineering needs a third perspective. AutoGen handles this with GroupChat and GroupChatManager. The manager uses an LLM to decide which agent speaks next based on the evolving message history.

from autogen import GroupChat, GroupChatManager

critic = ConversableAgent(
    name="critic",
    system_message="You are a strict code reviewer. Flag bugs, edge cases, and style violations. Never write code.",
    llm_config=llm_config,
)

group = GroupChat(
    agents=[user_proxy, assistant, critic],
    messages=[],
    max_round=12,
)

manager = GroupChatManager(
    group=group,
    llm_config=llm_config,
)

user_proxy.initiate_chat(
    manager,
    message="Produce a CSV parser that handles quoted fields. Then have it reviewed.",
)

The manager will alternate between assistant (writes code), user_proxy (runs it), and critic (comments). Set max_round to bound cost and time; group chats without a cap will happily spin until context limits hit.

Checkpoint: group chat dynamics

Expect a transcript where the critic interjects after the first code execution:

critic (to user_proxy):

The parser fails on escaped quotes (\"). Add handling for double-quote doubling inside quoted fields.

assistant (to user_proxy):

Updated parse function with a state machine for quotes...

If the critic’s note is actionable, the assistant will revise and the proxy will re-execute. This emergent iteration is why AutoGen is useful for refactoring tasks where a single pass is insufficient.

Routing models through a single endpoint

When you run multi-agent systems, you often want different models for different roles—a cheap model for the proxy’s trivial replies, a strong model for the critic. Hard-coding vendor keys spreads secrets and complicates fallback when a provider degrades.

An OpenAI-compatible gateway collapses this. For example, you can point every agent at n4n.ai’s endpoint and just change the model string per agent; the gateway honors client routing directives and forwards provider cache-control hints, so you keep control without managing N providers.

def make_llm(model_name: str) -> dict:
    return {
        "model": model_name,
        "api_key": os.environ["N4N_API_KEY"],
        "base_url": "https://api.n4n.ai/v1",
        "temperature": 0.1,
    }

assistant = ConversableAgent(
    name="assistant",
    system_message="You are a pragmatic Python engineer.",
    llm_config=make_llm("openai/gpt-4o-mini"),
)

critic = ConversableAgent(
    name="critic",
    system_message="You are a strict code reviewer.",
    llm_config=make_llm("anthropic/claude-3.5-sonnet"),
)

The key win is one billing meter and one fallback path. If a provider is rate-limited, the gateway shifts traffic without your code changing.

Inspecting agent state

Debugging multi-agent loops means reading the message list. AutoGen stores every turn in group.messages (or agent.chat_messages for direct chats). Dump it after each run:

import json

with open("run_log.json", "w") as f:
    json.dump(group.messages, f, indent=2)

Each entry has role, content, and name. When an agent goes silent or repeats itself, the transcript shows whether the manager selected it. A common bug: the critic’s system message says “never write code” but the manager still routes a coding task to it because the selection prompt is ambiguous. Tighten the critic’s instruction and raise max_round only after confirming the loop terminates.

Operational guardrails

AutoGen executes LLM-generated code by default. That is powerful and dangerous.

  • Restrict work_dir to a throwaway path and run inside a container or VM.
  • Set human_input_mode="NEVER" only for trusted tasks; use "TERMINATE" to require a person for destructive commands.
  • Cap max_round in group chats. Unbounded loops burn tokens with diminishing returns.
  • Disable code_execution_config entirely for agents that should only talk, like the critic.
critic = ConversableAgent(
    name="critic",
    system_message="You review code. No execution.",
    llm_config=llm_config,
    code_execution_config=False,
)

Tuning system prompts per role

The quality of a multi-agent system lives in the system messages. In this AutoGen tutorial for beginners we used one-liners; production needs specifics.

  • Assistant: “You write Python 3.11, use type hints, and avoid external dependencies unless asked.”
  • Critic: “You check for Off-by-one errors, missing tests, and unsafe file paths. Respond in under 100 words.”
  • User proxy: keep human_input_mode="NEVER" but set default_auto_reply to a short ack so the manager sees progress.

Small prompt changes shift agent behavior more than model upgrades. Iterate on prompts against a fixed task and read the JSON logs.

Where to go next

You now have a runnable AutoGen tutorial for beginners that covers agent definition, code execution, group review, and model routing. From here, replace the local proxy with a secured execution sandbox (e.g., a Docker executor), or wire GroupChatManager to a custom speaker selection function for tighter control. The framework is a toolbox, not a black box—inspect the messages and tune system prompts per role.

Tagsautogenai-agentstutorial

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All autogen & microsoft agent framework posts →