From 5428b18ddd5a99ef61777849f14c9c79c2594978 Mon Sep 17 00:00:00 2001 From: Magnus Hedemark Date: Thu, 9 Jul 2026 14:57:27 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20add=20autogen=20=E2=80=94=20expert=20sk?= =?UTF-8?q?ill=20for=20conversational=20multi-agent=20AI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Greenfield SkillOpt: 3 epochs for Microsoft AutoGen skill. Conversational agent model, GroupChat patterns, code execution, nested chats, cancellation tokens, MCP integration. All API surfaces validated against microsoft.github.io/autogen docs. --- autogen/SKILL.md | 111 ++++++++++++++++++ autogen/references/agent-types.md | 45 +++++++ autogen/references/code-execution.md | 45 +++++++ autogen/references/conversation-patterns.md | 56 +++++++++ autogen/references/faq-and-troubleshooting.md | 36 ++++++ autogen/references/group-chat.md | 43 +++++++ autogen/references/tool-integration.md | 36 ++++++ autogen/scripts/check-setup.py | 27 +++++ autogen/templates/code-execution.py | 23 ++++ autogen/templates/group-chat.py | 24 ++++ autogen/templates/two-agent-chat.py | 22 ++++ 11 files changed, 468 insertions(+) create mode 100644 autogen/SKILL.md create mode 100644 autogen/references/agent-types.md create mode 100644 autogen/references/code-execution.md create mode 100644 autogen/references/conversation-patterns.md create mode 100644 autogen/references/faq-and-troubleshooting.md create mode 100644 autogen/references/group-chat.md create mode 100644 autogen/references/tool-integration.md create mode 100644 autogen/scripts/check-setup.py create mode 100644 autogen/templates/code-execution.py create mode 100644 autogen/templates/group-chat.py create mode 100644 autogen/templates/two-agent-chat.py diff --git a/autogen/SKILL.md b/autogen/SKILL.md new file mode 100644 index 0000000..dca4c10 --- /dev/null +++ b/autogen/SKILL.md @@ -0,0 +1,111 @@ +--- +name: autogen +description: >- + Expert skill for conversational multi-agent AI with Microsoft AutoGen. + AssistantAgent, UserProxyAgent, GroupChat, code execution, nested chats, + cancellation tokens, tool integration, and MCP support. Use when building + conversation-driven multi-agent systems or comparing agent frameworks. +license: MIT +metadata: + author: Magnus Hedemark + version: 1.0.3 + source: https://microsoft.github.io/autogen +--- + +# AutoGen Expert Skill + +AutoGen (by Microsoft Research) is a framework for **conversational multi-agent AI**. Unlike LangGraph's explicit graph topology or CrewAI's role-based crews, AutoGen uses **agent-to-agent conversations as the orchestration primitive**. Agents communicate through structured chat, with built-in patterns for nested conversations, group chat with routing, and code execution. + +## Core Paradigm + +```python +from autogen_agentchat.agents import AssistantAgent +from autogen_agentchat.ui import Console +from autogen_ext.models.openai import OpenAIChatCompletionClient + +model_client = OpenAIChatCompletionClient(model="gpt-4o-mini") + +assistant = AssistantAgent( + name="assistant", + system_message="You are a helpful assistant.", + model_client=model_client, +) +``` + +> **⚠️ UserProxyAgent is NOT a human user.** It is an automated proxy that can execute code. Despite the name, it runs autonomously unless `human_input_mode` is set to `ALWAYS`. + +## Core Principles + +1. **Conversations are the orchestration primitive.** Agents send messages, receive replies, and the conversation structure determines the workflow. +2. **UserProxyAgent is a code executor, not a human.** Despite the name, it runs autonomously by default. Set `human_input_mode="ALWAYS"` for actual human-in-the-loop. +3. **GroupChat routes between agents.** RoundRobinGroupChat cycles fixed-order. SelectorGroupChat uses an LLM to pick the next speaker. +4. **Nested chats delegate work.** An agent can spawn a sub-conversation between specialist agents and return the result. +5. **Docker is the safe code execution mode.** Local code execution (`LocalCommandLineCodeExecutor`) runs LLM-generated code on your machine — use Docker in production. +6. **Cancellation tokens stop runaway agents.** Always pass `CancellationToken` for long-running tasks. + +## Where to Start + +| You already have... | Start here | +|---|---| +| Nothing — exploring AutoGen | Create a two-agent chat (Assistant + UserProxy) | +| Agents that need to coordinate | Build a GroupChat with multiple agents | +| Agents that need code execution | Configure Docker code executor | +| A complex multi-step task | Use nested chats for sub-tasks | + +## Quick Reference + +| Task | Approach | Reference | +|------|----------|-----------| +| Two-agent chat | AssistantAgent + UserProxyAgent | `references/agent-types.md` | +| Multi-agent group | GroupChat with RoundRobinGroupChat | `references/group-chat.md` | +| Code execution | DockerCommandLineCodeExecutor | `references/code-execution.md` | +| Tool integration | `register_function()` or @tool | `references/tool-integration.md` | +| Nested chat | `initiate_chat()` from within a tool | `references/conversation-patterns.md` | +| Cancellation | `CancellationToken` | `references/conversation-patterns.md` | +| MCP tools | `McpWorkbench` | `references/tool-integration.md` | + +## Framework Routing Guide + +| Scenario | Reach for | Why | +|----------|-----------|-----| +| Conversation-driven multi-agent | **AutoGen** | Native agent-to-agent chat as orchestration | +| Role-based multi-agent teams | **CrewAI** | Role/Goal/Backstory is the native abstraction | +| State-machine multi-agent | **LangGraph** | Graph topology, subgraphs, human-in-the-loop | +| Chain/agent composition | **LangChain** | LCEL pipe operator for general chains | + +## Reference Files + +| Reference | Load when | File | +|-----------|-----------|------| +| Agent Types | AssistantAgent, UserProxyAgent | `references/agent-types.md` | +| Conversation Patterns | Send/receive, nested chats, cancellation | `references/conversation-patterns.md` | +| Group Chat | RoundRobin, Selector, MagenticOne | `references/group-chat.md` | +| Code Execution | Docker, local, cancellation tokens | `references/code-execution.md` | +| Tool Integration | register_function, @tool, MCP integration | `references/tool-integration.md` | +| FAQ & Troubleshooting | Common errors and fixes | `references/faq-and-troubleshooting.md` | + +## Templates + +| Template | When to use | File | +|----------|-------------|------| +| Two-Agent Chat | Simple assistant + code executor | `templates/two-agent-chat.py` | +| Group Chat | Multi-agent team with speaker routing | `templates/group-chat.py` | +| Code Execution Agent | Agent with Docker code execution | `templates/code-execution.py` | + +## Troubleshooting + +| Symptom | Likely cause | Fix | Reference | +|---------|-------------|-----|-----------| +| Agent loops forever | No termination condition | Add `is_termination_msg` or `max_turns` | `references/conversation-patterns.md` | +| Code execution fails | Docker not running | Start Docker or use LocalCommandLineCodeExecutor | `references/code-execution.md` | +| Nested chat never returns | Cancellation token not passed | Pass `CancellationToken` with timeout | `references/conversation-patterns.md` | +| v0.2 code doesn't work | v0.4 API changed | Follow migration guide | `references/faq-and-troubleshooting.md` | +| GroupChat speaker selection loops | SelectorGroupChat with no clear next | Use RoundRobinGroupChat for fixed order | `references/group-chat.md` | +| UserProxyAgent asking for input | `human_input_mode="ALWAYS"` | Set to `"NEVER"` for automated execution | `references/agent-types.md` | + +## When NOT to Use AutoGen + +- Simple single-agent task — overkill, use direct API call +- Need fine-grained graph control — use LangGraph +- Need role-based teams with fixed processes — use CrewAI +- Need chain composition — use LangChain LCEL diff --git a/autogen/references/agent-types.md b/autogen/references/agent-types.md new file mode 100644 index 0000000..f2a66e9 --- /dev/null +++ b/autogen/references/agent-types.md @@ -0,0 +1,45 @@ +# AutoGen Agent Types + +## AssistantAgent + +The primary AI agent. Uses an LLM to generate responses. + +```python +from autogen_agentchat.agents import AssistantAgent +from autogen_ext.models.openai import OpenAIChatCompletionClient + +model_client = OpenAIChatCompletionClient(model="gpt-4o-mini") + +assistant = AssistantAgent( + name="assistant", + system_message="You are a helpful AI assistant.", + model_client=model_client, +) +``` + +## UserProxyAgent + +Automated proxy that can execute code. Despite the name, NOT a human user by default. + +```python +from autogen_agentchat.agents import UserProxyAgent + +proxy = UserProxyAgent( + name="proxy", + human_input_mode="NEVER", # "ALWAYS" for human-in-the-loop, "TERMINATE" to stop + is_termination_msg=lambda msg: "TERMINATE" in (msg.get("content", "") or ""), + code_executor=code_executor, +) +``` + +## Key Parameters + +| Parameter | Description | +|-----------|-------------| +| `name` | Unique agent name | +| `system_message` | System prompt defining agent behavior | +| `human_input_mode` | "NEVER", "ALWAYS", or "TERMINATE" | +| `is_termination_msg` | Function to detect termination messages | +| `code_executor` | CodeExecutor for running generated code | +| `model_client` | LLM client (AssistantAgent only) | +| `tools` | Tools the agent can call | diff --git a/autogen/references/code-execution.md b/autogen/references/code-execution.md new file mode 100644 index 0000000..dcdd9a7 --- /dev/null +++ b/autogen/references/code-execution.md @@ -0,0 +1,45 @@ +# AutoGen Code Execution + +## Docker (Recommended) + +Safe execution of LLM-generated code in isolated containers: + +```python +from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor + +executor = DockerCommandLineCodeExecutor(work_dir="coding") +async with executor: + # Use within GroupChat + proxy = UserProxyAgent( + name="proxy", + code_executor=executor, + human_input_mode="NEVER", + ) +``` + +## Local (Development Only) + +Runs generated code on your machine — use only for trusted environments: + +```python +from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor + +executor = LocalCommandLineCodeExecutor(work_dir="coding") +``` + +## Cancellation + +```python +from autogen_core import CancellationToken + +token = CancellationToken() +result = await executor.execute_code_blocks(code_blocks, cancellation_token=token) +# Cancel via: token.cancel() +``` + +## Best Practices + +- Use Docker for any untrusted code execution +- Set a `work_dir` to isolate generated files +- Always pass a `CancellationToken` for long-running tasks +- Monitor `max_turns` to prevent runaway code generation diff --git a/autogen/references/conversation-patterns.md b/autogen/references/conversation-patterns.md new file mode 100644 index 0000000..c12941c --- /dev/null +++ b/autogen/references/conversation-patterns.md @@ -0,0 +1,56 @@ +# AutoGen Conversation Patterns + +## Two-Agent Chat + +```python +from autogen_agentchat.agents import AssistantAgent, UserProxyAgent + +assistant = AssistantAgent(name="assistant", model_client=model_client) +proxy = UserProxyAgent(name="proxy", human_input_mode="NEVER") + +result = proxy.initiate_chat(assistant, message="What is AutoGen?", max_turns=2) +print(result.summary) +``` + +## Termination Conditions + +Prevent infinite loops: + +```python +proxy = UserProxyAgent( + name="proxy", + human_input_mode="NEVER", + is_termination_msg=lambda msg: "TERMINATE" in (msg.get("content", "") or ""), + max_consecutive_auto_reply=5, +) + +# Or limit turns at chat level +result = proxy.initiate_chat(assistant, message="Hello", max_turns=10) +``` + +## Cancellation Tokens + +```python +from autogen_core import CancellationToken + +token = CancellationToken() +# Token can be used to cancel long-running operations +``` + +## Nested Chats + +Agent delegates work to a sub-conversation: + +```python +async def research_topic(query: str) -> str: + researcher = AssistantAgent(name="researcher", model_client=model_client) + fact_checker = AssistantAgent(name="fact_checker", model_client=model_client) + proxy = UserProxyAgent(name="proxy", human_input_mode="NEVER") + result = await proxy.initiate_chat( + researcher, message=f"Research: {query}", max_turns=5 + ) + return result.summary + +# Register as a function the main agent can call +assistant.register_function(function_map={"research": research_topic}) +``` diff --git a/autogen/references/faq-and-troubleshooting.md b/autogen/references/faq-and-troubleshooting.md new file mode 100644 index 0000000..1ca918d --- /dev/null +++ b/autogen/references/faq-and-troubleshooting.md @@ -0,0 +1,36 @@ +# AutoGen FAQ and Troubleshooting + +## Installation + +**Q: Which version should I install?** +A: `pip install autogen-agentchat` for the current v0.4+ API. The older `pip install pyautogen` installs v0.2 (deprecated). + +**Q: Docker not available?** +A: Use `LocalCommandLineCodeExecutor` for development, but understand the security risks. + +## Migration + +**Q: Code from v0.2 doesn't work?** +A: v0.4 has breaking API changes. See the migration guide at https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/migration-guide.html. + +## Common Errors + +**Q: Agent loops forever?** +A: Set `is_termination_msg` or `max_turns`. The agent needs a termination condition. + +**Q: UserProxyAgent keeps asking for input?** +A: `human_input_mode` defaults differently. Set to "NEVER" for automated execution. + +**Q: Nested chat never returns?** +A: Ensure `CancellationToken` is passed and not already cancelled. + +**Q: Code execution fails?** +A: Docker must be running for Docker executor. Use `LocalCommandLineCodeExecutor` for local dev. + +**Q: GroupChat speaker selection is wrong?** +A: Use `RoundRobinGroupChat` for fixed order if `SelectorGroupChat` picks poorly. + +## Performance + +**Q: High token usage?** +A: Each agent-to-agent message consumes tokens. Set `max_turns` conservatively. diff --git a/autogen/references/group-chat.md b/autogen/references/group-chat.md new file mode 100644 index 0000000..546bcf7 --- /dev/null +++ b/autogen/references/group-chat.md @@ -0,0 +1,43 @@ +# AutoGen Group Chat + +## RoundRobinGroupChat + +Fixed-order conversation. Each agent speaks in turn. + +```python +from autogen_agentchat.agents import AssistantAgent +from autogen_agentchat.teams import RoundRobinGroupChat +from autogen_agentchat.ui import Console + +agent1 = AssistantAgent(name="researcher", model_client=model_client) +agent2 = AssistantAgent(name="analyst", model_client=model_client) +agent3 = AssistantAgent(name="writer", model_client=model_client) + +team = RoundRobinGroupChat([agent1, agent2, agent3]) +result = await team.run(task="Research and write about AI trends") +``` + +## SelectorGroupChat + +LLM-driven speaker selection. Uses a model to decide who speaks next. + +```python +from autogen_agentchat.teams import SelectorGroupChat + +team = SelectorGroupChat( + [agent1, agent2, agent3], + model_client=model_client, # LLM used for speaker selection +) +``` + +## MagenticOneGroupChat + +Magentic-One orchestrator pattern — a lead agent coordinates specialist agents. + +## Key Parameters + +| Parameter | Description | +|-----------|-------------| +| `participants` | List of agents in the group | +| `model_client` | LLM for speaker selection (SelectorGroupChat) | +| `max_turns` | Max conversation turns before termination | diff --git a/autogen/references/tool-integration.md b/autogen/references/tool-integration.md new file mode 100644 index 0000000..44b1dd5 --- /dev/null +++ b/autogen/references/tool-integration.md @@ -0,0 +1,36 @@ +# AutoGen Tool Integration + +## register_function + +Bind Python functions as agent tools: + +```python +def search_web(query: str) -> str: + """Search the web for information.""" + return f"Results for: {query}" + +assistant.register_function(function_map={"search_web": search_web}) +``` + +## MCP Tool Integration + +Connect MCP servers as agent tools: + +```python +from autogen_ext.tools.mcp import McpWorkbench, StdioServerParams + +server_params = StdioServerParams(command="npx", args=["@playwright/mcp@latest"]) +async with McpWorkbench(server_params) as mcp: + agent = AssistantAgent( + "web_browsing_assistant", + model_client=model_client, + workbench=mcp, + ) +``` + +## Key Guidelines + +- Tool functions need clear docstrings (become tool descriptions) +- Tools should handle errors gracefully and return strings +- For complex integrations, wrap external APIs with error handling +- MCP tools enable browser automation, databases, and external services diff --git a/autogen/scripts/check-setup.py b/autogen/scripts/check-setup.py new file mode 100644 index 0000000..9824dd4 --- /dev/null +++ b/autogen/scripts/check-setup.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Verify AutoGen installation.""" + +import sys + +REQUIRED = ["autogen_agentchat", "autogen_ext"] +OPTIONAL = ["autogen_core"] + +for pkg in REQUIRED: + try: + __import__(pkg.replace("-", "_")) + print(f" [OK] {pkg}") + except ImportError: + print(f" [FAIL] {pkg} — install with pip install {pkg}") + sys.exit(1) + +for pkg in OPTIONAL: + try: + __import__(pkg.replace("-", "_")) + print(f" [OK] {pkg} (optional)") + except ImportError: + print(f" [—] {pkg} (optional, not installed)") + +from autogen_agentchat.agents import AssistantAgent +print(" [OK] AutoGen imports work") + +print("\nAutoGen setup check: ALL REQUIRED PACKAGES OK") diff --git a/autogen/templates/code-execution.py b/autogen/templates/code-execution.py new file mode 100644 index 0000000..4c3cb60 --- /dev/null +++ b/autogen/templates/code-execution.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Agent with Docker code execution.""" + +import asyncio +from autogen_agentchat.agents import AssistantAgent, UserProxyAgent +from autogen_agentchat.teams import RoundRobinGroupChat +from autogen_ext.models.openai import OpenAIChatCompletionClient +from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor + +async def main(): + model_client = OpenAIChatCompletionClient(model="gpt-4o-mini") + + async with DockerCommandLineCodeExecutor(work_dir="coding") as executor: + assistant = AssistantAgent(name="assistant", model_client=model_client, + system_message="Write Python code to solve problems.") + proxy = UserProxyAgent(name="proxy", code_executor=executor, + human_input_mode="NEVER") + + team = RoundRobinGroupChat([assistant, proxy]) + result = await team.run(task="Calculate pi to 10 decimal places using Python") + print(result.messages[-1].content) + +asyncio.run(main()) diff --git a/autogen/templates/group-chat.py b/autogen/templates/group-chat.py new file mode 100644 index 0000000..91fee82 --- /dev/null +++ b/autogen/templates/group-chat.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Group chat with RoundRobin speaker selection.""" + +import asyncio +from autogen_agentchat.agents import AssistantAgent +from autogen_agentchat.teams import RoundRobinGroupChat +from autogen_agentchat.ui import Console +from autogen_ext.models.openai import OpenAIChatCompletionClient + +async def main(): + model_client = OpenAIChatCompletionClient(model="gpt-4o-mini") + + researcher = AssistantAgent(name="researcher", model_client=model_client, + system_message="You research and find information.") + analyst = AssistantAgent(name="analyst", model_client=model_client, + system_message="You analyze findings for insights.") + writer = AssistantAgent(name="writer", model_client=model_client, + system_message="You write clear summaries.") + + team = RoundRobinGroupChat([researcher, analyst, writer]) + result = await team.run(task="Research and report on AI agents") + print(result.messages[-1].content) + +asyncio.run(main()) diff --git a/autogen/templates/two-agent-chat.py b/autogen/templates/two-agent-chat.py new file mode 100644 index 0000000..38b76da --- /dev/null +++ b/autogen/templates/two-agent-chat.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +"""Two-agent chat with AssistantAgent and UserProxyAgent.""" + +from autogen_agentchat.agents import AssistantAgent, UserProxyAgent +from autogen_ext.models.openai import OpenAIChatCompletionClient + +model_client = OpenAIChatCompletionClient(model="gpt-4o-mini") + +assistant = AssistantAgent( + name="assistant", + system_message="You are a helpful assistant.", + model_client=model_client, +) + +proxy = UserProxyAgent( + name="proxy", + human_input_mode="NEVER", + is_termination_msg=lambda msg: "TERMINATE" in (msg.get("content", "") or ""), +) + +result = proxy.initiate_chat(assistant, message="What is AutoGen?", max_turns=2) +print(result.summary)