Thursday, September 25, 2025

AI Agentic Design Patterns with AutoGen

AI Agentic Design Patterns with AutoGen

What you’ll learn

  • Build and customize multi-agent systems using AutoGen.
  • Assign agents different roles and enable them to collaborate on complex tasks.
  • Implement agentic design patterns such as multi-agent conversations, tool use, reflection, and planning.

Hands-on Projects

You’ll create systems such as:

  • Two-agent comedy chat – using ConversableAgent for constructing multi-agent conversations.
  • Customer onboarding flow – sequence of chats with agents collaborating.
  • Blog post with reflection – nested critic and reviewer agents refine another agent’s writing.
  • Conversational chess game – agents play chess by calling tools for legal moves.
  • Coding agent for financial analysis – generates plots of stock gains and integrates user functions.
  • Collaborative financial agents – two systems:
    • Generate code from scratch.
    • Refine user-provided code.
  • Custom group chat with planning – multiple agents generate a detailed stock report.

Tools & Framework

  • AutoGen works with any LLM via API or local setup.
  • Patterns: multi-agent collaboration, tool use, reflection, planning.

What you will learn

  • Strong grasp of AutoGen’s core components.
  • Practical ability to implement agentic design patterns.
  • Skills to automate workflows with multi-agent AI systems.

Technology Used

  • Basic Python knowledge.
  • automation, AI workflows, and applied agent systems.

Learning Path

  • Introduction
  • Multi-Agent Comedy Chat
  • Sequential Chats & Onboarding
  • Reflection & Blogpost Writing
  • Tool Use & Conversational Chess
  • Coding & Financial Analysis
  • Planning & Stock Report Generation
  • Conclusion
AutoGen Multi-Agent Conversational Framework

AutoGen Multi-Agent Conversational Framework

Introduction

  • AutoGen is a multi-agent conversational framework.
  • Lets you create agents with different roles, personas, tasks, and capabilities.
  • Enables the use of agentic design patterns to implement complex AI applications.

Example Use Case: Financial Data Analysis

Normally requires days of research, coding, and report writing. With AutoGen:

  • Create agents as researcher, data collector, co-writer, executor.
  • Agents can review, critique, and refine the output until it meets the standard.

Learning Structure

You’ll learn six core design patterns/use cases:

  • Multi-agent conversations – ConversableAgent
    Example: two standup comedians chatting.
  • Sequential chats
    Agents work step-by-step to complete a sequence of tasks. Example: customer onboarding flow.
  • Agent reflection with nested chat
    Agents call other agents and iterate before producing a result.
    Examples: well-written blog post, conversational chess game.
  • Tool use
    Provide a user-defined function for agents. Example: checking if a chess move is legal.
  • Code writing & execution
    Agents generate, verify, and run code (e.g., in a sandbox). Example: financial analysis & stock gains plotting.
  • Custom multi-agent group chats with planning
    Add a planning agent to manage task flow. Example: generating a detailed financial report.

Key Concepts You’ll Learn

  • Multi-agent conversation & collaboration
  • Sequential task execution
  • Nested chat (agents managing sub-agents)
  • Tool use (integrating functions)
  • Code generation & execution
  • Planning & group chat orchestration
Lesson 1: Conversable Agent & Multi-Agent Conversation

1: Conversable Agent & Multi-Agent Conversation (Comedy Chat)

Key Concept: Conversable Agent

In AutoGen, an Agent is an entity that can:

  • Act on behalf of human intent
  • Send/receive messages
  • Perform actions
  • Generate replies
  • Interact with other agents

ConversableAgent (built-in class)

Provides a unified interface for different agent types. Supports:

  • LLM-based replies (via configurable models like GPT-3.5 Turbo)
  • Code execution and tool/function execution
  • Human-in-the-loop control (input modes: never, always, etc.)
  • Highly customizable to fit different applications

Basic Setup Example

  • Import API key and set up LLM configuration (GPT-3.5 Turbo in this course)
  • Create a ConversableAgent:
    • Name: Chatbot
    • Config: LLM setup
    • Input mode: "never" (fully autonomous)
  • Use generate_reply() with a message (e.g., "Tell me a joke")
  • Output: Agent generates a response, e.g., “Why did the scarecrow win an award? Because he was outstanding in his field.”
⚠️ Note: Calling generate_reply() again does not preserve state → agent generates a fresh response every time.

Creating Multi-Agent Conversations

Stand-up Comedy Example

  • Agent 1: Cathy → system message: "You are Cathy, a stand-up comedian."
  • Agent 2: Joe → system message: "You are Joe, a stand-up comedian. Start the next joke from the punchline of the previous joke."

Conversation initiated via initiate_chat() from Joe → Cathy.

Example exchange:
Joe: “I’m Joe. Cathy, let’s keep the jokes rolling.”
Cathy: “Why did the math book look sad? Because it had too many problems.”
Joe: “At least now we know why the math book was always so negative.”

Controlling Conversation Flow

  • Max Turns – limit how many back-and-forths occur
  • Stopping Condition (is_termination_message) – define a rule to end chat
Example: If a message contains “I gotta go”, conversation stops.

Conversation History & Metadata

