DigitalOcean
DigitalOcean
DigitalOcean을 자체 호스팅 샌드박스 제공자로 사용하는 방법을 안내하는 가이드예요. 웹훅 관리 또는 애플리케이션 관리 프로비저닝으로 DigitalOcean 샌드박스를 시작하고 executor를 연결하는 방법을 배워요.
출처: 문서
본문
OpenAI Cookbook의 application-managed 및 webhook-managed 예시를 참고하세요.
동작 방식
DigitalOcean의 Managed Agents Runtime Services(M.A.R.S.)가 codex-agentapi 이미지를 사용해 Firecracker microVM을 시작해요. 이 이미지는 Codex를 포함하고 executor를 시작하며, executor가 Agents API로 아웃바운드 연결해요.
OpenAI 이벤트에서 샌드박스를 시작하거나 재개하려면 webhook-managed 프로비저닝을 선택하고, 애플리케이션에서 제어하려면 application-managed 프로비저닝을 선택하세요. 대화형 퀵스타트에는 선택적 DigitalOcean CLI flow를 사용하세요. 연결 및 복구 동작은 Sandbox lifecycle을 참고하세요.
DigitalOcean Managed Agents는 공개 미리 보기(public preview) 상태예요. 접근 및 설정은 DigitalOcean's documentation을 참고하세요.
시작하기 전에
codex-agentapi에 접근할 수 있는 샌드박스 활성화 DigitalOcean 계정과 Agents API 접근이 있는 OpenAI 프로젝트가 필요해요.
애플리케이션 또는 CLI에는 OPENAI_API_KEY를 사용하세요. OPENAI_EXECUTOR_API_KEY를 environment key로 설정하세요. 환경 키만 CODEX_API_KEY로 샌드박스에 전달하세요.
웹훅 컨트롤러나 Python 애플리케이션에는 DIGITALOCEAN_TOKEN을 설정하고 비동기 지원(pydo[aio])이 있는 PyDo SDK 0.41.0 이상을 설치하세요. Agents API 요청에는 OpenAI SDK를 사용하세요. CLI 설치는 CLI 흐름에서만 필요해요.
웹훅 관리
- 저장된 에이전트를 만들고 그 ID를
OPENAI_AGENT_ID로 저장하세요. DigitalOcean App Platform에 이 ID, 세션 읽기용OPENAI_API_KEY,DIGITALOCEAN_TOKEN,OPENAI_EXECUTOR_API_KEY로 HTTPS 웹훅 컨트롤러를 배포하세요. - OpenAI 프로젝트에 컨트롤러의
/webhook엔드포인트를 등록하세요.agent.session.action_required와agent.session.failed를 활성화한 뒤 서명 시크릿을OPENAI_WEBHOOK_SECRET으로 저장하고 컨트롤러를 재배포하세요. - 동일한
OPENAI_AGENT_ID와 작업 디렉토리/workspace로 session steps을 따르세요. 이벤트 스트림을 열고 입력을 보내세요. OpenAI가environment_connection을 요청하면 컨트롤러가 서명을 검증하고 현재 세션을 검색하며 에이전트 ID와 필수 액션을 확인해요. DigitalOcean에서mars-{session_id}를 조회하고, 일시 중지된 샌드박스를 재개하거나 활성 샌드박스가 없으면 만듭니다. agent.session.failed가 발생하면 세션을 다시 검색하고, 현재 세션 상태가 여전히failed일 때만 그 샌드박스를 삭제하세요.
이미지가 executor를 세션의 환경에 연결해요. 여러분의 애플리케이션은 Agents API를 통해 입력을 보내고 결과를 스트리밍하며, 컨트롤러가 프로비저닝과 재연결을 처리해요. 중복 및 동시 전달을 처리하려면 세션별로 프로비저닝을 직렬화하세요. 컨트롤러 요구 사항은 webhook-managed lifecycle guidance를 참고하세요.
DigitalOcean CLI로 시도하기
CLI는 두 리소스를 모두 만들고 터미널에서 에이전트와 상호작용할 수 있게 해줘요. 웹훅 컨트롤러 없이 샌드박스를 직접 프로비저닝해요.
harness-runtime이 포함된 doctl 1.170.0 이상을 설치한 뒤 인증하세요:
doctl auth init
이 매니페스트를 environment.yaml로 저장하세요:
name: openai-codex-session
agent: codex-agentapi
config:
agent:
model: gpt-5.6-sol
instructions: Work from the files in /workspace.
environment:
type: self_hosted
workspace_directory: /workspace
egress:
- api.openai.com
- codex-cloud-environments.chatgpt.com
env:
CODEX_ENVIRONMENT_ID: ${ENV_ID}
secrets:
CODEX_API_KEY: ${OPENAI_EXECUTOR_API_KEY}
config 블록은 OpenAI create-session 요청이에요. CLI는 그 요청을 OPENAI_API_KEY로 인증하고, 응답에서 ${ENV_ID}를 채우며, 환경 키만 샌드박스에 전달해요. 해결된 매니페스트를 로그와 소스 컨트롤에 남기지 마세요. 도구가 필요한 모든 대상 위치를 egress에 추가하세요.
세션과 샌드박스를 만드세요:
doctl harness-runtime create --spec environment.yaml
이 명령은 기본적으로 최대 300초 동안 준비를 기다려요. 세션 세부 사항에서 OpenAI 세션 ID와 DigitalOcean 세션 ID를 저장한 뒤 연결하세요:
doctl harness-runtime launch openai-codex-session
에이전트에게 hello를 /workspace/hello.txt에 쓰고 다시 읽도록 요청하세요. Ctrl+D를 눌러 세션을 삭제하지 않고 분리하고, 같은 launch 명령을 실행해 다시 연결하세요. 작업이 끝나면 Cleanup을 따르세요.
애플리케이션 관리
세션 생성과 샌드박스 프로비저닝을 애플리케이션이 소유할 때 이 경로를 사용하세요. 먼저 OpenAI 세션을 만드세요:
자체 호스팅 세션 만들기
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
Connect a sandbox에 설명된 대로 session.id와 환경 ID를 저장하세요. 이 샌드박스 전용 매니페스트를 sandbox.yaml로 저장하세요. 에이전트 설정은 이미 OpenAI로 전송됐어요:
agent: codex-agentapi
egress:
- api.openai.com
- codex-cloud-environments.chatgpt.com
env:
CODEX_ENVIRONMENT_ID: ${ENV_ID}
secrets:
CODEX_API_KEY: ${OPENAI_EXECUTOR_API_KEY}
DIGITALOCEAN_TOKEN으로pydo.aio.Client를 만들고client.agents.create_session을 호출하세요.params.openai_session_id를 OpenAI 세션 ID로,body.manifest를sandbox.yaml의 내용으로,body.variables를ENV_ID와OPENAI_EXECUTOR_API_KEY에서 그 값으로의 매핑으로 설정하세요. 반환된 DigitalOceansession_id를 저장하세요.- 이벤트 스트림을 열고 입력을 보내 에이전트에게
/workspace/hello.txt를 쓰고 읽도록 요청하세요. 입력은 executor가 연결될 때까지 기다려요. 연결 이벤트와 완료된 턴을 확인하고, 에이전트의 출력에서 도구 실패를 검사하세요. - 상대 경로
hello.txt로workspace_download를 사용해 파일을 검색하세요. 후속 턴을 위해 두 리소스를 모두 유지하거나 정리하세요.
애플리케이션에서 제한된 setup 및 실행 타임아웃을 사용하고 연결 실패를 처리하세요. 애플리케이션이나 CLI가 직접 관리하는 세션에는 프로비저닝 웹훅 핸들러를 연결하지 마세요.
정리
필요한 파일을 저장한 뒤 OpenAI 세션을 삭제하고 DigitalOcean 샌드박스를 파괴하세요. 세션 삭제는 웹훅을 발생시키지 않으므로 두 작업을 모두 수행하고 정리 실패를 보고하세요.
PyDo에서는 DigitalOcean 세션 ID로 client.agents.destroy_session을 호출하세요. CLI에서는 그 ID나 샌드박스 이름을 전달하세요:
doctl harness-runtime remove openai-codex-session
웹훅 컨트롤러를 삭제하기 전에 OpenAI 웹훅 등록을 제거하세요.
참고 자료
더 알아보기 (Learn more)
관련 문서: 자체 호스팅 샌드박스와 샌드박스 수명 주기를 참고하세요.