Agent 架构文档 · Markdown
AutoGen Agent 架构全景讲解
以 Agent 的生命脉络 为主线,把 Microsoft 在 microsoft/autogen 这一条线索上做的 一整套东西( autogen core actor runtime + autogen agentchat 高级团队封装 + autogen ext 扩展生态 + AutoGen Studio no code UI + Magentic On
以 Agent 的生命脉络 为主线,把 Microsoft 在
microsoft/autogen这一条线索上做的 一整套东西(autogen-core actor runtime + autogen-agentchat 高级团队封装 + autogen-ext 扩展生态 + AutoGen Studio no-code UI + Magentic-One 通用多 agent 编排)讲成一个统一的故事。AutoGen 是经典的 conversational multi-agent 范式 —— "把任务拆给一群会聊天的 agent,让它们互相发消息直到达成共识"。在 2025 年初的 v0.4 重写之后,它已经从一个 "对话框抽象 + Python 脚本"长成了一个事件驱动的 actor 模型 runtime,能跨进程、跨 语言(Python / .NET)协作。
适合:想搞清楚 AutoGen v0.4 跟 v0.2 到底差在哪的迁移者 / 用 Magentic-One 做通用 agent 的研究员 / 评估开源 multi-agent 框架选型的架构师。
2026-06-08 官方复核补丁:PyPI
autogen-agentchat/autogen-core当前复核到0.7.5,GitHub latest release 为python-v0.7.5。本文讲的是 v0.4 重写后的 actor runtime 架构主线;当前包版本已高于文中最初口径,版本号以本条和官方发布为准。
#目录
- 写在前面:AutoGen 是什么 / 不是什么 0.5. 一张图看懂:AutoGen = Model + Harness(actor runtime + 对话总线)
- Agent 是什么 —— BaseChatAgent + 系统提示 + 工具 + 终止条件
- Agent 怎么活起来 —— Team.run() 一条链路到底
- Agent 怎么思考 —— GroupChat 五种 selector 的取舍
- Agent 怎么行动 —— Tool calling + Code executor + 跨 agent 委托
- Agent 怎么记忆 —— message thread + Memory 协议
- Agent 怎么开口 —— Console / Studio / 流式
- Agent 的外脑 —— ChatCompletionClient 抽象
- 关键设计权衡(架构师视角)
- 附录:包地图、关键概念与源码索引
#零、写在前面:AutoGen 是什么 / 不是什么
"In AutoGen, the team is the architecture." —— v0.4 把 v0.2 那种 "由 ConversableAgent 自己 reply 自己" 的隐式控制流,改成了 "Team 显式编排 + actor runtime 异步消息" 的两层。
#0.1 名称消歧:先把 "AutoGen" 这个词锁定
社区里围绕 AutoGen 这个名字其实有四个不同的项目,写文档前必须区分干净:
| 候选 | 是什么 | 跟 agent 有关吗 |
|---|---|---|
AutoGen v0.4 (microsoft/autogen,2025 年起) |
重写后的 actor-model + async event-driven 框架,本文主角 | 本文主角 |
| AutoGen v0.2 (legacy) | 早期 ConversableAgent / GroupChat 同步 API,仍有大量用户、且仍可 pip install autogen-agentchat==0.2.x |
本文配角,仅做迁移对比 |
Magentic-One (autogen-ext 子项目) |
基于 v0.4 的 5-agent 通用编排(Orchestrator + WebSurfer + FileSurfer + Coder + ComputerTerminal) | 本文配角 |
AG2 (ag2.ai) |
AutoGen v0.2 的社区 fork,独立演进 | 本文不展开 |
| Microsoft Agent Framework | Microsoft 2025 年底推出的"AutoGen + Semantic Kernel 合并版",AutoGen 自身已进入 maintenance | 本文不展开,只在末尾提一句 |
本文讲的是 microsoft/autogen v0.4 这一脉:
- 仓库主页:https://github.com/microsoft/autogen
- 官方文档(stable):https://microsoft.github.io/autogen/stable/
- v0.4 reimagined 博客:https://devblogs.microsoft.com/autogen/autogen-reimagined-launching-autogen-0-4/
- v0.2 文档(freeze):https://microsoft.github.io/autogen/0.2/
- Magentic-One 论文:https://arxiv.org/abs/2411.04468
仓库现状(2026 年):v0.4 是
microsoft/autogen仓库的"重写分水岭",此后小版本 持续迭代到 v0.7.x(2025-09 发布 python-v0.7.5),整体已进入 maintenance mode — README 明确写 "AutoGen is now in maintenance mode. It will not receive new features or enhancements and is community managed going forward.";新项目 Microsoft 推荐用 Microsoft Agent Framework(AutoGen + Semantic Kernel 合并版)。但 AutoGen 的 actor 抽象和 GroupChat 模式仍然是开源 multi-agent 领域最值得拆解的范式,所以本文 按"已稳定的最佳形态"来讲,下文凡说"v0.4"均指 v0.4 重写后的整条主线(含 v0.5/0.6/0.7)。
#0.2 核心矛盾:v0.4 在回答 v0.2 的什么痛点
| 矛盾 | v0.2 的做法 | v0.4 的回答 |
|---|---|---|
| 同步 reply 链导致单点阻塞、难扩展 | ConversableAgent.send() 同步、generate_reply() 自己 reply 自己 |
actor 模型 + async messaging:每个 agent 是一个 actor,runtime 用消息队列驱动 |
| GroupChat 的 speaker selection 是 prompt hack | GroupChatManager 用一段 prompt 让 LLM 选下一个发言者 |
把 selection 抽象成 BaseGroupChatManager,可以是 RoundRobin / Selector / Swarm / Graph / Magentic |
| Tool 注册/执行散落在多个 agent 之间 | register_function(executor=user_proxy, caller=assistant) |
tool 直接挂在 agent 上,AssistantAgent(tools=[...]),由 agent 自己执行 |
| 跨语言、跨进程难 | 只有 Python,且只能跑在一个进程里 | GrpcWorkerAgentRuntime + protobuf,支持 Python / .NET 跨语言、跨进程 |
| No observability | print + logger | 内置 OpenTelemetry tracing、流式事件、saving/restoring 任务进度 |
每个章节都会回到这五个矛盾,看具体的设计是怎么回应的。
#0.3 三层抽象:本文按这层关系展开
┌─────────────────────────────────────────────────────┐
第 6/8 章 ─→ │ AutoGen Studio (no-code UI, drag-and-drop team) │
└────────────────────────┬────────────────────────────┘
│ 落到 YAML/JSON team config
▼
┌─────────────────────────────────────────────────────┐
第 1/3 章 ─→ │ autogen-agentchat (高级 API:Agent + Team) │
│ AssistantAgent / UserProxyAgent / │
│ CodeExecutorAgent / SocietyOfMindAgent │
│ RoundRobinGroupChat / SelectorGroupChat / Swarm / │
│ GraphFlow / MagenticOneGroupChat │
└────────────────────────┬────────────────────────────┘
│ 编译成 actor + 消息流
▼
┌─────────────────────────────────────────────────────┐
第 2 章 ─→ │ autogen-core (actor runtime) │
│ Agent / AgentRuntime / RoutedAgent / │
│ @message_handler / TopicId / Subscription │
│ SingleThreadedAgentRuntime / GrpcWorkerRuntime │
└────────────────────────┬────────────────────────────┘
│ 消费扩展能力
▼
┌─────────────────────────────────────────────────────┐
第 4/7 章 ─→ │ autogen-ext (扩展生态) │
│ OpenAIChatCompletionClient / Anthropic / Azure / │
│ DockerCommandLineCodeExecutor / Jupyter / ACA / │
│ ChromaDBVectorMemory / MultimodalWebSurfer / ... │
└─────────────────────────────────────────────────────┘
记住这张图:autogen-core 是底座,agentchat 是大众工程师的入口,ext 是后台货架, Studio 是给 PM/分析师拖出来的 UI。
#零·五、一张图看懂:AutoGen = Model + Harness(actor runtime + 对话总线)
业界视角:端到端 agent 产品的差距不在底层模型,而在"模型之上的外壳(Harness)"—— 指令、能力、基础设施、可观测性四层共同决定 agent 的真实上限。
AutoGen 的特殊定位:它是 multi-agent 协作框架,不是端到端产品。 v0.4 把 harness 中"基础设施"这一层做得最重——actor runtime + 消息总线 + GroupChat 编排 几乎自成体系,跨进程跨语言都覆盖;但"指令层"主要靠开发者写
system_message,"能力层" 把 tool / code executor 拆成独立 protocol,"可观测"靠 OTel + Studio 外接。下面按"4 层 + 8 支柱" 反向索引本文档每个章节,并诚实标注"框架给了什么 / 留给开发者什么"。
#0.5.1 四层 Harness 结构
┌──────────────────────────────────────────────────────────────────────┐
│ Agent = Model (LLM) + Harness (AutoGen 提供 actor 底座) │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ ① 指令层 │ ⚠ 框架不管:每个 agent 的 system_message 由开发者写 │
│ │ AssistantAgent.system_message + description → §1.1 │
│ │ SelectorGroupChat.selector_prompt(决定谁来发言) → §3.3 │
│ │ Magentic Orchestrator 内置 ledger prompt 模板(少数"自带指令")→ §3.6 │
│ │ Swarm 的 handoff 名单写在 agent 的 handoffs= 参数 → §3.4 │
├──────────────────────────────────────────────────────────────────────┤
│ ② 能力层 │ tools=[fn]:Python callable 自动 schema 化 → §4.1 │
│ │ FunctionTool / BaseTool:自定义 tool 协议 → §4.1 │
│ │ CodeExecutor 接口(Local/Docker/Jupyter/ACA 四种 backend) → §4.2 │
│ │ Handoff / SocietyOfMindAgent:跨 agent 委托原语 → §4.3 │
│ │ reflect_on_tool_use:tool 结果后再来一轮 LLM → §4.1 │
│ │ ext 货架:WebSurfer / FileSurfer / Coder / Terminal 现成实现 → §3.6 │
├──────────────────────────────────────────────────────────────────────┤
│ ③ 基础设施│ ★ AutoGen 最重的一层 ★ │ │
│ │ autogen-core actor runtime(SingleThreaded / Grpc Worker) → §2.2 │
│ │ message_queue + TopicId + Subscription(消息总线) → §2.2 │
│ │ GroupChat 共享 message thread(多 agent 通信底层) → §3 / §5.1 │
│ │ ChatCompletionContext:unbounded / buffered / token-limited → §5.1 │
│ │ Memory protocol(外挂长期记忆,ListMemory / ChromaDB / Redis)→ §5.2 │
│ │ save_state / load_state:team 级序列化 → §5.4 │
│ │ ComponentBase:组件 dump/load(Studio 基础) → §6.3 │
├──────────────────────────────────────────────────────────────────────┤
│ ④ 可观测 │ run_stream:异步事件流(TextMessage / ToolCallEvent / Thought)→ §6 │
│ │ Console:彩色终端输出(调试 / demo 标配) → §6.1 │
│ │ AutoGen Studio:no-code UI + 实时对话气泡 → §6.3 │
│ │ OpenTelemetry tracing:每次 agent / tool 调用打 span → §6 │
│ │ ⚠ 没有内置 cost / 失败聚合面板(要自己接 Jaeger / 看板) │
└──────────────────────────────────────────────────────────────────────┘
#0.5.2 八支柱对照表
| # | Harness 支柱 | 一句话定义 | AutoGen 的实现(框架给 vs 开发者写) | 对应章节 |
|---|---|---|---|---|
| 01 | FS + Git | state 必须活在 context 之外 | ⚠ 给序列化不给文件系统:save_state / load_state 能把 team 全态 dump 成 dict(含 model_context / memory / speaker pointer / termination 计数),但没有"工作目录 / 产物文件"概念;要文件系统得 CodeExecutor 跑代码写或自己加 tool |
§5.4 / §4.2 |
| 02 | Bash 通用工具 | 随用随装避免 token 爆炸 | ✅ CodeExecutorAgent + DockerCommandLineCodeExecutor:LLM 写代码 → 容器里跑 → 返回 stdout/stderr,相当于"通用 bash";JupyterCodeExecutor 还能保持变量;⚠ 但不是"按需加载工具"模型,工具集合在 agent 创建时固定 | §4.2 |
| 03 | 沙箱 + 子工具 | 行动可隔离 + 自检 | ✅ 沙箱级别最高:Local / Docker / Jupyter / ACA Dynamic Sessions(云端按 session 隔离)四档可选;⚠ "自检"没有专门原语,靠 reflect_on_tool_use 让 LLM 看 tool 输出再说一遍,或者写一个 critic agent 单独评 | §4.2 / §3.2 |
| 04 | 记忆 + 搜索 | 跨 turn / 跨用户拿历史 | ⚠ Memory protocol 设计干净但内置实现少:ListMemory(全塞)/ ChromaDBVectorMemory(向量 top-k)/ RedisMemory;update_context 是关键钩子,每次推理前自动塞相关记忆。RAG pipeline / GraphRAG 框架不管,自己接 | §5.2 |
| 05 | 对抗 Context Rot | 长对话也别糊 | ⚠ 给窗口策略不给 condenser:ChatCompletionContext 四种实现(Unbounded / Buffered / HeadAndTail / TokenLimited)按规则裁;没有"自动 summarize 历史",长任务靠 SocietyOfMindAgent 把内层折叠成一条对外 reply 间接缓解 |
§5.1 / §4.3 |
| 06 | 长程执行 | 多 phase 任务不跑偏 | ⚠ 给协作不给 plan:GroupChat 五种 selector(RoundRobin / Selector / Swarm / GraphFlow / Magentic)覆盖编排,但只有 Magentic-One 内置 Task Ledger / Progress Ledger 的显式规划,其它范式要"plan"得自己加 agent 或 prompt | §3 / §3.6 |
| 07 | Hooks 强制层 | 失败转成永久规则 | ❌ 没有内置 hook 强制层。TerminationCondition 可组合(MaxMessageTermination(20) | TextMentionTermination("APPROVE"))算是一种"硬规则",但 "agent 必须先 plan / 必须先校验"这种 phase-level 强制要靠 GraphFlow 画死边或者自定义 selector 实现 |
§1.4 / §3.5 |
| 08 | 规划 + 工具选择 | 别什么都试 | ⚠ 推给团队拓扑:单 agent 内部就是普通 OpenAI tools 协议(看 description 让 LLM 选),跨 agent 才有"选谁"的概念(Selector / Magentic Orchestrator);没有"先 plan 后 execute"的内置范式,要么用 Magentic-One,要么用 GraphFlow 画死 | §3 / §3.6 |
判读规则:✅ = 框架原生提供且大多场景够用;⚠ = 框架给了原语但要开发者组装;❌ = 框架不管,需要自己写或外接。
#0.5.3 当前架构的短板(按 Harness 视角看出来的)
AutoGen v0.4 的根本设计哲学是 "the team is the architecture"——它把基础设施做到极致 (actor + 消息总线 + 跨进程 + 序列化),但指令层 / 能力层 / 长程规划基本不替开发者做决策。 所以"短板"在这里更像是"它把哪些工作留给了开发者,这些工作在工程化时是真实代价":
- Actor runtime 学习曲线陡:相比单进程 ReAct 的"调函数"心智,actor + topic + subscription + envelope 的异步消息模型要花时间消化。文档里的 §2.1 启动链路要 6 步才完成"一条用户消息发出去 → 第一个 agent 拿到"。 v0.2 那种"send / generate_reply"的直觉性彻底没了,换来的是可扩展、可观测、可恢复。
- Context rot 没有 condenser:长会话只能靠
BufferedChatCompletionContext(N)或TokenLimitedChatCompletionContext硬截断;想做"滚动摘要 + 关键事实保留"得自己写一个 middleware agent 或者塞进 Memory.update_context 的 hook 里——没有像 Claude Code/Cursor 那样的"自动 fold + summarize"管道。 - Magentic-One 是唯一开箱即用的"通用编排器":但它本质是一个特别精致的 SelectorGroupChat
- ledger prompt,单一编排器策略。要做"deep research + 长任务 + checkpoint 续跑"的复合场景, 对照 LangGraph 的 deep agents(todo / fs / subagent 三件套)AutoGen 没有等价模板。
- 跨语言序列化是把双刃剑:GrpcWorkerAgentRuntime 让 Python / .NET agent 同台协作很酷, 但所有消息类型必须共享 protobuf schema——message type 演化代价大;本机 demo 跑得欢的 agent, 跨进程上线时 schema 对齐 / 版本兼容能耗掉一周。
- 可观测主要靠 Studio(重)或自己接 OTel:框架自带
run_stream+ Console 的体验很好, 但没有内置的 cost 看板 / 失败聚合 / 跨 team 的 trace 聚合。AutoGen Studio 官方明说 "not meant to be production-ready",生产可观测要 (a) 自己写 OTel exporter 到 Jaeger / Tempo, 或 (b) 接 Microsoft Agent Framework 的托管栈(AutoGen 自身已进入 maintenance)。 - Memory 实现少而薄:ListMemory 全塞 / ChromaDBVectorMemory 向量召回 / RedisMemory, vs 同期 LangChain 几十个 vectorstore——AutoGen 的取舍是"protocol 自己接,不替你做选型", 但意味着第一次接的开发者得自己写一个 connector(好处是三十行代码搞定)。
这些"短板"换个角度看就是 AutoGen 的设计取舍——做对话 multi-agent 的 actor 底座, 把指令 / 能力 / 长程规划留给团队拓扑去回答。要做端到端 agent 产品,要么自己在 GroupChat 上面叠 plan / fs / condenser 这一层(很多生产团队的实际做法),要么迁到 Microsoft Agent Framework (AutoGen + Semantic Kernel 合并版,是 Microsoft 后续主推方向)。
#一、Agent 是什么 —— BaseChatAgent + 系统提示 + 工具 + 终止条件
"AssistantAgent 是 v0.4 的 'kitchen sink' agent:一个原型用、教学用、八九不离十 都够使的通用 agent,但生产环境里你最终多半要继承 BaseChatAgent 自己写一个。"
#1.1 在 AutoGen 里,"一个 Agent" = 一份配置 + 一个 actor
┌─────────────────────────────────────────────────────────────┐
│ 一个 AutoGen Agent │
├─────────────────────────────────────────────────────────────┤
│ name : 唯一标识(runtime 内寻址用) │
│ description : 自然语言描述(GroupChat selector 看这个挑人) │
│ system_message : 系统提示(决定它"是谁、能干什么") │
│ model_client : LLM 客户端(OpenAI / Azure / Anthropic ...) │
│ tools : 工具列表(Python callable 或 ToolSchema) │
│ handoffs : 可委托的目标 agent(Swarm 模式用) │
│ memory : Memory 列表(每轮调用 update_context) │
│ model_context : ChatCompletionContext(对话窗口管理策略) │
│ reflect_on_tool_use : tool 返回后是否再过一遍 LLM(默认 False) │
│ model_client_stream : 是否启用 token 级流式(默认 False) │
│ │
│ ── 行为方法 ── │
│ on_messages(msgs, ctx) : 单次推理 │
│ on_messages_stream(msgs, ctx) : 流式推理 │
│ on_reset(ctx) : 重置内部状态 │
│ produced_message_types : 声明它会产生哪些消息类型 │
└─────────────────────────────────────────────────────────────┘
源码位置:python/packages/autogen-agentchat/src/autogen_agentchat/agents/
#1.2 v0.4 内置的几种 agent,覆盖 90% 用法
| Agent 类 | 角色 | 最适合的场景 |
|---|---|---|
AssistantAgent |
带 LLM + tools 的标配选手 | 你 90% 的场景,等价于 v0.2 的 AssistantAgent |
UserProxyAgent |
单纯收集用户输入再回传 | human-in-the-loop,等价于但比 v0.2 简化非常多 |
CodeExecutorAgent |
把 LLM 生成的代码块送进 executor 跑 | code interpreter 类需求 |
SocietyOfMindAgent |
对外暴露成单 agent,内部跑一个完整 Team | 想做"团队封装成 agent"的嵌套场景 |
MessageFilterAgent |
包另一个 agent,按规则过滤其上下游消息 | 多 agent 共享 thread 时屏蔽噪音(v0.4 后期补的) |
这几个类共同实现 BaseChatAgent,签名约束:
class BaseChatAgent(ABC):
@abstractmethod
async def on_messages(
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
) -> Response: ...
async def on_messages_stream(
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
) -> AsyncGenerator[BaseAgentEvent | BaseChatMessage | Response, None]: ...
@property
@abstractmethod
def produced_message_types(self) -> Sequence[type[BaseChatMessage]]: ...
关键认知:v0.4 里 agent 是 stateful 的,但
on_messages调用语义是 "传入新消息,不是完整历史"。runtime / team 负责把"完整历史"管在外层(ChatHistory 或 GroupChat 的共享上下文),而不是每次都把全量塞回 agent。这是 v0.2 那种 "send 一条消息、自己反复 reply"模式的根本反转。
#1.3 用一个最小 AssistantAgent 解剖
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
async def web_search(query: str) -> str:
"""Fake web search."""
return f"AutoGen is a multi-agent framework. (q={query})"
agent = AssistantAgent(
name="researcher",
description="A researcher who can use the web to answer questions.",
model_client=OpenAIChatCompletionClient(model="gpt-4o-mini"),
tools=[web_search],
system_message="Use tools to solve tasks.",
reflect_on_tool_use=True, # tool 返回后让 LLM 再总结一遍
model_client_stream=True, # 启用流式 token
)
result = await agent.run(task="Search 'AutoGen v0.4'")
run(task=...) 是 BaseChatAgent 自带的便捷封装,本质是:把 task 包成
TextMessage → 调 on_messages → 收集所有产生的消息 → 包成 TaskResult 返回。
run_stream() 则是返回一个异步迭代器,吐出每一条事件 / 消息 / 工具调用,最后再吐
一个 TaskResult。
#1.4 终止条件:v0.4 的"你别一直说下去"
v0.2 用 max_consecutive_auto_reply 等参数挂在每个 agent 上;v0.4 把它抽出来,
作为 TerminationCondition 显式传给 Team:
| 终止条件 | 触发时机 |
|---|---|
MaxMessageTermination(n) |
全队累计消息数 ≥ n |
TextMentionTermination("APPROVE") |
任意 agent 发出包含该字符串的消息 |
TokenUsageTermination(max_tokens) |
累计 token 用量到阈值 |
TimeoutTermination(seconds) |
墙钟时间到点 |
HandoffTermination(target) |
出现指向某个 agent 的 HandoffMessage(Swarm 必用) |
SourceMatchTermination(name) |
指定 agent 发完一条就停 |
StopMessageTermination() |
某个 agent 显式产出 StopMessage |
TextMessageTermination() |
一旦有 TextMessage 就停(适合 nested team) |
FunctionCallTermination(name) |
某个具体 tool 被调用并返回 |
FunctionalTermination(callable) |
自定义谓词 |
ExternalTermination() |
进程外手动调 set() 停掉(UI 集成必备) |
可以用 | & 组合:
termination = MaxMessageTermination(20) | TextMentionTermination("APPROVE")
"stateful but auto-reset":每个 termination 实例在一次
team.run()里累积状态, 但 run 结束后会自动 reset,所以同一个 team 可以连续跑多轮任务。
源码位置:python/packages/autogen-agentchat/src/autogen_agentchat/conditions/
#二、Agent 怎么活起来 —— Team.run() 一条链路到底
"在 v0.4 里,'启动一个 agent' 不是 new 一个对象就完事,而是 'Team 帮你把 agent 注册到 runtime,把 termination 挂上,把消息总线接通'。"
#2.1 启动链路全景
我们以最常用的 RoundRobinGroupChat 为例,看从用户调 team.run(task="...")
到第一个 agent 拿到消息的完整链路:
用户调 await team.run(task="...") autogen-agentchat
│
▼
┌─────────────────────────────────────────────────┐
│ 1. BaseGroupChat.run() │
│ - 把 task 包装成 TextMessage │
│ - 调用 run_stream() 收集结果 │
└────────────────────┬────────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ 2. BaseGroupChat._init_runtime() (lazy) │
│ - 创建 SingleThreadedAgentRuntime │
│ - 把每个参与 agent 包成一个 ChatAgentContainer│
│ - 注册 GroupChatManager(RoundRobin/Selector)│
│ - 建立 topic 订阅(agents <-> manager) │
└────────────────────┬────────────────────────────┘
▼ autogen-core
┌─────────────────────────────────────────────────┐
│ 3. runtime.publish_message(GroupChatStart, …) │
│ - 走 SingleThreadedAgentRuntime 的消息队列 │
│ - 派给 GroupChatManager │
└────────────────────┬────────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ 4. GroupChatManager.handle_start() │
│ - 选第一个 speaker(RoundRobin 拿第 0 个) │
│ - publish GroupChatRequestPublish 到该 agent │
└────────────────────┬────────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ 5. ChatAgentContainer.handle_request_publish() │
│ - 取出共享 message thread │
│ - 调 BaseChatAgent.on_messages_stream(thread) │
│ - 把每条产生的 message 推回 manager │
└────────────────────┬────────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ 6. GroupChatManager.handle_message_publish() │
│ - append 到共享 thread │
│ - 调 termination_condition(messages) │
│ - 没终止就选下一个 speaker,回到第 4 步 │
│ - 终止就 publish GroupChatTermination │
└─────────────────────────────────────────────────┘
看清楚 actor 模型在哪: Team 不是直接调 agent 的方法,而是通过
AgentRuntime.publish_message()推到 topic,runtime 再 dispatch 给订阅了这个 topic 的 ChatAgentContainer。所有 agent 之间的"对话"都是异步消息,没有任何 同步调用栈。
#2.2 SingleThreadedAgentRuntime:单进程 actor 调度器
┌─────────────────────────────────────────────────────────┐
│ SingleThreadedAgentRuntime │
├─────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────┐ │
│ │ message_queue : asyncio.Queue[Envelope] │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ subscriptions : List[Subscription] │ │
│ │ TypeSubscription("default", "agent_id") │ │
│ │ TypePrefixSubscription(...) │ │
│ └──────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ agent_factories : Dict[type, factory] │ │
│ │ lazy 创建 agent 实例 │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ 主循环: │
│ while not stopped: │
│ envelope = await queue.get() │
│ targets = [s.matched(envelope.topic) │
│ for s in subscriptions] │
│ for tgt in targets: │
│ agent = await get_or_create(tgt) │
│ await agent.on_message(envelope.payload, ctx) │
└─────────────────────────────────────────────────────────┘
源码位置:
python/packages/autogen-core/src/autogen_core/_single_threaded_agent_runtime.py
#2.3 跨进程:GrpcWorkerAgentRuntime
把同一份代码改个 runtime 类,就能让 agent 跑在不同的机器/进程:
┌─────────────────────────────────────────────┐
│ Host (GrpcWorkerAgentRuntimeHost) │
│ ─ 维护到所有 worker 的连接 │
│ ─ 路由消息(按 subscription) │
│ ─ 维护 RPC session(direct messaging) │
└─────────┬───────────────┬───────────────────┘
│ gRPC bidi │ gRPC bidi
│ stream │ stream
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Worker A │ │ Worker B │
│ (Python) │ │ (.NET) │
│ - WebSurfer │ │ - Coder │
│ - FileSurfer │ │ - Terminal │
└────────────────┘ └────────────────┘
关键约束:跨语言时所有消息类型必须共享 protobuf schema(在
autogen-core 的 agent_worker.proto / cloudevent.proto 基础上扩展)。
源码位置:python/packages/autogen-ext/src/autogen_ext/runtimes/grpc/
#2.4 v0.2 的对比:为什么要这么改
v0.2: v0.4:
user_proxy.send( team = RoundRobinGroupChat([...])
msg, recipient=assistant) await team.run(task=...)
│ │
▼ 同步 call ▼ 异步 publish
assistant.generate_reply() runtime.publish_message()
│ │
▼ 内部循环 reply ▼ runtime dispatch 到所有订阅者
assistant.send(reply, manager.handle() → 选下一个
recipient=user_proxy) agent → publish_message → ...
差别一句话:v0.2 是"agent 之间互相调函数",v0.4 是"agent 之间互相发消息,runtime 负责送达"。前者天然单线程,后者天然事件驱动、可扩展、可观测。
#三、Agent 怎么思考 —— GroupChat 五种 selector 的取舍
"AutoGen 的 'agent 怎么思考' 问题,其实分成两层:单 agent 内部就是普通 ReAct(LLM 看 system + history,决定 reply 还是 call tool);多 agent 之间则是 'Team 怎么 决定下一个发言者',这是 GroupChat 的核心。"
单 agent 的内循环(AssistantAgent):
on_messages(new_messages):
1. memory.update_context(model_context) # 把 memory 塞进上下文
2. model_context.add_messages(new_messages)
3. model_client.create(messages, tools=...)
├─ 返回纯 text → 包成 TextMessage 返回
└─ 返回 tool_calls → 并发执行 → ToolCallExecutionEvent
→ reflect_on_tool_use? → 再来一轮 model_client.create
→ 否则把 tool result 包成 ToolCallSummaryMessage 返回
这没什么特别,就是标准 OpenAI tools 协议的封装。真正有意思的是 Team 层的五种 speaker selection 策略。
#3.1 五种 Team 模式总览
| Team 类 | 选下一个发言者的方式 | 适合场景 |
|---|---|---|
RoundRobinGroupChat |
按定义顺序轮转 | 角色固定、流程线性(write → review → revise) |
SelectorGroupChat |
用一个 LLM 看历史 + 每个 agent 的 description,挑下一个 | 角色多、需要"看情况派人" |
Swarm |
当前 agent 显式发 HandoffMessage 指定下家 | 复杂工作流,agent 自己懂得"该把球传给谁" |
GraphFlow |
按预定义 DAG(DiGraph)走,支持条件、并行、循环 | 工程化场景,要确定性和可重放 |
MagenticOneGroupChat |
由专门的 Orchestrator agent 负责 plan + 选人 + 重新规划 | 通用任务("帮我查 X 然后写报告") |
#3.2 RoundRobinGroupChat:最简单也最常用
team = RoundRobinGroupChat(
[primary_agent, critic_agent],
termination_condition=TextMentionTermination("APPROVE"),
)
result = await team.run(task="Write a short poem about fall.")
行为:primary 写 → critic 评 → primary 改 → critic 评 → ... → critic 说 APPROVE → 停。 所有 agent 看同一份 message thread,所以 critic 能看到 primary 写的全文。
#3.3 SelectorGroupChat:让 LLM 当工头
team = SelectorGroupChat(
participants=[planning_agent, web_search_agent, data_analyst],
model_client=model_client,
selector_prompt="""You are a coordinator. Read the conversation
and pick which agent should speak next from {participants}.
Each agent's role is described as: {roles}.
Only pick one.""",
allow_repeated_speaker=False,
termination_condition=...,
)
工作机制:每收到一条消息,selector 把 history + agent description 送给 LLM,让它 返回一个 agent name;然后 publish 给那个 agent。这就是 v0.2 的 GroupChatManager prompt-based selection 的"显式版":v0.2 是在 manager 内部偷偷干这件事,v0.4 把 selector 单独抽出来,prompt、model、是否允许连发都可配置。
#3.4 Swarm:agent 自己决定下一个谁来
灵感来自 OpenAI 的 Swarm 项目。每个 agent 在 system message 里被告知 "你可以
handoff 给 [agent A, agent B]",模型生成 HandoffMessage(target="A") 后,team 直接
把控制权转给 A:
travel_agent = AssistantAgent(
name="travel",
handoffs=["flights", "hotels", "user"], # 它知道可以传给谁
system_message="...",
)
team = Swarm(
[travel_agent, flights_agent, hotels_agent],
termination_condition=HandoffTermination(target="user"),
)
Swarm + HandoffTermination 是 human-in-the-loop 的标配:agent 把任务做完之后
handoff 给 "user",team 结束,外层应用收集用户输入,再调一次 team.run() 续上。
#3.5 GraphFlow:工程派的最爱
把团队画成一个有向图,节点是 agent,边带条件:
from autogen_agentchat.teams import DiGraphBuilder, GraphFlow
builder = DiGraphBuilder()
builder.add_node(researcher).add_node(writer).add_node(reviewer)
builder.add_edge(researcher, writer)
builder.add_edge(writer, reviewer)
# 条件边走 add_edge(condition=...),条件可以是字符串("REVISE" in message)或 callable
builder.add_edge(reviewer, writer, condition=lambda m: "REVISE" in m.to_model_text())
# 没有显式 END 节点——流程在叶节点跑完后自动停止(由内置 DiGraphStopAgent 发 StopMessage)
team = GraphFlow(
participants=builder.get_participants(),
graph=builder.build(),
)
跟 LangGraph 思路高度重合 —— 这其实是 AutoGen 在"GroupChat 太自由不可控"和 "LangGraph 太强约束不灵活"之间找的折中。支持 sequential / parallel / conditional / loop 四种基本结构。
#3.6 MagenticOneGroupChat:开箱即用的"通用 agent 团队"
from autogen_agentchat.teams import MagenticOneGroupChat
from autogen_ext.agents.web_surfer import MultimodalWebSurfer
from autogen_ext.agents.file_surfer import FileSurfer
from autogen_ext.agents.magentic_one import MagenticOneCoderAgent
from autogen_agentchat.agents import CodeExecutorAgent
from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor
team = MagenticOneGroupChat(
participants=[
MultimodalWebSurfer("WebSurfer", model_client=mc),
FileSurfer("FileSurfer", model_client=mc),
MagenticOneCoderAgent("Coder", model_client=mc),
CodeExecutorAgent("Terminal", code_executor=DockerCommandLineCodeExecutor()),
],
model_client=orchestrator_model_client, # 单独给 orchestrator 一个强模型
)
result = await team.run(task="Find the latest AutoGen release notes and summarize.")
内部机制(来自论文):
┌────────────────────────┐
│ Magentic Orchestrator │
│ ─ Task Ledger │
│ ─ Progress Ledger │
│ ─ outer / inner loop │
└─┬──────────────────────┘
│
│ 选 agent + 给指令
┌─────────┼──────────┬─────────┬──────────┐
▼ ▼ ▼ ▼ ▼
┌─────────┐┌─────────┐┌─────────┐┌─────────┐
│WebSurfer││FileSurfer││ Coder ││Computer │
│浏览器 ││ 本地文件 ││ 写代码 ││Terminal │
└─────────┘└─────────┘└─────────┘└─────────┘
- Task Ledger:开局 orchestrator 让 LLM 列出 facts、guesses、subtasks,写到 ledger。
- Progress Ledger:每轮 agent 发完话,orchestrator 让 LLM 更新这个 ledger,回答四个问题:
- 任务完成了吗?2. 在原地打转吗?3. 下一步该谁?4. 下一步具体说啥?
- Outer / Inner Loop:inner loop 是不停选 agent 推进任务;inner loop 卡住或重复 N 次 没进展时,跳到 outer loop 重新规划 task ledger。
MagenticOne 是 AutoGen 给 v0.4 写的 "招牌应用" —— 它本质上就是"一个 SelectorGroupChat
- 一个特别精致的 selector prompt(含 ledger 维护)"。生产场景也可以拿这个模式自己写 orchestrator,不一定要用现成的 MagenticOneGroupChat。
源码位置:
python/packages/autogen-ext/src/autogen_ext/teams/magentic_one/python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/python/packages/autogen-ext/src/autogen_ext/agents/file_surfer/
#四、Agent 怎么行动 —— Tool calling + Code executor + 跨 agent 委托
"AutoGen 把 'agent 怎么动手' 拆成三个独立机制:tool calling 走 OpenAI 协议、code execution 单独抽象成 CodeExecutor 接口、agent 之间委托走 handoff/SocietyOfMind。 三件事互不绑死,可以自由组合。"
#4.1 Tool calling:OpenAI 协议 + reflect_on_tool_use
AutoGen 的 tool 抽象兼容 OpenAI tools 格式。三种注册方式:
# (a) 直接传 Python 函数,AutoGen 自动从 type hints + docstring 生成 schema
async def web_search(query: str) -> str:
"""Search the web."""
...
agent = AssistantAgent(..., tools=[web_search])
# (b) 传 FunctionTool 显式声明
from autogen_core.tools import FunctionTool
tool = FunctionTool(web_search, description="Search the web", strict=True)
# (c) 自己继承 BaseTool,自定义 schema 和 run() 行为
class MyTool(BaseTool[Args, Result]): ...
核心循环(在 AssistantAgent.on_messages 里):
LLM.create(messages, tools=tool_schemas)
│
├─ no tool_calls → 返回 TextMessage,结束
└─ has tool_calls → asyncio.gather(*[tool.run(args) for ...])
│ (注意:默认并发执行所有 tool)
▼
ToolCallExecutionEvent (流式吐给上层)
│
├─ reflect_on_tool_use=False (默认)
│ → 把 tool 结果直接拼成 ToolCallSummaryMessage 返回
│
└─ reflect_on_tool_use=True
→ 把 tool 结果加进 model_context,再调一次 LLM.create
→ 让模型"看完结果再发话"
reflect_on_tool_use 是个性能/成本权衡:开了多花一次 LLM 调用,但模型能基于 结果做总结/纠正;不开就直接把 tool 输出塞回去,适合 tool 已经返回结构化文本的情况。
#4.2 Code executor:四种 backend,统一接口
CodeExecutor 接口在 autogen-core 里:
class CodeExecutor(ABC):
@abstractmethod
async def execute_code_blocks(
self, code_blocks: list[CodeBlock], cancellation_token
) -> CodeResult: ...
四个实现(在 autogen-ext 里):
| 实现 | 隔离强度 | stateful? | 适合 |
|---|---|---|---|
LocalCommandLineCodeExecutor |
无(直接跑在主机) | 否(每块写到独立文件) | 开发期、信任的 agent |
DockerCommandLineCodeExecutor |
Docker 容器 | 否 | 默认推荐,生产环境基础隔离 |
JupyterCodeExecutor |
Jupyter kernel | 是(变量保持) | ML 迭代式建模 |
ACADynamicSessionsCodeExecutor (Azure Container Apps) |
完全云端、按 session 隔离 | 否 | 多租户托管、企业合规 |
绑定方式有两种:
# 方式 1:作为独立 agent
code_agent = CodeExecutorAgent(
name="executor",
code_executor=DockerCommandLineCodeExecutor(work_dir="/tmp/coding"),
)
team = RoundRobinGroupChat([coder_agent, code_agent], ...)
# 方式 2:作为 AssistantAgent 的一个 tool(通过 PythonCodeExecutionTool)
agent = AssistantAgent(
name="coder",
tools=[PythonCodeExecutionTool(executor=DockerCommandLineCodeExecutor())],
...
)
历史包袱提醒:v0.2 里的 UserProxyAgent 自带
code_execution_config,它实际 就是一个 ConversableAgent + 一个 code executor 的合体。v0.4 把这两件事彻底解耦, UserProxyAgent 退化成只负责"接收用户输入",代码执行单独由 CodeExecutorAgent 干。 迁移 v0.2 项目时这是最容易踩坑的地方。
#4.3 跨 agent 委托:handoff vs SocietyOfMind
两种"agent 喊另一个 agent 来干活"的玩法:
| 机制 | 控制权转移 | 谁能看到中间过程 |
|---|---|---|
| Swarm + HandoffMessage | 显式转移:A handoff 给 B,B 接管对话 | 整个 team 共享 thread,所有 agent 看得见 |
| SocietyOfMindAgent | A 内部跑一个 inner team,最后只把"团队结论"返回给外层 | 外层只看到结论,inner thread 被封装 |
SocietyOfMind 的典型用法:把"研究 + 写作 + 审稿"的 3-agent 团队封装成一个对外的 "内容生产 agent",再放进更高层的 Team 里:
inner_team = RoundRobinGroupChat([writer, critic], termination_condition=...)
content_agent = SocietyOfMindAgent(
name="content_producer",
team=inner_team,
model_client=summarizer_client, # 用来把 inner thread 总结成对外回复
)
outer_team = SelectorGroupChat([planner, content_agent, deployer], ...)
SocietyOfMind 在最后一步会调一次 model_client,让它把 inner team 的最后几条消息 压缩成一条对外的 reply —— 这就是它名字的由来(多个 agent 的 "mind" 合成一个对外 人格)。
#五、Agent 怎么记忆 —— message thread + Memory 协议
"AutoGen 的记忆是分层的:短期靠 message thread(GroupChat 共享),中期靠 ChatCompletionContext 的窗口策略,长期靠 Memory 协议外挂。三层之间的衔接点 都在 update_context。"
#5.1 三层记忆模型
┌──────────────────────────────────────────────────────────┐
│ L3: Memory(长期,外挂) │
│ - ListMemory / ChromaDBVectorMemory / RedisMemory ... │
│ - 实现 Memory protocol:add / query / update_context │
└────────────────────────┬─────────────────────────────────┘
│ update_context 时把相关记忆 push
▼
┌──────────────────────────────────────────────────────────┐
│ L2: ChatCompletionContext(窗口策略) │
│ - UnboundedChatCompletionContext │
│ - BufferedChatCompletionContext(buffer_size=N) │
│ - HeadAndTailChatCompletionContext(head=k, tail=m) │
│ - TokenLimitedChatCompletionContext(max_tokens=...) │
└────────────────────────┬─────────────────────────────────┘
│ on_messages 时拼装上下文
▼
┌──────────────────────────────────────────────────────────┐
│ L1: Message thread(短期,团队共享) │
│ - GroupChat 维护一个 messages: List[BaseChatMessage] │
│ - 每个 agent 看到的是 thread 的快照 │
└──────────────────────────────────────────────────────────┘
#5.2 Memory 协议:插件式长期记忆
class Memory(ABC):
@abstractmethod
async def add(self, content: MemoryContent, ...) -> None: ...
@abstractmethod
async def query(self, query: str | MemoryContent, ...) -> MemoryQueryResult: ...
@abstractmethod
async def update_context(self, model_context: ChatCompletionContext) -> UpdateContextResult: ...
@abstractmethod
async def clear(self) -> None: ...
@abstractmethod
async def close(self) -> None: ...
update_context 是关键:每次 agent 推理前,它把 model_context 拿出来,根据当前
最后一条消息查相关记忆,再把命中的记忆作为一条 SystemMessage append 进去。
两个内置实现:
# (a) ListMemory:按时间顺序保留全部,update_context 时全塞进去
mem = ListMemory()
await mem.add(MemoryContent(content="User likes concise answers", mime_type="text/plain"))
# (b) ChromaDBVectorMemory:向量检索 top-k
mem = ChromaDBVectorMemory(
config=PersistentChromaDBVectorMemoryConfig(
collection_name="user_prefs",
persistence_path="/tmp/chroma",
k=3,
score_threshold=0.4,
)
)
agent = AssistantAgent(..., memory=[mem])
源码位置:
python/packages/autogen-core/src/autogen_core/memory/python/packages/autogen-ext/src/autogen_ext/memory/chromadb/
#5.3 GraphRAG / RAG 不在框架里
跟 LangChain 那种"内置 RAG chain"不一样,AutoGen 把 RAG 推到外面 —— 你自己拿 向量库查文档,写到 memory 或当 tool 暴露给 agent。框架不假设你的检索栈。
#5.4 状态保存与恢复(v0.4 新功能)
v0.4 显式支持把整个 team 的状态序列化下来:
state = await team.save_state() # 返回 dict,可 json.dump
# ... 重启进程 ...
await team.load_state(state)
result = await team.run(task="continue")
state 里包含:每个 agent 的 model_context、memory 状态、GroupChat manager 的 speaker pointer、termination condition 的累积计数。这是 v0.2 完全做不到的(v0.2 的 reply 链是同步函数调用,断了就断了)。
#六、Agent 怎么开口 —— Console / Studio / 流式
"AutoGen 的 'agent 怎么开口' 跟厂商私有平台最大的不同:它不假设你有前端。每个 agent 的输出都是一串 BaseAgentEvent / BaseChatMessage 流,要不要做 UI、做什么 UI 都是上层的事。"
#六种"输出消费方式":
┌──────────────────────────────────────────────────────────┐
│ team.run(task=...) │
│ → 返回 TaskResult(messages 列表 + stop_reason) │
│ → 适合后台批处理 │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ team.run_stream(task=...) │
│ → AsyncGenerator,吐每条消息/事件,最后吐 TaskResult │
│ → 适合自定义 UI(WebSocket / SSE 转发) │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ Console(team.run_stream(...)) │
│ → 把 stream 转成漂亮的彩色终端输出 │
│ → 调试和 demo 标配 │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ AutoGen Studio (Web UI) │
│ → 把 team 配置存成 YAML/JSON,加载后用 UI 跑 │
│ → 实时显示 agent 之间的对话气泡 │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ ChainLit / Streamlit / FastAPI 集成 │
│ → 业内常见做法:把 run_stream 转 SSE / WebSocket │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ OpenTelemetry Trace │
│ → 每个 agent 调用 / tool 调用都可以打 span │
│ → 接到 Jaeger / Zipkin / Tempo │
└──────────────────────────────────────────────────────────┘
#6.1 Console:debug 必备
from autogen_agentchat.ui import Console
await Console(team.run_stream(task="..."))
它会按事件类型上色:
- TextMessage 显示作者 + 内容
- ToolCallRequestEvent 显示要调的 tool 名 + 参数(黄色)
- ToolCallExecutionEvent 显示返回结果(绿色)
- ThoughtEvent (reasoning model 的思考过程)斜体灰色
#6.2 流式 token:model_client_stream=True
默认 AssistantAgent 是 "等 LLM 全部生成完再吐 TextMessage"。打开
model_client_stream=True 后,run_stream 里会先吐一连串 ModelClientStreamingChunkEvent
(每个 token 一个事件),最后才是完整的 TextMessage。前端可以照着 OpenAI SSE 协议
转出去。
#6.3 AutoGen Studio:no-code 拖拽 + 实时调试
它本身是一个 FastAPI + React 的 web app,跟 v0.4 同构:
AutoGen Studio
├── 左侧 Component Library
│ Agent / Tool / Model / Termination / Memory(可拖)
├── 中间 Team Builder
│ 把组件拖进来,连线,配置参数
├── 右侧 Run Panel
│ 跑 team,看实时消息流
└── 底层
把 UI 配置序列化成 component config(YAML/JSON)
加载时反序列化成真正的 BaseChatAgent / Team 实例
Studio 的核心抽象是 component_config —— 每个 AutoGen 组件都实现
ComponentBase,能 dump 成 dict,也能从 dict 重建。这套序列化机制是 v0.4 才有的
(v0.2 的 agent 不可序列化),是 Studio 能存在的前提。
源码位置:python/packages/autogen-studio/
生产警告:Studio 官方文档明确说"It is not meant to be a production-ready app"。 它是给 PM 和研究员快速 prototype 的工具,正经线上服务还是得自己写 backend。
#七、Agent 的外脑 —— ChatCompletionClient 抽象
"v0.4 把 LLM 抽象成 ChatCompletionClient 接口,所有 agent 只跟这个接口对话; 接哪家模型就在 autogen-ext 里挑一个 client 实现。"
#7.1 ChatCompletionClient 接口
class ChatCompletionClient(ABC):
@abstractmethod
async def create(
self,
messages: Sequence[LLMMessage],
*,
tools: Sequence[Tool | ToolSchema] = [],
json_output: Optional[bool] = None,
extra_create_args: Mapping[str, Any] = {},
cancellation_token: Optional[CancellationToken] = None,
) -> CreateResult: ...
@abstractmethod
def create_stream(...) -> AsyncGenerator[str | CreateResult, None]: ...
@abstractmethod
def actual_usage(self) -> RequestUsage: ...
@abstractmethod
def total_usage(self) -> RequestUsage: ...
@abstractmethod
def model_info(self) -> ModelInfo: ...
model_info 报告"我支不支持 vision、function calling、json_output、structured_output、
是不是 reasoning model",agent 在调用时会按需 degrade。
#7.2 内置实现矩阵
| Client | 包路径 | 支持模型 |
|---|---|---|
OpenAIChatCompletionClient |
autogen_ext.models.openai |
GPT-4o / GPT-5 / 兼容 OpenAI 协议的模型 |
AzureOpenAIChatCompletionClient |
autogen_ext.models.openai |
Azure OpenAI 部署 |
AnthropicChatCompletionClient |
autogen_ext.models.anthropic |
Claude 3.x / 4.x |
OllamaChatCompletionClient |
autogen_ext.models.ollama |
本地 Ollama |
AzureAIChatCompletionClient |
autogen_ext.models.azure |
Azure AI Foundry |
SemanticKernelChatCompletionAdapter |
autogen_ext.models.semantic_kernel |
任意 SK connector |
ChatCompletionCache |
autogen_ext.models.cache |
给任意上面的 client 加一层缓存 |
小细节:v0.2 里默认开 cache(
use_cache=True),v0.4 默认关。要想缓存得 显式ChatCompletionCache(inner=OpenAIChatCompletionClient(...), store=...)包一层。这是 v0.2 → v0.4 迁移最容易忘的成本变化点。
#7.3 Tool 协议的对齐方式
每家 LLM 的 tool calling 格式各不相同(OpenAI / Anthropic / Gemini / DeepSeek 都 有差异),AutoGen 的策略是:
agent 这边只看 ToolSchema(中性表示)
│
▼
client 实现负责把 ToolSchema 翻译成本家协议
│
▼ 调 LLM
│
▼
client 把本家返回的 tool_calls 翻译回中性的 FunctionCall 列表
所以写 agent 代码完全不用关心后端是哪家模型,client 把这事吸收了。但反过来:
如果你换 client,又用了某家独有的高级特性(比如 Anthropic 的 cache_control),就
得通过 extra_create_args 透传。
#7.4 Reasoning model 的特殊处理
OpenAI o1 / o3、DeepSeek-R1 这类 reasoning model 会输出 <think>...</think>
段或者通过额外字段返回 thinking tokens。v0.4 把这个抽象成 ThoughtEvent:
- agent 收到 thinking tokens → 包成 ThoughtEvent 流式吐出
- 完整 thinking 内容不会默认进 model_context 的下一轮(避免污染)
- UI 端可以选择性显示 thought(Console 默认显示,灰色斜体)
#八、关键设计权衡(架构师视角)
看完前 7 章会有一种"AutoGen 怎么什么都包了"的错觉。其实每个设计都是一次取舍。 以下挑 6 个最关键的,问题 / 回答 / 启发 三段式记下来。
#8.1 Actor model vs ReAct 单进程循环
问题:单 agent 的 ReAct 循环(思考 → 调 tool → 看结果 → 再思考)很经典也很 直觉,为什么 v0.4 一定要把它套上一层 actor model?
回答:单 agent ReAct 在工程上有三个软肋:(1) 不可拆分到多进程;(2) 不可观测, 所有思考步骤都埋在一个函数调用栈里;(3) 不可暂停 / 恢复。actor model 解决全部 三个:每个 agent 是独立 actor,消息是显式 envelope,可以 trace、可以序列化、可以 跨进程。
启发:你自己写 agent 框架的时候,不要从"我有一个 ReAct 循环"开始,而要从 "我有一个消息总线 + 若干消费者"开始。前者是 demo,后者是基础设施。
#8.2 五种 GroupChat selector 为什么要并存?
问题:RoundRobin / Selector / Swarm / Graph / Magentic,从外面看好像可以 互相模拟(比如 Selector 可以模拟 RoundRobin)。为什么不收敛成一种?
回答:因为它们对应了不同的"工程上你愿意付出的代价":
| 模式 | 你给的约束 | 你换来的好处 |
|---|---|---|
| RoundRobin | 你保证流程线性 | 零额外 LLM 调用,可重放 |
| Selector | 你写好 selector_prompt | 灵活但每轮多花一次 LLM |
| Swarm | 你训练/提示 agent 知道 handoff | 完全去中心化,无需 manager |
| Graph | 你画好 DAG | 工程化 / 确定性 |
| Magentic | 你接受一个重型 orchestrator | 通用任务,开箱即用 |
收敛成一种意味着要么强制大家用最弱约束(成本爆炸),要么强制最强约束(不灵活)。 留多种是务实的工程选择。
启发:选 selector 时先问自己一个问题 —— 这个流程的"对错"是先验已知的,还是 需要 runtime 看情况判断的?前者用 RoundRobin / Graph,后者才用 Selector / Magentic。
#8.3 v0.2 → v0.4 迁移最大的一个坑
问题:迁移 v0.2 项目到 v0.4,最容易忽视的破坏性变化是什么?
回答:UserProxyAgent 的角色塌缩。在 v0.2 里 UserProxyAgent 是个"瑞士军刀": 它既负责接收用户输入,又持有 code_execution_config 来执行代码,还经常被当作 "function executor"接收别的 agent 的 tool call。三件事都干。v0.4 把它拆成三个东西:
v0.2 UserProxyAgent = v0.4 UserProxyAgent (只接收用户输入)
+ v0.4 CodeExecutorAgent (跑代码)
+ tools 直接挂在 AssistantAgent 上 (不需要"function executor")
迁移的时候如果只机械替换类名,会发现 "我的 user_proxy 不会跑代码了"、"我的 function 没人执行了"。
启发:迁移老项目时先把 v0.2 用法分类:哪些 UserProxy 是真"代理用户输入", 哪些是"假装用户的代码执行器",哪些是"function 路由器"。三类对应 v0.4 三个不同 组件。
#8.4 Memory 内置实现为什么这么少?
问题:v0.4 内置的 Memory 实现只有 ListMemory + ChromaDBVectorMemory + RedisMemory 寥寥几个,对比 LangChain 的几十个 vectorstore,是不是太弱了?
回答:AutoGen 的设计哲学是"框架不替你做选型"。Memory 是个 protocol,你接什么 向量库都行;如果接得太多反而会绑住框架版本。LangChain 那种"我帮你接好 50 家"的 风格短期看方便,长期看依赖地狱。
启发:评估 multi-agent 框架时不要只看"内置了多少 connector",要看 "我自己 要接一个新 connector 难不难"。AutoGen 的 Memory protocol 实现起来三十行代码就 能搞定,这才是关键指标。
#8.5 SocietyOfMindAgent vs 嵌套 Team:什么时候选哪个?
问题:v0.4 里"团队封装成 agent"有两条路:用 SocietyOfMindAgent 包一个 Team, 或者直接把外层 Team 的某个 agent 实现成"内部跑 sub team"的自定义 agent。两者 等价吗?
回答:不等价。区别在 "内层消息能否被外层消费者看到":
SocietyOfMindAgent:内层 thread 完全封装,外层只看到 model_client 总结的一条 对外消息。适合"实现细节不应暴露"的场景(比如把"内容生产团队"作为黑盒卖给 外部 orchestrator)。- 自定义嵌套 agent:你可以选择把内层每条消息直接转发到外层 stream(绕过 society of mind 的总结环节)。适合"调试期希望看到全过程"或"外层 selector 要根据内 层细节决策"的场景。
启发:抽象层次不是越深越好。每多一层抽象就意味着 (1) 多一次 LLM 总结的成本和 信息损失,(2) 调试时多一层栈。SocietyOfMind 是"信息隐藏的工程化封装",不是"包就 对了"。
#8.6 跟 LangGraph / CrewAI 比,AutoGen 的位置
问题:选 multi-agent 框架时,AutoGen / LangGraph / CrewAI 怎么挑?
回答:一句话总结三家的核心隐喻:
| 框架 | 核心隐喻 | 最适合的场景 |
|---|---|---|
| CrewAI | "公司里的角色分工"(CEO / 经理 / 员工 / 任务) | 角色清晰、流程线性的业务工作流,最低学习成本 |
| LangGraph | "状态机 / DAG"(节点 + 边 + 共享 state) | 工程化、可重放、需要 checkpoint / human-in-the-loop |
| AutoGen | "一群人开会聊天"(actor + message + group chat) | 需要灵活协作、研究型多 agent、跨进程跨语言 |
成本上:AutoGen 因为 GroupChat 模式天然多轮对话,token 花费比 LangGraph 高 (社区数据 5-6 倍量级),但灵活性也是最高的。
启发:如果你的"多 agent"需求其实是"一个 agent + 几个 tool",先别上 AutoGen 这种 框架,直接 OpenAI SDK + tools 就够了。multi-agent 框架要解决的问题,是当你确信 "单 agent 不够"之后才出现的。
#九、附录:包地图、关键概念与源码索引
#9.1 packages 地图(microsoft/autogen 仓库)
microsoft/autogen/
├── python/
│ └── packages/
│ ├── autogen-core/ # ★ actor runtime 底座
│ │ src/autogen_core/
│ │ _agent.py # Agent 抽象
│ │ _agent_runtime.py # AgentRuntime 接口
│ │ _routed_agent.py # @message_handler 装饰器
│ │ _single_threaded_agent_runtime.py
│ │ _topic.py # TopicId / Subscription
│ │ memory/ # Memory protocol
│ │ models/ # ChatCompletionClient 接口
│ │ tools/ # Tool 抽象
│ │
│ ├── autogen-agentchat/ # ★ 高级 Agent + Team
│ │ src/autogen_agentchat/
│ │ agents/ # AssistantAgent / UserProxyAgent /
│ │ # CodeExecutorAgent / SocietyOfMindAgent /
│ │ # MessageFilterAgent
│ │ teams/ # RoundRobinGroupChat / SelectorGroupChat /
│ │ # Swarm / GraphFlow (含 DiGraphBuilder) /
│ │ # MagenticOneGroupChat
│ │ conditions/ # 各种 termination
│ │ messages.py # TextMessage / HandoffMessage / ...
│ │ ui/ # Console
│ │
│ ├── autogen-ext/ # ★ 扩展生态
│ │ src/autogen_ext/
│ │ models/openai/ # OpenAIChatCompletionClient
│ │ models/anthropic/ # AnthropicChatCompletionClient
│ │ models/ollama/ # 本地 Ollama
│ │ code_executors/docker/ # DockerCommandLineCodeExecutor
│ │ code_executors/jupyter/ # JupyterCodeExecutor
│ │ code_executors/azure/ # ACA Dynamic Sessions
│ │ memory/chromadb/ # ChromaDB 向量记忆
│ │ memory/redis/ # Redis 向量记忆
│ │ agents/web_surfer/ # MultimodalWebSurfer
│ │ agents/file_surfer/ # FileSurfer
│ │ agents/magentic_one/ # MagenticOneCoderAgent
│ │ teams/magentic_one/ # MagenticOne 辅助类(编排封装)
│ │ # ※ MagenticOneGroupChat 本体住在
│ │ # autogen_agentchat.teams
│ │ runtimes/grpc/ # 分布式 runtime
│ │ auth/ # azure / 其它认证
│ │
│ ├── autogen-studio/ # no-code UI(FastAPI + React)
│ │ frontend/
│ │ autogenstudio/
│ │
│ ├── autogen-magentic-one/ # 早期 Magentic 单包(已并入 autogen-ext)
│ ├── magentic-one-cli/ # `m1` 命令行
│ ├── agbench/ # benchmarking
│ ├── autogen-test-utils/ # 测试工具
│ ├── component-schema-gen/ # component schema 生成
│ └── pyautogen/ # legacy v0.2 兼容包
│
└── dotnet/ # .NET 实现(cross-language 关键)
└── src/
└── Microsoft.AutoGen/
Core/ # autogen-core 的 .NET 版
AgentChat/ # autogen-agentchat 的 .NET 版
Extensions/ # 扩展
#9.2 关键概念速查
| 概念 | 一句话定义 | 出现章节 |
|---|---|---|
| Agent | 实现了 on_messages 的 actor,名字 + 描述 + 行为 | 一 |
| AgentRuntime | 负责 agent 注册、消息路由、生命周期的运行时 | 二 |
| AssistantAgent | "kitchen sink" agent,LLM + tools + memory | 一 |
| UserProxyAgent | v0.4 简化版,只负责接收用户输入 | 一、八 |
| CodeExecutorAgent | 把 LLM 生成的代码块送进 executor 跑的 agent | 四 |
| SocietyOfMindAgent | 包一个 Team 对外暴露成单 agent,封装内层细节 | 四、八 |
| GroupChat | 共享 message thread 的多 agent 团队 | 三 |
| GroupChatManager | 决定 GroupChat 下一个 speaker 是谁的内部 actor | 二、三 |
| RoutedAgent | autogen-core 里带 @message_handler 路由的 agent 基类 | 二 |
| TopicId / Subscription | 消息总线的 pub-sub 抽象 | 二 |
| HandoffMessage | Swarm 模式里 agent 显式转移控制权的消息类型 | 三 |
| TerminationCondition | 决定 team.run() 何时停的条件,可组合 | 一 |
| CodeExecutor | 代码执行抽象,Local / Docker / Jupyter / ACA 四种实现 | 四 |
| Memory | 长期记忆 protocol(add / query / update_context) | 五 |
| ChatCompletionContext | 模型上下文窗口策略(unbounded / buffered / token-limited) | 五 |
| ChatCompletionClient | LLM 客户端接口,所有模型对接的统一抽象 | 七 |
| ComponentBase | 让组件能 dump 成 dict / 从 dict 重建的 mixin(Studio 基础) | 六 |
| Magentic Orchestrator | Magentic-One 的领导 agent,维护 Task / Progress Ledger | 三 |
#9.3 跟其它框架的术语映射
| AutoGen v0.4 | LangGraph | CrewAI | OpenAI Swarm |
|---|---|---|---|
| AssistantAgent | Node (LLM with tools) | Agent | Agent |
| Team / GroupChat | Graph | Crew | Swarm |
| RoundRobinGroupChat | Sequential Graph | Sequential Process | — |
| SelectorGroupChat | Conditional Graph | Hierarchical Process | — |
| Swarm | Conditional Graph + handoff | — | Swarm (本体) |
| GraphFlow | Graph (本体) | — | — |
| TerminationCondition | END node + condition | — | — |
| Memory | Checkpointer + memory store | Knowledge | — |
| AutoGen Studio | LangGraph Studio | CrewAI UI | — |
#9.4 跟 v0.2 的关键差异速查
| 主题 | v0.2 | v0.4 |
|---|---|---|
| 默认编程模型 | 同步 send/reply | 异步 actor + message |
| 配置模型 | llm_config dict |
model_client 对象 |
| 工具注册 | register_function(executor=…, caller=…) |
直接 AssistantAgent(tools=[...]) |
| GroupChat 编排 | GroupChat + GroupChatManager | RoundRobin/Selector/Swarm/Graph/Magentic |
| 用户输入 | UserProxyAgent (复杂) | UserProxyAgent (只输入) |
| 代码执行 | UserProxyAgent.code_execution_config | CodeExecutorAgent + CodeExecutor 接口 |
| 缓存 | 默认开(DiskCache) | 默认关(ChatCompletionCache 包一层) |
| RAG / Teachability | 内置 Teachability | 用户自己实现 Memory protocol |
| 状态保存 | 不支持 | save_state / load_state |
| 跨进程 / 跨语言 | 无 | GrpcWorkerAgentRuntime + .NET |
| 可观测性 | print + logger | OpenTelemetry tracing + 流式事件 |
#9.5 一句话总结
AutoGen v0.4 = "把 v0.2 的对话 multi-agent 体验,重写在一个 actor model 底座 上,再补全跨进程 / 跨语言 / 可观测 / 可序列化"。 它的最佳形态是
autogen-agentchat这一层(90% 用户的入口),底下的autogen-core是给少数 需要自己实现 runtime / 跨语言协作的人准备的。Magentic-One 是它在 "通用 agent 团队" 这个 demo 命题上的招牌答案,但你自己用 SelectorGroupChat 也能写出同样 形状的东西。
#9.6 进一步阅读
- AutoGen v0.4 reimagined 公告(DevBlog)
- AutoGen v0.4 官方文档(stable)
- Migration Guide v0.2 → v0.4
- Magentic-One 论文(arXiv 2411.04468)
- Distributed Agent Runtime 教程
- AutoGen Studio 介绍
- Microsoft Research: AutoGen v0.4 Reimagining the Foundation
2026-06-08 复核补充:当前包版本为 autogen-agentchat@0.7.5 / autogen-core@0.7.5,
GitHub release 为 python-v0.7.5。旧文中"v0.4 当前主线"应理解为架构代际,不是当前包号。