简介
springai/alibaba是java的ai agent框架,本系列将深入剖析 Spring AI/Alibaba 的源码实现与核心原理,用以指导agent的开发,框架培训,改造框架,增加新特性。
系列内容:
系列(一) 架构 完成
系列(三) 调用
I 工具 完成
II MCP
1 MCP MCP能力,工具,资源,Prompts,sampling,。。。;springboot自动配置 完成
2 分布式 MCP 注册和发现@nacos,gateway
3 MCP security, oauth2
III skills 完成
系列(四) RAG 完成
I 知识库,文档读取,分块;嵌入,向量store
II 检索,增强生成,模块化;混合检索,融合重排
系列(二) I 模型 model模型 完成
chat模型,消息,提示词,结构化输出,记忆
chat client,advisor组件
II 提示词工程@nacos
系列(五) graph 完成
I 图结构,节点和边;StateGraph;外部介入 完成
推理框架 graph映射: ReAct,relection,CoT,Plan-And-Execute
II 图编译 CompiledGraph,扁平化图结构,邻接表结构 完成
III 图执行,响应式流执行,检查点,回溯/回放,中断和恢复,容错
系列(六) agent及组件 ReactAgent,AgentLlmNode,AgentToolNode,钩子和拦截器,记忆,结构化输出
系列(七) MAS
I MAS模式 flow模式 编排器-子智能体,智能体团队;数据交接
II 分布式MAS,远程通讯,负载均衡,注册发现,容错
系列(八) 观测
I 观测组件(micrometer-observation), langfuse
II spring ai观测,观测组件,ChatClient,ChatModel
III spring ai alibaba观测 图观测
系列(九) 评估 I spring ai 评估组件 本地开发测试
II spring ai alibaba admin,数据集构建、线上链路数据复用,试验,评估器
III langfuse评估
系列(十) 沙箱
本文分析沙箱的原理和源码
based spring ai v1.1.1.2,spring ai Alibaba v1.1.2,agentscope-runtime v1.0.2
关键词
沙箱
容器
缩写
spring ai缩写sa
spring ai alibaba 本文缩写saa
参考资料
概览 | Spring AI Alibaba spring ai alibaba官网文档
https://docs.spring.io/spring-ai/reference/index.html spring ai官方文档
SAA概览

上图是saa原理源码分析场景视图,每个包对应着saa/sa组件或特性,是本文分析的目录
model 大模型的封装,模型包括Chat,嵌入,audio,image等类型,其中chat模型包括,advisor组件,提示词,记忆等
agent/graph agent和图紧密相关,可以认为agent是一种既定的"图"形,开发人员可以使用graph底层api直接构建graph,使用agent获得既定的图形,简化agent的开发
外部调用(calling) 工具,MCP,skills
RAG 检索增强生成
MAS MAS模式 flow模式 编排器-子智能体,智能体团队;数据交接
沙箱 隔离工具调用
评估
studio 简易的agent管理工具,嵌入到agent,带有agent面板,列表agent;提供chat界面,用于调试agent,是开发agent的便利工具
沙箱
Agent沙箱目的是为 AI Agent 提供一个安全、隔离的工具执行环境。saa的依赖agentscope-runtime的沙箱组件提供工具的隔离,本文分析agentscope-runtime的沙箱组件,saa集成提供沙箱隔离执行的工具
分析用例
agentscope 沙箱组件的第一个版本在agentscope-runtime ,saa 集成该组件实现工具的沙箱隔离执行

上图展示分析用例
注册沙箱
沙箱 沙箱模型
沙箱工具 文件,浏览器等命令执行,注意:此工具不是agent工具,一套独立的工具组件
沙箱agent工具 适配沙箱工具为agent工具
注册沙箱
本节分析注册沙箱

