Introduction to AutoGen for Data Analysis
AutoGen is an open-source framework developed by Microsoft Research that enables the creation of multi-agent conversational systems powered by large language models (LLMs). At its core, AutoGen allows developers to define multiple AI agents that can communicate, collaborate, and autonomously solve complex tasks — including sophisticated data analysis workflows. Rather than prompting a single LLM repeatedly, AutoGen orchestrates conversations between specialized agents that can write code, execute it, review results, and iterate until the analysis is complete.
In this tutorial, you will learn how to build a complete data analysis agent system using AutoGen. We will cover everything from setting up your environment to deploying a multi-agent team capable of loading datasets, cleaning data, generating visualizations, and producing comprehensive analytical reports — all with minimal human intervention.
What Is a Data Analysis Agent in AutoGen?
A data analysis agent in AutoGen is typically composed of two or more specialized agents working in tandem:
- Assistant Agent (Coder): An LLM-backed agent responsible for generating Python code to perform analysis tasks. It writes code for data loading, cleaning, statistical analysis, and visualization.
- Executor Agent (Code Executor): A sandboxed environment agent that receives code from the assistant, executes it safely, and returns the output — including errors, dataframes, and chart images.
- Critic / Reviewer Agent (optional): An agent that reviews outputs, suggests improvements, and ensures analysis quality before final delivery.
The magic of AutoGen lies in its conversation loop. The assistant proposes code, the executor runs it and returns results, and the assistant adapts based on feedback — all without the user needing to manually intervene at each step. This creates a powerful autonomous pipeline for exploratory data analysis, reporting, and insight generation.
Why AutoGen Matters for Data Analysis
Traditional data analysis workflows require analysts to manually write code, debug errors, inspect outputs, and iterate. AutoGen transforms this process in several key ways:
- Automation of the Code-Debug Cycle: When code fails, the executor returns the error traceback directly to the assistant, which automatically attempts to fix it — no human debugging required.
- Multi-turn Reasoning: Complex analyses often require multiple steps. AutoGen agents can plan a sequence of operations, execute them, and adjust based on intermediate results.
- Safe Code Execution: The executor runs code in an isolated environment (like Docker), preventing harmful operations from affecting your system.
- Scalable Collaboration: You can add specialized agents — one for SQL queries, one for statistical modeling, one for visualization — all coordinated through AutoGen's conversation framework.
- Human-in-the-Loop Flexibility: AutoGen supports configurable human intervention points, allowing analysts to approve critical steps while automating routine tasks.
Setting Up Your Environment
Before building your data analysis agent, you need to install the required packages and configure your LLM provider. Here's the complete setup:
# Create a virtual environment (recommended)
python -m venv autogen_env
source autogen_env/bin/activate # On Windows: autogen_env\Scripts\activate
# Install AutoGen and data analysis dependencies
pip install pyautogen
pip install pandas numpy matplotlib seaborn scikit-learn
pip install jupyter # Optional, for notebook-based workflows
# For Docker-based code execution (recommended for safety)
# Install Docker on your system first, then:
pip install docker
AutoGen supports multiple LLM providers. For this tutorial, we'll use OpenAI's GPT-4, but you can substitute with Azure OpenAI, local models via Ollama, or other providers. Set your API key as an environment variable:
# Set your OpenAI API key
export OPENAI_API_KEY="your-api-key-here"
# Or on Windows PowerShell
$env:OPENAI_API_KEY = "your-api-key-here"
Building Your First Data Analysis Agent
Let's start with a simple two-agent system: an assistant that writes Python code and an executor that runs it. We'll analyze the classic Iris dataset.
Step 1: Import Libraries and Configure the LLM
import autogen
from autogen import AssistantAgent, UserProxyAgent
import pandas as pd
import os
# Configure the LLM for AutoGen
llm_config = {
"config_list": [
{
"model": "gpt-4",
"api_key": os.environ.get("OPENAI_API_KEY"),
"temperature": 0.1, # Lower temperature for more consistent code generation
"timeout": 120,
}
],
"seed": 42, # For reproducibility
}
Step 2: Create the Assistant and Executor Agents
# Create the Assistant Agent - responsible for writing code
assistant = AssistantAgent(
name="DataAnalyst",
system_message="""You are an expert data analyst. Your role is to:
1. Write Python code to analyze datasets provided by the user.
2. Use pandas, matplotlib, seaborn, and scikit-learn for analysis.
3. When you receive a task, write clear, well-commented code.
4. If code execution fails, read the error traceback carefully and fix the code.
5. After successful analysis, provide a concise summary of findings.
6. Save any generated plots using plt.savefig() so they can be reviewed.
Always output code in markdown code blocks with the language specified as 'python'.""",
llm_config=llm_config,
)
# Create the UserProxyAgent - acts as the executor and human interface
executor = UserProxyAgent(
name="CodeExecutor",
human_input_mode="NEVER", # Fully automated mode
max_consecutive_auto_reply=10, # Allow up to 10 auto-replies
code_execution_config={
"work_dir": "analysis_output", # Directory for generated files
"use_docker": False, # Set to True if Docker is available
"timeout": 300, # 5-minute timeout for code execution
},
system_message="You are a code executor. Run the provided Python code and report results.",
)
Step 3: Initiate the Analysis Conversation
# Define the analysis task
analysis_task = """
I have the Iris dataset available at this URL:
'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv'
Please perform the following analysis:
1. Load the dataset and display basic information (shape, columns, data types).
2. Check for missing values and handle them if any exist.
3. Generate summary statistics for all numerical columns.
4. Create a scatter plot of sepal_length vs sepal_width, colored by species.
5. Create a boxplot showing petal_length distribution by species.
6. Perform a correlation analysis and create a heatmap.
7. Provide a brief summary of key insights from the visualizations.
"""
# Start the conversation - the executor sends the task to the assistant
executor.initiate_chat(
assistant,
message=analysis_task,
max_turns=20, # Maximum conversation turns
)
When you run this, AutoGen orchestrates a multi-turn conversation where the assistant writes code, the executor runs it, and they iterate until all analysis tasks are complete. The generated plots will appear in the analysis_output directory.
Understanding the Conversation Flow
The conversation between agents follows a structured pattern. Here's what happens behind the scenes:
- Turn 1: The executor sends the analysis task to the assistant.
- Turn 2: The assistant generates Python code to load and explore the dataset, sends it back.
- Turn 3: The executor runs the code and returns the output (dataframe info, summary stats).
- Turn 4: The assistant reviews the output, then generates code for visualizations.
- Turn 5: The executor runs the visualization code and confirms plots were saved.
- Turn 6: The assistant provides the final summary of insights.
If any step fails — for example, a missing column name or a syntax error — the executor returns the error, and the assistant automatically attempts to fix it in the next turn. This self-healing capability is what makes AutoGen so powerful for data workflows.
Advanced: Building a Multi-Agent Analysis Team
For more complex data analysis projects, you can expand your agent team with specialized roles. Let's build a three-agent system with a dedicated code reviewer.
Creating a Reviewer Agent
# Create a Reviewer Agent that critiques analysis quality
reviewer = AssistantAgent(
name="AnalysisReviewer",
system_message="""You are a senior data analyst who reviews analysis work.
Your responsibilities:
1. Review code outputs, visualizations, and statistical results.
2. Identify potential issues: incorrect statistical methods, misleading visualizations, data quality problems.
3. Suggest improvements and additional analyses that would add value.
4. Be constructive and specific in your feedback.
5. When the analysis meets high standards, approve it with the keyword 'APPROVED'.
Do not write code yourself - only provide review feedback.""",
llm_config=llm_config,
)
# Create a GroupChat to orchestrate all three agents
from autogen import GroupChat, GroupChatManager
# Define the group chat with all agents
group_chat = GroupChat(
agents=[assistant, executor, reviewer],
messages=[],
max_round=30,
speaker_selection_method="auto", # AutoGen chooses who speaks next
allow_repeat_speaker=True,
)
# Create a manager to handle the group conversation
manager = GroupChatManager(
groupchat=group_chat,
llm_config=llm_config,
)
Running the Multi-Agent Analysis
# More complex analysis task
complex_task = """
I have a CSV file 'sales_data.csv' with the following columns:
- date: transaction date
- product_category: category of product sold
- revenue: revenue from the transaction
- units_sold: number of units sold
- region: geographic region
- customer_type: new or returning customer
Please perform a comprehensive analysis:
1. Load and clean the data (check for missing values, outliers, date parsing).
2. Analyze revenue trends over time (monthly aggregation, growth rates).
3. Identify top-performing product categories and regions.
4. Compare new vs returning customer behavior.
5. Detect any seasonality patterns.
6. Create appropriate visualizations for each insight.
7. Generate a final executive summary with actionable recommendations.
The reviewer should check each major step before we proceed to the next.
"""
# Start the group conversation
executor.initiate_chat(
manager,
message=complex_task,
max_turns=30,
)
With this setup, the conversation flows through the manager, which intelligently routes messages between the assistant (writing code), the executor (running code), and the reviewer (providing quality feedback). The reviewer acts as a gatekeeper, ensuring analysis quality before the team moves forward.
Working with Real-World Data Sources
Real data analysis often involves databases, APIs, and various file formats. Here's how to configure your agents to handle these scenarios:
Database Integration Example
# Assistant configured for database analysis
db_assistant = AssistantAgent(
name="DatabaseAnalyst",
system_message="""You are a data analyst with SQL expertise.
When analyzing data from databases:
1. Use SQLAlchemy or sqlite3 to connect to databases.
2. Write parameterized queries to prevent SQL injection.
3. Use pandas read_sql() for efficient data loading.
4. Handle large datasets with chunked reading when necessary.
Always include connection closing in your code with try/finally blocks.""",
llm_config=llm_config,
)
# Example task for database analysis
db_task = """
Connect to the SQLite database at 'sales.db'.
List all tables, then analyze the 'orders' table:
- Show the schema
- Calculate total revenue by month for 2023
- Identify top 10 customers by order value
- Analyze order status distribution
"""
executor.initiate_chat(db_assistant, message=db_task, max_turns=15)
Handling Large Datasets
# Assistant configured for large dataset handling
big_data_assistant = AssistantAgent(
name="BigDataAnalyst",
system_message="""You are a data analyst specializing in large datasets.
Key practices:
1. Always check memory usage before loading full datasets.
2. Use dask or polars for datasets exceeding available RAM.
3. Implement chunked processing when possible.
4. Sample data first for exploration, then apply full analysis.
5. Use efficient data types (category dtype for strings, float32 instead of float64).
6. Report memory usage and processing time in your outputs.""",
llm_config=llm_config,
)
Adding Human-in-the-Loop Control
While full automation is powerful, you may want human approval for critical decisions. AutoGen makes this easy with configurable human input modes:
# Executor with human approval for critical steps
interactive_executor = UserProxyAgent(
name="InteractiveExecutor",
human_input_mode="TERMINATE", # Ask human before terminating
# Alternative modes:
# "NEVER" - fully automated
# "ALWAYS" - human input at every turn
# "TERMINATE" - human input only when conversation would end
max_consecutive_auto_reply=8,
code_execution_config={
"work_dir": "analysis_output",
"use_docker": False,
},
)
# You can also customize when human input is needed
interactive_executor_with_approval = UserProxyAgent(
name="ApprovalExecutor",
human_input_mode="ALWAYS",
# Custom function to determine if human input is needed
human_input_config={
"prompt": "Do you approve executing this code? (yes/no): ",
"timeout": 60, # Auto-approve after 60 seconds if no response
},
code_execution_config={
"work_dir": "analysis_output",
"use_docker": False,
},
)
Best Practices for Data Analysis Agents
1. Craft Detailed System Messages
The quality of your agent's output depends heavily on the system message. Be specific about:
- What libraries to use and when
- Code style requirements (comments, error handling)
- Output format expectations (saved files, printed summaries)
- Edge cases to handle (empty data, encoding issues, date parsing)
# Example of a well-crafted system message excerpt
system_message_excerpt = """
When writing visualization code:
- Use plt.figure(figsize=(10, 6)) for consistent sizing
- Always include plt.tight_layout() before saving
- Save plots as PNG with dpi=150 for clarity
- Include descriptive titles and axis labels
- Use colorblind-friendly palettes from seaborn (color_palette='colorblind')
- Handle non-numeric data gracefully with appropriate error messages
"""
2. Set Appropriate Temperature and Model Selection
# Configuration for different analysis phases
exploration_config = {
"config_list": [{
"model": "gpt-4",
"temperature": 0.3, # More creative for exploration
}]
}
production_config = {
"config_list": [{
"model": "gpt-4",
"temperature": 0.0, # Deterministic for production pipelines
}]
}
3. Implement Robust Error Handling
Teach your assistant to write defensive code that anticipates common data issues:
# Assistant with error-handling focus
robust_assistant = AssistantAgent(
name="RobustAnalyst",
system_message="""Always wrap your code in try/except blocks for robust execution.
Handle these common data issues:
- FileNotFoundError: Provide clear path instructions
- Encoding errors: Try multiple encodings (utf-8, latin-1, cp1252)
- Parse dates with dayfirst/monthfirst inference
- Handle missing columns with graceful degradation
- Check for empty DataFrames before operations
- Validate data types before computations
Include helpful error messages that guide debugging.""",
llm_config=llm_config,
)
4. Use Docker for Production Safety
# Docker-based executor for production
docker_executor = UserProxyAgent(
name="DockerExecutor",
human_input_mode="NEVER",
code_execution_config={
"work_dir": "/workspace/analysis",
"use_docker": True,
"docker_image": "python:3.11-slim", # Specific Python version
"timeout": 600,
# Mount a volume for persistent output
"volumes": ["/host/output:/workspace/analysis/output"],
},
)
5. Manage Conversation Budget and Limits
# Configure conversation limits to prevent infinite loops
executor.initiate_chat(
assistant,
message=analysis_task,
max_turns=15, # Hard limit on conversation turns
# The assistant also has max_consecutive_auto_reply set
# Together these prevent runaway conversations
)
# For cost control, monitor token usage
# AutoGen provides callbacks for tracking
def track_tokens(agent, messages):
total_tokens = sum(
msg.get("usage", {}).get("total_tokens", 0)
for msg in messages
)
print(f"Total tokens used so far: {total_tokens}")
if total_tokens > 50000:
return "TERMINATE" # Stop if token budget exceeded
return None
6. Save and Resume Analysis Sessions
# Save conversation history for later analysis or resumption
import json
from datetime import datetime
def save_conversation(agent_history, filename=None):
"""Save the full conversation history to disk."""
if filename is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"conversation_{timestamp}.json"
with open(filename, "w") as f:
json.dump(agent_history, f, indent=2, default=str)
print(f"Conversation saved to {filename}")
return filename
# After your analysis run
save_conversation(executor.chat_messages)
Complete End-to-End Example
Here is a complete, production-ready script that brings together all the concepts we've covered. This script creates a data analysis agent team, loads a dataset, performs comprehensive analysis, and generates a report:
#!/usr/bin/env python3
"""
Complete AutoGen Data Analysis Pipeline
Analyzes any CSV dataset with multi-agent collaboration
"""
import autogen
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
import os
import sys
import pandas as pd
from pathlib import Path
# ============================================================
# Configuration
# ============================================================
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "your-key-here")
OUTPUT_DIR = Path("analysis_results")
OUTPUT_DIR.mkdir(exist_ok=True)
llm_config = {
"config_list": [
{
"model": "gpt-4",
"api_key": OPENAI_API_KEY,
"temperature": 0.1,
"timeout": 180,
}
],
"seed": 42,
}
# ============================================================
# Agent Definitions
# ============================================================
# Lead Analyst - writes all code
lead_analyst = AssistantAgent(
name="LeadAnalyst",
system_message="""You are a principal data scientist leading analysis projects.
CRITICAL INSTRUCTIONS:
1. When given a dataset path, first write code to load and inspect it.
2. Always print df.info(), df.head(), and df.describe() for initial exploration.
3. Check for: missing values, duplicates, outliers, incorrect data types.
4. For each analysis step, write complete, executable Python code.
5. Use pandas, matplotlib, seaborn, and scikit-learn.
6. Save all plots to the 'analysis_results' directory using absolute paths.
7. Include proper error handling in all code blocks.
8. After each code execution, review the output before writing next steps.
9. When analysis is complete, write a comprehensive summary report.
10. Use markdown code blocks with python for all code.
Your analysis should be thorough and uncover actionable insights.""",
llm_config=llm_config,
)
# Code Executor - runs code safely
executor = UserProxyAgent(
name="CodeRunner",
human_input_mode="NEVER",
max_consecutive_auto_reply=8,
code_execution_config={
"work_dir": str(OUTPUT_DIR),
"use_docker": False,
"timeout": 300,
},
system_message="Execute Python code and return outputs including errors.",
)
# Quality Reviewer - ensures high standards
reviewer = AssistantAgent(
name="QualityReviewer",
system_message="""You are a quality assurance specialist for data analysis.
Review each analysis output for:
- Statistical correctness and appropriate methodology
- Visualization quality (clear labels, appropriate chart types, colorblind-friendly)
- Data quality issues that may affect results
- Missing analyses that would add value
- Code quality and efficiency
Provide specific, actionable feedback. When the analysis meets professional standards,
respond with exactly: QUALITY_APPROVED
Do not write code - only provide review and feedback.""",
llm_config=llm_config,
)
# ============================================================
# Group Chat Setup
# ============================================================
group_chat = GroupChat(
agents=[lead_analyst, executor, reviewer],
messages=[],
max_round=25,
speaker_selection_method="auto",
allow_repeat_speaker=True,
speaker_selection_prompt="""Select the next speaker based on the conversation flow:
- After LeadAnalyst writes code, select CodeRunner to execute it.
- After CodeRunner returns output, select LeadAnalyst to continue analysis.
- After significant analysis milestones, select QualityReviewer to review.
- When QualityReviewer gives feedback, select LeadAnalyst to address it.
- When QualityReviewer says QUALITY_APPROVED, the analysis is complete.""",
)
manager = GroupChatManager(
groupchat=group_chat,
llm_config=llm_config,
)
# ============================================================
# Analysis Task Definition
# ============================================================
def create_analysis_task(dataset_path, dataset_description=""):
"""Generate a comprehensive analysis task."""
task = f"""
ANALYSIS PROJECT: Comprehensive Data Analysis
Dataset Location: {dataset_path}
{dataset_description}
Please perform the following complete analysis:
PHASE 1 - DATA LOADING & INSPECTION:
- Load the dataset and display shape, columns, dtypes
- Show the first 10 rows and last 5 rows
- Generate comprehensive summary statistics
PHASE 2 - DATA QUALITY ASSESSMENT:
- Check for missing values (count and percentage per column)
- Identify duplicate rows
- Detect potential outliers using IQR method for numerical columns
- Check for inconsistent data types
- Report all findings clearly
PHASE 3 - EXPLORATORY DATA ANALYSIS:
- Analyze distributions of key numerical variables (histograms, KDE plots)
- Examine categorical variable frequencies
- Identify correlations between numerical variables (heatmap)
- Create pairwise scatter plots for top correlated features
- Detect any obvious patterns or anomalies
PHASE 4 - DEEP DIVE ANALYSIS:
- Perform grouping analysis (by key categorical variables)
- Create boxplots comparing distributions across groups
- Conduct time-based analysis if datetime columns exist
- Generate pivot tables for multidimensional insights
PHASE 5 - FINAL REPORT:
- Summarize all key findings in a structured format
- List actionable insights and recommendations
- Note any data quality concerns for stakeholders
- Save a final summary report as 'analysis_report.txt'
The QualityReviewer will review each phase before proceeding to the next.
"""
return task
# ============================================================
# Execution
# ============================================================
if __name__ == "__main__":
# Get dataset path from command line or use default
if len(sys.argv) > 1:
dataset_path = sys.argv[1]
else:
# Default: Use a sample dataset
dataset_path = "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/tips.csv"
print(f"No dataset specified. Using sample dataset: {dataset_path}")
task = create_analysis_task(
dataset_path,
dataset_description="This is the tips dataset from seaborn containing restaurant transaction data."
)
print("=" * 60)
print("STARTING AUTOANALYSIS PIPELINE")
print("=" * 60)
# Initiate the analysis conversation
executor.initiate_chat(
manager,
message=task,
max_turns=30,
)
print("\n" + "=" * 60)
print("ANALYSIS COMPLETE")
print(f"Results saved in: {OUTPUT_DIR.absolute()}")
print("=" * 60)
This complete pipeline can analyze any CSV dataset you provide. Run it with:
python autoanalysis.py path/to/your_dataset.csv
The agents will autonomously load, clean, analyze, and visualize your data, with the reviewer ensuring quality at each step. All outputs — plots, reports, and conversation logs — are saved in the analysis_results directory.
Common Pitfalls and Troubleshooting
Pitfall 1: Infinite Conversation Loops
If agents keep repeating similar messages, set tighter limits:
executor = UserProxyAgent(
name="Executor",
max_consecutive_auto_reply=5, # Lower this if loops occur
# ...
)
# Also set max_turns in initiate_chat
executor.initiate_chat(assistant, message=task, max_turns=10)
Pitfall 2: Code Execution Failures
If the assistant repeatedly generates broken code, improve the system message with explicit examples of correct code patterns for your specific data environment.
Pitfall 3: Token Limit Exhaustion
Long conversations can exhaust context windows. Mitigate by:
- Using models with larger context windows (GPT-4-32k, Claude)
- Summarizing conversation history periodically
- Breaking large tasks into separate conversation sessions
Pitfall 4: Docker Connection Issues
If Docker execution fails, verify:
# Check Docker is running
docker ps
# Test Docker Python SDK
python -c "import docker; client = docker.from_env(); print(client.ping())"
Conclusion
Building data analysis agents with AutoGen represents a significant leap forward in automating analytical workflows. By orchestrating specialized agents — coders, executors, and reviewers — you can create systems that autonomously handle the full analysis lifecycle: from data loading and cleaning through exploratory analysis to final reporting. The framework's flexibility allows you to start simple with two-agent systems and progressively add complexity as your needs grow, incorporating human oversight at precisely the points where it adds the most value.
The key to success lies in thoughtful agent design: crafting detailed system messages that guide behavior, configuring appropriate model parameters, implementing robust error handling, and setting conversation limits that balance thoroughness with efficiency. With the complete pipeline provided in this tutorial, you have a production-ready foundation that can be adapted to virtually any data analysis domain — from business intelligence to scientific research. As AutoGen continues to evolve, the possibilities for increasingly sophisticated, collaborative AI analysis systems will only expand.