概述
官网,阿里云智能团队开源(GitHub,11.7K Star,972 Fork)的面向AI应用场景的通用沙箱平台,旨在提供安全、一致且可扩展的运行环境,用于安全执行与LLM相关的能力(命令执行、文件操作、代码运行、浏览器自动化、Agent运行等)。
项目提供多语言SDK、统一的沙箱协议规范,以及多种沙箱运行时实现,便于开发者在受控环境中运行插件、工具链或智能体(智能体)。允许用户在任意k8s或Docker环境部署沙盒集群。
特性
- 多语言SDK:提供Python、Java、TypeScript/JavaScript等客户端SDK,便于在不同语言生态中集成沙箱能力;
- 统一沙箱协议:基于OpenAPI的沙箱协议规范(
specs/),采用协议优先(Protocol-First)设计,支持扩展自定义运行时和能力组件:所有交互都通过OpenAPI规范定义:- 可基于规范实现自己的运行时
- 不同语言SDK之间完全兼容
- 社区可以共建扩展能力
- 丰富沙箱环境:代码解释器、浏览器自动化、远程开发环境;
- 可扩展运行时:支持Docker运行时,以及k8s集群执行以满足生产部署需求;
- OpenAPI规范驱动:通过统一的接口规范定义沙箱生命周期与能力调用,降低集成成本;
- 组件化设计:将执行器、文件系统、命令运行等能力模块化,便于扩展与替换;
- 企业级并发调度能力:基于k8s的池化加速方案;
- 示例与文档齐全:参考
examples/、docs/,内置Code Interpreter、Browser、Filesystems等沙箱示例,快速上手并作为集成参考。
四层解耦架构设计
#mermaid-svg-93pvaCfK39KS3cwf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-93pvaCfK39KS3cwf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-93pvaCfK39KS3cwf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-93pvaCfK39KS3cwf .error-icon{fill:#552222;}#mermaid-svg-93pvaCfK39KS3cwf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-93pvaCfK39KS3cwf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-93pvaCfK39KS3cwf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-93pvaCfK39KS3cwf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-93pvaCfK39KS3cwf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-93pvaCfK39KS3cwf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-93pvaCfK39KS3cwf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-93pvaCfK39KS3cwf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-93pvaCfK39KS3cwf .marker.cross{stroke:#333333;}#mermaid-svg-93pvaCfK39KS3cwf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-93pvaCfK39KS3cwf p{margin:0;}#mermaid-svg-93pvaCfK39KS3cwf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-93pvaCfK39KS3cwf .cluster-label text{fill:#333;}#mermaid-svg-93pvaCfK39KS3cwf .cluster-label span{color:#333;}#mermaid-svg-93pvaCfK39KS3cwf .cluster-label span p{background-color:transparent;}#mermaid-svg-93pvaCfK39KS3cwf .label text,#mermaid-svg-93pvaCfK39KS3cwf span{fill:#333;color:#333;}#mermaid-svg-93pvaCfK39KS3cwf .node rect,#mermaid-svg-93pvaCfK39KS3cwf .node circle,#mermaid-svg-93pvaCfK39KS3cwf .node ellipse,#mermaid-svg-93pvaCfK39KS3cwf .node polygon,#mermaid-svg-93pvaCfK39KS3cwf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-93pvaCfK39KS3cwf .rough-node .label text,#mermaid-svg-93pvaCfK39KS3cwf .node .label text,#mermaid-svg-93pvaCfK39KS3cwf .image-shape .label,#mermaid-svg-93pvaCfK39KS3cwf .icon-shape .label{text-anchor:middle;}#mermaid-svg-93pvaCfK39KS3cwf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-93pvaCfK39KS3cwf .rough-node .label,#mermaid-svg-93pvaCfK39KS3cwf .node .label,#mermaid-svg-93pvaCfK39KS3cwf .image-shape .label,#mermaid-svg-93pvaCfK39KS3cwf .icon-shape .label{text-align:center;}#mermaid-svg-93pvaCfK39KS3cwf .node.clickable{cursor:pointer;}#mermaid-svg-93pvaCfK39KS3cwf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-93pvaCfK39KS3cwf .arrowheadPath{fill:#333333;}#mermaid-svg-93pvaCfK39KS3cwf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-93pvaCfK39KS3cwf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-93pvaCfK39KS3cwf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-93pvaCfK39KS3cwf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-93pvaCfK39KS3cwf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-93pvaCfK39KS3cwf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-93pvaCfK39KS3cwf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-93pvaCfK39KS3cwf .cluster text{fill:#333;}#mermaid-svg-93pvaCfK39KS3cwf .cluster span{color:#333;}#mermaid-svg-93pvaCfK39KS3cwf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-93pvaCfK39KS3cwf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-93pvaCfK39KS3cwf rect.text{fill:none;stroke-width:0;}#mermaid-svg-93pvaCfK39KS3cwf .icon-shape,#mermaid-svg-93pvaCfK39KS3cwf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-93pvaCfK39KS3cwf .icon-shape p,#mermaid-svg-93pvaCfK39KS3cwf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-93pvaCfK39KS3cwf .icon-shape .label rect,#mermaid-svg-93pvaCfK39KS3cwf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-93pvaCfK39KS3cwf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-93pvaCfK39KS3cwf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-93pvaCfK39KS3cwf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-93pvaCfK39KS3cwf .sdk>*{fill:#e3f2fd!important;stroke:#1976d2!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .sdk span{fill:#e3f2fd!important;stroke:#1976d2!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .sdk tspan{fill:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .specs>*{fill:#fff3e0!important;stroke:#f57c00!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .specs span{fill:#fff3e0!important;stroke:#f57c00!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .specs tspan{fill:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .runtime>*{fill:#f3e5f5!important;stroke:#7b1fa2!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .runtime span{fill:#f3e5f5!important;stroke:#7b1fa2!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .runtime tspan{fill:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .instance>*{fill:#e0f2f1!important;stroke:#00897b!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .instance span{fill:#e0f2f1!important;stroke:#00897b!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .instance tspan{fill:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .policy>*{fill:#eceff1!important;stroke:#546e7a!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .policy span{fill:#eceff1!important;stroke:#546e7a!important;stroke-width:2px!important;color:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .policy tspan{fill:#000!important;}#mermaid-svg-93pvaCfK39KS3cwf .layerBox>*{fill:#ffffff!important;stroke:#ccc!important;stroke-width:1px!important;stroke-dasharray:5 5!important;}#mermaid-svg-93pvaCfK39KS3cwf .layerBox span{fill:#ffffff!important;stroke:#ccc!important;stroke-width:1px!important;stroke-dasharray:5 5!important;} NetworkPolicy和Timer
NetworkPolicy
default deny + 白名单
Timer
过期自动清理 + 守护线程 + 服务重启恢复
Sandbox实例层
Sandbox#1
execd | Jupyter
C++/Java
Sandbox#2
execd | Jupyter
Python
Sandbox#N
execd | Jupyter
Go
Runtime层 (双运行时支持)
Docker 运行时
(1) 拉取镜像
(2) 创建容器
(3) 注入 execd
(4) 启动设置过期
K8s Operator
(1) CRD 定义
(2) 池化预热
(3) 自动扩缩
(4) 生命周期管理
Specs层 (规范定义)
Sandbox Lifecycle API
→ 创建/查询/暂停/恢复
→ 销毁/续期
Execd API
→ 代码执行/中断
→ 命令执行/中断
→ 文件上传/下载
→ 系统监控
Python SDK
Java/Kotlin SDK
Go SDK
TypeScript SDK
适用场景
- 在隔离环境中执行LLM驱动的代码解释器或工具链,防止外部副作用
- 提供给平台或应用的插件运行时,实现第三方工具以沙箱方式安全运行
- 用于自动化测试、浏览器自动化、远程开发(VS Code Web)以及桌面应用场景的沙箱化执行
核心创新在于将交互规范标准化,形成两套独立的API规范:
- Sandbox Lifecycle API:管理沙盒实例的整个生命周期:
| 端点 | 方法 | 描述 |
|---|---|---|
/sandboxes |
POST | 创建新的沙盒实例 |
/sandboxes/{id} |
GET | 查询沙盒状态 |
/sandboxes/{id}/pause |
POST | 暂停沙盒 |
/sandboxes/{id}/resume |
POST | 恢复沙盒 |
/sandboxes/{id} |
DELETE | 销毁沙盒 |
/sandboxes/{id}/renew |
POST | 续期沙盒 |
状态机流转:
#mermaid-svg-BttgJAJrpP85Jh2f{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BttgJAJrpP85Jh2f .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BttgJAJrpP85Jh2f .error-icon{fill:#552222;}#mermaid-svg-BttgJAJrpP85Jh2f .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BttgJAJrpP85Jh2f .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BttgJAJrpP85Jh2f .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BttgJAJrpP85Jh2f .marker.cross{stroke:#333333;}#mermaid-svg-BttgJAJrpP85Jh2f svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BttgJAJrpP85Jh2f p{margin:0;}#mermaid-svg-BttgJAJrpP85Jh2f defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-BttgJAJrpP85Jh2f g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-BttgJAJrpP85Jh2f g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-BttgJAJrpP85Jh2f g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-BttgJAJrpP85Jh2f g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-BttgJAJrpP85Jh2f g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-BttgJAJrpP85Jh2f .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-BttgJAJrpP85Jh2f .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-BttgJAJrpP85Jh2f .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-BttgJAJrpP85Jh2f .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-BttgJAJrpP85Jh2f .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-BttgJAJrpP85Jh2f .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-BttgJAJrpP85Jh2f .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-BttgJAJrpP85Jh2f .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BttgJAJrpP85Jh2f .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BttgJAJrpP85Jh2f .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BttgJAJrpP85Jh2f .edgeLabel .label text{fill:#333;}#mermaid-svg-BttgJAJrpP85Jh2f .label div .edgeLabel{color:#333;}#mermaid-svg-BttgJAJrpP85Jh2f .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-BttgJAJrpP85Jh2f .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-BttgJAJrpP85Jh2f .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-BttgJAJrpP85Jh2f .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-BttgJAJrpP85Jh2f .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-BttgJAJrpP85Jh2f .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BttgJAJrpP85Jh2f .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BttgJAJrpP85Jh2f #statediagram-barbEnd{fill:#333333;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BttgJAJrpP85Jh2f .cluster-label,#mermaid-svg-BttgJAJrpP85Jh2f .nodeLabel{color:#131300;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-BttgJAJrpP85Jh2f .note-edge{stroke-dasharray:5;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-note text{fill:black;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram-note .nodeLabel{color:black;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagram .edgeLabel{color:red;}#mermaid-svg-BttgJAJrpP85Jh2f #dependencyStart,#mermaid-svg-BttgJAJrpP85Jh2f #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-BttgJAJrpP85Jh2f .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BttgJAJrpP85Jh2f :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建成功
暂停完成
恢复
每隔X分钟续期
超时/手动销毁
内部错误
Pending
Running
Pausing
Paused
Terminated
Failed
- Execd API:定义沙盒内部的代码执行接口,由
execd代理在Sandbox实例内部提供服务:
| 路由 | 方法 | 描述 |
|---|---|---|
/code |
POST | 执行代码 |
/code/{id}/interrupt |
POST | 中断正在执行的代码 |
/code/context/{id} |
POST | 创建/切换执行上下文 |
/command |
POST | 执行shell命令 |
/command/{id}/interrupt |
POST | 中断正在执行的命令 |
/files/upload |
POST | 上传文件到沙盒 |
/files/download/{path} |
GET | 从沙盒下载文件 |
/system/monitor |
GET | 获取CPU/内存等系统指标 |
通过WebSocket与Jupyter内核通信,采用SSE(Server-Sent Events)流式返回执行结果:
#mermaid-svg-hqovQX3aRh2WZcIZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hqovQX3aRh2WZcIZ .error-icon{fill:#552222;}#mermaid-svg-hqovQX3aRh2WZcIZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hqovQX3aRh2WZcIZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hqovQX3aRh2WZcIZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hqovQX3aRh2WZcIZ .marker.cross{stroke:#333333;}#mermaid-svg-hqovQX3aRh2WZcIZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hqovQX3aRh2WZcIZ p{margin:0;}#mermaid-svg-hqovQX3aRh2WZcIZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ .cluster-label text{fill:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ .cluster-label span{color:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ .cluster-label span p{background-color:transparent;}#mermaid-svg-hqovQX3aRh2WZcIZ .label text,#mermaid-svg-hqovQX3aRh2WZcIZ span{fill:#333;color:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ .node rect,#mermaid-svg-hqovQX3aRh2WZcIZ .node circle,#mermaid-svg-hqovQX3aRh2WZcIZ .node ellipse,#mermaid-svg-hqovQX3aRh2WZcIZ .node polygon,#mermaid-svg-hqovQX3aRh2WZcIZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hqovQX3aRh2WZcIZ .rough-node .label text,#mermaid-svg-hqovQX3aRh2WZcIZ .node .label text,#mermaid-svg-hqovQX3aRh2WZcIZ .image-shape .label,#mermaid-svg-hqovQX3aRh2WZcIZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-hqovQX3aRh2WZcIZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hqovQX3aRh2WZcIZ .rough-node .label,#mermaid-svg-hqovQX3aRh2WZcIZ .node .label,#mermaid-svg-hqovQX3aRh2WZcIZ .image-shape .label,#mermaid-svg-hqovQX3aRh2WZcIZ .icon-shape .label{text-align:center;}#mermaid-svg-hqovQX3aRh2WZcIZ .node.clickable{cursor:pointer;}#mermaid-svg-hqovQX3aRh2WZcIZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hqovQX3aRh2WZcIZ .arrowheadPath{fill:#333333;}#mermaid-svg-hqovQX3aRh2WZcIZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hqovQX3aRh2WZcIZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hqovQX3aRh2WZcIZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hqovQX3aRh2WZcIZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hqovQX3aRh2WZcIZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hqovQX3aRh2WZcIZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hqovQX3aRh2WZcIZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hqovQX3aRh2WZcIZ .cluster text{fill:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ .cluster span{color:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hqovQX3aRh2WZcIZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hqovQX3aRh2WZcIZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-hqovQX3aRh2WZcIZ .icon-shape,#mermaid-svg-hqovQX3aRh2WZcIZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hqovQX3aRh2WZcIZ .icon-shape p,#mermaid-svg-hqovQX3aRh2WZcIZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hqovQX3aRh2WZcIZ .icon-shape .label rect,#mermaid-svg-hqovQX3aRh2WZcIZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hqovQX3aRh2WZcIZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hqovQX3aRh2WZcIZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hqovQX3aRh2WZcIZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-hqovQX3aRh2WZcIZ .container>*{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:2px!important;stroke-dasharray:4 4!important;}#mermaid-svg-hqovQX3aRh2WZcIZ .container span{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:2px!important;stroke-dasharray:4 4!important;}#mermaid-svg-hqovQX3aRh2WZcIZ .node>*{fill:#e3f2fd!important;stroke:#1976d2!important;stroke-width:1px!important;}#mermaid-svg-hqovQX3aRh2WZcIZ .node span{fill:#e3f2fd!important;stroke:#1976d2!important;stroke-width:1px!important;} WebSocket/SSE 连接
OpenSandbox Runtime
Jupyter Gateway
Kernel Manager
Kernel Instance
(语言相关)
Python Kernel
Java Kernel
Go Kernel
当前支持的语言内核:
- Python:IPython内核,最成熟
- Java:IJava内核
- Go:
gophernotes内核 - JavaScript/TypeScript:
ijavascript/itypescript内核 - C++:
xeus-cling内核
OpenSandbox采用default deny+白名单的网络策略模式:
yml
# 默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: sandbox-default-deny
spec:
podSelector:
matchLabels:
app: opensandbox
policyTypes:
- Egress
- Ingress
egress: [] # 无出站规则,默认拒绝
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: opensandbox-system
---
# 白名单允许访问特定服务
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: sandbox-whitelist
spec:
podSelector:
matchLabels:
app: opensandbox
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/8
ports:
- protocol: TCP
port: 443
这种设计确保:
- 沙盒默认无法访问外部网络
- 通过白名单可控地开放特定域名/IP
- AI Agent无法通过沙盒恶意传播
OpenSandbox的沙盒都有TTL(Time-To-Live),到期自动清理:
python
# 内部守护线程伪代码
class SandboxCleaner:
def __init__(self):
self.sandboxes = {}
self.timer = threading.Timer(30.0, self._check_expired)
def _check_expired(self):
now = time.time()
for sid, sandbox in list(self.sandboxes.items()):
if sandbox.expires_at <= now:
self._destroy(sid)
# 重启定时器
self.timer = threading.Timer(30.0, self._check_expired)
self.timer.start()
def _destroy(self, sid):
# 1. 发送SIGTERM给execd
# 2. 等待grace period
# 3. 强制销毁容器/VM
# 4. 回收资源
# 5. 更新数据库状态
pass
def renew(self, sid, extra_minutes):
# 续期操作
self.sandboxes[sid].expires_at += timedelta(minutes=extra_minutes)
服务重启恢复机制:
- 守护线程的状态记录在数据库中
- 服务重启后,扫表恢复所有活跃沙盒
- 重新创建Timer定时器,确保过期清理不丢失
运行时
支持Docker与K8s双运行时
- Docker运行时流程
- 拉取镜像
- 创建容器
- 注入execd
- 启动
- 设置过期
- Kubernetes运行时基于Operator模式,核心CRD定义:
yaml
apiVersion: opensandbox.io/v1
kind: Sandbox
metadata:
name: sandbox-demo-001
spec:
image: opensandbox/code-interpreter:latest
timeout: 600 # 10分钟过期
resources:
cpu: "2"
memory: "4Gi"
networkPolicy:
egressWhitelist:
- "pypi.org"
- "github.com"
jupyter:
enabled: true
kernel: python3
status:
phase: Running
execdEndpoint: "sandbox-demo-001.sandbox:8080"
expiresAt: "2026-06-23T12:00:00Z"
Operator的池化预热机制:
- 维护一个预热沙盒池,
prewarm pool - 用户请求时,从池中分配已预热的沙盒
- 池容量动态调整,根据负载自动扩缩
- 设配速度从秒级降到毫秒级
双运行时支持,灵活部署