上图注册沙箱类图,类互动图
SAA 的沙箱注册组件采用了可扩展的设计:
- SPI 机制: SandboxProvider接口
- 注解驱动:通过 @RegisterSandbox注解,读取元数据(镜像名称、沙箱类型)。
类分析
SandboxRegistryInitializer ( 注册初始化器 )
- 角色:静态初始化块触发注册
- 逻辑:注册流程的触发者,在系统启动的"静态初始化"阶段,SPI 机制扫描载入SandboxProvider实现
SandboxProvider & BuiltInSandboxProvider ( 沙箱提供者 )
- 角色:沙箱(类型)提供者
- 逻辑:BuiltInSandboxProvider 是组件实现,
返回沙箱类型(如 BaseSandbox, FilesystemSandbox, BrowserSandbox, GuiSandbox 等)
- 作用:告诉注册器:"有这些沙箱类要注册"
用户自定义沙箱类型,提供自己 SandboxProvider 实现
RegisterSandbox ( 沙箱注解 )
- 角色:元数据载体
- 逻辑:标注在沙箱实现类,定义了该沙箱的关键属性,例如 imageName (Docker镜像名) 和 sandboxType (沙箱分类)
SandboxAnnotationProcessor ( 注解处理器 )
- 角色:标注处理器
- 逻辑:抓取沙箱类上的 标注RegisterSandbox元素据,生成SandboxConfig
SandboxRegistryService ( 注册服务 )
- 角色:沙箱注册存储库(Registry)。
- 逻辑:静态工具类,内部方法是静态,维护着一个静态的数据结构 typeConfigRegistry: Map。
- 作用:接收处理器构建好的 SandboxConfig,并将其放入 Map 中缓存,后续其他组件可获取使用。
类互动
沙箱注册的类互动实现:
- 触发 (Initialization)
系统启动,SandboxRegistryInitializer 开始执行静态初始化逻辑。 - 发现 (SPI 机制 )
SandboxRegistryInitializer 通过 SPI 机制找Provider,默认 BuiltInSandboxProvider。Provider 返回了一组待注册的沙箱类列表(例如 BrowserSandbox.class, FilesystemSandbox.class)。 - 处理 (Processing)
SandboxRegistryInitializer 将沙箱类给 SandboxAnnotationProcessor 的 processClass 方法处理 - 解析与构建 (Parsing & Building)
SandboxAnnotationProcessor 检查传入的类:- 获取类上标注 @RegisterSandbox
- 提取标注属性(如 imageName="browser-v1", sandboxType=WEB)。
- 利用这些属性实例化一个 SandboxConfig 对象。
- 注册 (Registration)
SandboxAnnotationProcessor 调用 SandboxRegistryService 的 register 方法,将生成的沙箱定义 SandboxConfig 传入。 - 存储 (Storage)
SandboxRegistryService 将沙箱定义存入静态变量 typeConfigRegistry Map 中。
至此,该沙箱类型注册完成,随时可被获取,构建沙箱实例
总结:
沙箱注册的核心是SPI机制载入沙箱类型,读取注解,抓取出沙箱元素据,构建SandBoxConfig;所有的SandBoxConfig存入typeConfigRegistry,其他组件可获取,typeConfigRegistry类型是Map,key沙箱类型名称,value: SandBoxConfig.
沙箱
本节分析沙箱设计,包括容器client,容器是实现沙箱的底层技术,目前有docker,k8s等实现。docker是默认容器,k8s在extendsion包。

上图 沙箱类图,还包括沙箱底层的容器client
SAA 的沙箱设计采用了经典的分层架构,"业务逻辑(沙箱)"与"基础设施(容器)"解耦。
容器 client
- 图的上方, BaseClient 定义容器操作(创建,连接、启动、停止,pull镜像)。
- DockerClient BaseClient的docker实现,依赖第三方库 com.github.dockerjava.api.DockerClient
- BaseClientStarter/DockerClientStarter BaseClient的工厂,携带Client的属性,放入ManagerConfig
**!**BaseClient类名不理想,应该改成ContainerClient
沙箱服务:
位于图的C位,SandboxService 聚集了沙箱,沙箱工具的服务,沙箱用SandboxService 管理容器,沙箱工具用SandboxService连接容器,调用http服务,实现工具调用
沙箱:
- 图的下方,Sandbox 是基类,FilesystemSandbox、BrowserSandbox 是具体实现,对应文件工具和浏览器工具,沙箱意义是隔离的环境,每类工具对应各自的沙箱实现,提供不同的环境。这里只列举了常用的两类沙箱,沙箱组件还有多种的沙箱类型。
- @RegisterSandbox 每个沙箱类具都带有,是沙箱类型的元数据。
容器:
容器的创建是在沙箱初始化时,managerApi就是SandBoxService

关于容器的创建涉及容器的知识,本文不深入分析
**!**这个方法是延时调用,第一次调用工具创建容器,导致比较慢
沙箱工具
沙箱隔离文件,浏览器等命令的执行,沙箱工具以工具的形式封装操作,注意,沙箱工具不是agent工具,是独立的工具组件