After chat finishes, you can inspect:

  • Chat history (all exchanged messages)
  • Token usage (prompt vs. completion)
  • Cost (based on API tokens)
  • Summary (last message or reflection via LLM)

Preserving State

With multi-agent chat setup, agents can now remember prior exchanges.

Example: Cathy asks → “What was the last joke we talked about?”
Joe recalls correctly → “The Scarecrow joke (outstanding in his field).”

Lesson Wrap-Up

You learned how to:

  • Create your first ConversableAgent
  • Generate replies with generate_reply()
  • Build a multi-agent comedy chat
  • Control flow with max turns or termination messages
  • Inspect history, usage, and summaries
  • Enable state preservation for ongoing conversations

This is just the foundation. Next lessons → Sequential Chats, Reflection, Tool Use, Planning, Code Execution.

2. Sequential Multi-Agent Chats (Customer Onboarding)

2. Sequential Multi-Agent Chats for Customer Onboarding

In the previous lesson, we built basic Conversable Agents and explored a comedy-style multi-agent conversation. Now, in Lesson 2, we extend this concept into a practical use case: customer onboarding. Instead of jokes, the agents work together in sequence to simulate a pipeline:

  • Personal Information Agent – asks for name and location.
  • Topic Preference Agent – surveys what topics the customer likes.
  • Engagement Agent – uses info + interests to create a fun interaction.
  • Customer Proxy Agent – represents the actual user (human in the loop).

1. Setup


from autogen import ConversableAgent
from utils import get_openai_api_key  

OPENAI_API_KEY = get_openai_api_key()
llm_config = {"model": "gpt-3.5-turbo"}
  

Just like before, we load the OpenAI API key and configure the LLM (default: gpt-3.5-turbo). You can swap in gpt-4 or others.

2. Define the Agents

(a) Personal Info Collection Agent


