在体系中的位置:第二章是"读懂内部机理",而 2.1 是这章的地图。你连整体分层都没建立,后面逐层下钻会像在没坐标的城里乱走。
一个数字先摆出来:AgentScope 把一次多智能体协作拆成了三层运行边界 + 一类贯穿服务。记住这个"3+1"结构,本章后面所有零件都能挂回这里。
先讲因果,不讲定义。多智能体系统最大的工程痛点,是"谁在什么时候该知道什么"。如果智能体 A 直接调用 B 的方法,A 就硬编码了 B 的存在——B 一改名、一重构,A 就崩。这叫紧耦合,系统一大就寸步难行。
AgentScope 的解法是:禁止直接调用,所有交互走消息。A 只管往消息中枢发一条消息,至于谁接收、怎么处理,A 不知道也不关心。这种"发布-订阅"范式把耦合点从"智能体之间"转移到了"消息格式"这一种约定上。约定比实现稳定得多,所以系统随规模膨胀时反而更稳。
# AgentScope 风格:A 只发消息,不知谁处理 from agentscope.message import Msg msg = Msg(name="A", content="请处理:去重函数", role="user") # 框架负责把 msg 投递给订阅了该类消息的智能体
运行说明:上面的 Msg 是 AgentScope 里一切交互的载体,字段含 name(发送者)、content(内容)、role(角色,如 user/system/assistant)。第二章 2.4 会细讲它的字段约定。
AgentScope 的运行视图可拆成三层和一类横切服务,下图是俯视图。

三层各自的职责和取舍:
我们把运行时层的五个组件逐一过一遍,后面章节会分别展开,这里先建索引。
| 组件 | 在 reply 流程中的位置 | 为什么鲁棒/灵活 |
|---|---|---|
| Agent 内核 | 收到消息后启动思考-行动循环 | 灵活:模型/工具/记忆可插拔 |
| 通信中间件 | 消息进出 Agent 的通道 | 鲁棒:序列化与重试固定 |
| 记忆后端 | 每次思考前读取、思考后写入 | 灵活:后端可换 |
| 工具沙箱 | 思考中决定调用外部能力时 | 鲁棒:隔离执行防越权 |
| 环境引擎 | 多 Agent 共享状态与规则 | 灵活在规则、鲁棒在托管 |
注意一个设计纪律:鲁棒性都落在"通道和底座"(通信、沙箱、环境托管),灵活性都落在"内容和配置"(模型、工具、记忆后端)。这和第一章讲的"灵活在上、鲁棒在下"完全对齐。框架不是平均用力,而是把稳定性风险集中到底座统一治理。
把"三层 + 贯穿服务"翻译成一次真实调用,你能看到接口层只写业务、服务层 MsgHub 做路由、运行时层跑循环,三者各管一段。
# 三层运行边界的一次落地:接口层写业务,服务/运行时由框架兜 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="环境变量占位") planner = ReActAgent(name="规划者", sys_prompt="把用户任务拆成步骤。", model=model) coder = ReActAgent(name="执行者", sys_prompt="按步骤写并运行代码。", model=model) async def run(): # 接口层:只声明"谁参与、说什么"——这就是全部业务代码 async with MsgHub([planner, coder]) as hub: await hub.broadcast(Msg("user", "写函数判断回文", "user")) await planner() # 服务层 MsgHub 负责把发言路由给执行者 await coder() # 运行时层 Agent 内核跑思考-行动循环 # 路由、重试、观测这些"贯穿服务"你一行没写,框架在服务层统一给 # asyncio.run(run())
运行输出(典型):规划者广播"先定函数签名 → 再写主体 → 最后自测"三步;执行者收到后产出完整 Python 函数并附自测用例。你只写了接口层的业务意图,服务层的消息路由和运行时层的循环全部由框架承担——这就是"3+1"分层在运行时的红利。
背景:用户让"规划者"智能体出方案,规划者需要查一个外部接口。
操作:接口层定义规划者订阅 user 消息;用户发消息,服务层 MsgHub 路由给规划者;运行时层 Agent 内核启动循环,思考后决定调工具,工具沙箱隔离执行返回结果,记忆后端记下这次交互;规划者产出回复消息,再经服务层广播。
结果:用户收到方案,且整个过程在 Studio 里可见每跳。
解读:你看不到任何一层"替另一层做决定"。接口层不碰路由,服务层不碰业务,运行时层不碰模型选型。职责切得干净,才是规模化的前提。
变式:若工具接口挂了,鲁棒性在运行时层(沙箱捕获异常)和服务层(重试/广播失败消息)兜底,接口层的业务代码一行都不用改。这就是分层带来的"故障局部化"。
⚠️ 不要在接口层写死对其他智能体的调用。一旦你写了 B.do_task() 这种紧耦合,分层带来的扩展性瞬间归零,系统退化成单体堆叠。
💡 调试时先定位"故障在哪一层":消息没到是服务层路由问题,到了但不回是运行时层或业务问题,回了的格式不对是接口层消息约定问题。分层让你能分而治之。