🔬 AutoGen 深度源码分析

Microsoft Research | v0.5.x AgentChat + Core | 双层架构:Actor Model Runtime + 高级 AgentChat 抽象

多 Agent 协作
Actor Model
群组编排
Handoff 机制
工具系统
代码执行沙箱

1. 架构总览

AutoGen 采用 双层架构:底层是 autogen-core 基于 Actor Model 的异步消息运行时,上层是 autogen-agentchat 提供高级 Chat Agent 抽象。这种设计让核心运行时可以独立于聊天场景使用(如分布式 Agent 系统),同时 Chat 层为常见对话模式提供便捷 API。

┌─────────────────────────────────────────────────────────────────────┐ │ autogen-agentchat (高层) │ │ ┌───────────┐ ┌──────────────┐ ┌──────────────────────────────┐ │ │ │Assistant │ │UserProxy │ │GroupChat Teams │ │ │ │Agent │ │Agent │ │ ┌────────┐ ┌─────────────┐ │ │ │ └─────┬─────┘ └──────┬───────┘ │ │RoundRobin│SelectorGroup│ │ │ │ │ │ │ │ Chat │ Chat │ │ │ │ └───────┬───────┘ │ └────────┘ └─────────────┘ │ │ │ │ │ ┌────────┐ ┌─────────────┐ │ │ │ BaseChatAgent │ │ Swarm │ DiGraph │ │ │ │ │ │ │ │ GroupChat │ │ │ │ │ │ └────────┘ └─────────────┘ │ │ │ │ │ ┌──────────────────────────┐ │ │ │ │ │ │ MagenticOne (Ledger编排) │ │ │ │ │ │ └──────────────────────────┘ │ │ │ │ └──────────────────────────────┘ │ ├────────────────┼────────────────────────────────────────────────────┤ │ ▼ autogen-core (底层) │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ SingleThreadedAgentRuntime │ │ │ │ ┌─────────┐ ┌───────────┐ ┌──────────────┐ │ │ │ │ │AgentId │ │TopicId │ │Subscription │ │ │ │ │ │(路由) │ │(发布/订阅) │ │Manager │ │ │ │ │ └─────────┘ └───────────┘ └──────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ Message Queue → Handler → Agent.on_message() │ │ │ │ │ │ RPC (点对点) | Event (发布/订阅) │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ ┌──────────────┐ ┌───────────────┐ ┌──────────────────────┐ │ │ │ Model Context │ │ Memory │ │ Tools / Workbench │ │ │ │ (ChatHistory) │ │ (ListMemory) │ │ (FunctionTool etc.) │ │ │ └──────────────┘ └───────────────┘ └──────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘

📦 包结构


2. Core Runtime — Actor Model

AutoGen Core 实现了一个 Actor Model 风格 的消息运行时。每个 Agent 是一个 Actor,通过 AgentId 唯一标识,通过两种通信模式交互:

📨 RPC (点对点)

runtime.send_message(message, recipient) — 发送消息给特定 Agent,等待返回值。内部使用 asyncio.Future 实现请求-响应。

📢 Event (发布/订阅)

runtime.publish_message(message, topic_id) — 发布到 Topic,所有订阅该 Topic 的 Agent 都会收到。通过 SubscriptionManager 管理路由。

2.1 Agent Protocol

# autogen_core/_agent.py — 核心协议
@runtime_checkable
class Agent(Protocol):
    @property
    def metadata(self) -> AgentMetadata: ...
    @property
    def id(self) -> AgentId: ...

    async def on_message(self, message: Any, ctx: MessageContext) -> Any:
        """消息处理器 — Runtime 调用,非 Agent 间直接调用"""
        ...

    async def save_state(self) -> Mapping[str, Any]: ...
    async def load_state(self, state: Mapping[str, Any]) -> None: ...

2.2 SingleThreadedAgentRuntime

核心运行时实现。维护消息队列、订阅关系、Agent 实例池:

SingleThreadedAgentRuntime │ ├── _message_queue: Queue[MessageEnvelope] │ ├── PublishMessageEnvelope (topic-based broadcast) │ └── SendMessageEnvelope (point-to-point with Future) │ ├── _subscription_manager: SubscriptionManager │ ├── map_handler_to_subscriptions() │ └── get_subscriptions() → 匹配 Topic → AgentId │ ├── _agent_instances: Dict[AgentId, Agent] │ ├── send_message(msg, recipient) → await Future └── publish_message(msg, topic_id) → enqueue to queue └── _process_message() → route to handler
关键设计:Core 层的 Agent 完全不关心"聊天"语义。它只知道消息路由和订阅。Chat 语义全部由上层 autogen-agentchat 定义。

