자체 호스팅 샌드박스

자체 호스팅 샌드박스 (Self-hosted sandboxes)

에이전트의 환경을 더 잘 제어하고 싶거나 신뢰할 수 있는 컴퓨팅을 사용하고 싶을 때 자체 환경을 연결해요. 환경은 노트북, 컨테이너, 원격 샌드박스가 될 수 있어요. OpenAI가 환경을 프로비저닝하게 하려면 OpenAI 호스팅 샌드박스를 사용하세요.

출처: 문서

본문

연결이 동작하는 방식 (How the connection works)

OpenAI가 에이전트 하네스를 실행해요. 사용자는 환경 안에서 실행기(executor)인 codex exec-server를 실행해요. 실행기는 하네스의 요청에 따라 셸 명령을 실행하고, 파일을 읽고 쓰며, 로컬 MCP 서버를 사용해요.

실행기는 환경 ID와 제한된 API 키로 API에 등록한 뒤 WebSocket으로 연결해 명령을 받고 결과를 돌려줘요. 모든 연결은 아웃바운드이고, 연결이 끊기면 실행기가 다시 연결해요.

환경 준비하기 (Prepare your environment)

에이전트가 필요한 파일과 의존성을 준비하세요. 사용자나 워크로드별로 환경을 격리하세요. 환경을 공유하는 에이전트는 같은 파일, 자격 증명, 기타 리소스에 접근할 수 있어요.

작업 디렉터리를 만들고 환경 안에 Codex CLI를 설치하세요. 이 예시는 /workspace를 사용해요:

mkdir -p /workspace
npm install -g @openai/codex@alpha

네트워크 접근 (Network access)

다음 호스트로의 아웃바운드 연결을 허용하세요:

  • 환경 등록용 https://api.openai.com.
  • 명령과 결과용 wss://codex-cloud-environments.chatgpt.com.

인증 (Authentication)

애플리케이션 요청에는 OPENAI_API_KEY를 사용하세요. 세션 작업에는 api.agents.read, api.agents.write, 모델 추론에는 api.responses.write를 부여하세요. 애플리케이션이 볼트를 관리한다면 api.vaults.read, api.vaults.write를 추가하세요.

플랫폼 대시보드의 Agents 탭에서 별도의 환경 키를 만드세요. 이 키는 세션을 소유한 조직, 프로젝트, 사용자 또는 서비스 계정과 같은 소속이어야 해요. 다른 모든 권한은 None으로 설정하세요.

애플리케이션 또는 프로비저닝 서비스에서 OPENAI_EXECUTOR_API_KEY를 이 환경 키로 설정하세요. 그 값을 CODEX_API_KEY로 샌드박스에 전달하면 codex exec-server가 읽어요. 애플리케이션의 OPENAI_API_KEY는 샌드박스 밖에 두세요.

에이전트가 생성한 코드는 환경 키를 읽을 수 있지만, 그 키는 환경 연결만 허용해요. 다른 어떤 API 작업도 승인할 수 없어요. 소스 코드, 컨테이너 이미지, 로그에서 키를 빼고 필요하면 회전하거나 폐기하세요.

세션 만들기 (Create a session)

환경 밖의 애플리케이션에서 이 예시를 실행하세요. 이미 자체 호스팅 세션이 있다면 재사용하세요.

자체 환경으로 세션 만들기

import OpenAI from "openai";
const client = new OpenAI();

const session = await client.beta.agents.sessions.create({
  agent: {
    model: "gpt-6-astra",
    instructions:
      "You are a helpful coding assistant. Write clean code and verify that it works.",
  },
  environment: {
    type: "self_hosted",
    workspace_directory: "/workspace",
  },
});

console.log(session);
from openai import OpenAI

client = OpenAI()

session = client.beta.agents.sessions.create(
    agent={
        "model": "gpt-6-astra",
        "instructions": "You are a helpful coding assistant. Write clean code and verify that it works.",
    },
    environment={"type": "self_hosted", "workspace_directory": "/workspace"},
)
print(session.to_json())
import (
	"context"
	"fmt"

	"github.com/openai/openai-go/v3"
)

