跳转到内容

概念

现代智能体在能够操作文件系统中的真实文件时表现最佳。沙盒智能体可以利用专用工具和 shell 命令来搜索和处理大型文档集、编辑文件、生成产物以及运行命令。沙盒为模型提供了一个持久化工作区,智能体可以在其中代表您执行工作。Agents SDK 中的沙盒智能体可帮助您运行与沙盒环境配对的智能体,轻松将所需文件放入文件系统,并编排沙盒以大规模启动、停止和恢复任务。

您可以围绕智能体所需的数据来定义工作区。新工作区可以填充来自 GitHub 仓库、本地文件和目录、合成任务文件、S3 或 Azure Blob Storage 等远程文件系统,以及您提供的其他沙盒输入的内容。

带有计算资源的沙盒智能体运行框架

SandboxAgent 扩展了 Agent,因此它仍然是一个 Agent。它保留了常规智能体的接口,例如 instructions、tools、handoffs、mcpServers、modelSettings、输出类型、护栏和钩子,并且仍然通过标准的 run() 和 Runner API 运行。变化在于执行边界:

  • SandboxAgent 定义智能体本身:常规智能体配置,加上 defaultManifest、baseInstructions、runAs 等沙盒专属默认设置,以及文件系统工具、shell 访问、技能、记忆或压缩等能力。
  • Manifest 声明新沙盒工作区预期的初始内容和布局,包括文件、仓库、挂载和环境。
  • 沙盒会话是运行命令和修改文件的实际执行环境。
  • sandbox 运行选项决定本次运行如何获取沙盒会话,例如直接注入会话、从序列化的沙盒会话状态重新连接,或通过沙盒客户端创建新沙盒会话。
  • 保存的沙盒状态和快照使后续运行能够重新连接到先前的工作,或使用保存的内容初始化新沙盒会话。

Manifest 定义新沙盒工作区的初始内容。它并不描述每个活动沙盒中的当前文件,因为复用的会话、序列化的会话状态和快照都可以在运行时提供或更改工作区。

本页中的”沙盒会话”是指由沙盒客户端管理的实际执行环境。具体边界取决于客户端和配置:Unix 本地会话在 macOS 或 Linux 上运行宿主进程,不会增加操作系统级隔离,而 Docker 和托管客户端使用容器或由提供商管理的执行环境。这不同于会话中介绍的 SDK 对话式 Session 接口。

外层运行时仍然负责审批、追踪、交接和恢复状态管理。沙盒会话管理命令和文件变更。执行环境提供的隔离程度由后端和配置决定。

一次沙盒运行将智能体定义与每次运行的沙盒配置结合起来。运行器会准备智能体,将其绑定到活动沙盒会话,并可保存状态供后续运行使用。

SandboxAgent智能体加上沙盒默认设置
Runner准备指令并绑定能力工具
沙盒会话运行命令和修改文件的工作区
保存的状态稍后恢复或初始化新工作区

沙盒专属的默认设置保留在 SandboxAgent 上。每次运行的沙盒会话选择保留在 sandbox 运行选项中。

可以将生命周期分为三个阶段:

  1. 使用 SandboxAgent、Manifest 和能力来定义智能体及工作区的初始内容。
  2. 向 run() 或 Runner 提供 sandbox 运行选项,通过注入、恢复或创建沙盒会话来执行一次运行。
  3. 稍后从运行器管理的 RunState、显式沙盒 sessionState 或保存的工作区快照继续执行。

如果 shell 访问只是偶尔使用的工具之一,请从工具指南中的托管 shell 入手。当工作区管理、沙盒客户端选择或沙盒会话恢复行为属于设计的一部分时,再使用沙盒智能体。

沙盒智能体适合以工作区为中心的工作流,例如:

  • 编码和调试:针对 GitHub 仓库中的问题报告编排自动修复,并运行有针对性的测试。
  • 文档处理和编辑:从用户的财务文档中提取信息,并创建已填写的税务表格草稿。
  • 基于文件的审查或分析:在回答之前检查入职材料包、生成的报告或产物包。
  • 隔离的多智能体模式:为每个审查智能体或编码子智能体提供独立工作区。
  • 多步骤工作区任务:在一次运行中修复错误,稍后添加回归测试,或从快照或沙盒会话状态恢复。