3. AgentChat 层 — Chat 语义抽象

AgentChat 在 Core 之上定义了 ChatAgent 协议和 Team 协议,构建完整的对话系统:

# autogen_agentchat/base/_chat_agent.py
class ChatAgent(Protocol):
    @property
    def name(self) -> str: ...       # 唯一标识
    @property
    def description(self) -> str: ... # 供 Team 选择参考

    @property
    def produced_message_types(self) -> Sequence[type[BaseChatMessage]]: ...

    async def on_messages(self, messages, cancellation_token) -> Response: ...
    async def on_reset(self, cancellation_token) -> None: ...

# autogen_agentchat/base/_team.py
class Team(Protocol):
    async def run(self, *, task, cancellation_token) -> TaskResult: ...
    async def run_stream(self, *, task, cancellation_token) -> AsyncGenerator: ...
    async def reset(self) -> None: ...
    async def save_state(self) -> Mapping: ...
    async def load_state(self, state) -> None: ...

3.1 BaseChatAgent — 所有 Chat Agent 的基类

实现了 run() / run_stream() 的默认逻辑,子类只需实现 on_messages()on_messages_stream()

class BaseChatAgent(ChatAgent, ABC, ComponentBase[BaseModel]):
    async def run(self, *, task, cancellation_token=None) -> TaskResult:
        # 1. 将 task 转换为 input_messages (TextMessage)
        # 2. 调用 on_messages(input_messages, token)
        # 3. 收集 inner_messages + chat_message → TaskResult

    async def run_stream(self, *, task, cancellation_token=None):
        # 1. 同上转换 task
        # 2. 调用 on_messages_stream,逐个 yield 事件
        # 3. 最后 yield TaskResult
状态管理原则:Agent 是有状态的 — 每次调用 on_messages 只传入新消息,Agent 内部维护历史。调用方不应传入完整对话历史。

4. Agent 体系

BaseChatAgent (抽象基类) │ ├── AssistantAgent — LLM + Tools + Handoffs (核心) ├── UserProxyAgent — 人类输入代理 ├── CodeExecutorAgent — 代码生成+执行+反思 ├── SocietyOfMindAgent — 内嵌 Team 的子 Agent └── MessageFilterAgent — 消息过滤包装器

4.1 AssistantAgent — 核心 Agent

这是 AutoGen v0.5 的核心 Agent 实现,集成了 LLM 推理、工具调用、Handoff 和结构化输出。

初始化参数一览

参数类型说明
model_clientChatCompletionClientLLM 推理客户端 (必须)
toolsList[BaseTool | Callable]工具列表,自动包装为 FunctionTool
workbenchWorkbench | Sequence工具工作台 (与 tools 互斥)
handoffsList[Handoff | str]Handoff 配置,用于 Swarm 切换
model_contextChatCompletionContext对话上下文管理器
memorySequence[Memory]长期记忆存储
system_messagestr | None系统提示词
reflect_on_tool_usebool工具调用后是否反思
max_tool_iterationsint最大工具迭代轮数 (默认1)
output_content_typetype[BaseModel]结构化输出类型
model_client_streambool是否启用流式输出

on_messages_stream 执行流程

AssistantAgent.on_messages_stream(messages, token) │ ├── Step 1: _add_messages_to_context() │ └── 将新消息加入 model_context (含 HandoffMessage.context 展开) │ ├── Step 2: _update_model_context_with_memory() │ └── 遍历 memory 列表 → mem.update_context() → MemoryQueryEvent │ ├── Step 3: _call_llm() → 首次模型推理 │ ├── 构建 llm_messages = system_messages + model_context │ ├── 收集 tools = workbench.tools + handoff_tools │ └── model_client.create() / create_stream() │ ├── Step 4: 处理模型输出 (_process_model_result) │ ├── 如果 content 是 str → 直接返回 TextMessage / StructuredMessage │ ├── 如果 content 是 List[FunctionCall] → 工具调用循环: │ │ ├── yield ToolCallRequestEvent │ │ ├── _execute_tool_call() → 并发执行所有工具 │ │ │ ├── 检查是否 handoff tool → 执行 handoff │ │ │ └── 否则在 workbench 中查找并执行 │ │ ├── yield ToolCallExecutionEvent │ │ ├── _check_and_handle_handoff() → 如果有 Handoff │ │ ├── 循环: 如果 max_tool_iterations > 1 → 再次 _call_llm │ │ └── 循环结束 → 反思或摘要 │ │ │ ├── reflect_on_tool_use=True → _reflect_on_tool_use_flow() │ │ └── 再次推理 (tool_choice="none") → TextMessage │ └── reflect_on_tool_use=False → _summarize_tool_use() │ └── 格式化工具结果 → ToolCallSummaryMessage │ └── yield Response(chat_message, inner_messages)