info_agent = ConversableAgent(
    name="info_agent",
    system_message="You are a customer onboarding agent. Ask the customer for their name and location.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
  

(b) Topic Preference Agent


topic_agent = ConversableAgent(
    name="topic_agent",
    system_message="You are an onboarding agent. Ask the customer what topics they are interested in.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
  

(c) Engagement Agent


engage_agent = ConversableAgent(
    name="engage_agent",
    system_message="You are a fun engagement agent. Use the customer's name, location, and interests to tell them fun facts or jokes.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)
  

(d) Customer Proxy Agent


customer_proxy = ConversableAgent(
    name="customer",
    system_message="You are the customer. Answer questions honestly when asked.",
    llm_config=llm_config,
    human_input_mode="ALWAYS",  # requires real user input
)
  

The Customer Proxy acts as the real user in this pipeline. By setting human_input_mode="ALWAYS", it pauses to let you (the human) provide answers.

3. Run Sequential Chats

Step 1 – Collect Personal Info


chat1 = info_agent.initiate_chat(
    recipient=customer_proxy,
    message="Hello! Can you tell me your name and where you're from?",
    max_turns=2,
    summary_method="reflection_with_llm",
    summary_prompt="Extract customer info as JSON with fields: name, location."
)
  

Step 2 – Survey Topics


chat2 = topic_agent.initiate_chat(
    recipient=customer_proxy,
    message="Great, could you tell me what topics you’re interested in reading about?",
    max_turns=1,
    summary_method="reflection_with_llm"
)
  

Step 3 – Engage the Customer


chat3 = customer_proxy.initiate_chat(
    recipient=engage_agent,
    message="Let’s find something to read!",
    max_turns=2
)
  

4. Inspect Results


import pprint  

print("\n--- Chat 1 Summary (Customer Info) ---")
pprint.pprint(chat1.summary)

print("\n--- Chat 2 Summary (Interests) ---")
pprint.pprint(chat2.summary)

print("\n--- Chat 3 Engagement ---")
pprint.pprint(chat3.chat_history)

print("\n--- Costs ---")
print("Chat 1 Cost:", chat1.cost)
print("Chat 2 Cost:", chat2.cost)
print("Chat 3 Cost:", chat3.cost)
  

✅ Expected Flow

  • Chat 1: Asks your name and location (e.g., "Alice from New York").
  • Chat 2: Surveys your interests (e.g., "Dogs, Technology").
  • Chat 3: Engagement agent responds, e.g. “Hi Alice from New York! Did you know dogs can understand up to 250 words?”

💡 Key Takeaways

  • This lesson introduces Sequential Multi-Agent Chats.
  • Each step produces a summary that feeds into the next.
  • Human participation is possible via the Customer Proxy Agent.
  • This structure is perfect for onboarding pipelines, surveys, and guided flows.

In the next lessons, we’ll enhance this with reflection, tool use, and planning — making agents smarter and more autonomous in real-world tasks.

2. Breakdown: Sequential Multi-Agent Onboarding

Lesson 2 Breakdown: Sequential Multi-Agent Onboarding

In this part of Lesson 2, we’ll break down how the customer onboarding simulation works, step by step. You’ll see how agents are defined, chained together, and how summaries flow between them.

1. Setup


llm_config = {"model": "gpt-3.5-turbo"}
from autogen import ConversableAgent
  

Here we configure the LLM backend (default: gpt-3.5-turbo) and import ConversableAgent for building our agents.

2. Define the Agents

We create four agents, each with a specific role:

  • onboarding_personal_information_agent – Asks only for name and location. Ends after collecting them.
  • onboarding_topic_preference_agent – Asks for preferred topics. Ends once interests are gathered.
  • customer_engagement_agent – Uses name + location + interests to share fun facts, jokes, or stories.
  • customer_proxy_agent – Represents the human user. With human_input_mode="ALWAYS", it pauses for your real input.

3. Define the Sequential Tasks


chats = [
    {...}, 
    {...}, 
    {...}
]
  

The chats array defines three conversations in sequence:

  1. Personal Info Chat
    • Sender: onboarding info agent
    • Recipient: you (customer proxy)
    • Kickoff: "Tell me your name and location"
    • Summarizes output into JSON: {"name": "", "location": ""}
  2. Topic Preference Chat
    • Sender: topic preference agent
    • Recipient: you
    • Kickoff: "What topics are you interested in reading about?"
    • Summarized with reflection
  3. Engagement Chat
    • Sender: you (proxy)
    • Recipient: engagement agent
    • Kickoff: "Let’s find something fun to read."
    • Engagement agent responds with jokes/facts using your info

4. Run the Chats


from autogen import initiate_chats

chat_results = initiate_chats(chats)
  

This runs the chats in order. Each result object contains: history, summary, and cost breakdown.

5. Inspect Results

Print Summaries


for chat_result in chat_results:
    print(chat_result.summary)
    print("\n")
  

Example output:


{"name": "Alice", "location": "New York"}
Alice is interested in reading about dogs.
The agent shared a fun dog fact with Alice from New York.
  

Print Costs


for chat_result in chat_results:
    print(chat_result.cost)
    print("\n")
  

This reveals token usage and dollar cost for each step.

✅ What Happens When You Run It

A typical run looks like this:

  1. Chat 1: Agent asks “What’s your name and location?” → you reply.
  2. Chat 2: Agent asks “What topics are you interested in?” → you reply.
  3. Chat 3: Engagement agent uses your info to generate a tailored response.

For example, if you say:

  • Name: Alice
  • Location: New York
  • Topic: Dogs

The engagement agent might say:

Hey Alice from New York! Did you know dogs can smell 100,000 times better than humans? 🐶

💡 Key Takeaway

This breakdown shows how sequential multi-agent chats can form a complete onboarding pipeline. Each agent has a single purpose, and the flow feels natural — just like interacting with a real onboarding assistant.

Lesson 3: Reflection & Nested Chat Pattern

3. Reflection & Nested Chat Pattern

Got it 👍 — this lesson is all about agent reflection and how to use the nested chat conversation pattern to improve a blog post through multiple layers of review.

🔑 Key Concepts

  • Writer Agent – Generates the first draft of the blog post (e.g., about DeepLearning.AI, under 100 words).
  • Critic Agent – Reflects on the writer’s draft. Instead of giving direct feedback, it uses nested chats to consult specialized reviewer agents.
  • Reviewer Agents (nested under Critic):
    • SEO Reviewer → Checks keywords, ranking potential, organic traffic.
    • Legal Reviewer → Ensures compliance, no copyright or misleading claims.
    • Ethics Reviewer → Ensures fairness, avoids bias or harm.
    • Meta Reviewer → Aggregates all reviewer feedback into one final suggestion.

📚 Nested Chat Pattern

The Critic Agent doesn’t just reply directly to the Writer. Instead, it:

  1. Routes the draft into multiple sub-chats with reviewer agents.
  2. Collects structured JSON feedback from each reviewer.
  3. Passes everything to the Meta Reviewer, who produces a unified recommendation.
  4. Returns consolidated feedback to the Writer Agent for refinement.

🛠️ Workflow

1️⃣ Writer Agent produces the first draft (short blog post).
2️⃣ Critic Agent routes the draft to the SEO Reviewer for optimization tips.
3️⃣ Critic routes draft to Legal Reviewer → checks for compliance and accuracy.
4️⃣ Critic routes draft to Ethics Reviewer → ensures neutrality and no harm.
5️⃣ Meta Reviewer aggregates all feedback into one set of recommendations.
6️⃣ Critic Agent sends final, combined feedback to Writer Agent.
7️⃣ Writer Agent refines draft → produces a concise, SEO-friendly, safe, and ethical blog post.

🧠 Why Reflection + Nested Chat?

  • Provides multi-dimensional review (SEO, legal, ethical).
  • Mimics a real-world editorial workflow → Writer → Reviewers → Final Editor.
  • Improves quality, trustworthiness, and compliance of generated content.
👉 In short: The Critic becomes a manager of expert reviewers. This layered structure ensures the final blog post is optimized, safe, and reliable.
Lesson 3 Breakdown: Reflection & Nested Chat (Step-by-step)

3. Reflection & Nested Chat: Step-by-Step Breakdown

Perfect 👍 — you’ve built Lesson 3. Below is a concise, explicit walk-through of what each piece of code does and how the nested reflection pattern works in practice.

🔨 Step-by-Step Breakdown

1. Setup

llm_config = {"model": "gpt-3.5-turbo"}

Defines the LLM backend used by all agents. Swap to gpt-4 later if desired.

2. Task Definition

task = '''
    Write a concise but engaging blogpost about
    DeepLearning.AI. Make sure the blogpost is
    within 100 words.
    '''

A clear instruction block for the writer agent; the writer’s system prompt enforces the "within 100 words" constraint.

3. Writer Agent

writer = autogen.AssistantAgent(
    name="Writer",
    system_message="You are a writer. You write engaging and concise blogpost (with title) on given topics. You must polish your writing based on the feedback you receive and give a refined version. Only return your final work without additional comments.",
    llm_config=llm_config,
)

The Writer produces the initial draft and, after feedback, must return only the polished blogpost (no extra commentary).

4. Critic Agent

critic = autogen.AssistantAgent(
    name="Critic",
    is_termination_msg=lambda x: x.get("content", "").find("TERMINATE") >= 0,
    llm_config=llm_config,
    system_message="You are a critic. You review the work of the writer and provide constructive feedback to help improve the quality of the content.",
)

The Critic orchestrates reflection. It can terminate when it sees a special token (here: TERMINATE), and — crucially — it routes drafts into nested reviewer chats rather than replying directly.

5. Reviewer Agents (Specialists)

Four reviewers are defined; each returns structured JSON and concise 3-bullet feedback:

  • SEO Reviewer — keyword suggestions, optimization tips, ranking potential.
  • Legal Reviewer — checks compliance, flags potential copyright or misleading claims.
  • Ethics Reviewer — checks for bias/harm and ensures ethical tone.
  • Meta Reviewer — aggregates the reviewers’ JSON outputs into a final suggestion set.

6. Nested Chats (Reflection Workflow)

You pass the writer’s latest draft to the reviewers. Example helper function:

def reflection_message(recipient, messages, sender, config):
    return f'''Review the following content.

{recipient.chat_messages_for_summary(sender)[-1]['content']}'''

Then define the review pipeline:

review_chats = [
    {"recipient": SEO_reviewer,   ...},
    {"recipient": legal_reviewer,  ...},
    {"recipient": ethics_reviewer, ...},
    {"recipient": meta_reviewer,   ...},
]

Register nested chats with the critic so it automatically triggers the reviewers when the writer produces a draft:

critic.register_nested_chats(
    review_chats,
    trigger=writer,
)
Key point: The Critic acts as a manager — it routes the draft into sub-chats, gathers JSON feedback, and asks the Meta Reviewer to consolidate the results before returning a single, actionable feedback message to the Writer.

7. Run the Conversation

res = critic.initiate_chat(
    recipient=writer,
    message=task,
    max_turns=2,
    summary_method="last_msg"
)

Flow during execution:

Writer produces draft (turn 1).
Critic detects draft and triggers the nested review pipeline.
SEO / Legal / Ethics reviewers return structured JSON feedback.
Meta Reviewer aggregates feedback into a final suggestion.
Critic sends consolidated feedback back to Writer.
Writer refines the draft (turn 2) and outputs the final post.

8. Get the Final Output

print(res.summary)

The final output (summary) should be the refined blogpost — concise, SEO-aware, legally safe, and ethically sound.

🎯 What You’ve Built

  • A full reflection pattern where a Critic orchestrates nested reviewers.
  • A Writer (producer) and Critic (controller) setup that mimics editorial workflows.
  • Specialized reviewer agents (SEO, Legal, Ethics) that return structured JSON feedback.
  • A Meta Reviewer that consolidates reviewer outputs into one actionable recommendation.
  • An automated refine loop that produces a final polished blog post.

💡 Tips & next steps

  • Use strict, structured JSON schemas for reviewer outputs to make aggregation deterministic.
  • Limit reviewer verbosity — require 3 bullet points plus a compact JSON block to simplify the Meta Reviewer’s job.
  • Consider adding a "confidence" score from reviewers so the Writer knows which suggestions are highest priority.
  • For production, persist versions and reviewer outputs to storage for traceability & audits.
4. Chess Game with AutoGen Agents

4. Building a Chess Game with AutoGen Agents

This transcript walks through how two AutoGen agents (White & Black) play chess by using tools and nested chats to ensure rules are followed.

♟️ Key Roles

  • White Agent — plays first, chooses moves by calling tools.
  • Black Agent — responds with its moves, also uses tools.
  • Board Proxy Agent — executes tools, validates legality, updates state. It is not an LLM agent.

⚙️ Tool Use

  • get_legal_moves → returns all valid moves for the current position.
  • make_move → executes a move in UCI format (e.g., e2e4).

Players propose these tool calls; the board proxy executes them.

🧩 Nested Chats Workflow

Player agent proposes a move.
Board proxy validates via get_legal_moves.
If valid → make_move updates board state.
Proxy summarizes the updated position.
Outer conversation continues → looks like players are just chatting.

💬 Demonstration Highlights

  • Game starts: White plays e2e4, Black responds g8f6.
  • Moves are checked and updated correctly by the board proxy.
  • Chit-chat is layered in:
    • “I’m going for the Sicilian Defense!”
    • “Let’s see how you respond to this classic opening.”

📝 Code Structure (Simplified)

# Agents
white_agent = ConversableAgent(name="White", system_message="Play as White...")
black_agent = ConversableAgent(name="Black", system_message="Play as Black...")
board_proxy = ConversableAgent(name="Board", llm_config=None)  # No LLM

# Tools
def get_legal_moves(...): ...
def make_move(move): ...

# Register tools with board
board_proxy.register_tool(get_legal_moves)
board_proxy.register_tool(make_move)

# Nested chats ensure move validation
white_agent.initiate_chat(recipient=board_proxy, message="Play e2e4")
black_agent.initiate_chat(recipient=board_proxy, message="Play g8f6")

✅ Big Takeaway

This lesson demonstrates tool use inside nested conversations:

  • One agent proposes a tool call (e.g., make a move).
  • Another agent (board proxy) executes it and validates legality.
  • The result is summarized and returned to the players.
  • The outer chat looks natural, like two people playing chess, while the inner system ensures all rules are followed.
4. Walkthrough — Tool Use & Conversational Chess (Runnable)

4. Tool Use & Conversational Chess: Notebook Walkthrough

This lesson turns the full implementation into an easy-to-follow guide: how two AutoGen agents (White & Black) use tools and nested chats to play legal chess moves while still sounding like they're bantering.

🔧 Setup

Configure your LLM and import chess utilities for game logic and SVG rendering.

# Configure LLM (this demo uses GPT-4 turbo)
llm_config = {"model": "gpt-4-turbo"}

# Chess utilities
import chess
import chess.svg
from autogen import ConversableAgent  # or your framework's agent class
    

♟️ Board Initialization

Start a fresh board and a flag to mark when a legal move has been executed.

board = chess.Board()
made_move = False

🛠 Tools (executor functions)

Two core tools: get_legal_moves and make_move. The board proxy actually executes these.

def get_legal_moves():
    # returns list of UCI moves e.g. ['e2e4', 'd2d4', ...]
    return [m.uci() for m in board.legal_moves]

def make_move(move_uci):
    # validate and push; return human-friendly description + SVG
    move = chess.Move.from_uci(move_uci)
    if move in board.legal_moves:
        board.push(move)
        # sample description (piece glyphs optional)
        piece = board.piece_at(move.to_square)
        desc = f"Moved {piece.symbol().upper() if piece else 'piece'} from {move_uci[:2]} to {move_uci[2:]}"
        svg = chess.svg.board(board=board)  # optionally render board
        return {"ok": True, "desc": desc, "svg": svg}
    else:
        return {"ok": False, "error": "Illegal move"} 

The functions above are executed by the Board Proxy Agent (non-LLM), which enforces legality and updates the shared board state.

🤖 Agents

Agent roles in the demo:

  • player_white — Conversable agent that proposes a move and can chitchat.
  • player_black — Same as white but plays the responding color.
  • board_proxy — Executes the tools, validates moves, updates board. It does not use an LLM for validation.
player_white = ConversableAgent(
    name="White",
    system_message="You play White. First call get_legal_moves, then choose one and call make_move(UCI). After move, you may add a short chat line.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)

player_black = ConversableAgent(
    name="Black",
    system_message="You play Black. Same rules as White.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)

# Board proxy is a simple executor (no model)
board_proxy = ConversableAgent(
    name="BoardProxy",
    llm_config=None,
    system_message="I only execute tools: get_legal_moves, make_move. I enforce legality."
)

🔗 Tool Registration

Linking callers to the executor: players can propose tool calls but the board proxy runs them.

# This is conceptual — use your framework's register_function / register_tool API
board_proxy.register_tool("get_legal_moves", get_legal_moves)
board_proxy.register_tool("make_move", make_move)

# allow players to call board_proxy tools (framework-specific)
player_white.register_target(board_proxy)
player_black.register_target(board_proxy)

🔄 Nested Chats (validation before reply)

Before a player announces a move in the outer chat, they do an inner/nested chat with the board proxy to validate and execute it. The proxy returns the result, which the player summarizes in the outer conversation.

# Example flow (pseudo-runnable)
# Outer call: player proposes a move to player_black
chat_result = player_black.initiate_chat(
    recipient=player_white,
    message="Let's play chess! Your move.",
    max_turns=2,
)

# Inside the agent logic, White will:
# 1) call board_proxy.get_legal_moves()
# 2) choose a UCI move (e.g. "e2e4")
# 3) call board_proxy.make_move("e2e4")
# 4) receive confirmation and include a short chitchat line in the outer message

▶️ Start the Demo

In the notebook the demo runs only a couple moves (controlled by max_turns) so it's quick to show the pattern.

chat_result = player_black.initiate_chat(
    player_white,
    message="Let's play chess! Your move.",
    max_turns=2,
)

🎉 Fun Extension: Chit-chat Mode

Give both player agents flavor text in their system prompts so they banter after each legal move:

system_message = "After a move is made, add a one-line banter sentence (e.g., 'Going Sicilian!')."\n
# Recreate agents with this system_message to get fun dialogue.

👨‍💻 Play as Human

If you want one player to be human-controlled in the notebook, set:

player_white = ConversableAgent(..., human_input_mode="ALWAYS")

That will pause and prompt you to type moves instead of the agent choosing them.

✅ Big takeaway

This lesson demonstrates tool use inside nested conversations: an agent proposes a tool call (choose move) → a non-LLM proxy executes and validates the tool (legal move) → results are summarized back into the outer player-to-player chat so the whole game looks natural while remaining rule-abiding.

5. Freeform Coding with AutoGen Agents

5. Freeform Coding with AutoGen Agents

This lesson introduces coding capabilities to AutoGen agents — letting them write, run, and refine code automatically or with human oversight.

🎯 Goal

Add coding abilities to agents so they can solve tasks like financial analysis or data visualization.

  • Model-generated code — agent writes code entirely from scratch.
  • User-provided code — agent uses helper functions you supply.

🔧 Setup

Use GPT-4 turbo for the code-writer and a local executor for running Python scripts.

from autogen import LocalCodeExecutor  

executor = LocalCodeExecutor(
    timeout=60,
    work_dir="coding"
)

🤖 Agents

Code Executor Agent

  • Type: ConversableAgent
  • Executes code proposed by the writer.
  • Asks for confirmation if human_input_mode="ALWAYS".
  • Default fallback: "Please continue. If everything is done, reply terminate."

Code Writer Agent

  • Type: AssistantAgent
  • Generates code, but does not run it.
  • Uses LLM (GPT-4 turbo).
  • human_input_mode="NEVER" (runs fully automatic).
  • System message includes instructions to:
    • Collect data, analyze, and plot results.
    • Check execution results and fix errors automatically.
    • Terminate after task completion.

📊 Example Task: Financial Analysis

Show year-to-date stock gains for Nvidia and Tesla.

  1. Code Writer generates Python code (e.g., with yfinance + matplotlib).
  2. Code Executor runs the code.
  3. Plot result is returned to Code Writer.
  4. Conversation terminates after completion.

With human-in-the-loop, you can review/approve code before execution.

📝 User-Provided Functions

You can define helper functions and pass them to the executor. The Writer will then build shorter code using them.

import yfinance as yf  

def get_stock_prices(ticker, start_date):
    """
    Download stock prices from start_date to today.
    Returns a DataFrame.
    """
    data = yf.download(ticker, start=start_date)
    return data

Another example: a custom plotting function. Update the writer’s system message with these docstrings so it knows to use them.

📂 Key Notes

  • Saving code — add a special line in the block to save code to files; otherwise it’s temporary.
  • Human-in-the-loop — optional, allows review before execution.
  • Difference vs tool calls:
    • Tool calls = deterministic (only predefined functions).
    • Freeform code = flexible, creative (any Python or shell).
  • Works even with models that lack built-in “tool call” support.

✅ Summary

5. demonstrates two ways of coding with AutoGen:

  • Default: Writer generates full code from scratch.
  • Optional: Writer leverages user-defined helper functions for cleaner results.

Flexible for many tasks: financial analysis, data processing, plotting, or running shell scripts — with or without human oversight.

5. Coding and Financial Analysis with AutoGen Agents

5. Coding and Financial Analysis with AutoGen Agents

In this lesson, AutoGen agents gain the ability to generate, run, and refine Python code to perform financial analysis — with or without human oversight.

1. ⚙️ Setup

We start by configuring GPT-4 turbo and a local code executor.

llm_config = {"model": "gpt-4-turbo"}

from autogen.coding import LocalCommandLineCodeExecutor  

executor = LocalCommandLineCodeExecutor(
    timeout=60,
    work_dir="coding"  # all code and outputs stored here
)

2. 🤖 Create Agents

a) Code Executor Agent

Executes Python code generated by the writer. Runs in human-in-the-loop mode (asks before execution).

from autogen import ConversableAgent  

code_executor_agent = ConversableAgent(
    name="code_executor_agent",
    llm_config=False,
    code_execution_config={"executor": executor},
    human_input_mode="ALWAYS",
    default_auto_reply="Please continue. If everything is done, reply 'TERMINATE'.",
)

b) Code Writer Agent

Generates Python code but never executes it directly.

from autogen import AssistantAgent  

code_writer_agent = AssistantAgent(
    name="code_writer_agent",
    llm_config=llm_config,
    code_execution_config=False,
    human_input_mode="NEVER",
)

Check the writer’s default system instructions:

print(code_writer_agent.system_message)

3. 📊 Define the Task

Example: plot year-to-date stock gains for NVDA and TSLA.

import datetime  

today = datetime.datetime.now().date()

message = f"Today is {today}. " \
          "Create a plot showing stock gain YTD for NVDA and TLSA. " \
          "Make sure the code is in markdown code block and save " \
          "the figure to a file ytd_stock_gains.png."

chat_result = code_executor_agent.initiate_chat(
    code_writer_agent,
    message=message,
)

Display the generated plot:

import os  
from IPython.display import Image  

Image(os.path.join("coding", "ytd_stock_gains.png"))

4. 📝 User-Defined Functions

Instead of writing everything from scratch, define reusable helpers for the LLM to use.

a) Download stock prices

def get_stock_prices(stock_symbols, start_date, end_date):
    """
    Get the stock prices for the given stock symbols between the
    start and end dates.
    """
    import yfinance
    stock_data = yfinance.download(stock_symbols, start=start_date, end=end_date)
    return stock_data.get("Close")

b) Plot stock prices

def plot_stock_prices(stock_prices, filename):
    """
    Plot the stock prices for the given stock symbols and save to a file.
    """
    import matplotlib.pyplot as plt
    
    plt.figure(figsize=(10, 5))
    for column in stock_prices.columns:
        plt.plot(stock_prices.index, stock_prices[column], label=column)
    plt.title("Stock Prices")
    plt.xlabel("Date")
    plt.ylabel("Price")
    plt.grid(True)
    plt.legend()
    plt.savefig(filename)

5. 🔗 Update Executor & Writer

Add these functions to the executor and update the writer’s system message.

executor = LocalCommandLineCodeExecutor(
    timeout=60,
    work_dir="coding",
    functions=[get_stock_prices, plot_stock_prices],
)

code_writer_agent_system_message += executor.format_functions_for_prompt()

code_writer_agent = ConversableAgent(
    name="code_writer_agent",
    system_message=code_writer_agent_system_message,
    llm_config=llm_config,
    code_execution_config=False,
    human_input_mode="NEVER",
)

code_executor_agent = ConversableAgent(
    name="code_executor_agent",
    llm_config=False,
    code_execution_config={"executor": executor},
    human_input_mode="ALWAYS",
    default_auto_reply="Please continue. If everything is done, reply 'TERMINATE'.",
)

6. ▶️ Run Task with User Functions

chat_result = code_executor_agent.initiate_chat(
    code_writer_agent,
    message=f"Today is {today}. "
            "Download the stock prices YTD for NVDA and TSLA and create "
            "a plot. Make sure the code is in markdown code block and "
            "save the figure to a file stock_prices_YTD_plot.png.",
)

Image(os.path.join("coding", "stock_prices_YTD_plot.png"))

✅ Key Takeaways

  • Freestyle coding: Writer agent can generate full Python code.
  • Human-in-the-loop: Executor can ask for confirmation before running.
  • Reusable functions: Define once, reuse for cleaner outputs.
  • Files auto-saved: Code and plots stored in the coding folder.
  • Flexible: Works even with models that lack OpenAI tool-call support.
Lesson 6: Multi-Agent Group Chats with Planning Agents in AutoGen

6. Multi-Agent Group Chats with Planning Agents in AutoGen

1. Objective

  • Learn group chat conversation pattern: multiple agents collaborate dynamically to complete a complex task.
  • Introduce planning agents to break down tasks into smaller subtasks.
  • Customize speaker transitions to control agent interaction flow.
  • Example Task: Generate a detailed stocks performance report over the past month.

2. Key Agents

a) Admin (User Proxy Agent)

  • Acts as a user proxy to send instructions.
  • human_input_mode="ALWAYS" → asks for human feedback.
  • System message: “Give the task and send instructions to the writer to refine the blog post.”

