17 KiB
Executable File
阶段三 · 小点 5:AutoGen(微软多智能体框架·进阶)
所属:阶段三 主流 Agent 开发框架 定位:AutoGen 和 CrewAI 完全不同——它不是"派活",而是让多个 Agent 像拉群开会一样互相聊,聊到有人说「完成」为止。它适合研究实验与原型,但有个必须记住的安全雷区:模型生成的代码可能真在你机器上执行。这一讲把核心类和熔断讲透,安全防线单独划重点。
精简大纲
- 核心理念:对话式多智能体
- 核心类:ConversableAgent / AssistantAgent / UserProxyAgent
- 双人组与 GroupChat 群聊
- 工程要点:熔断、TERMINATE、沙箱安全
- AutoGen 0.4+ 迁移对照:0.2 与 0.4 差异速查
学习内容详情
⚠️ 重要状态提示(2026 年必读):微软已把 AutoGen 与 Semantic Kernel 合并为 Microsoft Agent Framework(MAF),并于 2026 年 4 月发布 1.0;此后 AutoGen / Semantic Kernel 进入维护模式(不再新增特性),官方明确建议新项目转向 MAF。AutoGen 的 0.2 / 0.4 思路(对话式多智能体、代码执行安全、
TERMINATE约定)与 MAF 一脉相承,其底层机制仍值得学习;但做选型、上生产时请优先考虑 MAF。本文保留 AutoGen 教程,用于理解「对话式多智能体」的机理。版本说明:本文主体对应 AutoGen 0.2.x 经典 API(
pip install pyautogen);0.4+ 为全新 async API,写法不同,差异速查见第 5 节「AutoGen 0.4+ 迁移对照」。
1. 核心理念
- 多个 Agent 像拉群开会一样,靠互相发自然语言消息协作完成任务,直到有人说「完成」。
- 适合研究实验与原型验证。
graph LR
A[AssistantAgent: 会说不会做] -->|发代码块/方案| B[UserProxyAgent: 可执行代码]
B -->|把执行结果发回| A
A -->|回复 TERMINATE| C[结束]
2. 核心类
- ConversableAgent: 所有 Agent 的基类,能收消息、能回消息、可配置是否执行代码、是否需人工输入。
- AssistantAgent: 默认「只会说不会做」的纯 LLM 角色:分析问题、写方案、生成代码,但自己不执行。
- UserProxyAgent: 代表「人」或「执行环境」:默认可执行 Assistant 发来的代码块,可设定人工介入模式。
| human_input_mode | 行为 | 风险 |
|---|---|---|
ALWAYS |
每次发言都问真人 | 最低 |
TERMINATE |
仅结束时问(默认半自动) | 中 |
NEVER |
全程无人 | 最高 |
import autogen
# Assistant: "会写代码但自己不执行" 的纯LLM
assistant = autogen.AssistantAgent(
name="coder",
llm_config={"model": "gpt-4o", "api_key": "YOUR_KEY"},
system_message="你是一个Python专家, 只输出代码块。", # 角色设定
)
# UserProxy: 代表"人/执行环境", 默认可执行代码
user_proxy = autogen.UserProxyAgent(
name="executor",
human_input_mode="TERMINATE", # 仅结束时才问真人 (半自动)
code_execution_config={"work_dir": "sandbox"}, # 代码在 sandbox 目录执行
max_consecutive_auto_reply=10, # ★ 熔断1: 双聊最大连续自动回复
)
🔬 深度理解 · 对话式多 Agent(ConversableAgent)机制:
- 本质:AutoGen 的核心不是"派活 / 流水线",而是让若干 Agent 通过「互相发自然语言消息」推进任务,直到有人发终止信号。对话既是协作过程,也是共享状态本身。
- 机制:
ConversableAgent是所有 Agent 的基类,封装了"收消息 → 决定如何回复 → 生成回复"的循环(内部generate_reply会依次尝试 LLM / 执行代码 / 询问人工等回复策略)。AssistantAgent是"只说方案 / 代码但自己不动手"的纯 LLM 角色;UserProxyAgent代表"人 / 执行环境",可执行代码块并把结果发回——两者靠自然语言一来一回配合。- 为什么重要:对话式范式让"分工"隐含在消息里,适合研究 / 原型与开放式任务;但它把控制权交给模型的叙事,可控性弱、无显式状态机——这正是它与 LangGraph(显式 State + 图编排)的最大分野。
- 易错点:以为多个 Agent 各自拥有完整独立状态——其实上下文就是聊天历史;也不清楚"谁自动回谁"由
initiate_chat建立的一对一聊天关系决定,群聊则多一个管理者在指派说话人。
3. 运行模式
3.1 双人组
# 让 assistant 帮 user_proxy 完成任务
result = user_proxy.initiate_chat(
assistant,
message="写一个计算斐波那契数列的 Python 函数",
)
# 期望流程:
# 1. assistant 发代码块
# 2. user_proxy 提取并执行
# 3. 结果发回 → assistant 确认无误
# 4. assistant 回复 TERMINATE → 结束
3.2 GroupChat 群聊(多 Agent 开会)
pm = autogen.AssistantAgent(name="产品经理", llm_config=LLM, system_message="你负责梳理需求")
pg = autogen.AssistantAgent(name="程序员", llm_config=LLM, system_message="你负责写代码")
qa = autogen.AssistantAgent(name="测试", llm_config=LLM, system_message="你负责审代码")
group = autogen.GroupChat(
agents=[pm, pg, qa],
messages=[], # 群聊消息列表, 只会存在内存
max_round=15, # ★ 熔断2: 群聊最大发言轮数(防无限互聊)
)
manager = autogen.GroupChatManager(groupchat=group, llm_config=LLM)
# user_proxy.initiate_chat(manager, message="设计并实现一个登录接口")
graph TD
M[GroupChatManager 管理员: LLM判断该谁发言] --> A[产品经理]
M --> B[程序员]
M --> C[测试]
A -->> M
B -->> M
C -->> M
4. 工程要点(重点)
- 两个熔断都要设:
max_consecutive_auto_reply(双聊)+max_round(群聊),否则互聊到天荒地老。 - TERMINATE 约定: 写进
system_message——AutoGen 靠这个关键字判断任务结束。
🔬 深度理解 · TERMINATE 与对话终止机制:
- 本质:
TERMINATE是一个约定好的字符串关键字,出现在某条回复末尾时 AutoGen 据此判定"任务完成、停止对话",而它本身没有任何"任务完成"的内置判定能力。- 机制:你把它写进
system_message,模型觉得任务完成时以TERMINATE结尾回复;管理循环检测到该关键字即终止回复链。若所有参与方都不发TERMINATE,就只能靠熔断(max_consecutive_auto_reply/max_round)硬性截断。- 为什么重要:它把"何时结束"这个开放问题外包给了模型判断,正因如此不可靠——模型可能过早终止、也可能忘了终止,所以熔断是必须的兜底。
- 易错点:以为框架能自动识别"任务完成";或依赖模型恰好按约定回复。TERMINATE 与熔断必须成对设置,缺一个都会出问题——光有约定会死循环,光有熔断会截断正常任务。
- ★ 沙箱安全(最重要):
use_docker=False时模型代码直接跑在你机器上!模型生成os.remove("C:/重要目录")完全可能。
# 三档安全方案(从最安全到最省事):
# 方案1: 完全禁用代码执行 —— 最安全
user_safe = autogen.UserProxyAgent(
name="safe",
code_execution_config=False, # 不执行任何代码, 模型只输出文本方案
)
# 方案2: Docker 沙箱隔离 —— 推荐生产
user_docker = autogen.UserProxyAgent(
name="docker",
code_execution_config={"docker_image": "python:3.12-slim"}, # 代码在容器里跑, 与宿主隔离
)
# 方案3: 云沙箱 E2B —— 远程隔离
# code_execution_config={"executor": "e2b", ...}
🔬 深度理解 · 代码执行安全(UserProxyAgent 三档):
- 本质:AutoGen 的威力与风险同源——
UserProxyAgent默认在本地工作目录里执行模型生成的代码,因此模型产出的任意命令都可能真在你的机器上跑。- 机制:
code_execution_config控制执行策略——设为False完全禁用(只出文本方案);指定docker_image则把代码送进容器 / 隔离环境执行;也可接云沙箱(如 E2B)。human_input_mode决定是否 / 何时插入人工确认。- 为什么重要:模型生成恶意或意外危险代码的概率非零,且存在 prompt 注入风险——沙箱是"让 Agent 能执行"与"不让它搞坏宿主"之间最关键的安全边界。
- 易错点:
use_docker=False且human_input_mode="NEVER"时风险最高——模型代码直接、无人确认地跑在宿主机上;以为"沙箱目录"绝对安全(仍可能被系统调用逃逸);Docker 需显式配置,默认不一定可用。
- 消息默认只存内存 → 生产自建消息持久化(改
register_reply钩子存库)。
⏳ 短期可不深究:
register_reply这套"给 Agent 注入自定义回复逻辑"的钩子机制,以及消息持久化改造细节,第一遍只需知道"AutoGen 消息默认只存内存、生产要自建持久化"即可;真要接入存储时再根据你装的 0.2 / 0.4 / MAF 版本对照实现。
- 适用边界: 研究原型 / 内部实验最佳;对外生产系统优先 LangGraph(可控性、持久化、审批流齐全)。
5. AutoGen 0.4+ 迁移对照
5.1 背景:0.4 是完全重写
- AutoGen 0.4(2024 年底起)不是常规升级,而是完全重写:async-first(对话入口全部 async/await)、可组合的小 Agent、基于
autogen_core的消息路由架构。 - 社区另维护 AG2 分支(
pip install ag2),延续本文所讲的 0.2.x 经典 API——老代码不想迁移,可换 AG2 继续跑。
5.2 对照表(0.2 → 0.4)
| 概念 | 0.2.x(本文) | 0.4+ |
|---|---|---|
| 包名 | pyautogen |
autogen-agentchat + autogen-ext |
| 模型配置 | llm_config=dict(config_list=[...]) |
构造 model_client(如 OpenAIChatCompletionClient)传入 AssistantAgent |
| 对话入口 | 同步 agent.initiate_chat() |
异步 await agent.on_messages() / on_messages_stream()(后者返回 async generator,可流式取内部思考) |
| 人工代理 | UserProxyAgent(human_input_mode) |
人机交互由 runtime 终端与 autogen_ext 中的 UserProxyAgent 承接 |
| 群聊 | GroupChat + GroupChatManager |
Team 抽象(RoundRobinGroupChat / SelectorGroupChat 等)+ termination condition |
5.3 0.4 最小示例(伪代码)
# 依赖: pip install autogen-agentchat autogen-ext[openai]
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_ext.models.openai import OpenAIChatCompletionClient
async def main() -> None:
# 1) 模型先构造成 client 对象, 而不是塞进 llm_config 字典
model_client = OpenAIChatCompletionClient(model="gpt-4o")
agent = AssistantAgent(
name="coder",
model_client=model_client,
system_message="你是一个Python专家, 只输出代码块。",
)
# 2) on_messages_stream 返回 async generator, 可流式取内部思考
stream = agent.on_messages_stream(
[TextMessage(content="写一个斐波那契函数", source="user")]
)
async for msg in stream:
print(getattr(msg, "content", msg))
asyncio.run(main()) # 脚本入口统一用 asyncio.run 收束; Jupyter 中可直接 await main()
⏳ 短期可不深究:AutoGen 已进入维护模式、官方主推 MAF,0.4 / MAF 的具体异步 API 写法迭代快且社区仍在变迁——这一遍把「对话式多 Agent」的机理与 0.2 安全雷区吃透即可,真要新起项目直接从 MAF 学,不必在 0.4 迁移细节上较劲。
⚠️ 装包前先看包名:0.2.x 教程在网络上大量存在(标志:
pip install pyautogen+initiate_chat),搜到的代码先判断版本再照抄。官方迁移指南(0.2 → 0.4):https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/migration-guide.html⚠️ 新项目选型注意:AutoGen 已进入维护模式,官方推荐的新一代框架是 Microsoft Agent Framework,迁移文档见 https://microsoft.github.io/agent-framework/ 。若要新起项目,建议直接从 MAF 开始。
本节自检
- 能跑通一次双人组协作并正确设置两个熔断
- 能说清 AutoGen 代码执行的三档安全方案
- 能说出 0.2 与 0.4 的三个核心差异
本节配套思考题(快速入门的检验)
- 为什么"双聊"和"群聊"各自要设不同的熔断参数?
max_consecutive_auto_reply和max_round分别防的是什么? - AutoGen 怎么判断"任务结束了"?
TERMINATE为什么必须写进 system_message? - 如果
use_docker=False且human_input_mode="NEVER",会发生什么最坏情况?你会怎么强制避免? - AutoGen 的消息存在哪?为什么生产要自己持久化?它和 LangGraph 的 Checkpointer 对比如何?
本节常见面试题(深度解析)
针对本节核心知识的面试高频点,配合"本质+机制"式理解,能让你答得既有深度又有广度。
面试题 1:AutoGen「对话式多 Agent」与 CrewAI「派活式」在协作模型上有何本质区别?
- 面试官想考察:是否理解两种多智能体范式的内核差异,而不是只记住"一个是拉群一个是派活"。
- 专业作答(含深度):
- AutoGen:Agent 之间用自然语言消息互相"对话",上下文就是聊天历史,分工与决策都隐含在消息流里;由
ConversableAgent基类统一封装收发与回复策略。 - CrewAI:预声明角色(Agent)、任务(Task)与流程(Process),任务按序 / 分层派发,
context显式注入依赖,更像一条可预期的流水线。 - 关键差异:AutoGen 灵活但把控制权交给模型叙事(无显式状态机)、可控性弱;CrewAI 结构固定、可预期但表达力有限(难做精确回滚 / 复杂分支)。
- 选型:开放式研究与原型多用 AutoGen 思路;要可预期 / 要审批 / 要状态管理,LangGraph 是最稳的兜底。
- AutoGen:Agent 之间用自然语言消息互相"对话",上下文就是聊天历史,分工与决策都隐含在消息流里;由
- 加分亮点 / 深度追问:把三者放进一张"表达能力 vs 可控性"的谱系(LangGraph 强可控、AutoGen 强表达但不控、CrewAI 中间);追问常是"为何 AutoGen 消息只存内存"——答:为了性能简单,生产需自建持久化,这与 LangGraph 内建 Checkpointer 是一处关键能力落差。
面试题 2:为什么 TERMINATE 约定不可靠?为什么它必须与熔断成对设置?
- 面试官想考察:对"靠语言约定终止 vs 靠硬熔断兜底"这一确定性问题的理解。
- 专业作答(含深度):
TERMINATE只是一个写进 system_message 的字符串关键字,由模型判断"何时任务完成"并回带它;框架自身没有任务完成的内置判定。- 模型可能过早终止(漏做关键步骤)或忘了终止(无限续聊),所以不可靠。
- 熔断兜底:双聊用
max_consecutive_auto_reply,群聊用max_round,在约定失效时从"轮数"层面强制停止,防死循环烧钱。 - 二者必须配合:只有约定 → 死循环;只有熔断 → 可能截断本该正常结束的任务。
- 加分亮点 / 深度追问:类比 LangGraph 的
recursion_limit熔断思路;追问常是"不用 TERMINATE 还能怎么终止"——答:可用函数返回值 / 轮数 / 外部条件等硬条件判定,比纯语言约定更可靠。
面试题 3:AutoGen 为什么会执行模型生成的代码?use_docker=False + human_input_mode="NEVER" 的最坏后果是什么?
- 面试官想考察:是否真正重视"模型即代码执行者"的安全边界与梯度防护思维。
- 专业作答(含深度):
- 设计使然:
UserProxyAgent代表"人 / 执行环境",默认可提取并执行 Assistant 发来的代码块,从而实现"模型写代码 → 环境跑代码 → 结果回传"的闭环。 - 最坏情况:
use_docker=False(本地执行)+NEVER(全程无人)时,模型生成的任意命令直接、无确认地跑在宿主机上——os.remove、删除目录、读写敏感文件都可能发生,且 prompt 注入可能诱导它这么干。 - 三档防护:完全禁用(
False,最安全)/ Docker 容器隔离(推荐生产)/ 云沙箱 E2B(远程隔离),配合human_input_mode分层控制。 - 结论:让 Agent"能执行"的每一步都要先回答"它跑在哪、谁能拦它、怎么拒绝它"。
- 设计使然:
- 加分亮点 / 深度追问:主动说"沙箱不等于绝对安全(仍需限制网络 / 文件系统权限)";追问常是"生产怎么落地"——答:代码全部送入容器 / 云沙箱执行、只暴露最小权限,并保留可审计日志。