如果不需要访问文件或持续可用的文件系统,请继续使用 Agent。如果 shell 访问只是偶尔使用的能力,添加托管 shell 即可;如果工作区边界本身就是功能的一部分,则使用沙盒智能体。

在 macOS 或 Linux 上进行可信的本地开发,或在已通过外部措施隔离的环境中,请使用 UnixLocalSandboxClient。Unix 本地工作区、工作目录和 HOME 环境变量不提供操作系统级隔离。对于不可信的命令,包括受不可信输入影响的命令,请选择配置适当的 DockerSandboxClient 或托管提供商,或提供外部隔离。在 Windows 上,请使用 Docker 或托管提供商。请参阅 Unix 本地执行限制。

在大多数情况下,SandboxAgent 定义保持不变,只需在 sandbox 运行选项中更改沙盒客户端及其选项。有关本地、Docker、托管和远程挂载选项,请参阅沙盒客户端。

层级主要 SDK 组件解答的问题
智能体定义SandboxAgent、Manifest、能力将运行哪个智能体,它应基于怎样的新会话工作区约定开始工作?
沙盒执行sandbox 运行选项、沙盒客户端和活动沙盒会话本次运行如何获取活动沙盒会话,工作在哪里执行?
保存的沙盒状态RunState 沙盒载荷、sessionState 和快照此工作流如何重新连接到先前的沙盒工作,或使用保存的内容初始化新沙盒会话?

主要 SDK 组件与这些层级的对应关系如下:

组件负责的内容需要考虑的问题
SandboxAgent智能体定义这个智能体应该做什么,哪些默认设置应随它一起使用?
Manifest新会话工作区的文件和文件夹运行开始时,文件系统中应该有哪些文件和文件夹?
Capability沙盒原生行为应为这个智能体附加哪些工具、指令片段或运行时行为?
sandbox 运行选项每次运行的沙盒客户端和沙盒会话来源本次运行应注入、恢复还是创建沙盒会话?
RunState由运行器管理的已保存沙盒状态我是否正在恢复先前由运行器管理的工作流,并自动延续其沙盒状态?
sandbox.sessionState显式序列化的沙盒会话状态我是否希望从已在 RunState 外部序列化的沙盒状态恢复?
sandbox.snapshot供新沙盒会话使用的已保存工作区内容新沙盒会话是否应从保存的文件和产物开始?

一个实用的设计顺序是:

  1. 使用 Manifest 或 manifest 初始化对象定义新会话的工作区约定。
  2. 使用 SandboxAgent 定义智能体。
  3. 添加内置或自定义能力。
  4. 在 run(agent, input, { sandbox: ... }) 或 new Runner({ sandbox: ... }) 中决定每次运行应如何获取沙盒会话。

在运行时,运行器会将上述定义转换为具体的沙盒支持的运行:

  1. 根据 sandbox 运行选项确定沙盒会话。
  2. 确定本次运行实际生效的工作区输入。
  3. 让各项能力处理生成的 manifest。
  4. 按固定顺序构建最终指令:首先是 SDK 的默认沙盒提示,或您显式覆盖时使用的 baseInstructions,然后是 instructions,接着是能力指令片段、所有远程挂载策略文本,最后是渲染后的文件系统树。
  5. 将能力工具绑定到活动沙盒会话,并通过标准的 run() 和 Runner API 运行准备好的智能体。

使用沙盒不会改变轮次的含义。一个轮次仍然是一个模型步骤,而不是一条 shell 命令或一次沙盒操作。沙盒端操作与轮次之间没有固定的一一对应关系。实际判断时,只有在完成沙盒工作后,智能体运行时需要模型再次响应,才会消耗一个新的轮次。

以下是在常规 Agent 字段之外的沙盒专属选项:

选项最佳用途
defaultManifest运行器创建新沙盒会话时使用的默认工作区。
instructions附加在 SDK 沙盒提示之后的角色、工作流和成功标准。
baseInstructions用于替换 SDK 沙盒提示的高级覆盖选项。
capabilities应随智能体一起使用的沙盒原生工具和行为。
runAs面向模型的沙盒工具(如 shell 命令、文件读取和补丁)所使用的用户身份。