b) Planner

  • Decomposes a complex task into simpler subtasks.
  • System message: suggests steps that can be executed via Python code.
  • Description: “Given a task, determine info needed, check progress, instruct remaining steps.”
  • Provides guidance after each step.

c) Engineer

  • Writes Python code based on planner’s instructions.
  • Uses default assistant agent system message.
  • Description: “Writes code according to the plan provided by planner.”

d) Executor

  • Executes Python code shared by the engineer.
  • Configuration:
    • Looks at last N messages for code.
    • Executes in coding/ directory.
    • user_docker=False.

e) Writer

  • Writes and refines blog posts in Markdown format.
  • Takes feedback from Admin.
  • Description: “Writes blogs with titles, content in markdown, and applies feedback.”

3. Group Chat Manager

  • Special AutoGen agent to manage turn-taking and conversation flow.
  • Decides which agent speaks next based on:
    • Conversation history
    • Agent roles and descriptions
  • Enables dynamic task flow without manual ordering.

4. How the Group Chat Works

  1. Admin sends the task to the chat manager.
  2. Chat manager broadcasts to all agents.
  3. Planner suggests subtasks (e.g., retrieve stock data, analyze, research events, draft blog).
  4. Engineer writes Python code.
  5. Executor runs the code and shares results.
  6. Planner reviews progress and suggests next steps.
  7. Writer drafts the blog post once info is ready.
  8. Admin provides user feedback → Writer refines post.

