Aller au contenu

MetaGPT

Installation

# Install via pip (Python 3.9–3.11 recommended)
pip install metagpt

# Install with all extras
pip install "metagpt[all]"

# Install from source (latest features)
git clone https://github.com/geekan/MetaGPT
cd MetaGPT
pip install -e .

# Verify installation
python -c "import metagpt; print(metagpt.__version__)"

# System dependencies for browser/scraping features
pip install playwright
playwright install chromium

Configuration

# Create config file (first-time setup)
metagpt --init-config

# Config file location:
# Linux/Mac: ~/.metagpt/config2.yaml
# Windows:   %USERPROFILE%\.metagpt\config2.yaml
# ~/.metagpt/config2.yaml
llm:
  api_type: "openai"           # openai | anthropic | azure | ollama | groq
  model: "gpt-4o"
  api_key: "sk-your-key-here"
  max_token: 4096
  temperature: 0.0

# For Anthropic Claude
# llm:
#   api_type: "anthropic"
#   model: "claude-3-5-sonnet-20241022"
#   api_key: "sk-ant-your-key"

# For local models (Ollama)
# llm:
#   api_type: "ollama"
#   model: "ollama/codellama"
#   base_url: "http://localhost:11434"

# Project output directory
workspace:
  path: "/home/user/metagpt-workspace"

# Enable human-in-the-loop review
human_review: false

# Cost controls
max_budget: 3.0          # USD limit per run
token_limit: 40000       # token limit per run

# Browser for web-enabled agents
browser:
  engine: "playwright"
  browser_type: "chromium"
# Environment variable alternative
export OPENAI_API_KEY=sk-your-key
export ANTHROPIC_API_KEY=sk-ant-your-key
export METAGPT_PROJECT_PATH=/home/user/metagpt-workspace

Core Commands / API

CLI CommandDescription
metagpt "requirement"Run software team on a requirement
metagpt "req" --project-name NAMESet output project name
metagpt "req" --project-path PATHSet output directory
metagpt "req" --n-round NLimit collaboration rounds
metagpt "req" --code-reviewEnable peer code review step
metagpt "req" --run-testsRun generated tests
metagpt "req" --recover-path PATHResume from saved state
metagpt "req" --human-approvalEnable human-in-the-loop
metagpt --init-configGenerate default config file
metagpt --helpShow all options
Python APIDescription
Team()Create a multi-agent team
team.hire([roles])Add roles to the team
team.invest(budget)Set investment budget (USD)
team.run_project("req")Start a software project
asyncio.run(team.run(n_round=N))Run N collaboration rounds
DataInterpreter()Create data science agent
di.run("task")Run a data analysis task

Advanced Usage

Software Team — Full Pipeline

import asyncio
from metagpt.roles import (
    ProductManager,
    Architect,
    ProjectManager,
    Engineer,
    QaEngineer,
)
from metagpt.team import Team

async def build_software(requirement: str):
    company = Team()
    
    # Hire the full software team
    company.hire([
        ProductManager(),    # Writes PRD from requirement
        Architect(),         # Designs system architecture
        ProjectManager(),    # Creates task breakdown
        Engineer(n_borg=3),  # 3 parallel engineer agents
        QaEngineer(),        # Writes and runs tests
    ])
    
    # Set cost limit (optional safety measure)
    company.invest(3.00)     # $3.00 USD max
    
    # Start the project
    company.run_project(requirement)
    
    # Run collaboration rounds
    await company.run(n_round=5)

requirement = """
Build a web scraper that:
1. Accepts a URL and CSS selector as input
2. Extracts matching elements and their text content
3. Saves results to a CSV file with timestamp
4. Handles errors gracefully (timeouts, invalid URLs)
5. Include a CLI interface with --url and --selector flags
"""

asyncio.run(build_software(requirement))

Understanding the Role Pipeline

User Requirement

ProductManager   → writes PRD (Product Requirements Document)

Architect        → designs system design doc + file structure

ProjectManager   → creates task list, assigns to engineers

Engineer(s)      → writes actual code files

QaEngineer       → writes unit tests, runs them

Output: complete codebase in workspace/
# CLI equivalent of full pipeline
metagpt "Build a web scraper CLI tool" \
  --code-review \
  --run-tests \
  --n-round 5 \
  --project-name web_scraper

Data Interpreter (Data Science Agent)

import asyncio
from metagpt.roles.di.data_interpreter import DataInterpreter

async def analyze_data():
    di = DataInterpreter()
    
    # Natural language data analysis task
    result = await di.run("""
    I have a CSV file at /data/sales_2024.csv with columns:
    date, product, category, revenue, units_sold, region
    
    Please:
    1. Load and clean the data (handle missing values)
    2. Calculate monthly revenue trends by category
    3. Identify top 5 products by total revenue
    4. Find which region has the highest growth rate
    5. Create visualizations for each analysis
    6. Save a summary report to /data/analysis_report.md
    """)
    
    print(result)

asyncio.run(analyze_data())
# DataInterpreter with specific tools enabled
from metagpt.roles.di.data_interpreter import DataInterpreter
from metagpt.tools.tool_registry import TOOL_REGISTRY

