openai-agents-python 沙箱客户端完全指南:本地、Docker 与托管后端的选型与挂载实战
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
本文以 openai-agents-python 仓库的沙箱客户端文档为主体,系统讲解沙箱工作负载的三种运行位置——UnixLocalSandboxClient(macOS/Linux 本地文件系统)、DockerSandboxClient(容器隔离)与各类托管沙箱客户端(E2B、Modal、Cloudflare、Blaxel、Daytona、Runloop、Vercel)。读完本文,你将掌握:如何保持SandboxAgent定义不变、仅通过SandboxRunConfig切换执行后端;如何配置 Docker 网络与镜像;如何理解并选用mount_path、read_only、mount_strategy三种挂载要素;如何为 Modal 沙箱指定 CPU/内存资源;以及托管挂载的凭证边界确认机制。
注意:沙箱 Agent 目前仍处于Beta 阶段。正式发布前,API 细节、默认值与支持能力都可能发生变化,SDK 也会随时间加入更多高级特性(参见 docs/sandbox/clients.md)。
决策指南:把沙箱工作放在哪里
沙箱客户端决定"沙箱工作在哪里执行"。多数场景下,SandboxAgent的定义保持不变,你只需要在SandboxRunConfig中替换沙箱客户端(client)与客户端专属选项(options)即可。官方文档给出的决策建议如下:
| 目标 | 起点 | 理由 |
|---|---|---|
| macOS 或 Linux 上最快的本地迭代开发 | UnixLocalSandboxClient | 无需额外安装,直接在本地文件系统上做简单开发 |
| 基础容器隔离 | DockerSandboxClient | 在带有特定镜像的 Docker 内部执行工作 |
| 托管执行或生产级隔离 | 托管沙箱客户端 | 把工作空间边界移交给供应商托管的运行环境 |
从源码结构看,两个本地客户端均实现自BaseSandboxClient/BaseSandboxClientOptions(见 src/agents/sandbox/session/sandbox_client.py),托管客户端则位于agents.extensions.sandbox扩展包中。这意味着"换后端不换 Agent"的设计是有底层抽象支撑的:客户端负责创建会话、执行命令、读写工作空间,而 Agent 只需描述任务与 manifest。
本地客户端:UnixLocal 与 Docker
对于大多数用户,推荐从以下两个沙箱客户端之一开始:
| 客户端 | 安装方式 | 何时选择 | 示例 |
|---|---|---|---|
UnixLocalSandboxClient | 无需安装 | 需要在 macOS 或 Linux 上做最快的本地迭代,是本地开发的良好默认项 | examples/sandbox/unix_local_runner.py |
DockerSandboxClient | openai-agents[docker] | 需要容器隔离,或希望用特定镜像在本地复现目标环境 | examples/sandbox/docker/docker_runner.py |
Unix 本地客户端是面向本地文件系统开始开发的最简单途径。当需要更强的环境隔离或生产级一致性时,再切换到 Docker 或托管供应商。
UnixLocalSandboxClient 的实现要点
从源码看(src/agents/sandbox/sandboxes/unix_local.py):
- 平台限制:模块在
sys.platform == "win32"时直接抛出ImportError,提示 Windows 上应改用DockerSandboxClient或其他后端(unix_local.py#L3-L7)。 - 本地工作空间:会话以 host 文件系统为工作空间,根目录由
manifest.root指定;启动时自动mkdir(parents=True, exist_ok=True)创建工作区(_prepare_backend_workspace)。 - manifest 限制:
UnixLocalSandboxSession不支持 manifest 中的users/groups(因为账号预置会在宿主机上执行),也不支持SandboxPathGrant.host_path的跨路径映射,只支持同路径授权。 - macOS 沙箱增强:在 Darwin 平台上,SDK 会用系统
sandbox-exec生成沙箱 profile,把命令执行限制在工作空间与显式授权的额外路径内,默认拒绝/Users、/Volumes、/Applications、/etc、/tmp等敏感目录(_darwin_exec_profile,见 unix_local.py#L811-L876),并对宿主环境变量做了白名单过滤(_HOST_ENVIRONMENT_ALLOWLIST)。
参考 examples/sandbox/unix_local_runner.py 可以了解完整用法:它构造一个包含account_brief.md、renewal_request.md等文件的 manifest,通过extra_path_grants为沙箱授予外部目录的只读/读写路径权限,再用SandboxAgent+RunConfig(sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()))运行(unix_local_runner.py#L134-L179)。
从 UnixLocal 切换到 Docker
从 Unix 本地切换到 Docker 时,Agent 定义保持不变,只需改运行配置:
from docker import from_env as docker_from_env from agents.run import RunConfig from agents.sandbox import SandboxRunConfig from agents.sandbox.sandboxes.docker import DockerSandboxClient, DockerSandboxClientOptions run_config = RunConfig( sandbox=SandboxRunConfig( client=DockerSandboxClient(docker_from_env()), options=DockerSandboxClientOptions(image="python:3.14-slim"), ), )DockerSandboxClientOptions在源码中定义如下关键字段(src/agents/sandbox/sandboxes/docker.py#L213-L243):
image(必填):容器镜像,例如python:3.14-slim(agents.sandbox.config中的DEFAULT_PYTHON_SANDBOX_IMAGE默认值即为"python:3.14-slim")。exposed_ports:需要暴露的容器端口元组,默认()。network_mode:唯一显式支持的取值是"none",省略时保留 Docker 默认网络行为;也可以传入None。labels:附加到容器的标签字典,默认{}。
当你需要容器隔离、或希望沙箱镜像与另一个环境使用的镜像保持一致时,就采用这种方式。完整示例见 examples/sandbox/docker/docker_runner.py。
禁用 Docker 网络
当 Docker 沙箱必须没有任何网络访问能力时,设置network_mode="none":
options = DockerSandboxClientOptions( image="python:3.14-slim", network_mode="none", )源码层面对此做了严格校验:_validate_docker_network_configuration规定,当network_mode == "none"且exposed_ports非空时直接抛出ValueError("exposed_ports cannot be used when network_mode='none'")(docker.py#L174-L180),因为无网络沙箱无法暴露端口。该校验同时挂载在DockerSandboxClientOptions和DockerSandboxSessionState的 pydantic model validator 上。此外,network_mode会被写入DockerSandboxSessionState会话状态(docker.py#L183-L196),当 SDK 在恢复会话状态时需要创建替代容器时,该配置会被重新应用。
挂载与远程存储
挂载条目(mount entry)描述"暴露哪些存储",挂载策略(mount strategy)描述"沙箱后端如何挂接这些存储"。内置挂载条目与通用策略从agents.sandbox.entries导入(见 src/agents/sandbox/entries/init.py),托管供应商的策略则从agents.extensions.sandbox或供应商专属扩展包导入。
通用挂载选项
mount_path:存储出现在沙箱中的位置。相对路径基于 manifest 根目录解析,绝对路径原样使用。从源码看,Mount._resolve_mount_path_for_root在mount_path为绝对路径时直接返回该路径,为相对路径时拼接到 manifest root 下(src/agents/sandbox/entries/mounts/base.py#L536-L566)。read_only:默认True;仅当沙箱需要把变更写回挂载存储时才设为False。注意:Mount类中的 permissions 字段实际不生效——源码model_post_init会警告 "Mount permissions are not enforced" 并重置为默认值,访问控制应在云存储供应商侧配置(base.py#L395-L419)。mount_strategy:必填。必须同时匹配挂载条目与沙箱后端。
挂载被视为临时工作空间条目:快照(snapshot)与持久化流程会分离或跳过挂载路径,而不是把挂载的远程存储复制进已保存的工作空间。
通用本地/容器策略
| 策略或模式 | 使用时机 | 备注 |
|---|---|---|
InContainerMountStrategy(pattern=RcloneMountPattern(...)) | 沙箱镜像可以运行rclone | 支持 S3、GCS、R2、Azure Blob 和 Box。RcloneMountPattern可运行在fuse模式或nfs模式 |
InContainerMountStrategy(pattern=MountpointMountPattern(...)) | 镜像带有mount-s3,且需要 Mountpoint 风格的 S3 或 S3 兼容访问 | 支持S3Mount和GCSMount |
InContainerMountStrategy(pattern=FuseMountPattern(...)) | 镜像带有blobfuse2与 FUSE 支持 | 支持AzureBlobMount |
InContainerMountStrategy(pattern=S3FilesMountPattern(...)) | 镜像带有mount.s3files,且可访问既有的 S3 Files 挂载目标 | 支持S3FilesMount |
DockerVolumeMountStrategy(driver=...) | 需要在容器启动前由 Docker 挂接基于卷驱动器的挂载 | 仅限 Docker。S3、GCS、R2、Azure Blob、Box 可通过rclone挂载;S3 和 GCS 也可通过mountpoint挂载 |
从源码看,策略体系建立在MountStrategyBase(抽象基类)之上,并通过 pydantic 子类注册表按type字段反序列化;InContainerMountStrategy在激活挂载前会调用validate_mount_activation_credential_boundary做凭证边界校验(base.py#L228-L256)。各模式的具体执行逻辑位于 src/agents/sandbox/entries/mounts/patterns.py:
RcloneMountPattern:fuse模式执行rclone mount --daemon;nfs模式先启动rclone serve nfs再执行mount -t nfs,默认nfs_addr为127.0.0.1:2049,挂载选项默认vers=4.1,tcp,soft,timeo=50,retrans=1(patterns.py#L686-L990)。MountpointMountPattern:调用mount-s3,无凭证时附加--no-sign-request;GCS 挂载会追加--upload-checksums off(GCS XML API 不接受默认上传校验流程)(patterns.py#L438-L575)。FuseMountPattern:生成 blobfuse2 YAML 配置并执行blobfuse2 mount --read-only --config-file ...,支持 block_cache / file_cache 两种缓存类型(patterns.py#L173-L435)。S3FilesMountPattern:执行mount -t s3files,通过-o选项传入ro、mounttargetip、accesspoint、region等参数(patterns.py#L578-L651)。
注意:挂载前的工具检查(如command -v rclone、command -v blobfuse2、command -v mount-s3)失败时会抛出MountToolMissingError,提示镜像缺少对应挂载工具。
支持的托管平台
当需要托管环境时,通常沿用同一个SandboxAgent定义,仅在SandboxRunConfig中更换沙箱客户端。若你使用的是已发布的 SDK(而非本仓库 checkout),请通过对应的包 extra 安装沙箱客户端依赖。仓库内扩展示例的供应商专属配置说明见 examples/sandbox/extensions/README.md。
| 客户端 | 安装 | 示例 |
|---|---|---|
BlaxelSandboxClient | openai-agents[blaxel] | examples/sandbox/extensions/blaxel_runner.py |
CloudflareSandboxClient | openai-agents[cloudflare] | examples/sandbox/extensions/cloudflare_runner.py |
DaytonaSandboxClient | openai-agents[daytona] | examples/sandbox/extensions/daytona/daytona_runner.py |
E2BSandboxClient | openai-agents[e2b] | examples/sandbox/extensions/e2b_runner.py |
ModalSandboxClient | openai-agents[modal] | examples/sandbox/extensions/modal_runner.py |
RunloopSandboxClient | openai-agents[runloop] | examples/sandbox/extensions/runloop/runner.py |
VercelSandboxClient | openai-agents[vercel] | examples/sandbox/extensions/vercel_runner.py |
扩展示例的通用流程是:在内存中构建一个小型 manifest → 创建SandboxAgent通过一个 shell 工具检查工作空间 → 对 E2B、Modal、Daytona、Cloudflare、Runloop、Blaxel 或 Vercel 运行 Agent。所有示例都需要OPENAI_API_KEY(模型调用走标准Runner路径),且每个云后端还需要各自的供应商凭证(见 examples/sandbox/extensions/README.md)。
Modal 沙箱大小设置
使用ModalSandboxClientOptions.cpu与ModalSandboxClientOptions.memory为新 Modal 沙箱请求资源:
from agents.extensions.sandbox import ModalSandboxClientOptions options = ModalSandboxClientOptions( app_name="agents-sandbox", cpu=(1.0, 4.0), memory=(2048, 8192), )参数语义:单个数值表示"请求该数量";两项(request, limit)元组中,第一项是请求值(request),第二项是上限值(limit)。内存单位是 MiB。将cpu、memory或两者设为None,则使用 Modal 对每个省略资源的默认值。所选值会保存在沙箱会话状态中,因此替代沙箱(replacement sandbox)会沿用相同的资源配置。
托管后端的挂载策略
托管沙箱客户端各自暴露供应商专属挂载策略,应根据存储供应商选择最合适的后端与策略:
| 后端 | 挂载说明 |
|---|---|
| Docker | 通过InContainerMountStrategy、DockerVolumeMountStrategy等本地策略支持S3Mount、GCSMount、R2Mount、AzureBlobMount、BoxMount和S3FilesMount |
ModalSandboxClient | 通过ModalCloudBucketMountStrategy搭配S3Mount、R2Mount与 HMAC 认证的GCSMount支持云桶挂载;可使用内联凭证或具名 Modal Secret |
CloudflareSandboxClient | 通过CloudflareBucketMountStrategy搭配S3Mount、R2Mount与 HMAC 认证的GCSMount支持桶挂载 |
BlaxelSandboxClient | 通过BlaxelCloudBucketMountStrategy搭配S3Mount、R2Mount或GCSMount条目支持云桶挂载;还通过BlaxelDriveMount与BlaxelDriveMountStrategy支持持久化 Blaxel Drives,两者均位于agents.extensions.sandbox.blaxel |
DaytonaSandboxClient | 通过DaytonaCloudBucketMountStrategy使用rclone挂载云存储;搭配S3Mount、GCSMount、R2Mount、AzureBlobMount与BoxMount |
E2BSandboxClient | 通过E2BCloudBucketMountStrategy使用rclone挂载云存储;搭配S3Mount、GCSMount、R2Mount、AzureBlobMount与BoxMount |
RunloopSandboxClient | 通过RunloopCloudBucketMountStrategy使用rclone挂载云存储;搭配S3Mount、GCSMount、R2Mount、AzureBlobMount与BoxMount |
VercelSandboxClient | 通过VercelCloudBucketMountStrategy搭配S3Mount条目支持仅创建期(create-time)的 S3 与 S3 兼容桶挂载;被挂载的会话不可恢复,使用内联凭证需要allow_s3_credential_exposure=True |
凭证边界与确认机制
挂载表描述的是"每个后端可执行哪些存储类型"。对号(✓)并不代表绕过了模型可控沙箱内挂载助手的凭证边界,也不代表每种策略都能无凭证运行。Agents SDK 的规则是:
- 仅当所选挂载助手可以在无受保护权限的情况下运行时,才允许无确认(acknowledgement)的容器内挂载;
- 需要受保护权限的挂载,除非可信应用程序代码对精确的挂载路径显式确认该暴露,否则会在启动沙箱或挂载助手之前被拒绝。
凭证细则:
- 无凭证的
rclone挂载仅限 S3、GCS、R2 与 Azure Blob; - 容器内 Box 挂载需要非交互式认证源,以及与该认证源匹配的确认;
FuseMountPattern需要宽泛确认(broad acknowledgement),因为即使未配置内联凭证,blobfuse2也会探测环境中的 Azure 权限;S3FilesMountPattern同样需要宽泛确认,因为mount.s3files会使用环境 IAM 权限;- 这些要求在 Docker 作为后端时同样适用——下表的对号表示"满足相应权限边界后 Docker 可以执行该挂载"。
对于名为"data"的挂载条目,保留与已配置权限匹配的确认所返回的Manifest副本:
# Mount-scoped values such as inline access keys. manifest = manifest.with_in_container_mount_credential_exposure_acknowledged("data") # Broader authority such as managed or workload identity and external credential files. manifest = manifest.with_in_container_mount_broad_credential_exposure_acknowledged("data")要点:为每个需要确认的精确挂载路径调用确认方法;同时使用两类权限的挂载需要两个确认。确认仅运行时生效、不会序列化,且允许助手接收凭证而不把凭证使用范围限制在挂载路径内。因此,文档建议:尽可能优先使用外部或供应商原生策略;否则使用沙箱范围内的、短生命周期的、最小权限凭证。
VercelSandboxClientOptions(allow_s3_credential_exposure=True)仅作为兼容选项保留,用于创建期 Vercel S3 挂载配合挂载范围内的内联凭证;它不授权宽泛凭证权限。
各后端可直接挂载的远程存储矩阵
| 后端 | AWS S3 | Cloudflare R2 | GCS | Azure Blob Storage | Box | S3 Files |
|---|---|---|---|---|---|---|
| Docker | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
ModalSandboxClient | ✓ | ✓ | ✓ | - | - | - |
CloudflareSandboxClient | ✓ | ✓ | ✓ | - | - | - |
BlaxelSandboxClient | ✓ | ✓ | ✓ | - | - | - |
DaytonaSandboxClient | ✓ | ✓ | ✓ | ✓ | ✓ | - |
E2BSandboxClient | ✓ | ✓ | ✓ | ✓ | ✓ | - |
RunloopSandboxClient | ✓ | ✓ | ✓ | ✓ | ✓ | - |
VercelSandboxClient | ✓ | - | - | - | - | - |
更多可运行示例
- 本地、编码(coding)、内存(memory)、交接(handoff)与 Agent 组合模式:浏览 examples/sandbox/(例如 basic.py、memory.py、handoffs.py、sandbox_agents_as_tools.py);
- 托管沙箱客户端:浏览 examples/sandbox/extensions/(每个供应商的 runner 脚本及 README.md 中的环境变量与运行方式说明)。
小结
选型路径可以概括为一条主线:本地迭代先用UnixLocalSandboxClient,需要隔离与镜像一致性切换到DockerSandboxClient,需要生产级托管再换托管客户端——三种场景下SandboxAgent定义基本不动,只改SandboxRunConfig。挂载体系则遵循"条目描述存储、策略决定挂接方式"的分层设计:通用场景优先InContainerMountStrategy配RcloneMountPattern等模式,Docker 卷驱动场景用DockerVolumeMountStrategy;涉及云存储凭证时,务必理解精确路径确认与宽泛确认的边界,并优先采用短生命周期、最小权限的外部或供应商原生凭证方案。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考