工具调用循环详解

max_tool_iterations 控制顺序工具调用轮次:

# 伪代码:工具调用循环
for loop_iteration in range(max_tool_iterations):
    if isinstance(model_result.content, str):
        return text_response  # 模型返回文本,结束

    # 模型返回 FunctionCall 列表
    results = await asyncio.gather(*[execute_tool(call) for call in calls])

    if has_handoff(results):
        return HandoffMessage  # Handoff 优先

    if loop_iteration < max_tool_iterations - 1:
        model_result = await call_llm()  # 继续循环
⚠ 并发工具调用:同一轮中的多个工具调用通过 asyncio.gather 并发执行。如需禁用,需在模型客户端配置 parallel_tool_calls=False

4.2 UserProxyAgent — 人类输入代理

通过 input_func 获取人类输入。支持同步/异步函数、CancellationToken 超时取消:

class UserProxyAgent(BaseChatAgent):
    def __init__(self, name, *, input_func=None):
        self.input_func = input_func or cancellable_input  # 默认 stdin

    async def on_messages_stream(self, messages, cancellation_token):
        # 1. 检查是否有 HandoffMessage → 构建提示
        # 2. yield UserInputRequestedEvent
        # 3. await input_func(prompt, cancellation_token)
        # 4. 返回 TextMessage 或 HandoffMessage
InputRequestContext:通过 ContextVar 在输入回调中注入请求 ID,允许 UI 框架关联请求与响应。

4.3 CodeExecutorAgent — 代码执行 Agent

两种模式:被动模式(仅执行收到的代码块)和主动模式(带 model_client 生成+执行+反思):

class CodeExecutorAgent(BaseChatAgent):
    async def on_messages_stream(self, messages, cancellation_token):
        if model_client is None:
            # 被动模式:从消息中提取代码块执行
            code_blocks = extract_code_blocks(messages)
            result = await execute_code_block(code_blocks)
            return TextMessage(content=result.output)

        # 主动模式:生成 → 执行 → 反思循环
        for nth_try in range(max_retries + 1):
            model_result = await call_llm()
            code_blocks = extract_markdown_code_blocks(model_result)
            if not code_blocks:
                return TextMessage(content=model_result)
            yield CodeGenerationEvent(...)
            result = await execute_code_block(code_blocks)

            if result.exit_code == 0:
                break  # 成功

            # 结构化输出决定是否重试
            retry_decision = await model_client.create(json_output=RetryDecision)
            if not retry_decision.retry:
                break

        # 最终反思
        reflection = await reflect_on_code_results()

🔒 安全机制


5. 消息系统

AutoGen 定义了丰富的消息类型层次,分为 ChatMessage(Agent 间通信)和 AgentEvent(可观测事件):

BaseMessage (抽象) ├── BaseChatMessage (Agent 间通信,会被 Team 转发) │ ├── TextMessage — 文本消息 │ ├── HandoffMessage — Agent 切换 (Swarm 核心) │ ├── ToolCallSummaryMessage — 工具调用摘要 │ ├── StructuredMessage[T] — 结构化输出 (Pydantic) │ ├── MultiModalMessage — 多模态 (文本+图片) │ ├── StopMessage — 停止信号 │ └── (用户自定义子类) │ └── BaseAgentEvent (可观测事件,不转发) ├── ToolCallRequestEvent — 工具调用请求 ├── ToolCallExecutionEvent — 工具调用结果 ├── MemoryQueryEvent — 记忆查询 ├── ThoughtEvent — 思维链 (reasoning model) ├── UserInputRequestedEvent — 用户输入请求 ├── CodeGenerationEvent — 代码生成 ├── CodeExecutionEvent — 代码执行 ├── ModelClientStreamingChunkEvent — 流式 token └── SelectorEvent — Speaker 选择事件

关键消息类型

HandoffMessage — Agent 切换的核心

class HandoffMessage(BaseChatMessage):
    target: str              # 目标 Agent 名称
    context: List[LLMMessage] = []  # 附带的 LLM 上下文

    def to_model_message(self) -> UserMessage:
        return UserMessage(content=self.content, source=self.source)
HandoffMessage.context 字段允许在 Agent 切换时传递 LLM 级别的上下文(工具调用+结果),这是 Swarm 编排的关键:新 Agent 可以看到前一个 Agent 的工具调用历史。

StructuredMessage — 类型安全的输出

class StructuredMessage(BaseChatMessage, Generic[T]):
    content: T  # Pydantic BaseModel 实例

    def to_model_text(self) -> str:
        return self.content.model_dump_json()

6. 工具系统