沙盒客户端选择、沙盒会话复用、manifest 覆盖和快照选择属于 sandbox 运行选项,不应放在智能体上。

defaultManifest 是运行器为此智能体创建新沙盒会话时使用的默认工作区。可以传入 Manifest 实例,也可以传入与 new Manifest(...) 接受的相同的初始化对象。使用它来定义智能体通常开始工作时应具备的文件、仓库、辅助材料、输出目录和挂载。

defaultManifest 仅提供默认工作区。一次运行可以使用 sandbox.manifest 覆盖 defaultManifest,而复用或恢复的沙盒会话会保留其现有工作区状态。

定义 manifest
import { file, gitRepo, Manifest } from '@openai/agents/sandbox';
const manifest = new Manifest({
root: '/workspace',
entries: {
'task.md': file({
content: 'Fix the failing test and summarize the change.',
}),
repo: gitRepo({
repo: 'openai/openai-agents-js',
ref: 'main',
}),
},
environment: {
NODE_ENV: 'test',
},
});

将需要在不同提示中保持有效的简短规则放入 instructions。在 SandboxAgent 中,这些指令会附加在 SDK 的沙盒基础提示之后,因此您可以保留内置沙盒指引,同时添加自己的角色、工作流和成功标准。

仅在希望替换 SDK 沙盒基础提示时使用 baseInstructions。大多数智能体不应设置它。

放置位置用途示例
instructions智能体的稳定角色、工作流规则和成功标准。“检查入职文档,然后交接。""将最终文件写入 output/。“
baseInstructions完全替换 SDK 沙盒基础提示。自定义底层沙盒封装提示。
用户提示本次运行的一次性请求。“总结此工作区。“
manifest 中的工作区文件较长的任务规范、仓库内指令或范围有限的参考材料。repo/task.md、文档包、示例材料包。

避免将用户的一次性任务复制到 instructions 中、嵌入本应放入 manifest 的长篇参考材料、重复内置能力已注入的工具文档,或混入模型在运行时不需要的本地安装说明。

能力为 SandboxAgent 附加沙盒原生行为。它们可以在运行开始前调整工作区、附加沙盒专属指令、提供绑定到活动沙盒会话的工具,并调整该智能体的模型行为或输入处理方式。

内置能力包括:

能力添加时机说明
shell()智能体需要 shell 访问。添加 exec_command,并在沙盒客户端支持 PTY 交互时添加 write_stdin。
filesystem()智能体需要编辑文件或查看本地图像。添加 apply_patch 和 view_image;相对路径默认以工作区根目录为起点,如果配置了 sandbox.cwd,则以该目录为起点。
skills()您希望在沙盒中发现和物化技能。对于沙盒本地的 SKILL.md 技能,优先使用此能力,而不是手动挂载 .agents 或 .agents/skills。
memory()后续运行应读取或生成记忆产物。需要 shell();实时更新还需要 filesystem()。
compaction()长时间运行的流程需要在压缩项之后裁剪上下文。调整模型采样和输入处理。

默认情况下,SandboxAgent.capabilities 使用 Capabilities.default(),其中包含 filesystem()、shell() 和 compaction()。如果传入 capabilities: [...],该列表会替换默认值,因此请包含您仍想使用的默认能力。

view_image 接受最大 10 MB 的 PNG、JPEG、GIF、WebP、BMP、TIFF 和 SVG 图像。SDK 根据文件签名检测光栅格式,而不是信任光栅图像的文件扩展名,因此仅有光栅图像扩展名并不能使不受支持的字节内容变得有效。SDK 根据文件内容或 .svg、.svgz 文件名识别 SVG。

compaction() 默认使用 DynamicCompactionPolicy。对于已识别的模型,当渲染后的上下文达到该模型上下文窗口的 90% 时,该策略会要求 Responses API 进行压缩。如果未指定模型或模型未知,该策略会使用 240,000 个 token 的回退阈值。可以向 new DynamicCompactionPolicy(thresholdRatio, fallbackThreshold) 传入不同的比例和回退阈值;如果所有受支持的模型都应使用同一个固定 token 阈值,则使用 new StaticCompactionPolicy(threshold)。动态比例必须是 0 到 1 之间的有限数值。