自研高性能k8s沙箱调度器,支持大规模并发场景。
- 批量沙箱支持:通过k8s Operator实现批量沙箱生命周期管理;
- 高性能调度:优化的调度算法,支持大规模并发创建和销毁。
沙箱粒度网络控制策略

json
{
"defaultAction": "deny",
"egress": [
{"action": "allow", "target": "api.openai.com"},
{"action": "allow", "target": "*.pypi.org"},
{"action": "allow", "target": "*.npmjs.org"}
]
}
开箱即用的沙箱流量入口代理

execd
OpenSandbox的灵魂组件,一个用Go编写的轻量级HTTP服务器,运行在每个Sandbox实例内部,作为外部与沙盒内进程的桥梁。
注入过程分为四个步骤:
#mermaid-svg-MakgW92het5laXZa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MakgW92het5laXZa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MakgW92het5laXZa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MakgW92het5laXZa .error-icon{fill:#552222;}#mermaid-svg-MakgW92het5laXZa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MakgW92het5laXZa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MakgW92het5laXZa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MakgW92het5laXZa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MakgW92het5laXZa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MakgW92het5laXZa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MakgW92het5laXZa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MakgW92het5laXZa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MakgW92het5laXZa .marker.cross{stroke:#333333;}#mermaid-svg-MakgW92het5laXZa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MakgW92het5laXZa p{margin:0;}#mermaid-svg-MakgW92het5laXZa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MakgW92het5laXZa .cluster-label text{fill:#333;}#mermaid-svg-MakgW92het5laXZa .cluster-label span{color:#333;}#mermaid-svg-MakgW92het5laXZa .cluster-label span p{background-color:transparent;}#mermaid-svg-MakgW92het5laXZa .label text,#mermaid-svg-MakgW92het5laXZa span{fill:#333;color:#333;}#mermaid-svg-MakgW92het5laXZa .node rect,#mermaid-svg-MakgW92het5laXZa .node circle,#mermaid-svg-MakgW92het5laXZa .node ellipse,#mermaid-svg-MakgW92het5laXZa .node polygon,#mermaid-svg-MakgW92het5laXZa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MakgW92het5laXZa .rough-node .label text,#mermaid-svg-MakgW92het5laXZa .node .label text,#mermaid-svg-MakgW92het5laXZa .image-shape .label,#mermaid-svg-MakgW92het5laXZa .icon-shape .label{text-anchor:middle;}#mermaid-svg-MakgW92het5laXZa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MakgW92het5laXZa .rough-node .label,#mermaid-svg-MakgW92het5laXZa .node .label,#mermaid-svg-MakgW92het5laXZa .image-shape .label,#mermaid-svg-MakgW92het5laXZa .icon-shape .label{text-align:center;}#mermaid-svg-MakgW92het5laXZa .node.clickable{cursor:pointer;}#mermaid-svg-MakgW92het5laXZa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MakgW92het5laXZa .arrowheadPath{fill:#333333;}#mermaid-svg-MakgW92het5laXZa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MakgW92het5laXZa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MakgW92het5laXZa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MakgW92het5laXZa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MakgW92het5laXZa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MakgW92het5laXZa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MakgW92het5laXZa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MakgW92het5laXZa .cluster text{fill:#333;}#mermaid-svg-MakgW92het5laXZa .cluster span{color:#333;}#mermaid-svg-MakgW92het5laXZa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MakgW92het5laXZa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MakgW92het5laXZa rect.text{fill:none;stroke-width:0;}#mermaid-svg-MakgW92het5laXZa .icon-shape,#mermaid-svg-MakgW92het5laXZa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MakgW92het5laXZa .icon-shape p,#mermaid-svg-MakgW92het5laXZa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MakgW92het5laXZa .icon-shape .label rect,#mermaid-svg-MakgW92het5laXZa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MakgW92het5laXZa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MakgW92het5laXZa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MakgW92het5laXZa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-MakgW92het5laXZa .stepBox>*{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:1px!important;stroke-dasharray:4 4!important;}#mermaid-svg-MakgW92het5laXZa .stepBox span{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:1px!important;stroke-dasharray:4 4!important;}#mermaid-svg-MakgW92het5laXZa .techNode>*{fill:#ffffff!important;stroke:#6c757d!important;stroke-width:1px!important;}#mermaid-svg-MakgW92het5laXZa .techNode span{fill:#ffffff!important;stroke:#6c757d!important;stroke-width:1px!important;} 步骤4:execd 监听 + 用户进程管理
Sandbox内部
PID 1:execd (Go HTTP Server)
/code←代码执行
/command←命令执行
/files ←文件操作
/system←系统监控
PID N:用户进程组
(Python/Java/Node等)
步骤3:覆盖ENTRYPOINT
ENTRYPOINT /usr/bin/execd
先启动execd
→execd再fork用户进程
步骤2:docker cp / put_archive注入到容器
用户沙盒容器
(基于用户指定镜像)
/usr/bin/execd
(注入execd)
步骤1:从 execd 镜像提取二进制
opensandbox/execd:latest
/usr/bin/execd
(编译好的二进制)
关键优势:
- 镜像无关性:任何镜像都可注入
execd,无需预装特定工具 - 标准接口:
execd提供统一的HTTP API,屏蔽底层运行时差异 - 进程管理:
execd作为PID 1,可准确管理用户进程组,支持中断和清理
execd的路由定义(Go伪代码):
go
func main() {
router := mux.NewRouter()
// 代码执行
router.HandleFunc("/code", handleCodeExecute).Methods("POST")
router.HandleFunc("/code/{id}/interrupt", handleCodeInterrupt).Methods("POST")
router.HandleFunc("/code/context/{id}", handleCodeContext).Methods("POST")
// 命令执行
router.HandleFunc("/command", handleCommandExecute).Methods("POST")
router.HandleFunc("/command/{id}/interrupt", handleCommandInterrupt).Methods("POST")
// 文件操作
router.HandleFunc("/files/upload", handleFileUpload).Methods("POST")
router.HandleFunc("/files/download/{path}", handleFileDownload).Methods("GET")
// 系统监控
router.HandleFunc("/system/monitor", handleSystemMonitor).Methods("GET")
srv := &http.Server{Addr: ":8080", Handler: router}
log.Fatal(srv.ListenAndServe())
}
实战
通过pip安装:pip install opensandbox
Python SDK入门示例:
py
from opensandbox import Sandbox
from code_interpreter import CodeInterpreter
# 创建沙盒
sandbox = await Sandbox.create(
"opensandbox/code-interpreter:latest",
timeout=timedelta(minutes=10),
)
# 创建代码解释器会话
interpreter = await CodeInterpreter.create(sandbox)
# 执行Python代码
result = await interpreter.codes.run(
"print('Hello, Sandbox!')",
language=SupportedLanguage.PYTHON,
)
print(result.stdout)
# 多语言支持
java_result = await interpreter.codes.run(
"""
public class Hello {
public static void main(String[] args) {
System.out.println("Hello from Java!");
}
}
""",
language=SupportedLanguage.JAVA,
)
print(java_result.stdout)
# 清理
await sandbox.kill()
进阶示例:
py
import asyncio
from datetime import timedelta
from code_interpreter import CodeInterpreter, SupportedLanguage
from opensandbox import Sandbox
from opensandbox.models import WriteEntry
async def main() -> None:
sandbox = await Sandbox.create(
"sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:latest",
entrypoint= ["/opt/opensandbox/code-interpreter.sh"],
env={"PYTHON_VERSION": "3.11"},
timeout=timedelta(minutes=10),
)
async with sandbox:
execution = await sandbox.commands.run("echo 'Hello OpenSandbox!'")
print(execution.logs.stdout[0].text)
await sandbox.files.write_files([
WriteEntry(path="/tmp/hello.txt", data="Hello World", mode=644)
])
content = await sandbox.files.read_file("/tmp/hello.txt")
interpreter = await CodeInterpreter.create(sandbox)
# 单次执行
result = await interpreter.codes.run(
"""
import sys
print(sys.version)
result = 2 + 2
result
""",
language=SupportedLanguage.PYTHON,
)
print(result.result[0].text)
print(result.logs.stdout[0].text) # 3.11.14
await sandbox.kill()
if __name__ == "__main__":
asyncio.run(main())
提供Java/Kotlin SDK,安装依赖:
groovy
dependencies {
implementation("com.alibaba.opensandbox:sandbox:{latest_version}")
}
或
xml
<dependency>
<groupId>com.alibaba.opensandbox</groupId>
<artifactId>sandbox</artifactId>
<version>{latest_version}</version>
</dependency>
Java SDK集成示例省略,太简单。
提供CLI,安装命令:
bash
pip install opensandbox-cli
# or
uv tool install opensandbox-cli
命令行示例:
bash
osb config init
osb config set connection.domain localhost:8080
osb config set connection.protocol http
osb config set connection.api_key xxx
osb sandbox create --image python:3.12 --timeout 30m -o json
osb command run <sandbox-id> -o raw -- python -c "print(1 + 1)"
官方提供MCP服务器,可为MCP客户端如CC提供能力:沙盒创建、执行命令、文件操作等。
bash
pip install opensandbox-mcp
opensandbox-mcp --domain localhost:8080 --protocol http
在Cursor等MCP客户端添加如下配置:
json
{
"mcpServers": {
"opensandbox": {
"command": "opensandbox-mcp",
"args": ["--domain", "localhost:8080", "--protocol", "http"]
}
}
}
应用场景
如:
- Alibaba Coding Agent

