Microsoft Research | v0.5.x AgentChat + Core | 双层架构:Actor Model Runtime + 高级 AgentChat 抽象
AutoGen 采用 双层架构:底层是 autogen-core 基于 Actor Model 的异步消息运行时,上层是 autogen-agentchat 提供高级 Chat Agent 抽象。这种设计让核心运行时可以独立于聊天场景使用(如分布式 Agent 系统),同时 Chat 层为常见对话模式提供便捷 API。
autogen-core — Actor Runtime、Agent 生命周期、消息路由、序列化、Telemetryautogen-agentchat — BaseChatAgent、AssistantAgent、Teams、Termination Conditionsautogen-ext — OpenAI/Ollama 模型客户端、Docker 代码执行器、MCP WorkbenchAutoGen Core 实现了一个 Actor Model 风格 的消息运行时。每个 Agent 是一个 Actor,通过 AgentId 唯一标识,通过两种通信模式交互:
runtime.send_message(message, recipient) — 发送消息给特定 Agent,等待返回值。内部使用 asyncio.Future 实现请求-响应。
runtime.publish_message(message, topic_id) — 发布到 Topic,所有订阅该 Topic 的 Agent 都会收到。通过 SubscriptionManager 管理路由。
# 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: ...
核心运行时实现。维护消息队列、订阅关系、Agent 实例池:
autogen-agentchat 定义。
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: ...
实现了 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
on_messages 只传入新消息,Agent 内部维护历史。调用方不应传入完整对话历史。
这是 AutoGen v0.5 的核心 Agent 实现,集成了 LLM 推理、工具调用、Handoff 和结构化输出。
| 参数 | 类型 | 说明 |
|---|---|---|
model_client | ChatCompletionClient | LLM 推理客户端 (必须) |
tools | List[BaseTool | Callable] | 工具列表,自动包装为 FunctionTool |
workbench | Workbench | Sequence | 工具工作台 (与 tools 互斥) |
handoffs | List[Handoff | str] | Handoff 配置,用于 Swarm 切换 |
model_context | ChatCompletionContext | 对话上下文管理器 |
memory | Sequence[Memory] | 长期记忆存储 |
system_message | str | None | 系统提示词 |
reflect_on_tool_use | bool | 工具调用后是否反思 |
max_tool_iterations | int | 最大工具迭代轮数 (默认1) |
output_content_type | type[BaseModel] | 结构化输出类型 |
model_client_stream | bool | 是否启用流式输出 |
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。
通过 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
ContextVar 在输入回调中注入请求 ID,允许 UI 框架关联请求与响应。
两种模式:被动模式(仅执行收到的代码块)和主动模式(带 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()
DockerCommandLineCodeExecutorAutoGen 定义了丰富的消息类型层次,分为 ChatMessage(Agent 间通信)和 AgentEvent(可观测事件):
class HandoffMessage(BaseChatMessage):
target: str # 目标 Agent 名称
context: List[LLMMessage] = [] # 附带的 LLM 上下文
def to_model_message(self) -> UserMessage:
return UserMessage(content=self.content, source=self.source)
class StructuredMessage(BaseChatMessage, Generic[T]):
content: T # Pydantic BaseModel 实例
def to_model_text(self) -> str:
return self.content.model_dump_json()
AutoGen 的工具系统基于 Pydantic 模型自动生成 JSON Schema,支持函数工具和 Workbench 抽象:
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)
get_typed_signature(func) — 解析函数签名和类型注解args_base_model_from_signature() — 转换为 Pydantic BaseModelBaseTool.schema — 调用 args_model.model_json_schema() 生成 JSON SchemaAnnotated[type, "description"] 为参数添加描述strict=True 模式:所有参数必须 required,不允许 additionalPropertiesWorkbench 是工具的容器接口,提供统一的工具列表和调用 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 时内部创建 StaticStreamWorkbench,传入 workbench 时直接使用。两者不能同时设置。
AutoGen 提供 5 种群组编排模式,每种由 BaseGroupChat + 对应的 GroupChatManager 组成:
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)
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 作为参与者)。
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
MagenticOne 实现了论文 "Magentic-One: A Generalist Multi-Agent System for Solving Complex Tasks" 的编排策略:
# 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
基于有向图 (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=[]),
})
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)
| 维度 | 传统选择器 (SelectorGroupChat) | Handoff (Swarm) |
|---|---|---|
| 决策者 | 外部 LLM/函数 | Agent 自身 |
| 上下文传递 | 完整消息历史 | 精确的 context 字段 |
| 灵活性 | 低 (固定选择逻辑) | 高 (Agent 自主路由) |
| 可预测性 | 高 (确定性函数可覆盖) | 低 (依赖 LLM 决策) |
| 适用场景 | 固定角色轮转 | 动态任务分发 |
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))
AutoGen 的代码执行架构分为 Core 层执行器接口 和 AgentChat 层 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])
ChatCompletionContext 管理 Agent 的 LLM 消息历史:
# 自定义 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
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: ...
最简单的 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)
AutoGen 提供丰富的终止条件,支持 组合 (| 运算符):
| 终止条件 | 触发条件 | 典型用法 |
|---|---|---|
MaxMessageTermination | 消息数达到上限 | 防止无限循环 |
TextMentionTermination | 消息包含特定文本 | "TERMINATE" 信号 |
StopMessageTermination | 收到 StopMessage | Agent 主动停止 |
HandoffTermination | Handoff 到特定 Agent | 人类介入 |
SourceMatchTermination | 特定 Agent 发言 | 等待结果 |
TextMessageTermination | 特定 Agent 发 TextMessage | 等待文本回复 |
TimeoutTermination | 超时 | 防止长时间运行 |
ExternalTermination | 外部调用 set() | 程序控制停止 |
TokenUsageTermination | Token 用量超限 | 成本控制 |
# 组合终止条件
termination = (
HandoffTermination(target="user") | # Handoff 到人类
MaxMessageTermination(10) | # 最多 10 条消息
TimeoutTermination(60) # 60 秒超时
)
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 (节点+边+条件)
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
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 | 5 种编排模式 + MagenticOne 论文实现 |
| 动态任务分发 | AutoGen (Swarm) | Handoff 自主路由,最灵活 |
| 生产流水线 | CrewAI | Flow 装饰器 + Process 驱动,更稳定 |
| 复杂状态机 | LangGraph | StateGraph + Checkpoint,最强控制 |
| 软件工程 SOP | MetaGPT | PRD→设计→代码 流水线最成熟 |
| 分布式 Agent | AutoGen (Core) | 唯一支持 gRPC 分布式运行时 |
Handoff 将 Agent 切换建模为工具调用。LLM 看到 transfer_to_bob 工具,选择调用即触发切换。这是 Tool-Use Pattern 的高阶应用:不是调用函数,而是"调用另一个 Agent"。
SocietyOfMindAgent 将 Team 包装为 Agent。外层看到单一 Agent,内层是完整的多 Agent 协作。这是 Composite Pattern 在 Agent 系统中的经典应用。
MessageFilterAgent 在消息到达 Agent 前进行过滤。这是 Decorator Pattern,解决了多 Agent 环境下"信息过载"问题 — Agent 只需看到与自己相关的消息。
MagenticOne 的 Task/Progress Ledger 是 Blackboard Pattern 的变体。中央账本维护事实和计划,所有 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!")
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!")
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 | 基于源码深度阅读