在体系中的位置:3.2、3.3 把演员和舞台都备好了,这一节让它们真正"同台演出"——用消息中枢和群聊把多个智能体编排成工作流。这是第三章的高潮,也是多智能体从"几个会说话的对象"变成"一个能干活的系统"的转折点。
一个反问先抛出来:你有两个智能体,怎么让它们既各说各话、又互相看见对方的话?手写消息转发,三个智能体就乱成麻。AgentScope 的解法是两个原语:MsgHub(广播中枢)和 GroupChat / SelectorGroupChat(角色化群聊)。掌握这两个,编排才算入门。
MsgHub 是异步上下文管理器。进入它的智能体,彼此的回复会自动广播给对方,无需手动传参。最适合"大家都能看到全场"的讨论型场景。
import asyncio from agentscope.agents import ReActAgent from agentscope.msghub import MsgHub from agentscope.models import OpenAIChatModel from agentscope.message import Msg model = OpenAIChatModel(model_name="gpt-4o-mini", api_key="环境变量占位") alice = ReActAgent(name="Alice", sys_prompt="你是学生 Alice,乐于交流。", model=model, toolkit=None, memory=InMemoryMemory()) bob = ReActAgent(name="Bob", sys_prompt="你是学生 Bob,喜欢运动。", model=model, toolkit=None, memory=InMemoryMemory()) charlie = ReActAgent(name="Charlie", sys_prompt="你是学生 Charlie,爱旅行。", model=model, toolkit=None, memory=InMemoryMemory()) async def chat(): async with MsgHub( [alice, bob, charlie], announcement=Msg("system", "大家互相自我介绍。", "system"), ) as hub: await alice() await bob() await charlie() # 每个人发言后,另外两人自动收到,下一轮能接着对方的话 asyncio.run(chat())
运行输出(典型):Alice 先自我介绍,Bob 听到后介绍自己并呼应 Alice,Charlie 再接话。关键在——你没写任何"把 A 的话传给 B"的代码,MsgHub 自动做了广播。消息中枢把"转发逻辑"从业务里抽走,这是编排简洁的根本。
MsgHub 支持运行中用 hub.add() 拉新智能体入群,适合"中途请专家入场"的场景。
async def chat_with_expert(): async with MsgHub([alice, bob], announcement=Msg("system", "讨论旅行计划", "system")) as hub: await alice() await bob() # 中途引入旅行达人 Charlie hub.add(charlie) await charlie() # Charlie 能看到之前所有发言,无缝加入
运行说明:hub.add(charlie) 后,Charlie 自动获得入群前的历史消息,不会因为"迟到"而脱节。这种动态性在"按问题请专家"的工作流里极实用。
当群聊需要"谁先说、谁后说、谁来决定下一轮谁说",GroupChat 和 SelectorGroupChat 上场。前者按固定顺序轮转,后者由模型(或规则)动态选下一个发言者——适合辩论、评审这类需要"选人接话"的场景。
from agentscope.agents import DialogAgent # from agentscope.agents import SelectorGroupChat pro = DialogAgent(name="正方", sys_prompt="支持观点 X。", model=model) con = DialogAgent(name="反方", sys_prompt="反对观点 X。", model=model) judge = DialogAgent(name="评委", sys_prompt="总结并给判断。", model=model) # result = await group.run(Msg("user", "讨论 AI 是否取代程序员", "user"))
运行说明:上面 SelectorGroupChat 是角色化群聊的典型——评委当"主持人"决定话权流转,避免无意义的全员轮播。stop_if 给出终止条件,防止无限循环。具体类名/参数以你所装版本文档为准,但"动态选人 + 终止条件"的编排范式稳定。
三种原语适用形态不同,下面一张图 + 一张表说清。

| 原语 | 话权流转 | 可控性 | 适用场景 |
|---|---|---|---|
| MsgHub | 全员广播,自由 | 低(靠业务自觉) | 讨论、互见、头脑风暴 |
| GroupChat | 固定顺序轮转 | 高(可复现) | 流水线会签、步骤固定 |
| SelectorGroupChat | 动态选人 + 终止 | 中(规则/模型定) | 辩论、评审、需主持人 |
背景:让正方、反方、评委三方就"AI 是否取代程序员"辩论,最后评委总结。
操作:用 SelectorGroupChat,评委当 selector 决定每轮谁接话,正方反方交替立论反驳,stop_if 在评委给出"结论"后终止。
# 评委最后发言包含"结论",群聊终止,transcript 为完整辩论记录
结果:产出结构化辩论记录,正方反方论证交锋,评委给判断。无需手写"谁该说"的逻辑。
解读:这里 SelectorGroupChat 把"调度权"交给评委智能体,而非硬编码顺序。若改成固定顺序(GroupChat),则可能反方刚说完正方就被打断,交锋感差。选对原语,协作质量差很多。
变式:若评委模型不够稳,可把 selector 换成规则函数(如"交替、末轮评委"),用确定性替代模型决策,提升可复现性。编排不是非黑即白,可混用模型与规则。
MsgHub 是广播中枢,入群者回复自动互见,无需手写转发;支持 hub.add() 动态增员。GroupChat 固定顺序轮转,可控可复现;SelectorGroupChat 动态选人 + 终止条件,适合辩论评审。⚠️ SelectorGroupChat 一定要设 max_rounds 和 stop_if,否则模型可能无限接话,既烧钱又不出结果。终止条件是群聊编排的必备安全带。
💡 编排第一问:"谁来决定下一轮谁说?"——没人管(自由讨论)用 MsgHub;固定顺序用 GroupChat;要主持人用 SelectorGroupChat。先答这题,再选原语。