샌드박스 클라이언트
이 페이지에서는 샌드박스 작업을 어디에서 실행할지 선택하는 방법을 설명합니다. 대부분의 경우 SandboxAgent 정의는 그대로 유지되고, sandbox 실행 옵션에서 샌드박스 클라이언트와 클라이언트별 옵션만 변경됩니다.
결정 가이드
섹션 제목: “결정 가이드”| 목표 | 시작점 | 이유 |
|---|---|---|
| macOS 또는 Linux 에서 가장 빠른 로컬 반복 개발 | UnixLocalSandboxClient | 추가 서비스 의존성이 없고 로컬 파일시스템 워크플로가 단순합니다 |
| 기본적인 컨테이너 격리 | DockerSandboxClient | 특정 이미지를 사용해 Docker 내부에서 작업을 실행합니다 |
| 호스티드 실행 또는 프로덕션 수준 격리 | 호스티드 샌드박스 클라이언트 | 작업 공간 경계를 제공업체가 관리하는 환경으로 옮깁니다 |
로컬 클라이언트
섹션 제목: “로컬 클라이언트”대부분의 사용자에게는 다음 두 가지 샌드박스 클라이언트 중 하나로 시작하는 것을 권장합니다.
| 클라이언트 | 설치 | 이런 경우 선택 |
|---|---|---|
UnixLocalSandboxClient | 없음 | macOS 또는 Linux 에서 가장 빠른 로컬 반복 개발이 필요할 때. 로컬 개발의 기본 선택으로 적합합니다 |
DockerSandboxClient | 로컬에서 Docker CLI 사용 가능 | 컨테이너 격리 또는 로컬 환경 일치를 위한 특정 이미지가 필요할 때 |
Unix-local 은 로컬 파일시스템을 대상으로 개발을 시작하는 가장 쉬운 방법입니다. 더 강한 환경 격리나 프로덕션 수준의 환경 일치가 필요해지면 Docker 또는 호스티드 제공업체로 이동하세요.
Unix-local 에서 Docker 로 전환하려면 에이전트 정의는 그대로 두고 클라이언트만 변경하면 됩니다.
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);대개 동일한 에이전트를 두 로컬 클라이언트 중 어느 쪽으로도 실행할 수 있습니다.
import { DockerSandboxClient, UnixLocalSandboxClient,} from '@openai/agents/sandbox/local';
const client = process.env.USE_DOCKER ? new DockerSandboxClient({ image: 'node:22-bookworm-slim' }) : new UnixLocalSandboxClient();세션 소유권
섹션 제목: “세션 소유권”수명 주기 스타일은 두 가지입니다.
| 스타일 | 전달하는 값 | 세션을 닫는 주체 | 이런 경우 사용 |
|---|---|---|---|
| SDK 소유 | sandbox: { client } | 러너 | 샌드박스가 한 번의 실행 동안만 유지되면 될 때 |
| 개발자 소유 | sandbox: { 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.5', instructions: 'Inspect the sandbox workspace before answering.',});
const client = new UnixLocalSandboxClient();const session = await client.create({ manifest });
try { await run(agent, 'First pass.', { sandbox: { session } }); await run(agent, 'Follow-up pass.', { sandbox: { session } });} finally { await session.close?.();}재개와 스냅샷
섹션 제목: “재개와 스냅샷”샌드박스 상태와 대화 상태는 별개입니다.
- SDK 대화 상태는
result.history, SDKSession,conversationId, 또는previousResponseId에 저장됩니다 - 샌드박스 상태는 라이브 샌드박스 세션, 직렬화된
sessionState,RunState샌드박스 페이로드, 또는 스냅샷에 저장됩니다
샌드박스 클라이언트를 통해 동일한 백엔드 세션에 다시 연결하려면 sessionState 를 사용하세요. 저장된 작업 공간 내용을 바탕으로 새 세션을 시작하려면 스냅샷을 사용하세요.
import { Manifest } 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 session = await client.create({ manifest });const state = await client.serializeSessionState?.(session.state);await session.close?.();
if (state) { const restored = await client.resume?.( await client.deserializeSessionState!(state), ); await restored?.close?.();}더 큰 워크플로를 일시 중지하거나 재개할 때 RunState 로 러너가 관리하는 샌드박스 상태를 보존할 수도 있습니다. 직렬화된 실행 외부에서 샌드박스 수명 주기를 관리한다면 명시적인 sessionState 를 사용하세요.
매니페스트 구체화
섹션 제목: “매니페스트 구체화”매니페스트 항목은 에이전트가 실행되기 전에 준비됩니다. 실행 단위 또는 클라이언트 생성 호출 단위로 구체화 동시성을 조정할 수 있습니다.
import { run } from '@openai/agents';import { SandboxAgent } from '@openai/agents/sandbox';import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const agent = new SandboxAgent({ name: 'Repository inspector', model: 'gpt-5.5', instructions: 'Inspect the repository before answering.',});
await run(agent, 'Inspect the repo.', { sandbox: { client: new UnixLocalSandboxClient(), concurrencyLimits: { manifestEntries: 4, localDirFiles: 16, }, },});manifestEntries 는 최상위 항목 작업의 병렬 수를 제한합니다. localDirFiles 는 localDir() 항목 내부의 파일 복사 동시성을 제한합니다.
마운트와 원격 스토리지
섹션 제목: “마운트와 원격 스토리지”마운트 항목은 어떤 스토리지를 노출할지 설명하고, 마운트 전략은 샌드박스 백엔드가 그 스토리지를 어떻게 연결할지 설명합니다. 내장 마운트 항목과 범용 전략은 @openai/agents/sandbox 에서 import 하세요.
일반적인 마운트 옵션:
mountPath: 샌드박스에서 스토리지가 표시될 위치입니다. 상대 경로는 매니페스트 루트 아래에서 해석되고, 절대 경로는 그대로 사용됩니다readOnly: 샌드박스가 마운트된 스토리지에 다시 쓰면 안 되는 경우 설정합니다mountStrategy: 마운트 항목과 샌드박스 백엔드 둘 다에 맞는 전략을 사용합니다
마운트는 일시적인 작업 공간 항목으로 취급됩니다. 스냅샷 및 영속화 흐름에서는 마운트된 원격 스토리지를 저장된 작업 공간에 복사하지 않고, 마운트된 경로를 분리하거나 건너뜁니다.
범용 로컬/컨테이너 전략:
| 전략 또는 패턴 | 이런 경우 사용 | 참고 |
|---|---|---|
inContainerMountStrategy(...) | 샌드박스 이미지에서 rclone, mount-s3, blobfuse2 같은 마운트 명령을 실행할 수 있을 때 | 범용 전략으로 제공되며, 지원 여부는 백엔드에 따라 달라집니다 |
dockerVolumeMountStrategy(...) | 컨테이너 시작 전에 Docker 가 볼륨 드라이버 기반 마운트를 연결해야 할 때 | Docker 전용 |
localBindMountStrategy() | 로컬 백엔드가 절대 로컬 경로를 작업 공간에 바인드해야 할 때 | 허용되는 경우 로컬 작업 공간 구체화에서 지원됩니다 |
백엔드 지원은 의도적으로 명시적입니다.
| 백엔드 | 마운트 참고 |
|---|---|
UnixLocalSandboxClient | 로컬 작업 공간 모델을 통해 로컬 바인드 스타일 마운트를 지원합니다 |
DockerSandboxClient | Docker 가 스토리지를 연결할 수 있는 경우 로컬 바인드 마운트와 Docker 볼륨 스타일 전략을 지원합니다 |
| 호스티드 제공업체 | 제공업체별 전략은 각 제공업체 구현과 함께 제공됩니다. 지원되는 마운트와 필요한 설정은 해당 제공업체 문서를 확인하세요 |
모든 백엔드에서 마운트 항목이 동작한다고 가정하지 마세요. 클라이언트가 매니페스트 메타데이터, ID, 또는 마운트 동작을 강제할 수 없다면, 해당 매니페스트 부분을 조용히 무시하는 대신 초기에 실패해야 합니다.
지원되는 호스티드 플랫폼
섹션 제목: “지원되는 호스티드 플랫폼”호스티드 환경이 필요할 때도 동일한 SandboxAgent 정의를 대개 그대로 사용할 수 있으며, sandbox 실행 옵션에서 샌드박스 클라이언트만 변경하면 됩니다.
호스티드 제공업체 구현은 @openai/agents-extensions 의 제공업체 하위 경로에서 사용할 수 있습니다. 정확한 환경 변수, 실행 가능한 예제, 포트 동작, PTY 지원, 스냅샷 동작, 정리 동작은 제공업체 문서를 확인하세요.
@openai/agents-extensions 를 설치하고 해당 패키지 수준 peer 의존성을 충족하세요. 각 제공업체는 추가로 제공업체 SDK 패키지나 백엔드 설정이 필요할 수 있습니다.
| 클라이언트 | import 경로 | 제공업체 요구 사항 |
|---|---|---|
BlaxelSandboxClient | @openai/agents-extensions/sandbox/blaxel | npm peer: @blaxel/core |
CloudflareSandboxClient | @openai/agents-extensions/sandbox/cloudflare | Cloudflare Sandbox 브리지 Worker URL 및 Worker 인증 |
DaytonaSandboxClient | @openai/agents-extensions/sandbox/daytona | npm peer: @daytonaio/sdk |
E2BSandboxClient | @openai/agents-extensions/sandbox/e2b | npm peer: e2b 또는 @e2b/code-interpreter |
ModalSandboxClient | @openai/agents-extensions/sandbox/modal | npm peer: modal |
RunloopSandboxClient | @openai/agents-extensions/sandbox/runloop | npm peer: @runloop/api-client |
VercelSandboxClient | @openai/agents-extensions/sandbox/vercel | npm peer: @vercel/sandbox |
CloudflareSandboxClient 는 Cloudflare npm SDK 를 import 하지 않습니다. 대신 배포된 Cloudflare Sandbox 브리지 Worker 와 HTTP 로 통신합니다.
호스티드 샌드박스 클라이언트는 제공업체별 마운트 전략을 노출합니다. 스토리지 제공업체에 가장 잘 맞는 백엔드와 마운트 전략을 선택하세요.
| 백엔드 | 마운트 참고 |
|---|---|
| Docker | s3Mount(), gcsMount(), r2Mount(), azureBlobMount(), boxMount(), s3FilesMount() 를 inContainerMountStrategy() 및 dockerVolumeMountStrategy() 같은 로컬 전략과 함께 지원합니다 |
ModalSandboxClient | S3, R2, HMAC 인증 GCS 마운트 항목에서 ModalCloudBucketMountStrategy 를 사용한 클라우드 버킷 마운트를 지원합니다 |
CloudflareSandboxClient | S3, R2, HMAC 인증 GCS 마운트 항목에서 CloudflareBucketMountStrategy 를 사용한 Cloudflare 버킷 마운트를 지원합니다 |
BlaxelSandboxClient | S3, R2, GCS 마운트 항목에서 BlaxelCloudBucketMountStrategy 를 사용한 클라우드 버킷 마운트를 지원합니다. 또한 BlaxelDriveMount 및 BlaxelDriveMountStrategy 를 사용한 영구적인 Blaxel Drive 도 지원합니다 |
DaytonaSandboxClient | S3, GCS, R2, Azure Blob, Box 마운트 항목에서 DaytonaCloudBucketMountStrategy 를 사용한 rclone 기반 마운트를 지원합니다 |
E2BSandboxClient | S3, GCS, R2, Azure Blob, Box 마운트 항목에서 E2BCloudBucketMountStrategy 를 사용한 rclone 기반 마운트를 지원합니다 |
RunloopSandboxClient | S3, GCS, R2, Azure Blob, Box 마운트 항목에서 RunloopCloudBucketMountStrategy 를 사용한 rclone 기반 마운트를 지원합니다 |
VercelSandboxClient | 현재 호스티드 전용 마운트 전략을 노출하지 않습니다. 대신 매니페스트 파일, 리포지토리, 스냅샷 또는 다른 작업 공간 입력을 사용하세요 |
아래 표는 각 백엔드가 어떤 원격 스토리지 항목을 직접 마운트할 수 있는지 요약합니다.
| 백엔드 | AWS S3 | Cloudflare R2 | GCS | Azure Blob Storage | Box | S3 Files |
|---|---|---|---|---|---|---|
| Docker | 예 | 예 | 예 | 예 | 예 | 예 |
ModalSandboxClient | 예 | 예 | 예 | 아니요 | 아니요 | 아니요 |
CloudflareSandboxClient | 예 | 예 | 예 | 아니요 | 아니요 | 아니요 |
BlaxelSandboxClient | 예 | 예 | 예 | 아니요 | 아니요 | 아니요 |
DaytonaSandboxClient | 예 | 예 | 예 | 예 | 예 | 아니요 |
E2BSandboxClient | 예 | 예 | 예 | 예 | 예 | 아니요 |
RunloopSandboxClient | 예 | 예 | 예 | 예 | 예 | 아니요 |
VercelSandboxClient | 아니요 | 아니요 | 아니요 | 아니요 | 아니요 | 아니요 |
노출 포트
섹션 제목: “노출 포트”샌드박스 클라이언트는 백엔드가 지원하는 경우 resolveExposedPort(port) 를 통해 엔드포인트를 노출할 수 있습니다.
| 클라이언트 | 동작 |
|---|---|
UnixLocalSandboxClient | 구성된 포트를 127.0.0.1 로 해석합니다 |
DockerSandboxClient | 구성된 컨테이너 포트를 퍼블리시하고 해당 호스트 엔드포인트를 해석합니다 |
백엔드가 허용 목록을 강제해야 하는 경우 클라이언트 옵션에서 포트를 선언하세요.
import { DockerSandboxClient } from '@openai/agents/sandbox/local';
const client = new DockerSandboxClient({ image: 'node:22-bookworm-slim', exposedPorts: [3000],});기능 지원 매트릭스
섹션 제목: “기능 지원 매트릭스”| 기능 | Unix-local | Docker |
|---|---|---|
exec_command | 지원 | 지원 |
PTY write_stdin | 지원 | 지원 |
apply_patch | 지원 | 작업 공간 파일 API 를 통해 지원 |
view_image | 지원 | 작업 공간 파일 API 를 통해 지원 |
명령용 runAs | 호스트가 사용자를 확인하고 전환할 수 있으면 지원 | 컨테이너/사용자 설정에 따라 제한됨 |
| 로컬 스냅샷 | 지원 | 지원 |
| 로컬/Docker 마운트 | 로컬 바인드 스타일 지원 | 바인드 및 Docker 볼륨 스타일 지원 |
로컬 PTY 지원은 SDK 프로세스 안에서 작은 Python 3 브리지를 사용합니다. 이 브리지는 tty: true 세션에서만 사용되며, 이는 Node.js 가 내장 PTY API 를 제공하지 않고 SDK 가 대화형 stdin, 시그널 처리, 종료 상태 보고를 위해 표준 POSIX PTY 동작을 필요로 하기 때문입니다. SDK 코드를 실행하는 환경에 python3 를 설치하거나, Python 3 실행 파일을 가리키도록 OPENAI_AGENTS_PYTHON 을 설정하세요. 이는 Docker 샌드박스 이미지 내부에 설치된 Python 버전과는 별개입니다.
호스티드 제공업체 지원은 제공업체마다 다릅니다. 정확한 옵션, 환경 변수, 포트 동작, PTY 지원, 스냅샷 동작, 정리 동작은 제공업체별 문서를 확인하세요.