샌드박스
스크립트와 AI 에이전트가 실행하는 코드를 위한 격리된 Linux 마이크로 VM입니다. 약 1초 만에 시작되고 Python, Node.js, bash를 실행하며 서버와 같은 잔액에서 초 단위로 과금됩니다.
샌드박스란
API나 MCP로 만들어 몇 초에서 며칠 동안 쓰고 삭제하는 작은 Linux 머신입니다. 나가는 인터넷은 됩니다(pip install, npm install, git clone). 들어오는 포트와 SSH는 없습니다. 명령과 파일은 API로 주고받습니다. 내부: pip가 포함된 Python 3.12, npm이 포함된 Node.js 22, bash, git, curl.
두 가지 모드
요금제
| 요금제 | vCPU | RAM | 디스크 | 네트워크 | 시간당 | 영구, 월 최대 |
|---|---|---|---|---|---|---|
| micro | 0.25 | 512 MB | 3 GB | 50 Mbit/s | $0.0165 | $9.03 |
| small | 0.5 | 1 GB | 5 GB | 100 Mbit/s | $0.033 | $18.07 |
| standard | 1 | 2 GB | 10 GB | 200 Mbit/s | $0.066 | $36.14 |
| plus | 2 | 4 GB | 15 GB | 300 Mbit/s | $0.132 | $72.27 |
| pro | 4 | 8 GB | 20 GB | 400 Mbit/s | $0.264 | $144.54 |
| max | 8 | 16 GB | 40 GB | 500 Mbit/s | $0.528 | $289.08 |
선택한 요금제의 vCPU와 RAM에 대해 지불합니다: vCPU-시간당 $0.040, GiB-시간당 $0.013. 토큰 없이 보는 최신 가격: GET /sandboxes/tariffs.
알아 두면 좋은 제한
명령 하나는 최대 55초 실행됩니다. 더 긴 작업은 백그라운드 작업으로 돌리고 결과를 조회합니다. 파일은 요청당 5MB까지, 더 큰 파일(최대 2GB)은 일회용 다운로드·업로드 링크로 주고받습니다. 계정당 동시에 샌드박스 20개와 명령 2개까지 실행할 수 있습니다.
환경 변수
비밀 값과 설정은 env로 전달하세요. 생성 시 지정하면 샌드박스의 모든 명령에 적용되고, exec 또는 run에서 지정하면 해당 호출에만 적용되며 샌드박스 값을 덮어씁니다. 최대 64개, 값당 32KB, 합계 64KB까지 가능합니다. 값은 암호화되어 저장되며 API가 반환하지 않고 로그에도 기록되지 않습니다. 응답에는 이름(env_keys)만 표시됩니다.
API=https://api.eqvps.com/api/v1/eqvps
AUTH="Authorization: Bearer $EQVPS_API_KEY"
# env for the whole sandbox (only the names come back, as env_keys)
SB=$(curl -s -X POST $API/sandboxes -H "$AUTH" -H "Content-Type: application/json" \
-d '{"tariff":"small","env":{"DB_URL":"postgres://user:pass@db/app","MODE":"test"}}' | jq -r .id)
# env for one call, merged over the sandbox env
curl -s -X POST $API/sandboxes/$SB/exec -H "$AUTH" -H "Content-Type: application/json" \
-d '{"command":"echo $MODE $RUN_ID","env":{"RUN_ID":"42"}}'지출 한도
기본적으로 샌드박스에는 지출 한도가 없습니다. 대시보드 또는 PUT /sandboxes/budget으로 일별·월별 한도를 설정할 수 있습니다. 한도에 도달하면 새 샌드박스는 429 budget_exceeded를 받고, 실행 중인 임시 샌드박스는 삭제되며, 영구 샌드박스는 디스크를 유지한 채 일시 정지됩니다. 한도를 올리거나 새 날 또는 새 달(UTC)이 시작되면 다시 실행됩니다.
# daily cap $5, monthly cap $50 (null = no cap)
curl -s -X PUT $API/sandboxes/budget -H "$AUTH" -H "Content-Type: application/json" \
-d '{"daily_usd":5,"monthly_usd":50}'
# spent today / this month and when the caps reset (UTC)
curl -s $API/sandboxes/budget -H "$AUTH"빠른 시작: MCP(Claude Code, Cursor 등 클라이언트)
MCP 서버를 한 번 연결한 뒤에는 에이전트에게 평소 말로 부탁하면 됩니다. 샌드박스 도구: create_sandbox, run_code, exec_command, get_task, kill_task, get_upload_url, get_download_url, list_sandboxes, get_sandbox, kill_sandbox, sandbox_pricing.
claude mcp add --transport http eqvps https://mcp.eqvps.com/mcp \
--header "Authorization: Bearer $EQVPS_API_KEY"작은 샌드박스를 만들어 Python으로 print(2 + 2)를 실행하고, 출력을 보여 준 다음 샌드박스를 삭제해 줘.빠른 시작: Python과 Node.js에서 REST
추가 패키지는 필요 없습니다. 토큰을 환경 변수 EQVPS_API_KEY에 넣으세요(발급 방법은 '계정 연결' 참고).
# first_sandbox.py — Python 3.8+, standard library only
import json, os, urllib.request
API = "https://api.eqvps.com/api/v1/eqvps"
KEY = os.environ["EQVPS_API_KEY"]
def call(method, path, body=None):
req = urllib.request.Request(API + path, method=method,
data=json.dumps(body).encode() if body is not None else None,
headers={"Authorization": "Bearer " + KEY,
"Content-Type": "application/json", "Accept": "application/json"})
with urllib.request.urlopen(req, timeout=90) as r: # HTTPError on 401/402/…
return json.loads(r.read() or b"{}")
sb = call("POST", "/sandboxes", {"tariff": "small"})
try:
r = call("POST", f"/sandboxes/{sb['id']}/run",
{"language": "python", "code": "print(2 + 2)"})
print(r["exit_code"], r["stdout"]) # 0 4
finally:
call("DELETE", f"/sandboxes/{sb['id']}")// first_sandbox.mjs — Node.js 18+ (built-in fetch), run: node first_sandbox.mjs
const API = "https://api.eqvps.com/api/v1/eqvps";
const KEY = process.env.EQVPS_API_KEY;
async function call(method, path, body) {
const r = await fetch(API + path, {
method,
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json", Accept: "application/json" },
body: body ? JSON.stringify(body) : undefined,
});
const data = await r.json();
if (!r.ok) throw new Error(`${r.status} ${data.error ?? ""} ${data.message ?? ""}`);
return data;
}
const sb = await call("POST", "/sandboxes", { tariff: "small" });
try {
const r = await call("POST", `/sandboxes/${sb.id}/run`, { language: "node", code: "console.log(2 + 2)" });
console.log(r.exit_code, r.stdout); // 0 4
} finally {
await call("DELETE", `/sandboxes/${sb.id}`);
}Python 및 TypeScript용 SDK
라이브러리가 편하다면: Python과 TypeScript 패키지는 같은 REST 호출을 하고, 429와 503은 스스로 재시도하며, 블록이 끝나면 항상 샌드박스를 삭제합니다. 설치와 예제:
# pip install -U eqvps https://pypi.org/project/eqvps/ (0.2.0+ for env)
# "eqvps sandbox create" = Sandbox.create() here · create_sandbox in MCP · POST /sandboxes in REST (no CLI)
from eqvps import Sandbox
# EQVPS_API_KEY from the environment; env = secrets for your code, stored encrypted
with Sandbox.create(tariff="small", env={"DB_URL": "postgres://user:pass@db/app"}) as sb:
r = sb.run("print(2 + 2)")
print(r.stdout, r.exit_code) # "4\n" 0
sb.upload("/root/data.csv", "a,b\n1,2\n")
print(sb.exec("wc -l /root/data.csv").stdout)
print(sb.exec("echo $RUN_ID", env={"RUN_ID": "42"}).stdout) # env for one call
# the sandbox is deleted when the block exits, also on errors// npm i @eqvps/sdk@latest https://www.npmjs.com/package/@eqvps/sdk (0.2.0+ for env)
import { Sandbox } from "@eqvps/sdk";
// EQVPS_API_KEY from the environment; env = secrets for your code, stored encrypted
await Sandbox.with({ tariff: "small", env: { DB_URL: "postgres://user:pass@db/app" } }, async (sb) => {
const r = await sb.run("print(2 + 2)");
console.log(r.stdout, r.exit_code); // "4\n" 0
console.log((await sb.exec("echo $RUN_ID", { env: { RUN_ID: "42" } })).stdout); // env for one call
}); // deleted afterwards, also on errors
댓글
아직 댓글이 없습니다. 첫 번째가 되세요.