Note: Turn-taking is dynamic — agents can skip steps if allowed.

5. Controlling Speaker Transitions

You can define allowed/disallowed transitions:

allowed_transitions = {
    "engineer": ["admin", "executor"],
    "executor": ["admin", "engineer", "planner"],
}

This ensures Planner reviews before Writer starts, balancing flexibility with control.

6. Advantages of Group Chat Pattern

  • Non-linear execution → agents collaborate dynamically.
  • Planner support → automates task decomposition.
  • Human-in-the-loop optional → admin can intervene.
  • Customizable transitions → enforce order when needed.
  • Scalable → handle complex, multi-step tasks.

7. Summary of Learning

  • Introduced Group Chat pattern for dynamic collaboration.
  • Planner helps decompose complex tasks.
  • Engineer, Executor, and Writer automate Python code and blog writing.
  • Speaker transitions can be customized for smoother flow.
  • AutoGen enables flexible, scalable agent orchestration.

Next Steps / Advanced Features

  • Multi-modal agents (vision, audio, etc.)
  • Agent learning over time
  • Agent evaluation and benchmarking
  • Custom task-specific agents using OpenAI backend
  • More controlled conversation and planning logic
Lesson 6: Planning and Stock Report Generation with AutoGen

6. Planning and Stock Report Generation using AutoGen Multi-Agent Group Chat

