Actor 模型:异步消息与类型化运行时 本节摘要:大多数 Agent 框架是同步的——一个 Agent 产出、一个 Agent 消费,挤在一个调用栈里,失败会崩栈,并发是后 bolt 上去的,要做分布式得重写。AutoGen v0.4(Microsoft Research, 2025 年 1 月)的回答是把 Agent 当 Actor:每个 Agent 是一个带私有收件箱的 Actor,消息是它们之间唯一的交互方式,运行时把投递与处理解耦,失败隔离在单个 Actor 内,并发是原生的,分布式只是换一种传输。本节吃透 Actor 模型(私有状态 + 收件箱 + 处理器,两个 Actor 不能共享内存)、AutoGen v0.
本节摘要:大多数 Agent 框架是同步的——一个 Agent 产出、一个 Agent 消费,挤在一个调用栈里,失败会崩栈,并发是后 bolt 上去的,要做分布式得重写。AutoGen v0.4(Microsoft Research, 2025 年 1 月)的回答是把 Agent 当 Actor:每个 Agent 是一个带私有收件箱的 Actor,消息是它们之间唯一的交互方式,运行时把投递与处理解耦,失败隔离在单个 Actor 内,并发是原生的,分布式只是换一种传输。本节吃透 Actor 模型(私有状态 + 收件箱 + 处理器,两个 Actor 不能共享内存)、AutoGen v0.4 的三层 API(Core 底层 Actor 框架、AgentChat 任务驱动高层、Extensions 集成)、解耦带来的三大后果(故障隔离、天然并发、可分布),以及 RoundRobin / Selector / Magentic-One 三种拓扑。注意:AutoGen 已转入维护模式,Microsoft Agent Framework(2025 年 10 月公开预览)是其生产继任者,但 Actor 模型是经久不衰的思想。本节用标准库从零实现一个 Actor 运行时,并把一个双 Agent 代码评审流程搬上去。
对应原课程:Phase 14 · Lesson 14 ·
autogen-actor-model(原英文phases/14-agent-engineering/14-autogen-actor-model/docs/en.md)。
阅读完本节,你应当能够:
大多数 Agent 框架是同步的:一个 Agent 产出、一个 Agent 消费,挤在一个调用栈里。失败会崩栈。并发是后 bolt 上去的。分布式需要重写。
AutoGen v0.4 的回答:Actor 模型。每个 Agent 是一个带私有收件箱的 Actor。消息是唯一的交互。运行时把投递与处理解耦。失败隔离到一个 Actor。并发是原生的。分布式只是换一种传输。
一个 Actor 有:
receive(message) -> effects,其中 effects 可以是「回复」「发给别的 Actor」「spawn 新 Actor」「更新状态」「停止自己」。两个 Actor 不能共享内存,只能互发消息。
AutoGen v0.4 把表面分成三层:
AgentRuntime、Agent、Message、Topic。异步消息交换,事件驱动。ConversableAgent)。AssistantAgent、UserProxyAgent、RoundRobinGroupChat、SelectorGroupChat。在 v0.2 模型里,调用 agent_a.chat(agent_b) 会同步阻塞 agent_a 直到 agent_b 返回。在 v0.4 里,send(agent_b, msg) 把消息放进 agent_b 的收件箱就返回,运行时之后投递。三个后果:
💡 设计要点:Actor 模型的核心心法是「不共享内存,只发消息」。这条约束初看是限制,实则是解放——它强制你把所有交互显式化成消息,于是故障边界、并发模型、分布抽象自然就位。这与第 13 节状态图的「显式状态」是两种不同的显式化路径:状态图显式化控制流,Actor 显式化通信。
内置 OpenTelemetry 支持。每条消息发一个 span;工具调用带 gen_ai.* 属性,遵循 2026 年 OTel GenAI 语义约定(第 23 节)。
2026 年初:AutoGen v0.7.x 对研究与原型稳定。Microsoft 已把活跃开发转向 Microsoft Agent Framework——生产继任者(2025 年 10 月 1 日公开预览;1.0 GA 目标是 2026 年 Q1 末)。AutoGen 的模式能干净地前向移植——Actor 模型是经久不衰的思想。
原课程 code/main.py 用标准库实现一个 Actor 运行时:
Message —— 类型化载荷,带 sender、recipient、topic、body。Actor —— 抽象类,带 receive(message, runtime)。Runtime —— 带共享队列、投递、故障隔离的事件循环。ReviewerAgent 评审代码,ChecklistAgent 跑清单;它们交换消息直到达成共识。核心骨架如下,用伪代码展示。
class Message: def __init__(self, sender, recipient, topic, body): self.sender = sender self.recipient = recipient self.topic = topic self.body = body class Actor: def __init__(self, aid): self.id = aid self.state = {} # 私有,外部不碰 def receive(self, msg, runtime): raise NotImplementedError
class Runtime: def __init__(self): self.actors = {} # id -> Actor self.queue = [] # 待投递消息 def register(self, actor): self.actors[actor.id] = actor def send(self, msg): self.queue.append(msg) # 投递与处理解耦:放进队列就返回 def run(self): while self.queue: msg = self.queue.pop(0) actor = self.actors[msg.recipient] try: actor.receive(msg, self) # 处理 except Exception as e: # 故障隔离:一个 Actor 崩不崩别的 self.dead_letter(msg, e)
class ReviewerAgent(Actor): def receive(self, msg, runtime): if msg.topic == "code": verdict = llm_review(msg.body) self.state["last_verdict"] = verdict runtime.send(Message(self.id, "checklist", "review", verdict)) class ChecklistAgent(Actor): def receive(self, msg, runtime): if msg.topic == "review": checks = run_checklist(msg.body) if all(checks.values()): runtime.send(Message(self.id, "reviewer", "consensus", "通过")) else: runtime.send(Message(self.id, "reviewer", "review", "需修订"))
运行 python3 code/main.py 会展示消息投递、一个 Actor 内的模拟失败(不崩另一个)、以及对共享裁决的收敛。
💡 设计要点:
Runtime.run()里的try/except是 Actor 模型的故障隔离落点。同步框架里一个 Agent 抛异常会沿调用栈向上传播、崩掉整条链;Actor 框架里异常被运行时抓住、塞进死信队列,其他 Actor 继续干活。这就是 Erlang「let it crash」哲学在 Agent 层的重演。
| 选项 | 模型 | 并发 | 分布 | 适用 |
|---|---|---|---|---|
| AutoGen / MAF | Actor | 原生 | 收件箱+传输 | 高并发多 Agent |
| LangGraph | 状态机 | 需配 | 检查点+恢复 | 持久状态图 |
| LangGraph Swarm | 共享工具交接 | 中 | 中 | 对等协作 |
| 自建 | 全控 | 全控 | 全控 | 特定传输 |
⚠️ 选型警示:Actor 模型适合高并发、多 Agent、需故障隔离的场景。如果你的任务是线性工作流或需精确状态恢复,第 13 节的状态图更合身。不要因为「Actor 听起来酷」就上——它的代价是调试更难(消息时序、收件箱堆积、死信排查)。
本节产出一份可复用技能(原课程 outputs/skill-actor-runtime.md):
skill-actor-runtime.md:生成一个最小 Actor 运行时 + 一个团队模板(RoundRobin 或 Selector),适用于给定的多 Agent 任务。包含一份 Actor 设计清单(每个 Actor 的状态边界在哪?消息载荷是否类型化?故障如何进死信?),以及一份拓扑选择清单(轮次固定用 RoundRobin,上下文敏感用 Selector,需网页/代码/文件用 Magentic-One 式分工)。Python 代码(code/main.py)是独立可运行的 Actor 运行时骨架,消息、Actor、运行时、故障隔离都是传输无关的;把进程内队列换成 NATS/RabbitMQ/gRPC 即可分布式部署。
SelectorGroupChat:一个选择器 Actor 根据对话状态挑谁处理下一条消息。gen_ai.agent.name、gen_ai.operation.name。autogen_core API。你跳过的哪些东西在生产里要紧?send 进队列就返回,运行时之后投递。gen_ai.* 属性。try/except 抓异常进死信,其他 Actor 继续。下一节,我们看角色制团队——CrewAI 把多 Agent 协作组织成有角色、有目标、有背景故事的人类团队形态,当你的任务天然是「不同专长的角色协作」时,它比裸 Actor 更贴近直觉。