沙箱为 Agent 提供了一个隔离的类 Unix 执行环境,包含文件系统、Shell、已安装的包、挂载的数据、暴露的端口、快照,以及对外部系统的受控访问。
当模型需要此类工作区但仅接收提示词上下文时,Agent 工作流会变得脆弱。大型文档集、生成的产物、命令、预览和可恢复的工作,都需要一个 Agent 可以检查和更改的环境。
沙箱 Agents 可在 TypeScript 和 Python Agents SDK 中使用。它们目前处于 Beta 阶段,因此 API 详情、默认值和支持的功能可能会发生变化。
当 Agent 需要操作文件、运行命令、挂载数据室、生成产物、暴露服务或稍后继续有状态工作时,请使用沙箱。
关键的分割线是控制层和计算层之间的边界。控制层是围绕模型的控制平面:它负责 Agent 循环、模型调用、工具路由、交接、审批、追踪、恢复和运行状态。计算层则是沙箱执行平面,模型指导的工作在此读取和写入文件、运行命令、安装依赖、使用挂载的存储、暴露端口并生成状态快照。
保持这些边界独立,可以让你的应用程序将敏感的控制层工作保留在受信任的基础设施中,同时让沙箱专注于特定提供商的执行。沙箱可以使用受限的凭证和挂载对文件运行代码;而控制层可以将身份验证、计费、审计日志、人工审查和恢复状态保留在任何单一容器之外。
在沙箱内运行控制层对于原型设计可能很方便,但这会将编排和模型指导的执行置于同一计算边界内。
控制层可以在你的基础设施中运行,而沙箱负责处理特定于提供商的有状态执行。
何时使用沙箱
当 Agent 的回答取决于在沙箱工作区中完成的工作,而不仅仅是对提示词上下文进行推理时,请使用沙箱。
常见的痛点包括:
- 任务需要一个包含多个文档的目录,而不是单个提示词。
- Agent 应该写入文件,以便你的应用程序稍后检查。
- Agent 需要命令、包或脚本来完成工作。
- 工作流会生成 Markdown、CSV、JSONL、屏幕截图或生成的网站等产物。
- 需要在暴露的端口上运行服务、Notebook 或报告预览。
- 工作暂停以进行人工审查,然后在相同的工作区中恢复。
如果你的工作流只需要简短的模型响应而不需要持久的工作区,请直接调用 Responses API 或使用不带沙箱的基础 Agents SDK 运行时。
如果 Shell 访问只是偶尔使用的工具,请从托管 Shell 工具开始: 使用工具。当工作区隔离、沙盒提供商选择或可恢复的文件系统状态属于产品设计的一部分时,请使用沙盒代理。
沙箱增加了什么
SandboxAgent 仍然是 Agent。它保留了常见的代理接口,包括
instructions, prompt, tools, handoffs、MCP 服务器、模型设置、结构化输出、防护栏和钩子。改变的是执行边界:运行器在一个拥有文件、命令、端口和提供商特定隔离的实时沙盒会话中准备代理。
| 组件 | 职责 | 设计问题 |
|---|---|---|
SandboxAgent | Agent 定义及沙箱默认值 | 这个 Agent 应该做什么,以及哪些沙箱默认值随之携带? |
Manifest | The fresh-session workspace contract | 工作区初始应包含哪些文件、目录、代码库、挂载、环境、用户或组? |
| 能力 | 附加到 Agent 的沙箱原生行为 | 此 Agent 需要哪些沙箱工具、指令或运行时行为? |
| 沙箱客户端 | The provider integration | 实时工作区应在何处运行:本地 Unix、Docker 还是托管提供商? |
| 沙箱会话 | The live execution environment | 命令在何处运行、文件在何处更改、端口在何处开放,以及提供商状态存在于何处? |
| 沙箱运行配置 | 每次运行的沙箱会话源、客户端选项和新的输入 | 此运行应该注入、恢复还是创建沙箱会话? |
| 已保存的状态 | RunState、序列化的会话状态和快照 | 后续运行应如何重新连接到工作或初始化新的工作区? |
沙箱特定的默认值属于 SandboxAgent。每次运行的沙盒会话选择应属于该运行的沙盒配置。
沙箱 Agents 也不会改变“轮次”的含义。一轮仍然是单个模型步骤,而不是单个 Shell 命令或沙箱操作。某些工作可能保留在沙箱执行层内。Agent 运行时仅在沙箱工作完成后需要再次获取模型响应时,才会消耗另一个轮次。
创建工作区
Manifest 描述了全新沙箱工作区所需的初始内容和布局。将其用于 Agent 应该看到的文件、代码库、输入产物、辅助文件、挂载、输出目录和环境设置。
将清单视为新会话的契约,而不是每个实时沙箱的完整事实来源。运行的有效工作区可以来自复用的实时沙箱会话、序列化的沙箱会话状态或在运行时选择的快照。
清单输入路径是相对于工作区的。它们不能是绝对路径,也不能通过以下方式转义工作区: ..,这可以保持工作区契约在本地、Docker 和托管客户端之间保持可移植性。
| 清单输入 | 用途 |
|---|---|
File, Dir | 小型的合成输入、辅助文件或输出目录。 |
| 本地文件或目录 | 要具体化到沙箱中的主机文件或目录。 |
| Git 代码库 | 要获取到工作区中的代码库。 |
S3Mount, GCSMount, R2Mount, AzureBlobMount, BoxMount, S3FilesMount | 要在沙箱内提供的外部存储。 |
environment | 沙箱启动时所需的环境变量。 |
users and groups | 支持帐户预配的提供商对应的沙箱本地操作系统帐户和组。 |
良好的清单设计意味着:
- 将代码库、输入产物和输出目录放入清单中。
- 将较长的任务规格和代码库本地指令放在工作区文件中,例如
repo/task.mdorAGENTS.md. - 在指令中使用相对工作区路径,例如
repo/task.mdoroutput/report.md. - 将挂载存储的范围限定在智能体需要读写的输入内容上。
- 将挂载条目视为临时工作区条目:快照和持久化流程会跳过已挂载的远程存储,而不是将其复制到已保存的工作区内容中。
挂载文件和存储
有用的数据通常已经存在于其他位置。与其将大量文档粘贴到上下文中,不如将它们挂载到沙盒中,让智能体直接处理文件。
Examples:
- 挂载尽职调查数据室,并要求智能体生成一份带有引用的摘要。
- 挂载支持工单导出文件,并要求智能体将问题聚类整理成一份报告。
- 挂载生成的构件,以便另一个系统进行审查。
提供商集成会公开其自带的挂载辅助工具、凭据处理和持久化行为。请保持相同的应用程序约定:仅挂载智能体需要使用的输入内容,告知智能体读写的位置,并在使用生成的构件前对其进行检查。
处理机密和凭据
将沙盒凭据视为运行时配置,而非提示内容。智能体可能需要访问包管理器、存储挂载或提供商 API 的凭据,但这些凭据不应出现在用户提示、智能体指令、任务文件、已提交的清单或生成的构件中。
遵循以下规则:
- 对于托管的沙盒提供商,请优先使用提供商原生的机密管理系统。
- 将云存储凭据的范围限定在需要它们的挂载或提供商选项上。
- 使用
Manifest.environment用于提供沙箱进程启动时所需的值,并在你希望重新构建敏感或自动生成的条目而非将其持久化时,将这些条目标记为临时的。 - 避免保存密钥、生成的挂载配置、本地令牌,或不应在运行结束后保留的文件。
- 在将制品移出沙箱之前请务必审查,尤其是当代理能够读取私有文档或已挂载的存储时。
SDK 支持清单环境值和特定于提供商的挂载凭据。通用的密钥存储集成因提供商而异,因此本页将重点放在契约上:你的运行时或沙箱提供商应当注入凭据,而不是将凭据作为指令教给模型。
为代理赋予能力
能力将沙箱原生行为附加到 SandboxAgent。它们可以在运行开始前塑造工作区,追加特定于沙盒的指令,暴露绑定到实时沙盒会话的工具,并针对该代理调整模型行为或输入处理。
| 能力 | 添加时机 | 备注 |
|---|---|---|
Shell | 代理需要 Shell 访问权限。 | 添加命令执行功能,并在沙箱客户端支持时提供交互式输入。 |
Filesystem | 代理需要编辑文件或检查本地图像。 | 添加 apply_patch and view_image;补丁路径是相对于工作区根目录的。 |
Skills | 你希望在沙箱中进行技能发现和具体化。 | 相较于手动挂载,更推荐此方式 .agents or .agents/skills. |
Memory | 后续运行应读取或生成记忆工件。 | 需要 Shell;实时内存更新也需要 Filesystem. |
Compaction | 长时间运行的流程需要上下文裁剪。 | 在压缩项目后调整模型行为和输入处理。 |
默认情况下, SandboxAgent 包含文件系统、shell 和压缩功能。如果你传递一个 capabilities 列表,它将替换默认列表,因此请务必包含该 agent 仍需要的任何默认功能。
在适用时优先使用内置功能。仅当内置功能无法满足你所需的沙盒专属工具或指令界面时,才编写自定义功能。
加载技能
某些任务需要在 agent 启动前提供可重复的指令、脚本、参考资料或资产。请使用 Skills 功能,以便 agent 能够在运行期间发现该工作上下文。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import {
Capabilities,
SandboxAgent,
gitRepo,
skills,
} from "@openai/agents/sandbox";
const agent = new SandboxAgent({
name: "Tax prep assistant",
instructions: "Use the mounted skill before preparing the return.",
capabilities: [
...Capabilities.default(),
skills({
from: gitRepo({
repo: "owner/tax-prep-skills",
ref: "main",
}),
}),
],
});根据你希望的技能具体化方式来选择技能源:
- 对于较大的本地技能目录,当你希望模型先发现索引并仅加载所需内容时,请使用延迟加载的本地目录源。
- 对于较小的本地技能包,如需预先加载准备,请使用本地目录源。
- 当技能包有独立的发布周期,或多个沙盒共用它时,请使用 Git 仓库源。
暴露预览和端口
有时工件并不是文件,而是正在运行的进程。当 agent 创建了本地应用、笔记本、报表服务器、浏览器预览或其他需要在沙盒外部进行检查的服务时,请使用暴露的端口。
端口设置与提供商相关,但其产品契约是一致的:agent 在沙盒内启动服务,沙盒客户端暴露端口,然后你的应用程序共享或检查生成的预览 URL。
运行沙盒 agent
最简且实用的沙盒循环如下:
- 构建一个描述工作区的
Manifest描述该工作区。 - 使用模型所需的功能创建一个
SandboxAgent具备模型所需的能力。 - 为工作应该运行的环境选择一个沙盒客户端。
- 使用每次运行的沙盒配置来运行该 agent。
- 检查、复制、恢复或快照对你的应用程序重要的工件。
从 Unix-local 开始进行 macOS 或 Linux 上的本地开发。它为你提供了最小的本地循环,因为运行器可以根据 agent 的默认清单创建临时工作区,并在运行结束后将其清理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { run } from "@openai/agents";
import {
Manifest,
SandboxAgent,
file,
shell,
} from "@openai/agents/sandbox";
import { UnixLocalSandboxClient } from "@openai/agents/sandbox/local";
const manifest = new Manifest({
entries: {
"account_brief.md": file({
content:
"# Northwind Health\n\n" +
"- Segment: Mid-market healthcare analytics provider.\n" +
"- Renewal date: 2026-04-15.\n",
}),
"implementation_risks.md": file({
content:
"# Delivery risks\n\n" +
"- Security questionnaire is not complete.\n" +
"- Procurement requires final legal language by April 1.\n",
}),
},
});
const agent = new SandboxAgent({
name: "Renewal Packet Analyst",
model: "gpt-5.5",
instructions:
"Review the workspace before answering. Keep the response concise, " +
"business-focused, and cite the file names that support each conclusion.",
defaultManifest: manifest,
capabilities: [shell()],
});
const result = await run(
agent,
"Summarize the renewal blockers and recommend the next two actions.",
{
sandbox: {
client: new UnixLocalSandboxClient(),
},
},
);
console.log(result.finalOutput);有关完整的本地示例,请参见 TypeScript 沙箱代理快速入门 and Python unix_local_runner.py.
切换提供商
提供商是运行配置的一部分,而非代理定义。保持 SandboxAgent,保持工作区、清单和能力稳定,然后为你想要的环境切换沙盒客户端和提供商选项。
本示例使用 Docker 进行本地容器隔离。托管提供商遵循相同的模式,但使用各自的客户端类和选项。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { run } from "@openai/agents";
import { SandboxAgent } from "@openai/agents/sandbox";
import { DockerSandboxClient } from "@openai/agents/sandbox/local";
const agent = new SandboxAgent({
name: "Workspace reviewer",
model: "gpt-5.5",
instructions: "Inspect the sandbox workspace before answering.",
});
const result = await run(agent, "Inspect the workspace.", {
sandbox: {
client: new DockerSandboxClient({
image: "node:22-bookworm-slim",
}),
},
});
console.log(result.finalOutput);有关可运行的示例,请参阅 TypeScript 沙箱客户端指南 and 基础示例,以及 Python basic.py for provider selection, docker_runner.py for Docker, and main.py 了解 SDK 存储库中的数据室流程。
高级模式
一旦基本循环正常工作,当代理需要沙箱工作区而不是更多的提示上下文时,沙箱对这类工作流就变得非常有用。这些示例是工作流模式,而不是独立的 API:同一个控制程序可以对工作流进行路由、暂停、恢复和追踪,同时每个沙箱将执行过程保持在靠近其所需文件、工具和端口的地方。
| 示例 | 描述 |
|---|---|
| 数据室问答 | 回答有关已挂载数据室的问题。 |
| 数据室表格提取 | 从已挂载的数据室中提取表格。 |
| 仓库代码审查 | 克隆代码仓库、进行检查并生成代码审查产物。 |
| 视觉网站克隆 | 使用 Vision API 和屏幕截图反馈来克隆网站。 |
| 沙箱恢复 | 在预先存在的沙箱中恢复工作。 |
恢复或预设未来的工作
有用的代理工作通常不仅限于单次请求。用户需要审查产物,某个步骤需要审批,或者下一步依赖于稍后的事件。
请保持以下三个状态概念的区分:
| 状态层面 | 恢复内容 | 适用场景 |
|---|---|---|
RunState | 控制程序侧的状态,例如模型项、工具状态、审批和当前代理位置。 | 运行器应在暂停后继续推进工作流。 |
| 会话状态 | 客户端可以重新连接到的已序列化沙箱会话。 | 您的应用或作业系统直接存储提供商会话状态。 |
snapshot | 用于初始化全新沙箱会话的已保存工作区内容。 | 新的运行应从已保存的文件和产物开始,而不是空白工作区。 |
在实践中,运行器按以下顺序解析沙箱会话:
- 如果传入活动的沙箱会话,运行器将直接复用该会话。
- 否则,如果运行正在从以下位置恢复
RunState,运行器会从已存储的沙盒会话状态恢复。 - 否则,如果传入明确的已序列化沙箱状态,运行器将从该状态恢复。
- 否则,运行器将创建一个全新的沙箱会话。对于该全新会话,它会在提供时使用每次运行的清单,若未提供则使用代理的默认清单。
沙箱恢复示例将序列化已停止的会话状态,通过同一客户端恢复它,然后将恢复的会话传回给下一次运行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import { run } from "@openai/agents";
import { Manifest, SandboxAgent } from "@openai/agents/sandbox";
import { UnixLocalSandboxClient } from "@openai/agents/sandbox/local";
const manifest = new Manifest();
const client = new UnixLocalSandboxClient({
snapshot: { type: "local", baseDir: "/tmp/my-sandbox-snapshots" },
});
const agent = new SandboxAgent({
name: "Workspace builder",
model: "gpt-5.5",
instructions: "Inspect the sandbox workspace before answering.",
});
const session = await client.create({ manifest });
let conversation: any[] = [];
let frozenSessionState;
try {
const firstResult = await run(agent, "Build the first version of the app.", {
maxTurns: 20,
sandbox: { session },
});
conversation = firstResult.history;
frozenSessionState = await client.serializeSessionState?.(session.state);
} finally {
await session.close?.();
}
if (!frozenSessionState || !client.deserializeSessionState || !client.resume) {
throw new Error("Sandbox client does not support session resume.");
}
const resumedSession = await client.resume(
await client.deserializeSessionState(frozenSessionState),
);
try {
conversation.push({
role: "user",
content: "Continue from the existing workspace and add tests.",
});
await run(agent, conversation, {
maxTurns: 20,
sandbox: { session: resumedSession },
});
} finally {
await resumedSession.close?.();
}全新会话的输入(例如 manifest and snapshot 仅在运行器创建新沙箱会话时适用。如果注入活动的 session,能力处理可以添加兼容的非挂载条目,但不能更改根目录、环境变量、用户或组;不能移除现有条目;不能替换条目类型;也不能在已运行的沙盒上添加或更改挂载条目。
这种分离使得控制程序能够恢复代理循环,同时沙箱提供商恢复或重建工作区。这些路径的当前示例代码位于 TypeScript 恢复会话状态示例 and
Python main.py and
sandbox_agent_with_remote_snapshot.py.
在多次运行间持久化记忆
沙箱记忆让未来的沙箱代理运行能够从先前的运行中学习。它独立于 SDK 管理的对话 Session 记忆:会话保留消息历史,而沙箱记忆则从先前的工作区运行中提取有用的经验,并将其保存为代理稍后可以读取的文件。
当代理需要延续用户偏好、更正、项目特定经验或任务摘要,而无需重放之前的每一个轮次时,请使用记忆。恢复和快照保留了工作区状态;而记忆则保留了有关该工作区中已完成工作的可复用指导。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import {
Manifest,
SandboxAgent,
filesystem,
memory,
shell,
} from "@openai/agents/sandbox";
const manifest = new Manifest();
const agent = new SandboxAgent({
name: "Memory-enabled reviewer",
instructions:
"Inspect the workspace and retain useful lessons for follow-up runs.",
defaultManifest: manifest,
capabilities: [memory(), filesystem(), shell()],
});记忆默认启用读取和生成功能。读取记忆需要 shell 访问权限,以便代理能够搜索和打开记忆文件。默认情况下,实时的记忆更新也需要文件系统访问权限,以便代理能够修复过时的记忆或在用户提出请求时更新记忆。
记忆读取采用渐进式披露机制。SDK 会在运行开始时注入 memory_summary.md 当先前的工作看起来相关时,代理会搜索 MEMORY.md 并且仅当需要更多细节时才打开展开摘要。
| 记忆模式 | 适用场景 |
|---|---|
| 默认读/写 | 代理应读取现有记忆并生成新记忆。 |
| 只读记忆 | Agent 应读取记忆,但在运行后不应生成新记忆。 |
| 仅生成记忆 | 运行时应生成记忆,而不使用已有记忆。 |
| 读取配置 | 你需要禁用实时更新。 |
| 生成配置 | 你需要调整生成过程,例如额外的提示词。 |
| 布局配置 | Agent 在同一个沙箱工作区中需要隔离的记忆布局。 |
默认情况下,记忆产物存放在沙箱工作区中:
workspace/
sessions/
<rollout-id>.jsonl
memories/
memory_summary.md
MEMORY.md
raw_memories.md
phase_two_selection.json
raw_memories/
<rollout-id>.md
rollout_summaries/
<rollout-id>_<slug>.md
skills/运行时会在沙箱会话期间追加运行片段。当会话关闭时,记忆生成过程首先提取对话摘要和原始记忆,然后将这些原始记忆整合为 MEMORY.md and
memory_summary.md。要在后续运行中重用内存,请通过保持相同的实时沙盒会话、从会话状态恢复、从快照启动或挂载持久存储(例如 S3)来保留配置的内存目录。
对于多轮沙箱对话,请使用稳定的 SDK 会话以及同一个实时沙箱会话。记忆会按显式对话 ID 对运行进行分组,然后依次按 SDK 会话 ID、运行组 ID,最后是生成的单次运行 ID 进行分组。沙箱会话 ID 用于标识实时工作区;它不是记忆的对话 ID。
有关可运行的示例,请参阅 TypeScript 记忆指南,以及 Python memory.py 了解本地快照流程,
memory_s3.py 了解基于 S3 的记忆存储,以及
memory_multi_agent_multiturn.py 了解跨 Agent 的独立记忆布局。
组合沙箱 Agent
沙箱 Agent 可与 SDK 的其余部分组合使用。
当非沙箱的接收 Agent 只需将工作区密集型的工作流部分委托给沙箱 Agent 时,请使用移交。顶层运行会继续,但沙箱 Agent 将成为下一轮的活跃 Agent。
当外部协调器需要将一个或多个沙箱 Agent 作为嵌套工具调用时,请将 Agent 用作工具。每个沙箱工具 Agent 都可以拥有自己独立的沙箱运行配置、沙箱客户端、清单和 Provider 选项。
For examples, see handoffs.py and
sandbox_agents_as_tools.py.
沙箱 Provider
在本地快速迭代时请使用 Unix-local,在需要本地容器隔离时请使用 Docker。当任务需要托管执行、Provider 特定的隔离、扩缩容、预览、存储挂载、快照,或需要将凭证保留在应用服务器外部时,请迁移到托管 Provider。
有关特定于 Provider 的设置、凭证、隔离、存储、预览和持久化行为,请参阅 Provider 文档。
| 提供商 | SDK 客户端 | 文档与示例 |
|---|---|---|
| Blaxel | BlaxelSandboxClient | 沙箱概览 |
| Cloudflare | CloudflareSandboxClient | 沙箱文档 OpenAI Agents 教程 沙箱 Bridge 示例 |
| Daytona | DaytonaSandboxClient | 沙箱文档 OpenAI Agents SDK 指南 |
| Docker | DockerSandboxClient | Docker 文档 TypeScript Docker SDK 示例 Python Docker SDK 示例 |
| E2B | E2BSandboxClient | 沙箱文档 OpenAI Agents SDK 指南 发布博客 |
| Modal | ModalSandboxClient | 沙箱指南 集成博客 示例仓库 Modal 扩展参考 |
| Runloop | RunloopSandboxClient | Devbox 概览 隧道 |
| Unix-local | UnixLocalSandboxClient | TypeScript 本地 SDK 示例 Python 本地 SDK 示例 |
| Vercel | VercelSandboxClient | 沙箱文档 OpenAI Agents SDK 指南 FastAPI 模板 示例应用 |