- Coding产品评测环境
针对Coding产品的评测与验证,社区贡献Harbor这一卓越的环境驱动框架。通过对评测环境的高度封装,确保测试过程的一致性与可复现性。针对复杂Agent评测中单机效率低下的痛点,Harbor凭借出色的工程化弹性伸缩能力,能够调度成千上万个环境进行大规模并行测试。而OpenSandbox则作为底层基础设施,为这一高效评测流程提供理想的沙箱环境与性能支撑。

- Agentic RL训练环境
强化学习(RL)训练Agent依赖高频的环境交互与海量的样本数据采集,OpenSandbox为Agentic RL构建高性能的基础设施支撑:
- 极致并发与秒级响应:通过资源池化与预创建机制,支持数千个沙箱并发运行,实现环境的秒级分配。
- 高效任务编排:内置任务执行引擎,支持异构任务的灵活分发,确保每个沙箱可独立承担不同的训练指令。
- 强力状态隔离:各训练环境互不干扰,确保样本数据的独立性与实验结果的可复现性。
- 弹性资源管理:根据训练负载动态分配与回收资源,极大优化集群整体的资源利用率。
目前,OpenSandbox已在阿里大规模Agentic RL训练场景中得到实证,显著缩短训练周期并提升算力效率。

- Remote Agent Sandbox
支持将CC、Gemini CLI等Agent实例封装在远程沙箱中,通过将Agent行为远程化,解决本地环境配置复杂与安全合规问题:
- 环境隔离与沙箱化:通过远程部署实现Agent执行环境与宿主机的完全解耦,消除环境污染风险。
- 灵活的运行时预设:支持针对异构Agent定制专属运行时(Runtime),包括特定版本的编程语言环境与依赖包。
- 计算下沉与远程执行:核心代码执行逻辑下沉至云端沙箱,本地仅承载交互指令与结果渲染,实现轻量化办公。

官方提供丰富的沙箱使用案例
