已经能用官方 E2B Python SDK 起沙箱的人,换一条兼容端点时,最容易卡在两件事上:一是以为要换 SDK 或改创建逻辑,二是只改了域名,请求却被 SDK 自动拼到带 api. 前缀的主机上。2026-11-12(北京时间)我按 Sandbox quickstart 核对过环境变量,仍用官方 Python SDK,只把 E2B_API_KEY、E2B_API_URL、E2B_DOMAIN 改成 SandBase 这一侧,并保持 E2B_DEBUG=false、不设置 E2B_SANDBOX_URL。当天 PyPI 上的官方包最新是 2.63.0 (文档仍写针对 2.51.0),我用 2.63.0 在 https://sandbox.sandbase.ai 拉起公开模板 openagentcore-mcode-0-8-0-fbdea0c8,跑了 python3 --version 和一段 5 行探测脚本,退出码都是 0,标准输出里有事先写好的 HELLO=sandbase-e2b-ok-20261112,随后删除了实例。沙箱的创建、运行和停止,按当天定价页和产品 FAQ,目前不碰余额;文档里的 Experimental Playground 另有一句 "may incur charges",两处我并列记下,不擅自抹平。

1. 先别改代码,先看 SDK 读哪些环境变量
我自己以前也做过一次偷懒的迁移:代码里的 Sandbox.create 一行不动,只在 shell 里改了域名,结果控制面请求打到了 https://api. 拼出来的主机。官方 quickstart 把这件事写得很清楚:E2B_API_URL 和 E2B_DOMAIN 都要设 。只设域名时,文档针对的 SDK 2.51.0 会自己推导一个带 api. 前缀的 API 主机。我当天打开 PyPI 上的最新官方包 2.63.0 ,connection_config.py 里同样的回落还在:未设置 E2B_API_URL 时,非调试模式会变成 https://api.{domain}。对 SandBase 来说,正确的控制面是 https://sandbox.sandbase.ai,不是 https://api.sandbox.sandbase.ai。
另外两处也容易顺手设错:
E2B_DEBUG保持false。文档写明,调试模式会改变 SDK 的地址选择,对接这条 HTTPS 服务时应当关闭。- 不要设置
E2B_SANDBOX_URL。它会覆盖每个实例自己的命令和文件地址;不要把它设成控制面源站。文档还提醒:控制面只负责创建和管理实例,命令、文件和端口走的是sandbox.sandbase.ai下的实例子域。控制面请求成功,并不等于命令和文件已经通了。
代码里如果写死了上游的 endpoint、domain 或供应商密钥,环境变量改了也不生效------文档原话是显式连接参数优先于环境变量。这次跟做假定你的应用本来就是从环境里读这些配置的。不必另开一家沙箱厂商的开发者账号,一把具备 Sandbox 权限的普通 SandBase API Key 就能用;限制在别的能力上的 Key 可能会被拒绝。
文档还写了一句我同意的边界:装上官方 E2B SDK,本身不能证明和每一个供应商的全部能力都兼容。这次只验证创建、跑命令、读写文本文件、再删除。
2. 账单先记清楚,免得和模型调用混在一起
定价页 当天的口径是:Models、APIs、Runtimes 共用同一余额,按次计费,没有强制订阅,每笔费用出现在 Usage。和这次跟做直接相关的几条,我按原文意思记在下面。金额按页面写 USD,不用美元符号。
| 条目 | 当天公开页怎么写 |
|---|---|
| 沙箱 | 定价页:Agent sandboxes are free for now;公平使用上限可能适用,改价会提前公告。产品 FAQ(sandbox 产品页):创建、运行和停止目前不碰 SandBase 余额;沙箱任务里若再调模型或 Data API,仍按目录计费 |
| 合格 Data API | 每组织每天 100 次免费,UTC 00:00 重置,组织下全部 Key 共享;超出后按次计费,不会因为额度用尽被拒绝,未用完不结转。LLM 和媒体模型不计入这 100 次 |
| 目录与 schema | 搜目录、读工具的 schema 和价格不计费 |
| 失败调用 | 失败的模型或 API 调用不计费;状态和费用可在 Requests 里看 |
| Start 计划 | 标价写的是 USD 0,说明是 "Starter credits to try everything." 具体额度当天页面没有公布,本文不编造 |
对账看 Developer → Activities → Usage,单次任务也可以查任务成本接口。这次跟做没有登录控制台,也没有把沙箱创建当成一条模型任务去查 cost------沙箱目前的公开口径是不碰余额,我不拿一条不存在的结算记录去「证实免费」。公平使用上限的具体数字,官方同样没有公布。
还有一句只需记住、不必展开的产品边界:用 E2B SDK 创建的沙箱实例,和托管的 Agent Session 不是同一件事;Agents API 也不暴露这些实例。模型怎么选、账单怎么算,仍然是应用自己的事。

