# AutoGen

Microsoft's multi-agent conversation framework. Designed for agent-to-agent collaboration.

---

## Core Concepts

### Agent Types
```python
from autogen import (
    ConversableAgent,
    UserProxyAgent,
    AssistantAgent,
    GroupChat,
    GroupChatManager
)

# Basic agents
assistant = AssistantAgent(
    name="assistant",
    llm_config={"model": "gpt-4o"},
    system_message="You are a helpful assistant."
)

user_proxy = UserProxyAgent(
    name="user_proxy",
    human_input_mode="NEVER",  # ALWAYS, TERMINATE, NEVER
    code_execution_config={"work_dir": "coding", "use_docker": False},
)

# Group chat
agents = [assistant, user_proxy, coder, researcher]
groupchat = GroupChat(agents=agents, messages=[], max_round=20)
manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)

# Initiate
user_proxy.initiate_chat(manager, message="Build a web scraper")
```

### Agent Classes
| Class | Purpose | Key Features |
|---|---|---|
| **ConversableAgent** | Base class | LLM config, tools, memory, hooks |
| **AssistantAgent** | LLM-driven | System message, function calling |
| **UserProxyAgent** | Human-in-loop | Code execution, human input, termination |
| **GroupChatManager** | Orchestration | Speaker selection, round management |
| **RetrieveUserProxyAgent** | RAG-enabled | Vector DB integration |

---

## Conversation Patterns

### 1. Two-Agent (Assistant + User Proxy)
```python
assistant = AssistantAgent("assistant", llm_config=config)
user_proxy = UserProxyAgent("user", human_input_mode="NEVER")

# User proxy executes code, assistant writes
user_proxy.initiate_chat(assistant, message="Plot sin(x)")
```

### 2. Group Chat (Multi-Agent)
```python
coder = AssistantAgent("coder", system_message="Write Python code")
reviewer = AssistantAgent("reviewer", system_message="Review code for bugs")
tester = AssistantAgent("tester", system_message="Write unit tests")

groupchat = GroupChat(
    agents=[coder, reviewer, tester],
    messages=[],
    max_round=15,
    speaker_selection_method="auto"  # auto, round_robin, random
)

manager = GroupChatManager(groupchat=groupchat, llm_config=config)
user_proxy.initiate_chat(manager, message="Build a REST API")
```

### 3. Nested Chats (Hierarchical)
```python
# Sub-chat for specific domain
coding_chat = GroupChat(agents=[coder, reviewer], messages=[], max_round=10)
coding_manager = GroupChatManager(groupchat=coding_chat, llm_config=config)

# Main chat delegates to sub-chat
main_agents = [planner, coding_manager, deployer]
main_chat = GroupChat(agents=main_agents, messages=[], max_round=20)
```

---

## Speaker Selection

| Method | Description | Best For |
|---|---|---|
| **auto** | LLM chooses next speaker | Dynamic, complex |
| **round_robin** | Fixed order | Predictable, fair |
| **random** | Random | Exploration |
| **custom** | Function(state) -> agent | Rule-based |

```python
def custom_speaker(last_speaker, agents):
    if last_speaker == "coder":
        return "reviewer"  # Always review after code
    return "coder"

groupchat = GroupChat(
    agents=[coder, reviewer],
    speaker_selection_method=custom_speaker
)
```

---

## Tool Use

### Function Calling
```python
def get_weather(location: str) -> str:
    """Get current weather for a location."""
    return f"Sunny, 72°F in {location}"

assistant = AssistantAgent(
    name="weather_bot",
    llm_config={"model": "gpt-4o", "functions": [get_weather]},
    system_message="Use get_weather tool for weather queries."
)
```

### Code Execution (UserProxyAgent)
```python
user_proxy = UserProxyAgent(
    name="executor",
    code_execution_config={
        "work_dir": "workspace",
        "use_docker": True,  # Isolation
        "image": "python:3.11-slim",
        "timeout": 60
    },
    human_input_mode="NEVER"
)

# Agent writes code, user_proxy executes
assistant.initiate_chat(user_proxy, message="Create a dashboard")
```

---

## Memory & Context

### Built-in Memory
```python
agent = AssistantAgent(
    name="memory_agent",
    llm_config=config,
    # Automatic conversation history
    # Max tokens managed by LLM config
)
```

### External Memory (RetrieveUserProxyAgent)
```python
from autogen import RetrieveUserProxyAgent

rag_agent = RetrieveUserProxyAgent(
    name="rag_user",
    retrieve_config={
        "task": "qa",
        "docs_path": ["./docs"],
        "chunk_token_size": 1000,
        "model": "text-embedding-3-small",
        "vector_db": "chromadb",
        "collection_name": "my_docs"
    }
)
```

---

## Advanced Patterns

### 1. Teachable Agents
```python
from autogen import TeachableAgent

teachable = TeachableAgent(
    name="learnable",
    llm_config=config,
    teach_config={
        "recall_threshold": 1.5,
        "token_limit": 2000
    }
)

# Teach via natural language
user_proxy.initiate_chat(teachable, message="Remember: API_KEY = 'secret'")
# Later...
user_proxy.initiate_chat(teachable, message="What's the API key?")
```

### 2. AgentEval (Auto Evaluation)
```python
from autogen import AgentEval

evaluator = AgentEval(
    name="evaluator",
    llm_config=config,
    criteria={
        "correctness": "Does the answer solve the problem?",
        "completeness": "Are all parts addressed?",
        "clarity": "Is it well-explained?"
    }
)

score = evaluator.evaluate(task="Write a factorial function", response=code)
```