当服务器端压缩生成压缩项时,该能力会保留此项和后续输入,同时丢弃更早的重放项。压缩项是不透明的模型状态,而不是人类可读的摘要,因此应原样传递,不要编辑。这些控制仅适用于支持 Responses 压缩的模型传输机制。

Manifest 描述新沙盒会话的工作区。它可以设置工作区 root、声明文件和目录、复制本地文件、克隆 Git 仓库、附加远程存储挂载、设置环境变量、定义用户或组,并授予对工作区外特定绝对路径的访问权限。

Manifest 环境值默认会被持久化。对于不应随沙盒状态保存的 API 密钥、访问令牌或其他短期凭据,请使用 { value: "...", ephemeral: true } 这样的临时条目。

对于在 manifest 物化或恢复时必须重新查找的机密信息,请创建 EnvValueReference 的子类,并使用 registerEnvValueReference() 注册它。引用只会持久化不含机密信息的查找元数据,并通过 resolve() 解析当前运行时的值。每个子类都必须声明自己稳定且非空的静态 type,并且 serialize() 不得包含保留的 value 字段。在每个进程中重建 manifest 之前,都要注册解析器,并让解析器验证查找键、对其实施允许列表检查。恢复已持久化的 RunState 环境引用时,需要提供包含对应引用条目的当前可信 manifest;否则,SDK 会在还原会话之前拒绝恢复。

Manifest 条目路径是相对于工作区的路径。它们不能是绝对路径,也不能使用 .. 逃逸出工作区,从而使工作区约定能够在本地、Docker 和托管客户端之间保持可移植性。

使用 manifest 条目提供智能体开始工作前所需的材料:

Manifest 条目用途
file()、dir()小型合成输入、辅助文件或输出目录。
localFile()、localDir()应物化到沙盒中的宿主文件或目录。
gitRepo()应获取到工作区中的仓库。
s3Mount()、gcsMount()、r2Mount()、azureBlobMount()、s3FilesMount() 等挂载应在沙盒内可见的外部存储。

对于本地物化,localFile() 和 localDir() 的源路径必须位于本地源基础目录内。默认基础目录是 Node 进程的当前工作目录,本地沙盒客户端在物化条目时也可以提供客户端专属的基础目录。如果源必须来自另一个宿主绝对路径目录,请添加满足需求的最小范围的 Manifest.extraPathGrants 条目。

extraPathGrants 也用于本地惰性技能发现。指向源基础目录之外的 localDirLazySkillSource() 会被忽略,除非 manifest 已授予对该目录的访问权限。对于共享技能、数据集和参考仓库等输入包,优先使用 readOnly: true。

每个路径授权都包含一个沙盒路径,并在需要时包含一个单独的宿主路径:

  • path 是沙盒内可见的 POSIX 绝对路径。
  • hostPath 是可选的宿主系统原生绝对路径,用于宿主路径与沙盒路径不同时。在 Windows 上,它必须包含驱动器号;不支持 UNC 路径和设备路径。

UnixLocalSandboxClient 要求宿主路径和沙盒路径相同,因此使用它时应省略 hostPath。如果授权存在于用于创建容器的 manifest 中,DockerSandboxClient 支持单独的 hostPath。它无法在已运行的容器中添加或更改该映射。Docker 命令可以将创建时已授权的沙盒路径用作 workdir;工作区和已配置授权范围之外的路径仍会被拒绝。

对于 Unix 本地会话,这些授权控制通过 SDK 对本地源的访问,以及通过 SDK 文件 API 访问的路径。readOnly: true 授权会阻止 SDK 文件 API 向已授权路径写入。这些授权不会限制 macOS 或 Linux 上的任意 shell 命令:只要进程权限和外部隔离允许,命令就能访问宿主路径,即使这些路径没有获得授权。

授予对共享本地源的访问权限
import { Manifest, localDir, skills } from '@openai/agents/sandbox';
import { localDirLazySkillSource } from '@openai/agents/sandbox/local';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const appRoot = dirname(fileURLToPath(import.meta.url));
const repoDir = join(appRoot, 'repo');
const sharedSkillsDir = '/opt/company/agent-skills';
const manifest = new Manifest({
extraPathGrants: [
{
path: sharedSkillsDir,
readOnly: true,
description: 'Shared skill bundle.',
},
],
entries: {
repo: localDir({ src: repoDir }),
},
});
const skillCapability = skills({
lazyFrom: localDirLazySkillSource({
src: sharedSkillsDir,
}),
});