1. Objective

  • Build a multi-agent group chat to automatically generate a stock report blog post.
  • Example Task: "Write a blog post about Nvidia's stock price performance in the past month."
  • Introduce a planning agent to decompose tasks.
  • Use Engineer and Executor to handle Python code.
  • Use Writer to draft and refine the blog post.
  • Include Admin/User agent for feedback.

2. Agents in the Group Chat

a) Admin (User Proxy)

  • Purpose: Sends task and provides feedback.
  • human_input_mode="ALWAYS" → prompts user for input.
  • System message: “Give the task, and send instructions to writer to refine the blog post.”

b) Planner

  • Purpose: Breaks the task into sub-tasks achievable via Python.
  • Monitors progress and guides remaining steps.
  • System message: Guides what information to retrieve and how to handle failures.
  • Description: Explains role to other agents — task decomposition and progress monitoring.

c) Engineer

  • Purpose: Writes Python code following planner instructions.
  • Uses AutoGen default AssistantAgent system message.
  • Description: "Write code based on the plan provided by the planner."

d) Executor

  • Purpose: Executes Python code shared by Engineer.
  • Configuration:
    • Looks at last 3 messages containing code.
    • Executes in coding/ directory.
    • use_docker=False
    • human_input_mode="NEVER" → fully automated execution.

