五分钟用 E2B SDK 打通沙箱:环境变量只改三行

已经能用官方 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,你按自己的依赖策略选;连接这三行,今天两边读的是同一套。

相关推荐
用户951794225102925 分钟前
最小循环:让 Agent 跑起来(I1)
python·agent
沉默小管33 分钟前
上班鼓励器_桌宠版
python
SomeOtherTime42 分钟前
Rust 面向对象介绍(AI回答)
开发语言·python·rust
duansamve1 小时前
Flask中视图函数接收请求数据和返回响应实例
python·flask
用户298698530142 小时前
用 Python 自动化把 JavaScript 代码转换为 Word 文档
javascript·python·api
用户019027581612 小时前
AlphaFeed 标的池(universes)全解:CN_Stock / CN_ETF 与权限边界
python
青少儿编程课堂2 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园连连看解析
c++·python·算法·bfs·信息学竞赛
用户0332126663673 小时前
如何使用 Python 将 JSON 转换为 Excel
python·excel
小小张说故事3 小时前
Python 的切片到底切了什么:拆开 slice 对象、负步长和 __getitem__
python