挂载条目描述要提供哪些存储;挂载策略描述沙盒后端如何附加这些存储。有关挂载选项和提供商支持情况,请参阅沙盒客户端。

Permissions 控制 manifest 条目的文件系统权限。它针对的是沙盒物化的文件,而不是模型权限、审批策略或 API 凭据。

用户是可以执行工作的沙盒身份。如果希望某个身份存在于沙盒中,请将该用户添加到 manifest;如果希望面向模型的沙盒工具(如 shell 命令、文件读取和补丁)以该用户身份运行,则设置 SandboxAgent.runAs。

如果还需要文件级共享规则,可以将用户与 manifest 中的组及条目的 group 元数据结合使用。runAs 用户控制由谁执行沙盒原生操作;Permissions 则控制在沙盒物化工作区后,该用户可以读取、写入或执行哪些文件。

SnapshotSpec 告诉新沙盒会话应从哪里还原已保存的工作区内容,以及将内容持久化回哪里。它是沙盒工作区的快照策略,而 sessionState 是用于恢复特定沙盒后端的序列化连接状态。

需要本地持久化快照时使用本地快照;应用提供远程快照客户端时使用远程快照。挂载路径和临时路径不会作为持久化工作区内容复制到快照中。在还原过程中,SDK 会在将归档写入工作区之前,拒绝任何与受保护的挂载路径或临时路径重叠的归档成员。如果工作区根目录本身是临时的,则只能还原空归档。

生命周期有两种模式:SDK 管理和开发者管理。

SDK 管理Runner 负责管理活动沙盒。
  1. 传入 sandbox.client。

  2. Runner 创建或恢复沙盒会话。
  3. 智能体运行,支持快照的工作区状态可被持久化。

  4. Runner 关闭由运行器管理的资源。

开发者管理您的应用负责管理活动沙盒。
  1. 创建一个 session。

  2. 将 sandbox.session 传入本次运行。

  3. 智能体使用现有工作区。
  4. 自行检查、复用,然后关闭会话。

如果沙盒只需要在一次运行期间存在,请使用 SDK 管理的生命周期。传入 client、可选的 manifest、可选的 snapshot 和客户端 options;运行器会创建或恢复沙盒、运行智能体、持久化支持快照的工作区状态,并让客户端清理由运行器管理的资源。

由运行器管理沙盒会话
import { run } from '@openai/agents';
import { SandboxAgent } from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const agent = new SandboxAgent({
name: 'Workspace reviewer',
model: 'gpt-5.6-sol',
instructions: 'Inspect the sandbox workspace before answering.',
});
const result = await run(agent, 'Inspect the workspace.', {
sandbox: {
client: new UnixLocalSandboxClient(),
},
});
console.log(result.finalOutput);

如果希望提前创建沙盒、在多次运行间复用一个活动沙盒、在运行后检查文件、在自行创建的沙盒上进行流式传输,或精确决定何时清理,请使用开发者管理的生命周期。传入 session 会告诉运行器使用该活动沙盒,但不会代您关闭它。

自行管理沙盒会话
import { run } from '@openai/agents';
import { Manifest, SandboxAgent } from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const manifest = new Manifest();
const agent = new SandboxAgent({
name: 'Workspace reviewer',
model: 'gpt-5.6-sol',
instructions: 'Inspect the sandbox workspace before answering.',
});
const client = new UnixLocalSandboxClient();
const session = await client.create({ manifest });
try {
await run(agent, 'First task.', { sandbox: { session } });
await run(agent, 'Follow-up task.', { sandbox: { session } });
} finally {
await session.close?.();
}

沙盒操作事件为运行器管理的沙盒工作提供进程范围的可观测性。使用 addSandboxEventSink() 注册 SandboxEventSink,即可接收 sandbox_operation 事件。每项操作都会先发出 start 阶段事件,然后发出 end 或 error 事件;终结事件包含持续时间,而错误事件会在提供商提供相关信息时,包含错误码或是否可重试等规范化错误详情。

当运行配置了 sandbox.cwd 时,sandbox.exec 事件数据会报告以 cwd 为基准解析后的实际 workdir,sandbox.view_image 事件数据会报告以 cwd 为基准解析后的实际 path。这些值与发送给沙盒会话的路径一致。