上图 沙箱工具类图
核心类解析
1 工具模型
- SandboxTool: 沙箱工具基类,有3个属性,sandboxService,sandbox,schema,
其中schema是工具的输入参数定义
抽象方法getSandboxClass ,实现返回对应的沙箱类型,也即sandbox不同的SandboxTool对应指定类型
- FsSandboxTool/ BrowserSandboxTool: 工具类型的基类
FsSandboxTool 文件类型工具基类,对应的沙箱类型FilesystemSandbox
BrowserSandboxTool 浏览器工具基类,对应的沙箱类型BrowseSandbox
2 SandboxService
上节介绍过SandboxService,聚合了沙箱,沙箱工具服务,沙箱工具相关的方法有,列表工具(listTools),调用沙箱工具callTool,两者使用SandboxClient/RemoteHttpClient,连接容器,调用容器的http服务
3 SandboxClient/RemoteHttpClient
- > SanboxClient是沙箱的client,主要职责是调用工具,上节介绍BaseClient是容器的管理client。SandboxHttpClient是SanboxClient的实现,使用HttpClient组件访问容器,也就是说容器内置http服务,http服务处理工具调用相关请求,看到dockerfile有nginx服务,http服务应该是使用nginx,健康检测endpoint是/fastapi/healthz,估计http请求是fastapi组件处理
- > RemoteHttpClient 调用远程的独立部署的SandBox服务
用例实现
下面以调用文件系统工具 (CreateDirectoryTool)为例,分析类互动
1 调用CreateDirectoryTool的fs_create_directory方法

2 工具绑定的沙箱类型是FilesystemSandbox,调用其createDirectory方法

打包参数,调用基类SandBox的callTool
3 SandBox的callTool

managerApi就是SandboxService
4 SandboxService的callTool
这是底层的执行,执行分两种情况
4.1 RemoteHttpClient

RemoteHttpClient不为空,使用独立部署的SandBoxService,即agentscope-runtime-web包
4.2 SandboxClient

SandboxClient根据容器信息动态构建的client,直接连接容器,实现是SandboxHttpClient,使用httpclient组件
4.3 结果返回:容器内根据toolName识别执行何种命令或服务,执行后返回结果
沙箱agent工具
上节的沙箱工具打通了容器调用,执行文件,浏览器等操作,沙箱agent工具是沙箱工具(SandTool)适配为agent工具(ToolCallback),后续agent可以调agent工具一样调用沙箱工具
沙箱agent工具是saa组件,agentscope-runtime提供类似的适配agentscope工具体系的组件

上图 沙箱agent工具类图
SandboxAwareTool /BaseSandboxAwareTool 浅层包装SandboxTool,主要是使用自有的request/response,隔离agentscope的依赖
RuntimeFunctionToolCallback agent工具ToolCallback实现,包装SandboxTool
ToolkitInit 沙箱agent工具工厂
下面看一下示例,ToolkitInit 构建RuntimeFunctionToolCallback ,适配沙箱工具

上图是saa的sandbox-simple-tool示例,AgentConfiguration构建BrowserNavigateTool的代码,该工具属于浏览类型,首先new一个BrowserSandbox,sandboxService是另一个自动配置SandboxConfiguration实例并注入,
最后ToolkitInit 的 BrowserNavigateTool方法构建工具,每个工具ToolkitInit 有对应的构建方法
沙箱 agent 工具调用链:
调用者 RuntimeFunctionToolCallback.apply----> SandboxAwareTool(解释自有的request/返回合成为自有的response)--->SandboxTool--->SandBox--->SandboxService--->SandboxClient(Http)--->容器的http服务(执行命令)
**总结:**沙箱的使用,
1 agent启动,静态初始化块启动沙箱注册
2 沙箱注册使用SPI机制载入SandboxProvider,提供注册沙箱类型
3 标注处理器读取沙箱类型的注解@RegisterSandbox,获取沙箱类型信息,构建SandboxConfig,并保存到静态的map变量
4 agent按需实例沙箱agent工具,过程包括两部分,实例对应的沙箱,不同的工具类型对应的沙箱类型,然后使用ToolkitInit相应的方法,将沙箱工具包装成agent工具ToolCallback,agent可以工具机制调用
沙箱功能跑通,设计也比较清晰,使用容器还是比较重,多节点间共享也是要考虑的问题,目前进程内共享,使用redis SandboxMap,修改注册机制,可实现全局共享
示例
本节运行saa集成agentscope sandbox v1的示例,示例使用saa的sandbox-simple-tool,增加文件系统沙箱,容器使用docker-desktop,镜像比较大,预先pull下来需要的镜像

base沙箱测试,执行python脚本

返回

查看docker,容器构建并启动

**!**测试中,base沙箱可用,但文件系统沙箱镜像启动报错,Error: .ini file does not include supervisord section,应该是镜像问题;浏览器的镜像健康检查没通过,检查endpoint,http://{addr:port}/fastapi/healthz,是不是python模块没装上去
**!**沙箱有缓存机制,但测试时发现每次新建容器,后来发现ReactAgent scope设置prototype,工具在构建ReactAgent一起,因此每次都建新的沙箱