AutoGen 的工具系统基于 Pydantic 模型自动生成 JSON Schema,支持函数工具和 Workbench 抽象:

Tool (Protocol) │ ├── BaseTool[ArgsT, ReturnT] (抽象) │ ├── schema → ToolSchema (自动从 Pydantic 生成) │ ├── run_json(args, token) → Any │ └── FunctionTool — 包装 Python 函数 │ ├── 自动从函数签名生成 args_model (Pydantic BaseModel) │ ├── 支持 sync/async 函数 │ ├── 支持 CancellationToken 参数注入 │ └── 支持序列化/反序列化 (source_code + imports) │ ├── BaseStreamTool[ArgsT, StreamT, ReturnT] │ └── 流式工具输出 │ └── BaseToolWithState[ArgsT, ReturnT, StateT] └── 有状态工具 (save/load_state)

6.1 FunctionTool — 自动 Schema 生成

class FunctionTool(BaseTool[BaseModel, BaseModel]):
    def __init__(self, func, description, name=None, strict=False):
        self._signature = get_typed_signature(func)
        # 自动生成 Pydantic 参数模型
        args_model = args_base_model_from_signature(
            func_name + "args", self._signature
        )
        super().__init__(args_model, return_type, name, description, strict)

    async def run(self, args: BaseModel, cancellation_token) -> Any:
        kwargs = {name: getattr(args, name) for name in self._signature.parameters}
        if asyncio.iscoroutinefunction(self._func):
            return await self._func(**kwargs)
        else:
            return await run_in_executor(self._func, **kwargs)

🔧 Schema 生成流程

  1. get_typed_signature(func) — 解析函数签名和类型注解
  2. args_base_model_from_signature() — 转换为 Pydantic BaseModel
  3. BaseTool.schema — 调用 args_model.model_json_schema() 生成 JSON Schema
  4. 支持 Annotated[type, "description"] 为参数添加描述
  5. strict=True 模式:所有参数必须 required,不允许 additionalProperties

6.2 Workbench — 工具容器抽象

Workbench 是工具的容器接口,提供统一的工具列表和调用 API:

class Workbench(Protocol):
    async def list_tools(self) -> List[ToolSchema]: ...
    async def call_tool(self, name, args, token, call_id) -> ToolResult: ...
    async def call_tool_stream(self, name, args, token, call_id) -> AsyncGenerator: ...

# StaticStreamWorkbench — 包装静态工具列表
# McpWorkbench — 连接 MCP 服务器动态获取工具
tools vs workbench 互斥:AssistantAgent 中传入 tools 时内部创建 StaticStreamWorkbench,传入 workbench 时直接使用。两者不能同时设置。

7. 群组编排 — Teams

AutoGen 提供 5 种群组编排模式,每种由 BaseGroupChat + 对应的 GroupChatManager 组成:

BaseGroupChat (Team) │ 内部创建 GroupChatManager 并注册到 Runtime │ Manager 通过 Topic 订阅管理参与者 │ ├── RoundRobinGroupChat — 轮流发言 ├── SelectorGroupChat — LLM/自定义函数选择下一个发言者 ├── Swarm — 基于 Handoff 的动态切换 ├── DiGraphGroupChat — DAG 图执行 (实验性) └── MagenticOneGroupChat — Ledger 编排 (论文实现)

7.1 BaseGroupChatManager — 群组管理基类

class BaseGroupChatManager(BaseAgent):
    async def _process_messages(self, messages):
        # 1. 验证消息
        await self.validate_group_state(messages)
        # 2. 更新消息线程
        await self.update_message_thread(messages)
        # 3. 检查终止条件
        if await self._check_termination(messages):
            return
        # 4. 选择下一个发言者
        speaker = await self.select_speaker(self._message_thread)
        # 5. 路由消息给选中的 Agent
        await self._route_message(speaker, messages)

7.2 RoundRobinGroupChat — 简单轮转

class RoundRobinGroupChatManager(BaseGroupChatManager):
    async def select_speaker(self, thread):
        current = self._next_speaker_index
        self._next_speaker_index = (current + 1) % len(self._participant_names)
        return self._participant_names[current]

最简单的编排:按参与者顺序轮流。支持嵌套 Team(Team 作为参与者)。

7.3 SelectorGroupChat — LLM 选择发言者

SelectorGroupChat.select_speaker() │ ├── 1. 如果 selector_func 存在且返回非 None → 使用其结果 │ (selector_func 可以是 sync/async,覆盖模型选择) │ ├── 2. 如果 candidate_func 存在 → 过滤候选者 │ ├── 3. 否则: 移除上一个发言者 (如果 allow_repeated_speaker=False) │ └── 4. 构建选择 Prompt: ┌──────────────────────────────────────────┐ │ "You are in a role play game. │ │ The following roles are available: │ │ {roles} │ │ Read the following conversation. │ │ Then select the next role from │ │ {participants} to play. │ │ {history} │ │ Only return the role." │ └──────────────────────────────────────────┘ → model_client.create() → 提取 Agent 名称 → max_selector_attempts 次重试