async def run_di_with_tools():
    # Enable specific tools: web search, code execution, file I/O
    di = DataInterpreter(
        use_reflection=True,          # Self-correct on errors
        tools=["web_search", "file_read", "file_write", "execute_nb_code"],
    )
    
    result = await di.run("""
    Research the top 5 Python web frameworks by GitHub stars as of today,
    then create a comparison table and save it as frameworks.md
    """)
    
asyncio.run(run_di_with_tools())

Custom Roles

import asyncio
from metagpt.roles import Role
from metagpt.actions import Action
from metagpt.schema import Message

# Define a custom Action
class SecurityAudit(Action):
    name: str = "SecurityAudit"
    
    async def run(self, code: str) -> str:
        prompt = f"""
        Perform a security audit of the following code.
        Check for:
        - SQL injection vulnerabilities
        - Command injection risks
        - Hardcoded credentials
        - Insecure dependencies
        - Missing input validation
        
        Code:
        ```
        {code}
        ```
        
        Return a structured report with: severity (HIGH/MEDIUM/LOW), 
        description, line number (if applicable), and fix recommendation.
        """
        return await self._aask(prompt)

# Define a custom Role using the Action
class SecurityEngineer(Role):
    name: str = "SecurityEngineer"
    profile: str = "Security Engineer"
    goal: str = "Audit code for security vulnerabilities"
    constraints: str = "Be thorough, specific, and actionable"
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.set_actions([SecurityAudit])
    
    async def _act(self) -> Message:
        # Get the latest message (code to audit)
        todo = self.rc.todo
        msg = self.get_memories(k=1)[0]
        
        # Perform the audit
        audit_result = await todo.run(msg.content)
        
        return Message(
            content=audit_result,
            role=self.profile,
            cause_by=type(todo),
        )

# Use the custom role in a team
async def run_security_audit():
    from metagpt.team import Team
    from metagpt.roles import Engineer
    
    team = Team()
    team.hire([
        Engineer(),           # Writes code
        SecurityEngineer(),   # Reviews it for security
    ])
    
    team.run_project("Build a login system with user authentication")
    await team.run(n_round=3)

asyncio.run(run_security_audit())

Actions — Core Building Blocks

from metagpt.actions import Action
from metagpt.schema import Message

# Simple single-LLM-call action
class WriteUnitTests(Action):
    name: str = "WriteUnitTests"
    
    PROMPT_TEMPLATE: str = """
    Write comprehensive pytest unit tests for this Python code.
    Include: happy path, edge cases, error conditions.
    Use pytest fixtures and parametrize where appropriate.
    
    Code:
    {code}
    
    Return only the test file content.
    """
    
    async def run(self, code: str) -> str:
        prompt = self.PROMPT_TEMPLATE.format(code=code)
        return await self._aask(prompt)

# Action with structured output (using Pydantic)
from pydantic import BaseModel
from typing import List

class TaskList(BaseModel):
    tasks: List[str]
    estimated_hours: float
    priority: str

class PlanProject(Action):
    name: str = "PlanProject"
    
    async def run(self, requirements: str) -> TaskList:
        prompt = f"""
        Break down this project into specific tasks with time estimates.
        Requirements: {requirements}
        
        Return JSON matching: {{"tasks": [...], "estimated_hours": N, "priority": "high|medium|low"}}
        """
        response = await self._aask(prompt)
        # Parse and return structured output
        import json
        data = json.loads(response)
        return TaskList(**data)

Memory and Context Management

from metagpt.roles import Role
from metagpt.memory import Memory

# Roles automatically maintain message memory
# Access memory within a role:
class ContextAwareRole(Role):
    async def _act(self) -> Message:
        # Get all messages in memory
        all_messages = self.get_memories()
        
        # Get last N messages
        recent = self.get_memories(k=5)
        
        # Get messages from specific role
        prd_docs = [m for m in all_messages if m.role == "ProductManager"]
        
        # Full context for LLM call
        context = "\n".join([f"{m.role}: {m.content}" for m in recent])
        
        response = await self._aask(
            f"Given this context:\n{context}\n\nPerform your task."
        )
        return Message(content=response, role=self.profile)

Human-in-the-Loop

import asyncio
from metagpt.team import Team
from metagpt.roles import ProductManager, Architect, Engineer

async def run_with_human_review():
    team = Team()
    team.hire([
        ProductManager(),
        Architect(),
        Engineer(),
    ])
    
    # Enable human review at each major step
    team.invest(5.0)
    team.run_project(
        "Build a task management REST API",
        send_to="ProductManager",    # Start with PM
    )
    
    # Run one round at a time, review output
    await team.run(n_round=1)   # ProductManager writes PRD
    
    # Review .metagpt/workspace/output/PRD.md
    user_input = input("Review the PRD. Approve? (y/n/edit): ")
    if user_input == "n":
        print("Stopping for revision")
        return
    
    await team.run(n_round=1)   # Architect designs system
    # Review architecture...
    
    await team.run(n_round=2)   # Engineers code