3. 跟做:改三行环境变量,跑通一次创建和命令
3.1 先安装当天的官方 SDK
文档示例写的是:
bash
python -m pip install 'e2b==2.51.0'
并说明该指南针对 E2B JavaScript / Python SDK 2.51.0 。我当天在 PyPI 上看到的最新官方包是 2.63.0,这次跟做就用这个版本实际跑通。没有在本文里再重跑一遍 2.51.0。若你想和文档钉死的版本完全一致,可以按页面安装 2.51.0;环境变量的要求两边是同一套。
bash
python -m pip install 'e2b==2.63.0'
我这边的宿主是 Python 3.13.5。沙箱里面的 Python 版本以模板为准,不要和宿主混为一谈。
3.2 只改三行,另外两处保持文档要求的默认
bash
# 把你的 SandBase Key 注入为 E2B_API_KEY。若已存在 SANDBASE_API_KEY,可以这样复用:
export E2B_API_KEY="$SANDBASE_API_KEY"
export E2B_API_URL="https://sandbox.sandbase.ai"
export E2B_DOMAIN="sandbox.sandbase.ai"
export E2B_DEBUG="false"
unset E2B_SANDBOX_URL
标题里说的「三行」,指的就是密钥、API URL 和域名。后面两行不是「再改一处业务配置」,而是按文档把调试开关关掉,并清掉可能覆盖数据面地址的变量。.env 文件只有在启动器或应用自己先加载的前提下才会生效,SDK 读的是进程环境变量。

3.3 列出 ready 模板,不要假设默认的 base 还在
模板 ID 不要沿用上游 E2B 的默认值 base,也不要抄一份过期的名单。用同一把 Key,按文档调用列表接口:
bash
curl --fail --silent --show-error \
'https://sandbox.sandbase.ai/v2/templates?limit=100' \
-H "X-API-Key: $E2B_API_KEY"
我在 2026-11-12 **08:18:45(北京时间)**发出这次请求,HTTP 200 ,耗时约 1.16 秒 。响应是一个数组,当天看到 4 条,全部 public 为 true、buildStatus 为 ready。显示名在 names 里;这 4 条的 aliases 都是空数组。文档说名字和别名都可能出现,当天实际落到了 names。若响应头带 X-Next-Token,再按 nextToken 翻页;这次没有翻页。
| 显示名(names) | public | buildStatus | CPU | 内存 |
|---|---|---|---|---|
openagentcore-mcode-0-8-0-fbdea0c8 |
true | ready | 2 | 2048 MB |
openagentcore-codex-0-8-0-fbdea0c8 |
true | ready | 2 | 2048 MB |
sandbase-oac-37180911221-1 |
true | ready | 2 | 2048 MB |
openagentcore-claude-0-8-0-fbdea0c8 |
true | ready | 2 | 2048 MB |
创建时要把返回里的 templateID 赋给下面的变量。SANDBASE_TEMPLATE_ID 只是示例用的环境变量,不是 SDK 内置配置。我选了仍为 ready 的 openagentcore-mcode-0-8-0-fbdea0c8。实例 ID 留在组织内,不写进公开文章。
bash
export SANDBASE_TEMPLATE_ID='从 JSON 里复制对应的 templateID'