💡 设计亮点

7.4 Swarm — Handoff 驱动

Swarm 编排完全基于 HandoffMessage,不需要中央选择器:

class SwarmGroupChatManager(BaseGroupChatManager):
    async def select_speaker(self, thread):
        # 反向查找最近的 HandoffMessage
        for message in reversed(thread):
            if isinstance(message, HandoffMessage):
                self._current_speaker = message.target
                return [self._current_speaker]
        return self._current_speaker  # 默认继续当前 Agent
Swarm 设计哲学:发言者选择权下放给 Agent 自身。Agent 通过 Handoff 工具声明"我应该切换到谁",而非由外部选择器决定。这让 Agent 具有自主路由能力。

7.5 MagenticOne — Ledger 编排

MagenticOne 实现了论文 "Magentic-One: A Generalist Multi-Agent System for Solving Complex Tasks" 的编排策略:

MagenticOneOrchestrator │ ├── Task Ledger (任务账本) │ ├── Facts — 已知事实 │ └── Plan — 执行计划 (步骤列表) │ ├── Progress Ledger (进度账本) │ ├── is_request_completed? │ ├── is_in_progress? │ ├── is_step_complete? │ ├── next_speaker │ └── instruction_to_next_speaker │ └── 编排循环: 1. 初始化: 构建 Task Ledger (facts + plan) 2. 每轮: a. 更新 Facts Ledger (基于新消息) b. 更新 Plan Ledger (基于新事实) c. 查询 Progress Ledger → 确定 next_speaker + instruction d. 路由消息给 next_speaker e. 检查 stall → 如果连续 stall >= max_stalls → 重新规划 f. 检查完成 → 如果 is_request_completed → 生成最终答案
# MagenticOne 进度账本结构 (内部使用 LLM 结构化输出)
class LedgerEntry(BaseModel):
    is_request_completed: bool
    is_in_progress: bool
    is_step_complete: bool
    next_speaker: str | None
    instruction_to_next_speaker: str | None

7.6 DiGraphGroupChat — DAG 图执行 (实验性)

基于有向图 (DAG) 的编排,支持条件边和循环:

class DiGraphEdge(BaseModel):
    target: str
    condition: str | Callable | None  # 条件执行
    activation_group: str = ""       # 前向依赖分组
    activation_condition: Literal["all", "any"] = "all"

class DiGraphNode(BaseModel):
    name: str
    edges: List[DiGraphEdge]  # 出边

# 示例: A → B → C, B 可循环回 A
graph = DiGraph(nodes={
    "A": DiGraphNode(name="A", edges=[DiGraphEdge(target="B")]),
    "B": DiGraphNode(name="B", edges=[
        DiGraphEdge(target="C", condition="exit"),
        DiGraphEdge(target="A", condition="loop"),
    ]),
    "C": DiGraphNode(name="C", edges=[]),
})

8. Handoff 机制 — 深度解析

Handoff 是 AutoGen v0.5 的核心创新之一,它将 Agent 切换建模为工具调用

class Handoff(BaseModel):
    target: str          # 目标 Agent 名称
    description: str     # 自动生成: "Handoff to {target}."
    name: str            # 自动生成: "transfer_to_{target}"
    message: str         # 自动生成: "Transferred to {target}..."

    @property
    def handoff_tool(self) -> BaseTool:
        def _handoff_tool() -> str:
            return self.message
        return FunctionTool(_handoff_tool, name=self.name,
                           description=self.description, strict=True)
Handoff 执行流程: │ ├── 1. 注册阶段 (AssistantAgent.__init__) │ handoffs=["Bob"] → │ Handoff(target="Bob") → │ handoff_tool = FunctionTool(name="transfer_to_bob") │ self._handoff_tools.append(handoff_tool) │ self._handoffs["transfer_to_bob"] = Handoff(...) │ ├── 2. 推理阶段 (_call_llm) │ tools = [...normal_tools] + handoff_tools │ → 模型看到的工具列表包含 "transfer_to_bob" │ ├── 3. 执行阶段 (_process_model_result) │ 如果模型返回 FunctionCall(name="transfer_to_bob"): │ │ │ ├── 执行 handoff_tool → 返回 message 字符串 │ ├── _check_and_handle_handoff(): │ │ ├── 收集非 handoff 的工具调用+结果 → handoff_context │ │ └── 返回 HandoffMessage( │ │ target="Bob", │ │ context=[AssistantMessage(tool_calls), │ │ FunctionExecutionResultMessage(results)] │ │ ) │ │ │ └── Swarm Manager 收到 HandoffMessage: │ → select_speaker() → 选中 "Bob" │ → Bob.on_messages() 接收 HandoffMessage │ → 展开 context 到 Bob 的 model_context