使用 createSandboxJsonlEventSink() 将每个事件写入一个 JSONL 行,使用 createSandboxHttpEventSink() 将每个事件作为 HTTP POST 发送,或使用 createChainedSandboxEventSink() 将事件分发到多个接收器。addSandboxEventSink() 会返回一个移除函数;当应用不再需要该接收器时调用此函数,或使用 clearSandboxEventSinks() 移除所有已注册的接收器。

事件接收器仅用于观测。SDK 会等待已注册的接收器完成处理,无论成功还是失败,但接收器失败不会替换沙盒操作的结果或错误。如果应用需要更强的交付保证,请在接收器内部处理发送重试、缓冲以及接收器特有的故障。

sandbox 运行选项包含每次运行的选项,用于决定沙盒会话的来源以及新会话的初始化方式。

这些选项决定运行器应复用、恢复还是创建沙盒会话:

选项使用时机说明
client您希望运行器代您创建、恢复和清理沙盒会话。除非提供了活动沙盒 session,否则为必填项。
session您已经自行创建了活动沙盒会话。调用方负责生命周期;运行器复用该活动沙盒会话。
sessionState您拥有序列化的沙盒会话状态,但没有活动沙盒会话对象。需要 client;运行器从该显式状态恢复会话,并负责其生命周期。

在 sandbox 运行配置中设置 cwd,可将相对于工作区的某个目录设为本次运行的工作目录。内置的 exec_command、view_image 和 apply_patch 工具会从此目录解析相对路径;其他沙盒工具保留各自的路径约定。此设置会改变路径解析方式,但不会将本次运行与会话工作区的其他部分隔离。

该值必须是非空、相对于工作区的 POSIX 路径。绝对路径、反斜杠和父目录(..)路径段会被拒绝。在每个模型轮次之前,运行器都会检查该目录是否存在,以及沙盒智能体的 runAs 身份是否可访问该目录。与 cwd 配合使用的自定义或注入会话必须实现 directoryExists()。

这些选项仅在运行器创建新沙盒会话时生效:

选项使用时机说明
manifest您希望对新会话工作区进行一次性覆盖。接受 Manifest 或 manifest 初始化对象。省略时回退到 agent.defaultManifest。
snapshot新沙盒会话应从快照初始化。适用于类似恢复的流程或远程快照客户端。
options沙盒客户端需要创建时选项。常用于 Docker 镜像、提供商超时和类似的客户端专属设置。

concurrencyLimits 控制可并行执行的沙盒物化工作量。当大型 manifest 或本地目录复制需要更严格的资源控制时,使用 manifestEntries 和 localDirFiles。

物化控制特意设计为按次运行设置。将其放在 sandbox 运行选项附近,这样同一个 SandboxAgent 就可以对大型本地目录复制使用保守的限制,而对小型 manifest 使用更宽松的限制。

当 manifest 包含许多独立条目(如文件、目录、仓库和挂载)时,使用 concurrencyLimits.manifestEntries。当 localDir() 条目包含大量文件,需要限制本地复制压力时,使用 concurrencyLimits.localDirFiles。

使用 archiveLimits 限制工作区还原和恢复过程中的归档输入字节数、解压后字节数和成员数量。传入空对象会启用默认值:归档输入为 1 GiB、解压后为 4 GiB、成员数量为 100,000。将单个字段设为 null 可仅禁用该项限制。省略 archiveLimits 或将整个选项设为 null,会完全禁用归档限制。

以下编码类示例适合作为默认起点:

沙盒编码任务
import { run } from '@openai/agents';
import {
Capabilities,
Manifest,
SandboxAgent,
localDir,
skills,
} from '@openai/agents/sandbox';
import {
UnixLocalSandboxClient,
localDirLazySkillSource,
} from '@openai/agents/sandbox/local';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const exampleDir = dirname(fileURLToPath(import.meta.url));
const hostRepoDir = join(exampleDir, 'repo');
const hostSkillsDir = join(exampleDir, 'skills');
const manifest = new Manifest({
entries: {
repo: localDir({ src: hostRepoDir }),
},
});
const agent = new SandboxAgent({
name: 'Sandbox engineer',
model: 'gpt-5.6-sol',
instructions:
'Read `repo/task.md` before editing files. Load the `$invoice-total-fixer` skill before changing code. 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.',
defaultManifest: manifest,
capabilities: [
...Capabilities.default(),
skills({
lazyFrom: localDirLazySkillSource({
src: hostSkillsDir,
}),
}),
],
});
const result = await run(
agent,
'Open `repo/task.md`, fix the issue, run the targeted test, and summarize the change.',
{
sandbox: {
client: new UnixLocalSandboxClient(),
},
},
);
console.log(result.finalOutput);

