2.1 整体架构设计


2.1 整体架构设计

在体系中的位置:第二章是"读懂内部机理",而 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 的运行视图可拆成三层和一类横切服务,下图是俯视图。

二、三层运行边界 + 一类贯穿服务

三层各自的职责和取舍:

  • 接口层:纯开发者的自由区,写什么 Agent、怎么编排都行。这里是"灵活"的落点。
  • 服务层:消息路由、容错、观测横切所有智能体。它不关心业务逻辑,只保证"消息到得了、挂了兜得住、过程看得见"。这是"鲁棒"的落点。
  • 运行时层:Agent 内核、通信中间件、记忆、工具沙箱、环境引擎。协议固化,是系统稳定的最后一道墙。
  • 底层支撑:模型和后端的插槽。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"分层在运行时的红利。

案例:一次 reply 在三层间的旅行

背景:用户让"规划者"智能体出方案,规划者需要查一个外部接口。

操作:接口层定义规划者订阅 user 消息;用户发消息,服务层 MsgHub 路由给规划者;运行时层 Agent 内核启动循环,思考后决定调工具,工具沙箱隔离执行返回结果,记忆后端记下这次交互;规划者产出回复消息,再经服务层广播。

结果:用户收到方案,且整个过程在 Studio 里可见每跳。

解读:你看不到任何一层"替另一层做决定"。接口层不碰路由,服务层不碰业务,运行时层不碰模型选型。职责切得干净,才是规模化的前提。

变式:若工具接口挂了,鲁棒性在运行时层(沙箱捕获异常)和服务层(重试/广播失败消息)兜底,接口层的业务代码一行都不用改。这就是分层带来的"故障局部化"。

架构心智速记

  • "3+1"结构:接口层(灵活)、服务层(贯穿路由/容错/观测)、运行时层(鲁棒底座),底层支撑可替换。
  • 以消息为中心的本质,是把耦合点从"智能体之间"转移到"消息格式"这一稳定约定上。
  • 鲁棒性集中在通道与底座,灵活性集中在内容与配置——风险被统一治理。
  • 分层的直接红利是"故障局部化":底层出问题,上层业务代码不动。

⚠️ 不要在接口层写死对其他智能体的调用。一旦你写了 B.do_task() 这种紧耦合,分层带来的扩展性瞬间归零,系统退化成单体堆叠。

💡 调试时先定位"故障在哪一层":消息没到是服务层路由问题,到了但不回是运行时层或业务问题,回了的格式不对是接口层消息约定问题。分层让你能分而治之。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U