E2B 兼容
E2B 网关kibotos-e2b 服务,把 E2B SDK 的请求翻译成原生 API,让为 E2B 写的程序可以使用 Kibotos。 kibotos-e2b 把 E2B 的控制 API 和 envd 协议翻译成 Kibotos 的原生 API,用官方 E2B SDK 写的程序可以直接在 Kibotos 上运行。这一组页面介绍哪些 SDK 调用与接口可用、它们在 Kibotos 上的行为,以及哪些能力不支持。
兼容版本
E2B 兼容以官方 JavaScript SDK 为准:
- 通过验收的版本是
e2b@2.46.1。 - 兼容目标是
e2b@2.49.1,它还没有通过验收。 - 这一组页面列出的能力以
2.46.1的验收结果为准。
示例
示例需要 Node.js 22 或更新的版本与 e2b@2.46.1,从下面这些环境变量读取连接设置:
| 变量 | 含义 |
|---|---|
E2B_DOMAIN | 部署的 sandbox 域名,不带 scheme,例如 sandbox.example.com |
E2B_API_KEY_FILE | 保存网关 API key 的文件路径,API key 向部署方索取 |
E2B_API_URL | 可选。控制 API 的地址,默认为 https://api. 加上 E2B_DOMAIN |
E2B_TEMPLATE | 可选。要启动的 Template,默认为 kibotos-minimal |
部署的证书不是公共 CA 签发时,另外把 Node.js 自己的 NODE_EXTRA_CA_CERTS 设为该 CA 文件。
下面的示例创建一个短期 sandbox,执行一条命令,然后删除它。lifecycle 中显式选择到期后删除:
import { readFile } from 'node:fs/promises';
import { Sandbox } from 'e2b';
const domain = process.env.E2B_DOMAIN;
const sandbox = await Sandbox.create(process.env.E2B_TEMPLATE || 'kibotos-minimal', {
apiKey: (await readFile(process.env.E2B_API_KEY_FILE, 'utf8')).trim(),
domain,
apiUrl: process.env.E2B_API_URL || `https://api.${domain}`,
secure: true,
timeoutMs: 60_000,
lifecycle: { onTimeout: 'kill', autoResume: false },
});
try {
const result = await sandbox.commands.run('printf kibotos-ready');
console.log(result.stdout);
} finally {
await sandbox.kill();
}把示例保存为 example.mjs,安装 SDK 并运行:
npm install e2b@2.46.1
E2B_DOMAIN=sandbox.example.com E2B_API_KEY_FILE="$HOME/.config/e2b/api-key" node example.mjsSDK 默认创建的 sandbox 需要公网访问。不需要联网时,在创建参数中加 allowInternetAccess: false。部署环境支持的地址族和出网能力取决于 node 的配置,IPv4 支持的背景见 #59。出网策略见网络。
可用的能力
每一行是 SDK 的一块能力,第一列链到介绍它在 Kibotos 上行为的页面。
| 范围 | 可用的调用 | 接口 |
|---|---|---|
| Sandbox 与生命周期 | Sandbox.create、Sandbox.connect、getInfo()、列表、sandbox.kill()、sandbox.pause()、sandbox.setTimeout,以及 Idempotency-Key | POST /sandboxes、GET /sandboxes/{id}、GET /v2/sandboxes、DELETE /sandboxes/{id}、POST /sandboxes/{id}/pause、connect、timeout、refreshes |
| Volume | 按名称创建的独立 Volume,用 volumeMounts 挂载 | POST /volumes、GET /volumes、GET /volumes/{id}、DELETE /volumes/{id} |
| 命令与文件 | sandbox.commands.run、PTY、输入与信号,可以指定执行账号与 cwd | /process.Process/{Start,Connect,SendInput,CloseStdin,SendSignal,Update},均为 POST |
| 命令与文件 | sandbox.files.* 与非递归的 files.watchDir | /filesystem.Filesystem/{Stat,MakeDir,Move,ListDir,Remove,WatchDir}(POST),GET /files、POST /files、GET /health |
| 网络 | allowInternetAccess、network.allowOut 与 network.denyOut 里的地址与 CIDR、network.egressProxy,以及 sandbox.updateNetwork() | 创建请求的 allow_internet_access、PUT /sandboxes/{id}/network |
| 指标 | sandbox.getMetrics() 与 Sandbox.getMetrics(id),部署接入实例指标存储后可用 | GET /sandboxes/{id}/metrics、GET /sandboxes/metrics |
| 应用端口 | 转发到 sandbox 内端口的 HTTP 与 WebSocket,端口可公开或私有,可选改写 Host | {port}-{sandboxID}.<domain> |
网关没有提供的能力会明确返回错误,见不支持的能力。
不支持的能力
不支持的能力总是返回错误。网关不会忽略它们并报告成功,调用方能立刻发现。
返回的错误
- 网关返回 HTTP 501,响应体为
{"code":501,"message":"unimplemented: <能力名> is not supported by the core gateway"}。 - SDK 抛出
SandboxError,消息为501: unimplemented: <能力名> is not supported by the core gateway。 - 返回 501 而不是 404,是因为官方 SDK 把 404 理解为 sandbox 不存在。
- 网关完全没有实现的接口,例如
GET /sandboxes、sandbox 日志、模板的构建与列表,返回普通的 404,SDK 会报成 sandbox 不存在。
接口
以下路由存在,但统一返回 501。这些请求在通过认证后立即返回,不调用原生 API,网关状态也不变。
| 请求 | 能力名 | 缺少的原生能力 |
|---|---|---|
POST /sandboxes/{id}/fork | sandbox fork | 快照捕获与从快照创建副本 |
POST /sandboxes/{id}/snapshots | snapshot capture | Snapshot 资源与捕获命令 |
GET /snapshots | snapshot listing | 同上 |
DELETE /templates/{ref} | snapshot deletion | 同上 |
GET /teams/{teamID}/metrics、GET /teams/{teamID}/metrics/max | team metrics | 团队:网关的 API key 由整个部署共用,没有可统计的团队 |
部署没有接入实例指标存储时,GET /sandboxes/metrics 与 GET /sandboxes/{id}/metrics 也返回 501,能力名 metrics,见指标。
创建选项
官方 SDK 会把调用方配置的所有选项一起发出。网关无法实现的选项会让创建请求失败,而不是忽略它们返回 201。创建响应不会回显这些字段,所以只有失败才能让调用方知道选项没有生效。检查在写入任何状态、调用任何原生 API 之前完成。
| 字段 | 能力名 | 缺少的原生能力 |
|---|---|---|
envVars 非空 | sandbox environment variables | 创建时设置环境变量 |
iam 带 token | IAM tokens | token 绑定 |
mcp 非空 | MCP configuration | MCP 管理 |
network.allowOut 含域名 | network egress allowlist domains | 按域名的出网策略 |
network.rules | network egress rules | 同上 |
autoResume: {"enabled": true} | autoResume | 经应用端口自动唤醒 |
snapshotID 非空 | snapshot restore | 从快照创建 sandbox |
- 表中每一项都返回 501,响应体格式见上文。
- 错误消息与其他创建期错误格式相同,前面多一个
create sandbox:前缀。 - 字段缺省、为
null、空对象或空数组都视为未设置,正常创建。
其他调用与选项
| 能力 | 在 Kibotos 上 | 详见 |
|---|---|---|
| 内存暂停 | sandbox.pause() 与 autoPause 总是冷暂停,内存与运行中的进程不保留 | Sandbox 与生命周期 |
| 递归监视目录 | files.watchDir 带 recursive: true 返回 unimplemented,allowNetworkMounts 被忽略 | 命令与文件 |
CreateWatcher、GetWatcherEvents、RemoveWatcher | 返回 unimplemented:它们要求网关跨请求保存监视状态,而网关不保存状态 | 命令与文件 |
| 修改网络时的网络选项 | allowOut 里的域名、rules、只给 username 的 egressProxy,以及 ctrl 不支持的选项,都返回 501 | 网络 |
网关的工作方式
网关没有自己的存储:
- E2B 特有的信息(metadata、创建选项、volume 名称)随创建命令写进 Workspace给 AI Agent 用的完整 Linux 环境,运行在独立的 MicroVM 里。Agent 在里面读写文件、运行进程、启动服务,不会影响宿主机和其他 Workspace。 或 Volume独立于任何 Workspace 存在的持久卷。一个 Workspace 最多绑定一个 Volume,默认挂载在 /data。 的
labels与annotations,由 ctrl 保管。 - envd token 与 traffic token 不保存,由网关密钥按 sandbox ID 推导。
- 每台网关实例只缓存从 ctrl 读到的内容,多个实例可以同时服务。每个实例需要自己的 Operator 身份,见准备身份并启动。
sandbox 的创建、停止、执行命令、文件操作都转成对 Kibotos 原生 API 的调用,网关本身不运行任何 VM。原生 API 尚未提供的能力,网关不会自己模拟:它只通过原生 API 工作,不复制磁盘、不调用 VMM 的私有接口、不写 ctrl 的数据库,sandbox 的生命周期状态也不由它维护。
- 部署见安装 E2B 网关与重装网关。
- 代码结构与测试见 E2B 网关的代码结构与测试。
下一步
- 从 E2B 迁移:一步步迁移现有程序。
- Sandbox 与生命周期:在 Kibotos 上创建、暂停与恢复、到期。
- 命令与文件:运行进程与传输文件。
- 核心概念:Workspace、Volume 及其状态。
- 保证与边界:数据在什么情况下保留。