### 3. Magentic-One (Generalist Multi-Agent)
```python
from autogen import MagenticOne

orchestrator = MagenticOne(
    llm_config=config,
    agents=["web_surfer", "file_surfer", "coder", "computer_terminal"]
)

result = orchestrator.run("Find and summarize the latest AI papers")
```

---

## AutoGen Studio (No-Code UI)

```bash
pip install autogenstudio
autogenstudio ui --port 8081
```

Features:
- Visual agent builder
- Drag-and-drop workflows
- Chat interface for testing
- Session history
- Export to Python code

---

## Configuration

### LLM Config
```python
llm_config = {
    "model": "gpt-4o",
    "api_key": "sk-...",
    "temperature": 0.7,
    "top_p": 0.9,
    "max_tokens": 4096,
    "timeout": 120,
    "cache_seed": 42,  # Deterministic caching
    "functions": [tool1, tool2]  # For function calling
}
```

### Agent Config
```python
agent = AssistantAgent(
    name="specialist",
    llm_config=llm_config,
    system_message="You are a domain expert...",
    description="Use for technical questions",  # For speaker selection
    max_consecutive_auto_reply=3,  # Prevent loops
    human_input_mode="NEVER",
    is_termination_msg=lambda x: "TERMINATE" in x.get("content", "")
)
```

---

## Multi-Agent Patterns

### 1. Sequential Pipeline
```python
agents = [planner, researcher, writer, editor]
# Each passes output to next via group chat
```

### 2. Parallel with Aggregation
```python
# Multiple researchers in parallel
researchers = [Researcher(f"researcher_{i}") for i in range(3)]
aggregator = AssistantAgent("aggregator", system_message="Synthesize findings")

groupchat = GroupChat(agents=researchers + [aggregator], ...)
```

### 3. Debate / Consensus
```python
def consensus_speaker(last_speaker, agents):
    # Force debate: pro -> con -> pro -> con -> judge
    pass

debate_agents = [proponent, opponent, judge]
groupchat = GroupChat(agents=debate_agents, speaker_selection_method=consensus_speaker)
```

### 4. Hierarchical Delegation
```python
manager = AssistantAgent("manager", system_message="Delegate to specialists")
specialists = [coder, researcher, designer, tester]

# Manager initiates sub-chats
def delegate(task, specialist):
    sub_chat = GroupChat(agents=[specialist, user_proxy], max_round=5)
    sub_manager = GroupChatManager(groupchat=sub_chat)
    user_proxy.initiate_chat(sub_manager, message=task)
```

---

## Observability

### Logging
```python
import logging
logging.basicConfig(level=logging.INFO)
# Logs: agent messages, tool calls, code execution, speaker selection
```

### AgentOps Integration
```python
import agentops
agentops.init(api_key="...")

# Auto-traces: conversations, token usage, costs, errors
```

### Custom Callbacks
```python
agent = AssistantAgent(
    name="tracked",
    llm_config=config,
    # Hook into events
    on_message=lambda msg: log_to_analytics(msg),
    on_tool_call=lambda tool, args: track_tool(tool, args)
)
```

---

## Deployment

### Docker
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# For code execution
RUN apt-get update && apt-get install -y docker.io
COPY . .
CMD ["python", "main.py"]
```

### Kubernetes (Code Execution Isolation)
```yaml
# Each UserProxyAgent gets its own pod for code execution
# Use KubeSpawner or similar for dynamic pods
```

### Azure (Native)
```python
# AutoGen integrates with Azure AI
llm_config = {
    "model": "gpt-4o",
    "api_type": "azure",
    "api_base": "https://myresource.openai.azure.com",
    "api_version": "2024-02-01"
}
```

---

## Migration: AutoGen 0.2 → 0.4

| 0.2 | 0.4 |
|---|---|
| `autogen.agents` | `autogen` (flat) |
| `UserProxyAgent` | `UserProxyAgent` (same) |
| `GroupChat` | `GroupChat` (same) |
| `llm_config` dict | `LLMConfig` dataclass |
| `register_function` | `@function_tool` decorator |
| `Conversation` class | Removed (use GroupChat) |

---

## Performance Tips

1. **Reuse agents** — Don't recreate per task
2. **Limit rounds** — `max_round` prevents infinite loops
3. **Cache LLM responses** — `cache_seed` in config
4. **Batch tool calls** — Parallel where possible
5. **Monitor token usage** — AgentOps or custom tracking

---

## Related Notes

- [[Frameworks/Framework-Comparison.md]] — vs LangGraph, CrewAI, etc.
- [[Architectures/Multi-Agent-Patterns.md]] — Patterns implemented
- [[MultiAgent/Communication-Protocols.md]] — A2A vs AutoGen protocol
- [[MultiAgent/Coordination-Patterns.md]] — GroupChat, nested chats
- [[ToolUse/Code-Execution.md]] — Code execution patterns
- [[Frameworks/LangGraph.md]] — Alternative for stateful graphs
- [[Frameworks/CrewAI.md]] — Alternative for role-based
- [[Production/Observability.md]] — AgentOps integration

---

*Sources: AutoGen docs (microsoft.github.io/autogen), AutoGen GitHub, AutoGen Studio, AgentOps, Microsoft Research blog, AutoGen 0.4 migration guide, ArXiv: "AutoGen: Enabling Next-Gen LLM Applications" (Wu et al., 2023).*