ctx := context.Background()
client := openai.NewClient()
result, err := client.Beta.Agents.Sessions.New(ctx,
	openai.BetaAgentSessionNewParams{
		Agent: openai.BetaAgentSessionNewParamsAgent{
			Model:        openai.String("gpt-6-astra"),
			Instructions: openai.String("You are a helpful coding assistant. Write clean code and verify that it works."),
		},
		Environment: openai.EnvironmentParamUnion{
			OfParamSelfHosted: &openai.EnvironmentParamSelfHosted{WorkspaceDirectory: "/workspace"},
		},
	})
if err != nil {
	panic(err)
}
fmt.Println(result)
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.beta.agents.EnvironmentParam;
import com.openai.models.beta.agents.sessions.SessionCreateParams;

OpenAIClient client = OpenAIOkHttpClient.fromEnv();
var result =
    client
        .beta()
        .agents()
        .sessions()
        .create(
            SessionCreateParams.builder()
                .agent(
                    SessionCreateParams.Agent.builder()
                        .model("gpt-6-astra")
                        .instructions(
                            "You are a helpful coding assistant. Write clean code and verify"
                                + " that it works.")
                        .build())
                .environment(
                    EnvironmentParam.SelfHosted.builder()
                        .workspaceDirectory("/workspace")
                        .build())
                .build());
System.out.println(result);
require "openai"

client = OpenAI::Client.new
result = client.beta.agents.sessions.create(
  agent: {
    model: "gpt-6-astra",
    instructions: "You are a helpful coding assistant. Write clean code and verify that it works."
  },
  environment: {
    type: "self_hosted",
    workspace_directory: "/workspace"
  }
)
puts result

session.id를 애플리케이션의 대화 상태와 함께 저장하세요. session.environment.id와 session.environment.remote_url을 실행기에 전달하세요. 원격 URL은 재연결할 때를 포함해 변경하지 않고 그대로 사용하세요. 저장된 에이전트를 사용하려면 Agents 구성을 참고하세요.

환경 이미지, workspace_directory, capability_directories는 세션 간에 재사용할 수 있어요. 각 세션은 자체 환경 ID가 있고 자체 실행기가 필요해요. API 환경 템플릿은 OpenAI 호스팅 환경에만 적용돼요.

실행기 시작하기 (Start the executor)

애플리케이션에서 세션 이벤트 스트림을 열어 연결 이벤트를 받으세요. 그런 다음 위에서 CODEX_API_KEY로 구성한 환경 키를 사용해 환경 안에서 이 명령을 실행하세요. 자리 표시자는 API가 반환한 환경 값으로 바꾸세요:

codex exec-server \
  --remote "<session.environment.remote_url>" \
  --environment-id "<session.environment.id>"

에이전트가 작업하는 동안 실행기를 계속 실행해 두세요.

작업 보내고 연결 모니터링하기 (Send work and monitor the connection)

이벤트 스트림을 열어 둔 채 애플리케이션에서 입력을 보내세요. 에이전트가 작업을 시작하려면 연결된 환경과 사용자 입력이 모두 필요해요.

스트림은 이런 연결 상태를 보고해요:

  • agent.session.environment.pending: 세션이 실행기가 연결되기를 기다리고 있어요.
  • agent.session.environment.connected: 환경이 준비됐어요.
  • agent.session.environment.failed: 연결이 실패했어요. 환경 오류와 실행기 로그를 확인하세요.

턴의 결과와 출력을 계속 따라가세요. 시작, 재연결, 종료를 애플리케이션 또는 웹훅으로 관리하려면 환경 수명주기를 참고하세요.

샌드박스 프로바이더 (Sandbox providers)

코드를 실행하고 파일을 다루기 위한 샌드박스 프로바이더를 선택하세요. 애플리케이션 관리형과 웹훅 관리형 프로비저닝을 비교하려면 Sandbox lifecycle을 참고하세요.

프로바이더 가이드
Modal Modal 설정
Cloudflare Cloudflare 설정
Vercel Vercel 설정
Daytona Daytona 설정
Blaxel Blaxel 설정
E2B E2B 설정
Runloop Runloop 설정
DigitalOcean DigitalOcean 설정
Oracle Cloud Infrastructure (OCI) OCI 설정

웹훅 관리형 프로비저닝에서는 Sandbox lifecycle과 프로바이더의 SDK 또는 API로 핸들러를 구현하세요. 프로비저닝 소유권과 정리 정책을 명시적으로 유지하세요.

더 알아보기 (Learn more)