🎯 Handoff vs 传统选择器

维度传统选择器 (SelectorGroupChat)Handoff (Swarm)
决策者外部 LLM/函数Agent 自身
上下文传递完整消息历史精确的 context 字段
灵活性低 (固定选择逻辑)高 (Agent 自主路由)
可预测性高 (确定性函数可覆盖)低 (依赖 LLM 决策)
适用场景固定角色轮转动态任务分发

9. 嵌套 Agent — SocietyOfMind

SocietyOfMindAgent 将一个 Team 包装为单个 Agent,实现嵌套对话:

class SocietyOfMindAgent(BaseChatAgent):
    def __init__(self, name, team, model_client, *,
                 instruction=DEFAULT_INSTRUCTION,
                 response_prompt=DEFAULT_RESPONSE_PROMPT):
        self._team = team
        self._model_client = model_client

    async def on_messages_stream(self, messages, cancellation_token):
        # 1. 运行内嵌 Team
        async for msg in self._team.run_stream(task=messages):
            if isinstance(msg, TaskResult):
                result = msg
            else:
                yield msg  # 透传内部事件

        # 2. 用 LLM 生成总结响应
        llm_messages = [
            SystemMessage(self._instruction),  # "Earlier you were asked..."
            *[msg.to_model_message() for msg in inner_messages],
            SystemMessage(self._response_prompt),  # "Output standalone response..."
        ]
        completion = await self._model_client.create(messages=llm_messages)

        # 3. 重置内嵌 Team
        await self._team.reset()

        yield Response(chat_message=TextMessage(content=completion.content))
外层 Team: RoundRobinGroupChat │ ├── SocietyOfMindAgent("writer_team") │ └── 内层 Team: RoundRobinGroupChat │ ├── Writer Agent │ └── Reviewer Agent │ → 内部完成多轮写作-审稿 │ → SocietyOfMind 总结输出 │ └── Translator Agent → 接收 SocietyOfMind 的总结,翻译
SocietyOfMind 的两层压缩:(1) 内层 Team 的多轮对话压缩为单条响应;(2) 外层 Team 只看到总结,不感知内部细节。这是信息隐藏在多 Agent 系统中的经典应用。

10. 代码执行沙箱

AutoGen 的代码执行架构分为 Core 层执行器接口AgentChat 层 Agent 封装

autogen-core: CodeExecutor (接口) │ ├── CodeBlock(code, language) — 代码块 ├── CodeResult(exit_code, output) — 执行结果 │ └── 实现类 (在 autogen-ext 中): ├── DockerCommandLineCodeExecutor — Docker 容器执行 ├── LocalCommandLineCodeExecutor — 本地执行 (危险) └── (自定义实现) autogen-agentchat: CodeExecutorAgent │ ├── 被动模式 (无 model_client): │ └── 从消息提取代码块 → 执行 → 返回输出 │ ├── 主动模式 (有 model_client): │ └── 生成代码 → 执行 → 反思 → 可能重试 → 最终反思 │ └── 安全机制: ├── approval_func — 执行前审批 ├── supported_languages — 语言白名单 └── sources — Agent 来源白名单

主动模式执行流程

for nth_try in range(max_retries + 1):
    # 1. LLM 生成代码
    model_result = await model_client.create(messages)
    code_blocks = extract_markdown_code_blocks(model_result)

    if not code_blocks:
        return model_result  # 纯文本,无代码

    # 2. 执行代码 (可被 approval_func 拦截)
    result = await execute_code_block(code_blocks)

    if result.exit_code == 0:
        break  # 成功

    # 3. 错误时:LLM 决定是否重试
    retry_decision = await model_client.create(
        json_output=RetryDecision,  # {retry: bool, reason: str}
    )
    if not retry_decision.retry:
        break

# 4. 最终反思
reflection = await model_client.create(messages + [execution_result])

11. 上下文与记忆系统

11.1 Model Context — 对话上下文

ChatCompletionContext 管理 Agent 的 LLM 消息历史:

