E2B Sandbox (当前) → Cloudflare Think Durable Objects (新方案) 的技术对比与体验差异分析
当前 E2B Sandbox 方案在产品体验上有三个核心痛点,直接影响用户留存和平台可扩展性:
用户发送第一条消息后,需要等待 10-25 秒 才能收到回复。其中 5-15 秒是在创建虚拟机、启动进程、建立 WebSocket 连接 — 这些对用户来说都是 无意义的等待。
闲置 5 分钟后再发消息,又要等 2-8 秒 "恢复"。IM 场景下,用户期望的是即时响应。
SandboxManager 有 ~2000 行状态机代码,管理 6 个生命周期阶段、Redis 双锁、多实例竞争、Grace Period、22 小时续期……
每次改一个功能都需要考虑 所有状态转换路径。Bug 排查需要同时看 Server 日志、Redis 状态、E2B API 响应、Sandbox 内部日志 — 链路太长。
E2B 按 CPU 秒 + 内存秒 计费。即使 Agent 只是在等用户回复,只要 Sandbox 还在 running 状态就在烧钱。autoPause 有 5 分钟延迟窗口。
大量 Agent 同时在线时,空闲等待的成本 远大于 实际推理的成本。作为平台方,这个模型 规模化后不经济。
Durable Object 是 V8 isolate,不是虚拟机。按需唤醒 <1ms。用户感受到的延迟 = 纯 LLM 推理时间。
不需要状态机、Redis、多实例协调。DO 天然全局唯一 + 自动休眠。基础设施逻辑交给 Cloudflare。
空闲 = $0(仅 DO 存储费 $0.20/GB·月)。没有 "5 分钟等待窗口"。1000 个闲置 Agent 的成本 ≈ 0。
Think 的核心设计思想是 可组合的执行阶梯 — 每一层都是可选的,按需叠加。简单对话不需要沙箱,复杂任务才启用重计算。而 E2B 方案不管任务简单还是复杂,都要启动一个完整的虚拟机。
| 任务类型 | Bloome 占比 | E2B Sandbox | Cloudflare Think |
|---|---|---|---|
|
纯对话 聊天、问答、翻译、总结 |
~70% |
过度 启动完整 VM 只为调 LLM API 空闲 5 分钟窗口持续计费 |
Tier 0 DO 内直接调用 LLM 无 VM 开销,空闲 = $0 |
|
IM 操作 发消息、查历史、创建线程 |
~20% |
过度 VM 内运行 reson-cli CLI → WS → Server → DB |
Tier 0 + Tools DO 内 HTTP 直调 Server API 链路更短,延迟更低 |
|
轻量代码执行 数据处理、格式转换、计算 |
~7% |
匹配 VM 内 Node.js 执行 能力充足但启动成本高 |
Tier 1-2 Dynamic Worker isolate 按需启动,毫秒级 |
|
重型开发任务 git clone、npm install、运行测试 |
~3% |
匹配 完整 Linux 环境 Shell + 包管理器 + 文件系统 |
Tier 4 Cloudflare Sandbox DO 提供 Shell + FS,但较新 |
~90% 的 Agent 交互根本不需要虚拟机。E2B 方案对所有任务一视同仁地启动完整 VM,而 Think 的分层设计让简单任务(纯对话 + IM 操作)在 Tier 0 就能完成 — 零 VM 开销、毫秒级响应、按请求计费。只有真正需要完整 OS 的重型任务才会升级到 Tier 4。
User → Message → Server → MESSAGE_CREATED Event ↓ handleMessageForAgents() ↓ ┌─── dispatchAgentTrigger() ───┐ │ │ Local WS? ─yes→ pushToAgent() │ Redis Presence? (Agent在 直接推送 │ ─yes→ Redis Relay 本实例?) │ 转发到目标实例 │ │ no no ↓ ↓ ensureRunningAndPush() Pending Queue ↓ 等待认领 Phase=idle? → E2B Create (5-15s) Phase=paused? → E2B Resume (2-8s) Phase=running → 等待 WS 重连 ↓ Runner.cjs 启动 → WS 连接 → 刷新 Pending Queue ↓ createAgentSession() → LLM Call → Stream via WS → Server → IM
User → Message → Server → MESSAGE_CREATED Event ↓ handleMessageForAgents() ↓ dispatchAgentTrigger() — Think fast path ↓ ThinkAgentClient.trigger() HTTP POST → Cloudflare Worker ↓ DO auto-wake (<1ms if hibernated) ↓ ResonAgent.chat() → LLM Proxy → Server → Gateway → Bedrock ↓ onChatResponse() → HTTP POST → Server REST API → IM
| 维度 | E2B Sandbox | Cloudflare Think |
|---|---|---|
| 冷启动(首次触发) | 5 – 15s 慢 创建 MicroVM + 启动 Node + WS 握手 |
<50ms 极快 DO 首次创建 = V8 isolate 启动 |
| 温启动(从休眠唤醒) | 2 – 8s 中等 E2B Resume API + WS 重连 |
<1ms 极快 DO 自动唤醒,无显式 resume |
| 热启动(已在运行中) | <10ms 快 WS 直接推送 |
~50ms 快 HTTP POST + DO 路由 |
| 空闲成本 | $0 (auto-pause 后) 零 但 5 分钟活跃窗口有 CPU 计费 |
$0 零 休眠 = 仅 DO 存储费($0.20/GB·月) |
| 活跃成本 | $0.000014/s CPU + $0.0000045/s Mem 按秒 × 1.5 markup = ~$0.05/小时 (1vCPU+0.5G) |
CPU: $0.02/百万ms, Req: $0.15/百万 低 典型 Agent 单次触发 ~$0.0001 |
| 最大空闲超时 | 5 分钟 (E2B autoPause) 固定 | 无限 — 有请求就唤醒 无限 |
| 多实例协调 | Redis Presence + Ownership Lease 复杂 需要竞争、Grace Period、故障恢复 |
不需要 无 DO 全局唯一,CF 负责路由 |
| Session 持久化 | JSONL 文件 + R2 备份 脆弱 Sandbox 销毁 = 丢失未备份数据 |
SQLite (DO 内置) 持久 自动复制,支持 tree 结构 + fork |
| Sandbox 执行能力 | 完整 Linux 环境 强 Shell, git, npm, 文件系统,任意进程 |
Cloudflare Sandbox DO 新 Shell + FS via Sandbox SDK,但受 Worker 限制 |
| API Key 安全 | 注入为环境变量 暴露 API Key 存在于 Sandbox 内存中 |
Server LLM Proxy 中转 安全 Worker 只持有 agentToken,不接触真实 Key |
| 代码行数 | ~2000 行 庞大 cloud-sandbox/manager.ts + index.ts 调度逻辑 |
~300 行 精简 agent.ts + server.ts + think-client.ts |
Agent 此前从未被触发过,需要完全冷启动
Agent 上次回复已过 1 小时,Sandbox 已 auto-pause
Agent 正在处理第一条消息时,用户又发了第二条
用户要求 Agent "帮我写个脚本并运行测试"
| E2B 组件 | Think 替代 | 说明 |
|---|---|---|
| E2B Sandbox (Firecracker MicroVM) | Cloudflare Durable Object | 从完整 VM → 轻量 V8 isolate |
| Runner.cjs (sandbox 内进程) | ResonAgent.chat() | Think SDK 内置推理循环 |
| JSONL Session 文件 | Think Session (SQLite) | 结构化、可 fork、树形历史 |
| Redis Presence/Ownership | 不需要 | DO 天然全局唯一 |
| WebSocket 双向通信 | HTTP POST (触发) + HTTP POST (回复) | 无状态、更简单 |
| SandboxManager (~1500 行) | ThinkAgentClient (~100 行) | 从复杂状态机 → 3 个 HTTP 调用 |
| R2 Workspace 备份 | DO SQLite 自动持久化 | 无需手动管理备份/恢复 |
| API Key 注入环境变量 | Server LLM Proxy 中转 | API Key 不离开 Server |
| E2B Shell (完整 Linux) | Cloudflare Sandbox SDK | exec() + readFile() + writeFile() |
Zod v4 生成的 JSON Schema 缺少 input_schema.type 字段,导致 AWS Bedrock 拒绝请求 (400 Bad Request)。LLM 推理本身已打通(LLM Proxy → Gateway → Bedrock 链路正常),只是工具定义的 Schema 序列化有问题。临时方案:禁用所有工具后验证纯文本对话是否可用。
| 文件 | 状态 | 说明 |
|---|---|---|
| apps/think-agent/ | 新增 | Worker 完整实现(agent.ts, server.ts, reson-tools.ts, sandbox-tools.ts) |
| apps/server/.../think-client.ts | 新增 | Server 端 HTTP 客户端(含 ProxyAgent 代理支持) |
| apps/server/.../index.ts | 修改 | ACP 调度增加 Think fast path(含临时 DEBUG 日志) |
| agent.ts getTools() | 临时禁用 | 返回空 {} 以绕过 Zod v4 schema 问题 |