asyncio.run(run_with_human_review())
# Enable in config for automatic review prompts
# ~/.metagpt/config2.yaml
human_review: true

Resume from Checkpoint

# MetaGPT saves state automatically during runs
# If interrupted, resume from last checkpoint:
metagpt "Build a REST API" --recover-path /path/to/workspace/project_dir

# Find workspace path from previous run output or:
ls ~/.metagpt/workspace/
import asyncio
from metagpt.team import Team

async def resume_project():
    team = Team()
    team.recover_path = "/home/user/.metagpt/workspace/my_project"
    team.invest(5.0)
    # Continue from where it left off
    await team.run(n_round=3)

asyncio.run(resume_project())

Common Workflows

Full Software Project from Scratch

# Minimal CLI usage
metagpt "Create a Python CLI tool for managing a todo list with SQLite storage, \
supporting: add, list, complete, and delete operations" \
  --project-name todo_cli \
  --code-review \
  --run-tests \
  --n-round 6

# Output in: ./workspace/todo_cli/

Data Science Pipeline

import asyncio
from metagpt.roles.di.data_interpreter import DataInterpreter

async def ml_pipeline():
    di = DataInterpreter(use_reflection=True)
    
    await di.run("""
    Build a machine learning pipeline:
    1. Load the Iris dataset from sklearn
    2. Perform EDA: distributions, correlations, pairplot
    3. Train 3 models: LogisticRegression, RandomForest, SVM
    4. Cross-validate each with 5-fold CV
    5. Compare performance (accuracy, precision, recall, F1)
    6. Save the best model as model.pkl
    7. Create a predictions function and test it
    8. Generate a report.md summarizing results
    """)

asyncio.run(ml_pipeline())

Code Review and Improvement Team

import asyncio
from metagpt.roles import Role, Engineer, QaEngineer
from metagpt.team import Team

async def review_existing_code():
    team = Team()
    team.hire([Engineer(), QaEngineer()])
    
    with open("existing_code.py") as f:
        code = f.read()
    
    team.run_project(f"""
    Review and improve this existing Python code:
    
    ```python
    {code}
    ```
    
    Tasks:
    1. Add type hints to all functions
    2. Add docstrings following Google style
    3. Refactor any code smells
    4. Write comprehensive pytest tests
    5. Ensure all tests pass
    """)
    
    await team.run(n_round=4)

asyncio.run(review_existing_code())

Tips and Best Practices

Cost Control

# Always set a budget limit
team.invest(2.00)    # Hard stop at $2.00

# Fewer rounds = fewer LLM calls
await team.run(n_round=3)    # 3 rounds instead of default 5+

# Use cheaper model for lower-stakes tasks
# config2.yaml: model: "gpt-4o-mini"   (10x cheaper than gpt-4o)

# Monitor spend in output logs — MetaGPT prints token cost per step
RolePurposeSkip if…
ProductManagerWrites PRDRequirement is already detailed
ArchitectSystem designSimple scripts or single-file apps
ProjectManagerTask assignmentOnly 1 engineer
EngineerCode writingAlways needed
QaEngineerTest writingUse --run-tests flag

Effective Requirements Writing

# Write requirements that specify:
# 1. Tech stack (language, frameworks, versions)
# 2. Input/output format
# 3. File structure expectations  
# 4. How to run the app
# 5. Test expectations

good_requirement = """
Tech stack: Python 3.11, FastAPI 0.100+, SQLAlchemy 2.0, SQLite
Build a URL shortener service with:
- POST /shorten {url: str}{short_code: str, short_url: str}
- GET /{code} → redirects to original URL
- GET /stats/{code}{clicks: int, created_at: str}
- SQLite database with URL and clicks tables
- Runs with: uvicorn main:app --reload --port 8000
- Tests: pytest tests/ with at least 80% coverage
"""

Debugging Multi-Agent Runs

# Enable verbose logging
export METAGPT_LOG_LEVEL=DEBUG
metagpt "your requirement"

# Check individual agent outputs in workspace
ls workspace/your_project/docs/
# PRD.md           — ProductManager output
# system_design/   — Architect output
# task/            — ProjectManager output

# Each file contains full LLM output for that agent's step
# Inspect to understand where things went wrong

# Common issues:
# Agent loops — increase n_round or use --recover-path
# OOM / timeout — reduce engineer count (n_borg=1)
# Bad code — enable --code-review flag
# Tests failing — enable --run-tests and check workspace/tests/

Scaling Considerations

ScenarioConfiguration
Simple scriptEngineer() only, n_round=2
Small appPM + Architect + Engineer, n_round=4
Full productAll 5 roles, n_round=5–8
Data analysisDataInterpreter() only
Code reviewEngineer + QaEngineer, n_round=3
Parallel codingEngineer(n_borg=3) — 3 parallel agents
# For large projects, hire multiple engineers
company.hire([
    ProductManager(),
    Architect(),
    ProjectManager(),
    Engineer(n_borg=5),   # 5 engineers code in parallel
    QaEngineer(),
])