OpenAI 호스팅 샌드박스는 에이전트에 Python, Node.js, 명령줄 도구를 갖춘 Linux 워크스페이스를 제공합니다. OpenAI가 샌드박스를 준비하고 연결하면 애플리케이션은 작업을 전달하고 결과를 가져옵니다. 자체 이미지나 컴퓨팅 리소스, 사설 네트워크가 필요하면 자체 호스팅 샌드박스를 선택하세요.
브라우저로 웹사이트와 상호작용하는 작업은 컴퓨터 사용을 참고하세요.
세션을 만들기 전에 워크스페이스를 준비하려면 샌드박스 미리 준비하기를 참고하세요.
세션 생성 요청에서 environment.type을 openai_hosted로 설정하세요. 워크로드에 필요한 설정만 추가하세요. 샌드박스의 작업 디렉터리는 /workspace입니다.
container_size와 network로 작업에 필요한 리소스와 네트워크 접근 범위를 지정하세요. 환경 템플릿을 사용하면 생략한 설정에는 템플릿의 값이 적용됩니다.
다음 설정으로 샌드박스에서 사용할 종속성과 입력 파일을 준비하세요.
packages: Python 패키지, 시스템 패키지, 전역 npm 패키지를 각각 python, system, npm 목록에 지정해 설치하세요. 필요한 경우 pandas==2.2.3처럼 버전을 고정하세요.
files: Files API의 파일 ID를 지정하거나 base64로 인코딩한 내용을 요청에 직접 넣어 입력 파일을 제공하세요.
setup_commands를 사용하면 에이전트가 시작되기 전에 셸 명령어를 순서대로 실행할 수 있습니다. 예를 들어 [{ "command": "mkdir -p reports" }]는 디렉터리를 만듭니다. 명령어마다 cwd를 지정할 수 있으며 기본값은 /workspace입니다.
패키지와 입력 파일은 설정 명령어를 실행하기 전에 준비됩니다. 설정 명령어로 필요한 종속성이나 파일이 있는지 확인하세요. 설정 명령어가 0이 아닌 종료 코드를 반환하면 에이전트가 시작되지 않습니다.
env로 환경 변수에 문자열 값을 설정하세요. 에이전트가 생성한 코드는 이 값을 읽을 수 있습니다.
시크릿의 실제 값을 샌드박스 외부에 보관하려면 볼트 자격 증명을 사용하세요. PATH, CODEX_*, OPENAI_API_KEY 등 런타임에서 예약한 이름은 사용할 수 없습니다.
세션을 만들 때 environment.container_size를 설정해 샌드박스에 할당할 CPU와 메모리를 선택하세요. 기본값은 medium입니다.
| 크기 |
vCPU |
메모리 |
small |
1 |
1 GB |
medium |
2 |
4 GB |
large |
4 |
16 GB |
예를 들어 POST /v1/agents/sessions 요청에서 small을 선택하려면 다음 환경 설정을 포함하세요.
123456{
"environment": {
"type": "openai_hosted",
"container_size": "small"
}
}
응답으로 받은 세션의 environment.container_size에서 선택한 크기를 확인할 수 있습니다. 이 설정은 OpenAI 호스팅 샌드박스에만 적용됩니다.
network.access |
동작 |
enabled |
외부로 나가는 연결을 허용합니다. 템플릿의 네트워크 정책을 상속하지 않을 때의 기본값입니다. |
disabled |
외부로 나가는 연결을 차단합니다. |
restricted |
allowed_domains에 지정한 호스트에만 연결을 허용합니다. |
제한 모드에서는 api.example.com처럼 정확한 호스트 이름을 1~100개 지정할 수 있습니다. 와일드카드, 프로토콜, 경로, 포트는 포함하지 마세요. 하위 도메인과 리디렉션 대상 호스트는 각각 별도로 등록해야 합니다. 현재 호스팅된 stdio MCP 서버를 사용하려면 네트워크 접근을 enabled로 설정해야 합니다. stdio MCP 요구 사항을 참고하세요.
skills, plugins, capability_directories를 사용해 스킬과 플러그인을 추가하세요.
environment_template_id를 지정하면 저장한 설정을 재사용할 수 있습니다. 생략한 설정에는 템플릿의 값이 적용됩니다. 네트워크 설정을 재정의해도 템플릿 정책에서 허용한 범위를 넓힐 수는 없습니다. 템플릿에는 설정만 저장됩니다. 실행 중인 워크스페이스는 저장되지 않습니다.
세션 생성 응답을 받으면 설정이 시작된 것입니다. 설정 상태를 조회하려면 GET /v1/agents/environments/{environment_id}를 호출하세요. 환경 ID로는 세션의 environment.id를 사용하세요.
| 상태 |
조치 |
provisioning |
설정이 진행 중이므로 기다리세요. |
connected |
설정이 완료되었습니다. 실행 중인 샌드박스에 파일을 추가하거나 파일 목록을 조회할 수 있습니다. |
failed |
environment.error의 내용을 확인하세요. 이 필드는 agent.session.environment.failed 이벤트에 있습니다. |
실행 중인 샌드박스에 파일을 추가하거나 파일 목록을 조회하려면 상태가 connected가 될 때까지 기다리세요.
세션마다 별도의 워크스페이스가 있습니다. 샌드박스가 유지되는 동안에는 턴이 바뀌어도 파일이 보존됩니다. 턴이 완료되면 /workspace/outputs 아래의 파일이 수정할 수 없는 아티팩트로 게시됩니다. 이 사본은 샌드박스가 만료된 후에도 다운로드할 수 있습니다.
업로드, 경로 규칙, 실행 중인 샌드박스의 파일 작업, 다운로드, 제한 사항은 파일과 아티팩트를 참고하세요. 세션을 삭제하기 전에 필요한 출력 파일을 저장하세요.
연결된 샌드박스는 턴과 턴 사이에도 연결 유지 신호를 받습니다. 한 시간 동안 활동이 없고 연결 유지 신호도 수신되지 않으면 샌드박스가 삭제될 수 있습니다. 이 시간은 변경할 수 없습니다.
작업을 마치면 세션을 삭제해 샌드박스 정리를 요청하세요. 설정이나 실행이 아직 끝나지 않아 삭제 요청이 409를 반환하면 잠시 기다렸다가 재시도하되 시도 횟수를 제한하세요. 이벤트 스트림을 닫아도 작업은 취소되지 않습니다.
OpenAI 호스팅 샌드박스에는 표준 컨테이너 요금이 적용됩니다. 모델 사용료는 선택한 모델의 API 요금에 따라 별도로 청구됩니다.
에이전트에 10, 20, 30이 들어 있는 CSV 파일을 제공하세요. 에이전트는 Python을 실행해 합계를 계산하고 결과를 /workspace/outputs/summary.json에 저장합니다.
애플리케이션을 실행할 터미널에서 OPENAI_API_KEY를 설정하세요. 설정 방법은 빠른 시작의 사전 준비 사항을 참고하세요. 이 키는 샌드박스 외부에 보관하세요. OpenAI SDK는 베타 Agents API가 포함된 버전을 사용하세요.
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
35import OpenAI from "openai";
import { agentFileDestination } from "openai/helpers/beta/agents/filesystem";
const client = new OpenAI();
const stream = await client.beta.agents.sessions.create({
agent: { model: "gpt-6-astra" },
environment: {
type: "openai_hosted",
network: { access: "disabled" },
files: [
{
type: "inline",
path: "/workspace/amounts.csv",
data: "YW1vdW50CjEwCjIwCjMwCg==",
},
],
},
input:
"Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.",
stream: true,
});
stream.withResultCollection();
try {
for await (const event of stream) {
console.log(event);
}
const result = await stream.finalResult();
await client.beta.agents.sessions.artifacts.forResult(result).download({
path: "/workspace/outputs/summary.json",
to: agentFileDestination("summary.json"),
});
} finally {
stream.controller.abort();
}
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
28from openai import OpenAI
client = OpenAI()
stream = client.beta.agents.sessions.create(
agent={"model": "gpt-6-astra"},
environment={
"type": "openai_hosted",
"network": {"access": "disabled"},
"files": [
{
"type": "inline",
"path": "/workspace/amounts.csv",
"data": "YW1vdW50CjEwCjIwCjMwCg==",
}
],
},
input="Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.",
stream=True,
)
with stream.with_result_collection():
for event in stream:
print(event.model_dump_json())
result = stream.get_final_result()
client.beta.agents.sessions.artifacts.for_result(result).download(
"/workspace/outputs/summary.json", to="summary.json"
)
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
47package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go/v3"
)
func main() {
ctx := context.Background()
client := openai.NewClient()
stream := client.Beta.Agents.Sessions.NewStreaming(ctx, openai.BetaAgentSessionNewParams{
Agent: openai.BetaAgentSessionNewParamsAgent{Model: openai.String("gpt-6-astra")},
Environment: openai.EnvironmentParamUnion{OfParamOpenAIHosted: &openai.EnvironmentParamOpenAIHosted{
Network: openai.EnvironmentParamOpenAIHostedNetwork{Access: "disabled"},
Files: []openai.HostedEnvironmentFileParamUnion{{OfParamInline: &openai.HostedEnvironmentFileParamInline{
Path: "/workspace/amounts.csv",
Data: "YW1vdW50CjEwCjIwCjMwCg==",
}}},
}},
Input: openai.BetaAgentSessionNewParamsInputUnion{OfString: openai.String("Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.")},
})
defer stream.Close()
openai.BetaAgentSessionWithResultCollection(stream)
for stream.Next() {
fmt.Println(stream.Current().RawJSON())
}
result, err := openai.BetaAgentSessionFinalResult(stream)
if err != nil {
panic(err)
}
destination, err := os.Create("summary.json")
if err != nil {
panic(err)
}
defer destination.Close()
_, err = client.Beta.Agents.Sessions.Artifacts.ForResult(result).Download(ctx, "/workspace/outputs/summary.json", destination)
if err != nil {
panic(err)
}
if err := destination.Close(); err != nil {
panic(err)
}
}
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
41import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.helpers.beta.agents.AgentArtifactDownloads;
import com.openai.models.beta.agents.EnvironmentParam;
import com.openai.models.beta.agents.HostedEnvironmentFileParam;
import com.openai.models.beta.agents.sessions.SessionCreateParams;
import com.openai.services.beta.agents.AgentTurnResults;
import java.nio.file.Path;
public class HostedReport {
public static void main(String[] args) throws Exception {
var client = OpenAIOkHttpClient.fromEnv();
var params =
SessionCreateParams.builder()
.agent(SessionCreateParams.Agent.builder().model("gpt-6-astra").build())
.environment(
EnvironmentParam.OpenAIHosted.builder()
.network(
EnvironmentParam.OpenAIHosted.Network.builder()
.access(EnvironmentParam.OpenAIHosted.Network.Access.DISABLED)
.build())
.addFile(
HostedEnvironmentFileParam.Inline.builder()
.path("/workspace/amounts.csv")
.data("YW1vdW50CjEwCjIwCjMwCg==")
.build())
.build())
.input(
"Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object"
+ " with the total to /workspace/outputs/summary.json, then read it back to"
+ " verify it.")
.build();
try (var stream = client.beta().agents().sessions().createStreaming(params)) {
AgentTurnResults.withResultCollection(stream);
stream.stream().forEach(System.out::println);
var result = AgentTurnResults.getFinalResult(stream);
AgentArtifactDownloads.forResult(client.beta().agents().sessions().artifacts(), result)
.download("/workspace/outputs/summary.json", Path.of("summary.json"));
}
}
}
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
33require "openai"
require "json"
require "pathname"
client = OpenAI::Client.new
stream = client.beta.agents.sessions.create_streaming(
agent: { model: "gpt-6-astra" },
environment: {
type: :openai_hosted,
network: { access: :disabled },
files: [
{
type: :inline,
path: "/workspace/amounts.csv",
data: "YW1vdW50CjEwCjIwCjMwCg=="
}
]
},
input: "Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it."
)
begin
stream.with_result_collection
stream.each { |event| puts event.to_json }
result = stream.get_final_result
puts result.output_text
client.beta.agents.sessions.artifacts.for_result(result).download(
path: "/workspace/outputs/summary.json",
to: Pathname("summary.json")
)
ensure
stream.close
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24curl --no-buffer --fail-with-body https://api.openai.com/v1/agents/sessions \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": {
"model": "gpt-6-astra"
},
"environment": {
"type": "openai_hosted",
"network": {
"access": "disabled"
},
"files": [
{
"type": "inline",
"path": "/workspace/amounts.csv",
"data": "YW1vdW50CjEwCjIwCjMwCg=="
}
]
},
"input": "Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.",
"stream": true
}'
files의 base64 값에는 CSV 입력 데이터가 들어 있습니다. 예제 코드는 세션 이벤트를 출력합니다. session.id는 agent.session.created 이벤트에서 확인해 저장하세요. agent.session.turn.completed 이벤트를 받으면 아티팩트 목록을 조회한 다음 summary.json을 찾아 다운로드하세요. 파일 내용은 다음과 같아야 합니다.
{ "total": 60 }
턴이 완료되어도 일부 도구 실행은 실패했을 수 있습니다. 작업이 실패하거나 완료되기 전에 스트림이 종료되면 저장된 세션 항목을 확인하세요. 작업을 마치면 세션을 삭제하세요.
| 문제 |
확인 사항 |
| 설정 실패 |
환경 설정 실패 이벤트를 확인하고 패키지, 입력 파일 또는 설정 명령어에서 발생한 오류를 수정한 뒤 새 세션을 만드세요. |
| 샌드박스의 요청이 차단됨 |
network 설정과 리디렉션을 거쳐 연결되는 모든 호스트를 확인하세요. |
| 실행 중인 샌드박스에서 파일 작업 실패 |
샌드박스 상태가 connected인지 확인하세요. 만료되었다면 새 세션을 만들고 입력 파일을 다시 제공하세요. |
상태 또는 파일 목록 조회 요청이 5xx를 반환함 |
재시도 기한을 정하고 대기 시간을 점차 늘려 가며 재시도하세요. 오류가 계속되면 요청 ID를 보관하세요. |