3.4 一段可以复制的 Python
下面这段按官方 quickstart 的结构来:两分钟寿命,finally 里删除实例,并显式检查退出码和一段已知输出。和文档示例的差别是,我把探测命令换成了 python3 --version,再写入一个 5 行脚本并执行。不要打印 SDK 对象,里面可能带访问令牌;实例 ID 也不要贴到公开日志或文章里。
python
import os
import sys
from e2b import Sandbox
options = {"request_timeout": 30}
template = os.environ["SANDBASE_TEMPLATE_ID"]
sandbox = None
failed = False
PROBE = """# five-line probe
import sys
import platform
print("HELLO=sandbase-e2b-ok-20261112")
print("PY=" + sys.version.split()[0])
print("IMPL=" + platform.python_implementation())
"""
try:
sandbox = Sandbox.create(template, timeout=120, **options)
ver = sandbox.commands.run("python3 --version", timeout=15)
print("python:", (ver.stdout or "").strip(), "exit:", ver.exit_code)
path = "/tmp/probe_hello.py"
sandbox.files.write(path, PROBE)
run = sandbox.commands.run(f"python3 {path}", timeout=15)
print(run.stdout)
print("probe exit:", run.exit_code)
if (
ver.exit_code != 0
or run.exit_code != 0
or "HELLO=sandbase-e2b-ok-20261112" not in (run.stdout or "")
):
raise RuntimeError("Command verification failed")
ping = "/tmp/sandbase-hello.txt"
sandbox.files.write(ping, "hello from SandBase")
if sandbox.files.read(ping) != "hello from SandBase":
raise RuntimeError("File verification failed")
print("Command and file checks passed")
except Exception:
print("Sandbox example failed; retain the run ID for troubleshooting")
failed = True
finally:
if sandbox is not None:
try:
Sandbox.kill(sandbox.sandbox_id, **options)
print("Sandbox cleanup completed")
except Exception:
print("Cleanup failed; delete the recorded Sandbox ID")
failed = True
sys.exit(1 if failed else 0)
成功的定义和文档一致:命令、文件检查和清理都完成。如果创建在返回 ID 之前就超时,资源可能已经存在,不要立刻再创建另一个。进程被强杀时,finally 也不会跑到。
3.5 这次实际跑出来的结果
时间都按北京时间(Asia/Shanghai)记录。
| 步骤 | 北京时间 / 墙钟 | 结果 |
|---|---|---|
| 列出模板 | 08:18:45 CST,约 1.16 秒 | HTTP 200,4 条 ready 公开模板 |
| 开始创建 | 08:19:44 CST | 官方 e2b 2.63.0,模板 openagentcore-mcode-0-8-0-fbdea0c8 |
| 创建完成 | 08:19:46 CST,2.21 秒 | 成功拿到实例,ID 不公开 |
python3 --version |
1.733 秒 | 退出码 0,标准输出 Python 3.11.2,标准错误为空 |
| 5 行探测脚本 | 0.636 秒 | 退出码 0,标准输出见下,标准错误为空 |
| 文件往返 | --- | 写入并读回 hello from SandBase,一致 |
| 删除实例 | 08:19:52 CST,0.374 秒 | 清理完成 |
探测脚本的标准输出是:
text
HELLO=sandbase-e2b-ok-20261112
PY=3.11.2
IMPL=CPython
也就是说:环境变量指到 SandBase 之后,官方 SDK 能创建实例,能在模板自带的 CPython 3.11.2 里跑命令和写文件,也能把实例删掉。宿主的 3.13.5 只负责跑 SDK,没有进沙箱。

4. 两处不要自行抹平的分歧
第一处是版本。官方 quickstart 当天仍写「This guide targets E2B JavaScript and Python SDK 2.51.0」,安装命令也钉在 2.51.0。PyPI 当天最新是 2.63.0,我用 2.63.0 按同一组环境变量跑通了上面的路径。2.63.0 源码里,E2B_API_URL 被标注将在下一个 major 版本移除,但今天文档和 2.63.0 的运行时都还要靠它,否则就会走 https://api.{domain}。以后若 major 版本真的拿掉这个变量,以当时的官方文档为准,不要把今天的设置当成永久接口。
第二处是费用提示。Experimental Playground 文档 开篇写:"Operations connect to sandbox.sandbase.ai and may incur charges." 定价页 和 产品 FAQ 则写沙箱目前免费、创建运行停止不碰余额。两处不一致,我不选一边当「最终解释」;这次跟做按定价页和产品 FAQ 理解「目前不碰余额」,对账仍然以 Activities 为准。Playground 本身还有自己的界面限制(例如命令最长 25 秒、文件编辑限在 /tmp/ 且 32 KiB),应用集成应以 SDK 为主,不要把 Playground 的能力表当成 SDK 的能力表。
5. 这条路径够用、不够用的时候
够用的情况很具体:你已经在用官方 E2B Python SDK,创建和命令调用本来就从环境变量读连接配置;SandBase 上有你需要的、状态为 ready 的模板;你要的是给 Agent 一个可创建、可跑命令、可读写文件、用完就删的隔离环境。这时不需要换 SDK,也不需要改 Sandbox.create 的调用方式,把密钥、API URL、域名指过去即可。同一把 Key 还可以查目录、调合格 Data API(每组织每天 100 次免费额度)或模型,搜目录和读 schema 不计费,失败的模型或 API 调用不计费;这些是余额上的另一本账,不要和沙箱「目前不碰余额」混着说。
不够用、或者还要另做验证的情况,我也按文档和这次范围说清楚:
- 代码里写死了上游地址或密钥,只改环境变量不会生效。
- 不要假设默认模板
base或某个上游模板 ID 一定存在;每次用列表接口确认buildStatus为 ready。 - 暂停、恢复、端口访问、快照、webhook、模板构建和更复杂的网络策略,文档要求按所选模板和供应商单独确认。这次没有做 pause / resume,也不把「文件在暂停后还在」写成结论。
- 装上 SDK 不等于全部能力都兼容。遇到
unsupported_operation,先看该模板是否支持,而不是先怀疑环境变量。 - 沙箱目前免费不等于可以忽略公平使用,也不等于模型、Data API 或 Agent Session 免费。具体公平使用数字和 Start 计划的体验额度,当天都没有公布。
对我来说,五分钟的意义就是:环境变量改对,官方 SDK 能对着 sandbox.sandbase.ai 真正创建实例、跑出那串已知输出,再把实例删掉。版本钉死在文档的 2.51.0,还是用当天的 2.63.0,你按自己的依赖策略选;连接这三行,今天两边读的是同一套。