ChatCompletionContext (抽象) │ ├── UnboundedChatCompletionContext — 无限制 (默认) ├── BufferedChatCompletionContext — 保留最近 N 条 ├── TokenLimitedChatCompletionContext — Token 数限制 ├── HeadAndTailChatCompletionContext — 保留头部+尾部 │ └── 自定义实现 (如 ReasoningModelContext 过滤 thought)
# 自定义 Context 示例:过滤推理模型的 thought 字段
class ReasoningModelContext(UnboundedChatCompletionContext):
    async def get_messages(self) -> List[LLMMessage]:
        messages = await super().get_messages()
        for message in messages:
            if isinstance(message, AssistantMessage):
                message.thought = None  # 移除冗长的推理过程
        return messages

11.2 Memory — 长期记忆

Memory 是独立于对话上下文的长期存储,通过 update_context 注入到 model_context:

class Memory(ABC):
    async def update_context(self, model_context) -> UpdateContextResult:
        """根据当前 model_context 查询相关记忆,注入到 context"""
        ...

    async def query(self, query, cancellation_token) -> MemoryQueryResult: ...
    async def add(self, content, cancellation_token) -> None: ...
    async def clear(self) -> None: ...
AssistantAgent 记忆注入流程: │ ├── 1. _update_model_context_with_memory() │ for mem in self._memory: │ result = await mem.update_context(model_context) │ → Memory 内部: │ 1. 分析当前 model_context 内容 │ 2. 检索相关记忆条目 │ 3. 将记忆作为 SystemMessage/UserMessage 注入 │ ├── 2. yield MemoryQueryEvent │ → 通知外部:哪些记忆被注入了 │ └── 3. 后续 _call_llm 使用增强后的 model_context → 模型看到的上下文包含记忆内容

📝 ListMemory 实现

最简单的 Memory 实现 — 有序列表,每次 update_context 将所有内容注入:

class ListMemory(Memory):
    def __init__(self, name="ListMemory"):
        self._content: List[MemoryContent] = []

    async def update_context(self, model_context):
        for content in self._content:
            await model_context.add_message(
                SystemMessage(content=content.content)
            )
        return UpdateContextResult(memories=MemoryQueryResult(results=self._content))

    async def add(self, content): self._content.append(content)

12. 终止条件

AutoGen 提供丰富的终止条件,支持 组合 (| 运算符)

终止条件触发条件典型用法
MaxMessageTermination消息数达到上限防止无限循环
TextMentionTermination消息包含特定文本"TERMINATE" 信号
StopMessageTermination收到 StopMessageAgent 主动停止
HandoffTerminationHandoff 到特定 Agent人类介入
SourceMatchTermination特定 Agent 发言等待结果
TextMessageTermination特定 Agent 发 TextMessage等待文本回复
TimeoutTermination超时防止长时间运行
ExternalTermination外部调用 set()程序控制停止
TokenUsageTerminationToken 用量超限成本控制
# 组合终止条件
termination = (
    HandoffTermination(target="user") |  # Handoff 到人类
    MaxMessageTermination(10) |           # 最多 10 条消息
    TimeoutTermination(60)                # 60 秒超时
)

13. 对比分析:AutoGen vs CrewAI vs MetaGPT vs LangGraph

🏗️ 架构范式

AutoGen:Actor Model Runtime + Chat 抽象双层

CrewAI:Process-driven 编排 + Flow 装饰器

MetaGPT:SOP Watch-Publish 消息总线

LangGraph:State Graph + Pregel 执行引擎

🔄 编排模式

AutoGen:5 种 (RoundRobin/Selector/Swarm/DiGraph/MagenticOne)

CrewAI:3 种 (Sequential/Hierarchical/Custom Process)

MetaGPT:SOP 流水线 + Action 组合

LangGraph:任意 StateGraph (节点+边+条件)

🔀 Agent 切换

AutoGen:Handoff (工具调用建模) + Selector (LLM 选择)

CrewAI:Manager Agent 分配任务

MetaGPT:SOP 顺序执行

LangGraph:条件边 + Command/Send

🧠 上下文管理

AutoGen:ChatCompletionContext (多种策略) + Memory

CrewAI:统一 Memory (短期+长期+实体)

MetaGPT:Environment 共享 + ActionNode

LangGraph:State + Checkpoint + Memory

🔧 工具系统

AutoGen:FunctionTool (自动 Schema) + Workbench + MCP

CrewAI:@tool 装饰器 + BaseTool

MetaGPT:Action 基类 + BM25+LLM 工具推荐

LangGraph:@tool 装饰器 + ToolNode

📦 嵌套 Agent

AutoGen:SocietyOfMindAgent (Team→Agent)

CrewAI:Crew 嵌套 (Task→Crew)

MetaGPT:Team 内嵌 Team

LangGraph:Subgraph (编译后作为节点)

💾 状态持久化

AutoGen:save_state/load_state (Agent+Team)

CrewAI:Memory 持久化 + Kickoff 缓存

