OpenAI Agents SDK 沙箱 Agent 快速上手:为模型提供持久化工作区的完整实战指南
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
导读
本指南基于 OpenAI Agents SDK 的Sandbox Agents(沙箱 Agent)功能,讲解如何为模型提供一个具备真实文件系统的持久化工作区,让 Agent 可以检索大型文档集合、编辑文件、执行 Shell 命令、生成产物,并从保存的沙箱状态中恢复未完成的工作。读完本文后,你将掌握SandboxAgent、Manifest、Capabilities与SandboxRunConfig四个核心构件的用法,能够从零搭建一个可运行的本地沙箱编码 Agent,并理解沙箱会话的生命周期与常见组合模式。
注意:功能处于 Beta 阶段。在正式发布(GA)之前,API 细节、默认值和支持的能力都可能发生变化,未来也会持续加入更高级的功能。
上图展示了沙箱 Agent 的执行框架:外部服务(Server/Agent Harness)以工具或 API 调用的方式启动编码 Agent,任务进入沙箱(Sandbox)内的 Agent 循环,由文件系统、MCP/Tools 支撑执行,对外部网络请求则由网关服务(Gateway Service)统一拦截以保证安全。
沙箱 Agent 是什么:为什么需要持久化工作区
现代 Agent 只有在能够操作文件系统中的真实文件时才能发挥最大效能。沙箱 Agent 的核心思路是:给模型一个持久化的工作区,在这个工作区里它可以:
- 搜索和阅读大型文档集合;
- 编辑文件(通过
apply_patch等工具); - 运行 Shell 命令并查看输出;
- 生成报告、代码补丁、税表草稿等产物;
- 在后续运行中通过保存的沙箱状态接续之前的工作。
SDK 的目的不是让你自己把"文件暂存、文件系统工具、Shell 访问、沙箱生命周期、快照、供应商特定胶水代码"逐一拼装起来,而是让你延续原有的Agent+Runner编程模型,只需额外声明三样东西:
Manifest—— 定义全新沙箱会话的工作区内容(文件、仓库、目录、挂载);Capabilities—— 为 Agent 附加沙箱原生工具(文件系统、Shell、技能、记忆、压缩);SandboxRunConfig—— 决定本次运行在哪个沙箱后端、以何种方式获得沙箱会话。
从源码结构看,SandboxAgent本质上是Agent的扩展:在 src/agents/sandbox/sandbox_agent.py 中,SandboxAgent(Agent[TContext])继承了普通 Agent 的全部表面(instructions、prompt、tools、handoffs、mcp_servers、model_settings、output_type、guardrails、hooks),仅额外增加了default_manifest、base_instructions、capabilities、run_as四个沙箱专属字段,并且仍通过常规的Runner.run()/Runner.run_sync()/Runner.run_streamed()API 执行。改变的只是执行边界,而不是 Agent 模型本身。
何时该用沙箱 Agent,何时不该
以下工作流非常适合沙箱 Agent:
- 编码与调试:针对 GitHub issue 自动修复代码并运行针对性测试;
- 文档处理与编辑:从用户的财务文档中抽取信息,生成完成的税表草稿;
- 基于文件的审查/分析:先检查入职材料包、生成的报告或产物包,再给出回答;
- 隔离的多 Agent 模式:为每个审查者或编码子 Agent 分配独立工作区;
- 多步骤工作区任务:一次运行修 Bug,下一次运行补回归测试,或从快照/会话状态恢复。
反过来,如果你的任务不需要访问文件或有状态的、可变的文件系统,请继续使用普通Agent。如果 Shell 访问只是偶尔用一下的工具,可以从 工具指南 中介绍的 hosted shell 开始;只有当工作区隔离、沙箱客户端选择、沙箱会话恢复行为成为设计的一部分时,才应该使用沙箱 Agent。
前置条件与安装
前置条件:
- Python 3.10 或更高版本;
- 对 OpenAI Agents SDK 有基本了解;
- 一个沙箱客户端。本地开发建议从
UnixLocalSandboxClient开始。
安装 SDK:
pip install openai-agents如果使用 Docker 后端沙箱,安装 Docker 扩展:
pip install "openai-agents[docker]"在 src/agents/sandbox/sandboxes/unix_local.py 中,UnixLocalSandboxClient实现了BaseSandboxClient接口,backend_id = "unix_local",在 macOS / Linux 上直接以本地进程 + 临时目录的方式运行沙箱;而在 src/agents/sandbox/sandboxes/docker.py 中,DockerSandboxClient(backend_id = "docker")则通过容器提供隔离。Windows 平台上建议使用DockerSandboxClient或托管供应商。
创建第一个本地沙箱 Agent(完整示例)
下面这段完整示例(源自 examples/sandbox/docs/coding_task.py,对应的快速入门文档为 docs/sandbox_agents.md)完成了三件事:把本地repo/目录暂存进沙箱工作区、延迟加载本地技能(skills)、让 Runner 为本次运行创建 Unix 本地沙箱会话:
import asyncio from pathlib import Path from agents import Runner from agents.run import RunConfig from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig from agents.sandbox.capabilities import Capabilities, LocalDirLazySkillSource, Skills from agents.sandbox.entries import LocalDir from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient EXAMPLE_DIR = Path(__file__).resolve().parent HOST_REPO_DIR = EXAMPLE_DIR / "repo" HOST_SKILLS_DIR = EXAMPLE_DIR / "skills" def build_agent(model: str) -> SandboxAgent[None]: return SandboxAgent( name="Sandbox engineer", model=model, instructions=( "Read `repo/task.md` before editing files. Stay grounded in the repository, preserve " "existing behavior, and mention the exact verification command you ran. " "If you edit files with apply_patch, paths are relative to the sandbox workspace root." ), default_manifest=Manifest( entries={ "repo": LocalDir(src=HOST_REPO_DIR), } ), capabilities=Capabilities.default() + [ Skills( lazy_from=LocalDirLazySkillSource( # This is a host path read by the SDK process. # Requested skills are copied into `skills_path` in the sandbox. source=LocalDir(src=HOST_SKILLS_DIR), ) ), ], ) async def main() -> None: result = await Runner.run( build_agent("gpt-5.6-sol"), "Open `repo/task.md`, fix the issue, run the targeted test, and summarize the change.", run_config=RunConfig( sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()), workflow_name="Sandbox coding example", ), ) print(result.final_output) if __name__ == "__main__": asyncio.run(main())逐段拆解这个示例:
default_manifest=Manifest(entries={"repo": LocalDir(src=HOST_REPO_DIR)}):声明"新建沙箱会话时,把宿主机的HOST_REPO_DIR目录内容物化到工作区根目录下的repo/路径"。LocalDir是工作区条目之一,其src默认相对于 SDK 进程的工作目录解析(详见 src/agents/sandbox/entries/artifacts.py 中LocalDir的实现)。capabilities=Capabilities.default() + [Skills(...)]:Capabilities.default()返回[Filesystem(), Shell(), Compaction()](见 src/agents/sandbox/capabilities/capabilities.py)。这里用+追加了Skills能力。注意:如果你改用capabilities=[...]直接赋值,会替换掉默认列表,需要把仍然想要的默认能力一并写上。Skills(lazy_from=LocalDirLazySkillSource(source=LocalDir(src=HOST_SKILLS_DIR))):这是大型本地技能目录的推荐做法——SDK 先把技能索引(名称 + 描述 + 路径)注入指令,模型需要时再通过load_skill工具把单个技能按需物化进沙箱。LocalDir.src是 SDK 进程所在宿主机上的路径,不是只存在于沙箱镜像或工作区内部的路径。SandboxRunConfig(client=UnixLocalSandboxClient()):这是"沙箱后端"的注入点。client缺省时,Runner 会负责创建、恢复并清理沙箱会话。
该示例使用了一个小型、基于 Shell 脚本的仓库(repo/内是credit_note.sh等文件,测试命令为sh tests/test_credit_note.sh),因此可以在 Unix 本地执行环境中被确定性验证——同一份代码在多次运行中的行为可复现。
关键选择:七个决定沙箱行为的设计旋钮
基础运行跑通之后,大多数人接下来会调整这些选项(这也是沙箱 Agent 设计的核心决策面):
| 选项 | 作用 | 备注 |
|---|---|---|
default_manifest | 新沙箱会话中的文件、仓库、目录与挂载 | 仅作为默认值,运行时可被SandboxRunConfig(manifest=...)覆盖 |
instructions | 跨提示词稳定的短小工作流规则 | 追加在 SDK 沙箱基础提示词之后 |
base_instructions | 替换 SDK 沙箱基础提示词的高级逃生舱 | 大多数 Agent 不应设置 |
capabilities | 沙箱原生工具:文件系统编辑/图片检查、Shell、技能、记忆、压缩机制 | 直接赋值会替换默认集合 |
run_as | 模型可见工具(Shell、文件读取、补丁)执行所用的沙箱用户账户 | 用户需先出现在 manifest 中,否则 Runner 会自动补加 |
SandboxRunConfig.client | 沙箱后端(Unix 本地 / Docker / 托管供应商) | 决定工作在哪里执行 |
SandboxRunConfig.session/session_state/snapshot | 后续运行如何接续之前的工作 | 分别对应:注入在线会话、反序列化会话状态、从快照播种 |
下面逐一深入。
1.default_manifest:定义全新工作区的契约
default_manifest是 Runner 为该 Agent 创建全新沙箱会话时使用的默认Manifest。它的职责是声明"工作开始时文件系统上应该有哪些文件和文件夹"。
Manifest在 src/agents/sandbox/manifest.py 中定义,是一个 pydantic 模型,可配置项包括:
root:工作区根目录,默认为/workspace;entries:工作区条目字典,key 是工作区相对路径,value 是BaseEntry的各类子类;environment:环境变量;users/groups:沙箱内的用户与用户组身份;extra_path_grants:工作区之外的绝对路径访问授权;remote_mount_command_allowlist:远程挂载场景下的命令白名单(默认包含ls、find、cat、grep、rg、cp等常用只读/复制命令)。
常用的工作区条目类型如下:
| 条目 | 适用场景 |
|---|---|
File、Dir | 小型合成输入、辅助文件或输出目录(Dir在沙箱内创建目录,不从宿主机读取) |
LocalFile、LocalDir | 需要物化进沙箱的宿主机文件/目录(LocalDir才是"复制宿主机已有目录"的正确选择) |
GitRepo | 需要抓取进工作区的 Git 仓库 |
S3Mount、GCSMount、R2Mount、AzureBlobMount、BoxMount、S3FilesMount等挂载 | 需要出现在沙箱内的外部存储 |
两条重要的路径约束(源码中由_validate_rel_path/_normalize_rel_path_within_root强制):
- 条目路径必须是工作区相对路径,不能是绝对路径,也不能用
..逃逸工作区——这保证了 manifest 契约在本地、Docker、托管客户端之间可移植; LocalFile.src/LocalDir.src默认相对 SDK 进程工作目录解析,且必须位于该基准目录之内,除非通过extra_path_grants显式授权。
Manifest是"全新会话的工作区契约",不是每个在线沙箱的完整事实来源。一次运行的有效工作区可能来自:复用的沙箱会话、序列化的沙箱会话状态、或运行时选择的快照。manifest 只约束"由 Runner 新建沙箱会话"的场景。
2.instructions与base_instructions:指令的分层
在SandboxAgent中,最终指令按固定顺序拼接:SDK 默认沙箱提示词(或你显式覆盖的base_instructions)→instructions→ 各能力注入的指令片段 → 远程挂载策略文本 → 渲染后的文件系统树。
instructions:追加在 SDK 沙箱基础提示词之后,适合放稳定的角色、工作流规则与成功标准。例如:"检查入职文档,然后交接(hand off)"、"把最终文件写入output/"。base_instructions:整体替换 SDK 沙箱基础提示词,属于高级逃生舱,大多数 Agent 不应设置。
参考示例中对instructions的良好运用:
- examples/sandbox/unix_local_pty.py:当 PTY 状态重要时,让 Agent 保持在一个交互式进程中;
- examples/sandbox/handoffs.py:禁止沙箱审查者在检查之后直接回答用户;
- examples/sandbox/tax_prep.py:要求最终填好的文件确实落在
output/中; - examples/sandbox/docs/coding_task.py:固定确切的验证命令,并明确"当
SandboxRunConfig.cwd未设置时,补丁路径相对于工作区根目录"。
应该避免:把用户一次性任务抄进instructions、在指令里塞长参考材料(那属于 manifest 的职责)、重复内置能力已注入的工具文档、混入模型运行时不需要的本地安装说明。
指令内容的放置决策可参考下表:
| 放在哪里 | 用途 | 示例 |
|---|---|---|
instructions | 稳定的角色、工作流规则、成功标准 | "检查入职文档,然后交接。"、"把最终文件写入output/。" |
base_instructions | 完全替换 SDK 沙箱基础提示词 | 自定义底层沙箱包装提示词 |
| 用户提示词 | 本次运行的一次性请求 | "总结这个工作区。" |
| manifest 中的工作区文件 | 更长的任务说明、仓库本地指令、有界参考材料 | repo/task.md、文档包、样例包 |
3.capabilities:沙箱原生行为
Capability 可以为SandboxAgent附加沙箱原生行为:在运行开始前塑造工作区、追加沙箱专属指令、暴露绑定到在线沙箱会话的工具、调整模型行为或输入处理。内置能力如下:
| 能力 | 何时添加 | 说明 |
|---|---|---|
Shell | Agent 需要 Shell 访问 | 提供exec_command;当沙箱客户端支持 PTY 交互时还提供write_stdin |
Filesystem | Agent 需要编辑文件或检查本地图片 | 提供apply_patch与view_image;相对路径默认以工作区根为基准,配置SandboxRunConfig.cwd后以其为基准 |
Skills | 需要在沙箱中进行技能发现与物化 | 优先于手动挂载.agents/.agents/skills;由Skills代为索引与物化技能 |
Memory | 后续运行应读取或生成记忆产物 | 依赖Shell;运行中更新记忆产物还需要Filesystem |
Compaction | 长流程需要上下文裁剪 | 调整模型采样参数与输入处理 |
默认能力集合:SandboxAgent.capabilities默认使用Capabilities.default(),即Filesystem() + Shell() + Compaction()(见 src/agents/sandbox/capabilities/capabilities.py)。若显式传capabilities=[...],将替换默认集合。
Shell 能力的内部结构:在 src/agents/sandbox/capabilities/shell.py 中,Shell.tools()构造ShellToolSet:exec_command绑定会话与run_as用户;当session.supports_pty()为真时额外提供write_stdin。注入的指令提示模型:优先用rg/rg --files做文本发现、不要用 Python 脚本打印大文件块、通过write_stdin发送 Ctrl-C(\u0003)中断长任务。
Filesystem 能力的内部结构:在 src/agents/sandbox/capabilities/filesystem.py 中,Filesystem.tools()返回view_image与apply_patch两个工具。其中view_image通过文件内容而非扩展名识别 PNG、JPEG、GIF、WebP、BMP、TIFF 栅格图像:内容不支持的"栅格扩展名"文件会被拒绝,而内容受支持、扩展名无关的文件也能加载;对.svg/.svgz则保留基于文件名的兼容判定,同时也会从内容识别 SVG 标记。
Skills 能力的三种来源:
Skills(lazy_from=LocalDirLazySkillSource(source=LocalDir(src=...))):本地大技能目录的推荐默认,模型先看索引、按需加载;Skills(from_=LocalDir(src=...)):适合需要提前整体暂存的小型本地技能包;Skills(from_=GitRepo(repo=..., ref=...)):技能本身来自仓库时使用。
LocalDir.src是 SDK 宿主机上的源路径;skills_path(默认".agents")是沙箱工作区内的相对目标路径。如果你本地的技能已经以.agents/skills/<name>/SKILL.md的形式存在,把LocalDir(...)指向该源根目录,再用Skills(...)暴露即可。
从源码看(src/agents/sandbox/capabilities/skills.py),load_skill工具只有在配置了lazy_from时才暴露;技能索引由SKILL.md的 frontmatter(name、description)生成。内置能力能覆盖需求时应优先使用,只有内置能力覆盖不到的沙箱专属工具/指令面才值得写自定义 Capability。
4.run_as:沙箱内的执行身份
run_as指定模型可见的沙箱工具(Shell 命令、文件读取、补丁)以哪个沙箱用户执行。配合 manifest 中的users、groups与条目的Permissions,可以构建精细的权限模型。
在 src/agents/sandbox/types.py 中,Permissions分别存储 owner/group/other 三组权限位与directory标志,支持:
- 直接构造:
Permissions(owner=FileMode.READ | FileMode.WRITE, group=FileMode.NONE, other=FileMode.NONE); Permissions.from_str("drwxr-x---")从模式字符串解析;Permissions.from_mode(0o750)从 OS 模式推导。
典型用法(来自 docs/sandbox/guide.md 的"数据室分析员"示例):声明analyst用户,让dataroom/目录对 owner/group 只读可遍历、对 other 完全无权限,再给output/目录开放全部权限作为可写产物目录,最后run_as=analyst让沙箱动作以该身份执行——分析员能读数据室、写输出,但不能篡改原始数据。
5.SandboxRunConfig:每次运行的沙箱来源
SandboxRunConfig(定义于 src/agents/run_config.py)承载所有"本次运行"的沙箱决策。Runner 解析沙箱会话的顺序是:
- 显式注入
run_config.sandbox.session→ 直接复用该在线沙箱会话; - 否则若从
RunState恢复运行 → 恢复其中存储的沙箱会话状态; - 否则若传
run_config.sandbox.session_state→ 从显式序列化的会话状态恢复; - 否则 → 创建全新沙箱会话,使用
run_config.sandbox.manifest(若提供)或agent.default_manifest。
新建会话专用输入:
| 选项 | 何时使用 | 说明 |
|---|---|---|
manifest | 想要一次性覆盖全新会话工作区 | 省略时回退到agent.default_manifest |
snapshot | 全新沙箱会话应从快照播种 | 适合类恢复流程或远程快照客户端 |
options | 沙箱客户端需要创建期选项 | 常见于 Docker 镜像、Modal 应用名、E2B 模板、超时等客户端特定设置 |
物化控制:concurrency_limits=SandboxConcurrencyLimits(manifest_entries=..., local_dir_files=...)控制沙箱物化的并行度(默认均为 4,None表示不限制);archive_limits=SandboxArchiveLimits(max_input_bytes=..., max_extracted_bytes=..., max_members=...)控制归档解压的 SDK 侧资源检查(默认值分别为 1 GiB 输入、4 GiB 解压后、100,000 个成员,见 src/agents/run_config.py 中的DEFAULT_MAX_*常量)。archive_limits=None表示不启用 SDK 归档资源限制。
沙箱运行是如何准备的:原理与生命周期
运行准备五步
一次沙箱运行按以下顺序准备(详见 docs/sandbox/guide.md 的 "How a sandbox run is prepared"):
- 从
SandboxRunConfig解析沙箱会话:传session=...则复用在线会话,否则用client=...创建或恢复; - 确定本次运行的有效工作区输入:注入/恢复会话时以既有沙箱状态为准,否则从一次性 manifest 覆盖或
agent.default_manifest出发; - 让各 capability 处理得到的 manifest(capability 可以借此添加文件、挂载等工作区级行为);
- 按固定顺序构建最终指令:SDK 默认沙箱提示词(或被覆盖的
base_instructions)→instructions→ 能力指令片段 → 远程挂载策略文本 → 渲染的文件系统树; - 将能力工具绑定到在线沙箱会话,通过常规
RunnerAPI 运行准备好的 Agent。
关于"轮次(turn)"的重要澄清:沙箱化并不改变"一轮"的定义——一轮仍是一次模型步骤,而不是单条 Shell 命令或单个沙箱动作。沙箱侧操作与轮次之间没有固定的 1:1 映射:有些工作在沙箱执行层内部完成,有些则返回信息(工具结果、审批、其他状态)需要再走一次模型步骤。
两种生命周期模式
SDK 拥有(SDK-owned):沙箱只服务于一次运行。传入client(可选manifest、snapshot、options),Runner 负责创建/恢复 → 启动 → 运行 → 持久化快照 → 结束会话 → 清理 Runner 拥有的资源:
result = await Runner.run( agent, "Inspect the workspace and summarize what changed.", run_config=RunConfig( sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()), ), )开发者拥有(Developer-owned):你想要主动创建沙箱、跨多次运行复用同一个在线沙箱、运行后检查文件、在自建的沙箱上流式操作,或自己决定清理时机。传入session=...时 Runner 只使用该在线沙箱而不会替你关闭它:
sandbox = await client.create(manifest=agent.default_manifest) async with sandbox: run_config = RunConfig(sandbox=SandboxRunConfig(session=sandbox)) await Runner.run(agent, "Analyze the files.", run_config=run_config) await Runner.run(agent, "Write the final report.", run_config=run_config)上下文管理器是惯用形态:进入时启动沙箱,退出时执行会话清理生命周期。无法使用上下文管理器时,可显式调用生命周期方法:await sandbox.start()→ 运行 →await sandbox.stop()(仅持久化快照支持的工作区内容,不拆除沙箱)→await sandbox.aclose()(完整清理:运行 pre-stop 钩子、调用stop()、关闭沙箱资源与会话级依赖)。
快照:SnapshotSpec是全新沙箱会话工作区的快照策略(LocalSnapshotSpec用于本地持久快照,RemoteSnapshotSpec用于自建远程快照客户端;本地快照不可用时回退到 no-op 快照)。省略snapshot时,运行时在能够设置默认本地快照位置的情况下会尝试使用,否则回退为 no-op。挂载与临时路径不会被复制进快照作为持久工作区内容。
常用模式:同一 Agent,多种运行方式
在很多场景中,SandboxAgent定义保持不变,只改变沙箱客户端、会话来源或工作区来源。
切换沙箱客户端
保持 Agent 定义不变,只改运行配置。想要容器隔离或镜像一致性用 Docker;想要供应商托管执行用托管供应商。详见 沙箱客户端指南。
覆盖工作区(一次性的 manifest)
同一个 Agent 角色要跑不同仓库/任务包时,不必重建 Agent,只需在运行配置里换 manifest:
from agents.run import RunConfig from agents.sandbox import Manifest, SandboxRunConfig from agents.sandbox.entries import GitRepo from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient run_config = RunConfig( sandbox=SandboxRunConfig( client=UnixLocalSandboxClient(), manifest=Manifest( entries={ "repo": GitRepo(repo="openai/openai-agents-python", ref="main"), } ), ), )注入在线沙箱会话
需要显式生命周期控制、运行后检查或复制输出时注入在线会话(前面"开发者拥有"一节已展示)。参考 examples/sandbox/docs/coding_task.py 与 examples/sandbox/docker/docker_runner.py。
从会话状态恢复
如果你已经在RunState之外序列化了沙箱状态,可以让 Runner 直接从该状态重连:
serialized = load_saved_payload() restored_state = client.deserialize_session_state(serialized) run_config = RunConfig( sandbox=SandboxRunConfig( client=client, session_state=restored_state, ), )安全注意事项:会话状态序列化会省略原生的host_path值;恢复宿主路径授权需要你通过SandboxRunConfig.manifest或agent.default_manifest提供当前可信 manifest,否则恢复会在沙箱启动前失败。切勿从序列化或其他不可信输入推导宿主路径。会话状态与RunState序列化同样会移除云挂载凭证、含凭证的辅助配置与容器内凭证暴露确认;需要恢复挂载会话时,同样要提供当前可信 manifest。
从快照启动
新建沙箱会话时,从保存的文件与产物播种而不是仅从default_manifest出发:
from pathlib import Path from agents.run import RunConfig from agents.sandbox import LocalSnapshotSpec, SandboxRunConfig from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient run_config = RunConfig( sandbox=SandboxRunConfig( client=UnixLocalSandboxClient(), snapshot=LocalSnapshotSpec(base_path=Path("/tmp/my-sandbox-snapshot")), ), )参考 examples/sandbox/memory.py(本地快照流程)与 examples/sandbox/sandbox_agent_with_remote_snapshot.py(远程快照客户端)。
从 Git 加载技能
把本地技能源换成仓库托管的:
from agents.sandbox.capabilities import Capabilities, Skills from agents.sandbox.entries import GitRepo capabilities = Capabilities.default() + [ Skills(from_=GitRepo(repo="sdcoffey/tax-prep-skills", ref="main")), ]参考 examples/sandbox/tax_prep.py。
把沙箱 Agent 暴露为工具(Agent as Tool)
沙箱 Agent 可以作为工具被其他 Agent 调用,有两种边界选择:
复用父运行的在线沙箱——适合"快速只读探查"型工具 Agent:可以直接检查父运行正在使用的同一工作区,无需为创建、水合、快照再付一次代价。完整示例见 examples/sandbox/sandbox_agents_as_tools.py:协调者以coordinator身份运行,探查工具 Agent 以explorer身份在同一在线沙箱会话内运行;pricing_packet/对 other 用户可读,探查者能快速检查却无写权限,work/目录仅协调者的用户/组可写。
独立沙箱边界——当工具 Agent 需要自由修改、运行不可信命令或使用不同后端/镜像时:
from docker import from_env as docker_from_env from agents.run import RunConfig from agents.sandbox import SandboxAgent, SandboxRunConfig from agents.sandbox.sandboxes.docker import DockerSandboxClient, DockerSandboxClientOptions rollout_agent = SandboxAgent( name="Rollout Reviewer", instructions="Inspect the rollout packet and summarize implementation risk.", ) rollout_agent.as_tool( tool_name="review_rollout_risk", tool_description="Inspect the rollout packet and summarize implementation risk.", run_config=RunConfig( sandbox=SandboxRunConfig( client=DockerSandboxClient(docker_from_env()), options=DockerSandboxClientOptions(image="python:3.14-slim"), ), ), )与本地工具、MCP 组合
沙箱工作区与普通工具可以共存于同一 Agent:
from agents.sandbox import SandboxAgent from agents.sandbox.capabilities import Shell agent = SandboxAgent( name="Workspace reviewer", instructions="Inspect the workspace and call host tools when needed.", tools=[get_discount_approval_path], mcp_servers=[server], capabilities=[Shell()], )参考 examples/sandbox/sandbox_agent_with_tools.py。
组合与轮次:沙箱边界放在哪里
单 Agent 模式清晰之后,下一个设计问题是沙箱边界在更大系统中的位置。沙箱 Agent 仍与 SDK 其余部分自由组合:
- 交接(Handoffs):把文档密集型工作从非沙箱的 intake Agent 交给沙箱审查者(交接指南);
- Agent 即工具:把多个沙箱 Agent 暴露为工具,通常在每个
Agent.as_tool(...)调用上传run_config=RunConfig(sandbox=SandboxRunConfig(...)),让每个工具获得独立沙箱边界(工具指南); - MCP 与普通函数工具:沙箱能力可与
mcp_servers、普通 Python 工具共存(MCP 指南); - 运行 API:沙箱运行仍走常规
RunnerAPI(运行 Agent 指南)。
两种最常见的模式是:非沙箱 Agent 仅在工作流中需要工作区隔离的部分交接给沙箱 Agent;或由编排者把多个沙箱 Agent 暴露为工具,通常每个工具带独立沙箱RunConfig。
轮次语义的区分:
- 交接(handoff):仍然只有一个顶层运行、一个顶层轮次循环。活动 Agent 会变化,但运行不会嵌套——非沙箱 intake Agent 交接给沙箱审查者后,同一次运行的下一次模型调用按沙箱 Agent 准备,由沙箱 Agent 接管下一轮。参考 examples/sandbox/handoffs.py。
- Agent.as_tool(...):外层编排者用一次外层轮次决定调用工具,该工具调用启动沙箱 Agent 的嵌套运行。嵌套运行有自己的轮次循环、
max_turns、审批,通常还有自己的沙箱RunConfig。从外层编排者视角看,这些工作都在一次工具调用背后,因此嵌套轮次不计入外层运行的轮次计数。参考 examples/sandbox/sandbox_agents_as_tools.py。
审批行为遵循同样的划分:交接时审批留在同一顶层运行(沙箱 Agent 现在是该运行的活跃 Agent);Agent.as_tool(...)时,沙箱工具 Agent 内发起的审批仍浮现在外层运行,但来自存储的嵌套运行状态,外层运行恢复时会恢复嵌套沙箱运行。
Agent 记忆:跨运行保留经验
Memory能力用于让未来的沙箱 Agent 运行从前序运行中学习。它与 SDK 的对话式Session记忆不同:它把经验提炼成沙箱工作区内的文件,后续运行可以读取这些文件。参考 Agent 记忆指南,其中覆盖了配置、读取/生成行为、多轮对话与布局隔离。
下一步阅读
- 沙箱概念指南:深入理解 manifest、能力、权限、快照、运行配置与组合模式;
- 沙箱客户端指南:在 Unix 本地、Docker、托管供应商与挂载策略之间选择;
- Agent 记忆指南:保留并复用之前沙箱运行的经验;
- 可运行示例:examples/sandbox/ 下的本地、编码、记忆、交接与 Agent 组合模式。
何时回到普通 Agent:如果 Shell 访问只是偶尔使用的工具之一,从 工具指南 的 hosted shell 开始即可;只有当工作区隔离、沙箱客户端选择或沙箱会话恢复行为是设计的一部分时,才选用沙箱 Agent。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考