从上面的完整示例开始。在许多情况下,同一个 SandboxAgent 可以保持不变,只需更改沙盒客户端、沙盒会话来源或工作区来源。

保持智能体定义不变,仅更改运行配置。需要容器隔离或镜像一致性时使用 Docker,需要提供商管理的执行环境时使用托管提供商。有关代码示例和提供商选项,请参阅沙盒客户端。

保持智能体定义不变,仅通过 sandbox: { client, manifest } 替换新会话的 manifest。当同一个智能体角色需要针对不同仓库、材料包或任务包运行,而无需重新构建智能体时,使用此方式。

当需要显式控制生命周期、运行后检查或复制输出时,注入活动沙盒会话。为该次运行使用 sandbox: { session },并在应用代码中关闭会话。

如果已经在 RunState 外部序列化了沙盒状态,可以通过 sandbox: { client, sessionState } 让运行器从该状态重新连接。当沙盒状态保存在您自己的存储或作业系统中,并且希望 Runner 直接从中恢复时,使用此方式。

使用 sandbox: { client, snapshot },以保存的文件和产物初始化新沙盒。当新的运行应从保存的工作区内容开始,而不只是使用 agent.defaultManifest 时,使用此方式。

通过 skills({ from: gitRepo(...) }) 将本地技能源替换为基于仓库的技能源。当技能包有自己的发布节奏,或应在多个沙盒之间共享时,使用此方式。

工具智能体可以获取自己的沙盒会话,也可以复用父级运行中的活动沙盒。对于只需检查父级工作区的探索智能体,复用很有用,可以避免创建、还原另一个沙盒或为其生成快照的开销。共享会话本身并不会强制实施只读访问。

当工具智能体需要单独的工作区、后端或镜像时,通过 sandboxAgent.asTool(...) 为其提供独立的 runConfig。对于不可信的命令,请选择能提供所需隔离的后端和配置。仅使用单独的 Unix 本地会话并不能提供操作系统级隔离。

保留沙盒工作区的同时,仍可在同一智能体上使用普通工具。沙盒能力可以与 tools、mcpServers、交接、模型设置和输出配置共存。

当后续沙盒智能体运行应从先前运行中学习时,使用 memory() 能力。记忆独立于 SDK 的对话式 Session 记忆:它会将经验提炼到沙盒工作区内的文件中,后续运行便可以读取这些文件。

有关设置、读取和生成行为、多轮对话以及布局隔离,请参阅智能体记忆。

明确单智能体模式后,下一个设计问题是沙盒边界应位于更大系统中的什么位置。

沙盒智能体仍可与 SDK 的其他部分组合使用:

  • 交接:将文档密集型工作从非沙盒的接待智能体交接给沙盒审查智能体。
  • Agents as tools:将多个沙盒智能体作为工具提供,通常在每次 asTool(...) 调用中传入沙盒运行配置,使每个工具都有自己的会话。每个会话提供的隔离程度由后端和配置决定。
  • MCP 集成和普通函数工具:沙盒能力可以与 mcpServers 和普通工具共存。
  • 运行智能体:沙盒运行仍使用标准的 run() 和 Runner API。

在交接中,仍然只有一次顶层运行和一个顶层轮次循环。活动智能体会发生变化,但运行不会变成嵌套运行。

使用 asTool(...) 时,关系则不同。外层编排器使用一个外层轮次来决定调用工具,而该工具调用会为沙盒智能体启动一次嵌套运行。嵌套运行有自己的轮次循环、maxTurns、审批,通常也有自己的沙盒运行配置。从外层编排器的角度看,所有这些工作仍然封装在一次工具调用之内,因此嵌套轮次不会增加外层运行的轮次计数。