e) Writer

  • Purpose: Drafts blog posts in Markdown.
  • Takes feedback from Admin for refinement.
  • System message: Guides formatting in Markdown with titles and content.
  • Description: Explains role to other agents — write blog based on execution results and feedback.

3. Group Chat Setup

groupchat = autogen.GroupChat(
    agents=[user_proxy, engineer, writer, executor, planner],
    messages=[],
    max_round=10,
)
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)

groupchat_result = user_proxy.initiate_chat(manager, message=task)

Max rounds: 10 → limits conversation length. The manager decides which agent speaks next.

4. Adding Speaker Transition Rules

Allows controlled flow between agents. Example: Ensure Planner reviews before Writer starts drafting.

allowed_transitions = {
    user_proxy: [engineer, writer, executor, planner],
    engineer: [user_proxy, executor],
    writer: [user_proxy, planner],
    executor: [user_proxy, engineer, planner],
    planner: [user_proxy, engineer, writer],
}

groupchat = autogen.GroupChat(
    agents=[user_proxy, engineer, writer, executor, planner],
    messages=[],
    max_round=10,
    allowed_or_disallowed_speaker_transitions=allowed_transitions,
    speaker_transitions_type="allowed",
)

Type: allowed → only specified transitions are permitted. Ensures Planner reviews code/results before Writer starts.