MetaGPT:Experience Pool (语义缓存)

LangGraph:Checkpoint (Time Travel)

🧪 代码执行

AutoGen:CodeExecutorAgent + Docker 沙箱 + 审批

CrewAI:CodeInterpreterTool

MetaGPT:WriteCode Action + 运行验证

LangGraph:PythonREPL Tool

关键差异总结

🏆 AutoGen 的独特优势

  1. Handoff 机制 — 将 Agent 切换建模为工具调用,是所有框架中最优雅的设计。Agent 自主决定路由,context 传递精确。
  2. Actor Model 底层 — Core Runtime 独立于 Chat 语义,可构建分布式 Agent 系统(gRPC Worker 等)。
  3. 5 种编排模式 — 最丰富的选择:从简单轮转到论文级 MagenticOne。
  4. Workbench 抽象 — MCP 协议支持,动态工具发现。
  5. MessageFilterAgent — 唯一提供消息过滤的包装器,解决多 Agent 环境下的信息过载。

⚠️ AutoGen 的不足

  1. API 不稳定 — v0.2 → v0.4 → v0.5 经历了多次破坏性重构,老代码无法迁移。
  2. 调试困难 — Actor Model 的异步消息流难以追踪,Team 内部消息路由不透明。
  3. Handoff 仅限 Swarm — HandoffMessage 只在 Swarm Team 中生效,其他 Team 忽略。
  4. Memory 基础 — 仅提供 ListMemory,缺少向量检索、语义记忆等高级实现。
  5. 序列化限制 — selector_func、tool_call_summary_formatter 等回调无法序列化。

📊 框架选型建议

场景推荐理由
研究/实验AutoGen5 种编排模式 + MagenticOne 论文实现
动态任务分发AutoGen (Swarm)Handoff 自主路由,最灵活
生产流水线CrewAIFlow 装饰器 + Process 驱动,更稳定
复杂状态机LangGraphStateGraph + Checkpoint,最强控制
软件工程 SOPMetaGPTPRD→设计→代码 流水线最成熟
分布式 AgentAutoGen (Core)唯一支持 gRPC 分布式运行时

14. 核心设计模式提炼

🎭 Pattern 1: Agent-as-Tool

Handoff 将 Agent 切换建模为工具调用。LLM 看到 transfer_to_bob 工具,选择调用即触发切换。这是 Tool-Use Pattern 的高阶应用:不是调用函数,而是"调用另一个 Agent"。

📦 Pattern 2: Team-as-Agent

SocietyOfMindAgent 将 Team 包装为 Agent。外层看到单一 Agent,内层是完整的多 Agent 协作。这是 Composite Pattern 在 Agent 系统中的经典应用。

🔍 Pattern 3: Message Filter

MessageFilterAgent 在消息到达 Agent 前进行过滤。这是 Decorator Pattern,解决了多 Agent 环境下"信息过载"问题 — Agent 只需看到与自己相关的消息。

📋 Pattern 4: Ledger Orchestration

MagenticOne 的 Task/Progress Ledger 是 Blackboard Pattern 的变体。中央账本维护事实和计划,所有 Agent 通过账本协调,而非直接通信。


15. 附录:快速上手代码

基础 Agent

from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent

model_client = OpenAIChatCompletionClient(model="gpt-4o")
agent = AssistantAgent("assistant", model_client=model_client)
result = await agent.run(task="Hello!")

Swarm 多 Agent

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import Swarm
from autogen_agentchat.conditions import MaxMessageTermination

triage = AssistantAgent("triage", model_client=model_client,
    handoffs=["billing", "support"],
    system_message="Route to billing or support.")
billing = AssistantAgent("billing", model_client=model_client)
support = AssistantAgent("support", model_client=model_client)

team = Swarm([triage, billing, support],
    termination_condition=MaxMessageTermination(5))
await team.run(task="I was charged incorrectly!")

SocietyOfMind 嵌套

from autogen_agentchat.agents import AssistantAgent, SocietyOfMindAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination

writer = AssistantAgent("writer", model_client, system_message="Write well.")
reviewer = AssistantAgent("reviewer", model_client,
    system_message="Review. Say APPROVE when done.")
inner_team = RoundRobinGroupChat([writer, reviewer],
    termination_condition=TextMentionTermination("APPROVE"))

society = SocietyOfMindAgent("writing_team", team=inner_team,
    model_client=model_client)
translator = AssistantAgent("translator", model_client,
    system_message="Translate to Spanish.")

outer_team = RoundRobinGroupChat([society, translator], max_turns=2)
await outer_team.run(task="Write a short story.")

— 源码版本: autogen v0.5.x (2025-05) | 分析时间: 2026-05-17 | 基于源码深度阅读