5. How the Chat Works

  1. Admin sends task → broadcasted to all agents.
  2. Planner suggests steps:
    • Retrieve stock data
    • Analyze data
    • Research context/events
    • Draft blog
  3. Engineer writes Python code for tasks.
  4. Executor runs the code and reports results.
  5. Planner checks progress and updates next steps.
  6. Writer drafts the blog post using results.
  7. Admin/User provides feedback.
  8. Writer refines the post based on feedback.
  9. Process iterates through max_rounds or until task completion.
  10. Agents may correct errors dynamically — e.g., Engineer fixes code after Executor feedback.

6. Advantages

  • Automates complex tasks like stock report generation.
  • Dynamic collaboration between agents.
  • Human-in-the-loop optional for feedback or adjustments.
  • Controlled yet flexible flow using speaker transition rules.
  • Task decomposition via Planner ensures modular and maintainable workflow.
Key Takeaways

AutoGen Course: Key Takeaways

1. Agentic Design Patterns in AutoGen

  • Multi-Agent Collaboration: Multiple agents working together to accomplish complex tasks.
  • Reflection: Agents can review their own actions or outputs to improve performance.
  • Tool Use: Agents can call external tools or functions (e.g., Python functions, APIs) to get work done.
  • Code Generation: Agents like Engineers can write and refine code automatically.
  • Planning: Planner agents decompose tasks into manageable steps and monitor progress.

2. How to Apply These Patterns

  • Combine these building blocks to automate tasks like:
    • Stock market analysis and reporting
    • Blog generation
    • Data processing pipelines
    • Multi-step workflows
  • Customize agent roles, descriptions, and speaker transitions to maintain control while allowing flexibility.

No comments:

Post a Comment

Boost Your Productivity with Claude Code: Your AI Coding Partner

AI-assisted coding has come a long way—from asking language models occasional coding questions, to autocomplete in GitHub , to today’s highl...