Task Runner POC — 技术选型与架构
openspec-agent-platform v2 · POC ✓ E1+E2 真跑通过把单条 Task 在容器里完整跑完 explore → propose → apply → archive 四阶段,输出真实 GitHub PR,并把 status / stage / diff stats 实时回传到主 API。本期 POC 同时验证两条部署路径:公有云(Fly Machines)+ 私有化(VPS + Docker),通过 Sandbank 沙箱中间层抽象切换。
- 公有云栈
- Fly Machines
- 私有化栈
- VPS + Docker + Sandbank
- Agent SDK
- Claude Agent SDK
- 工期估算
- ~13 工作日
§1 背景
现状缺口与本期目标。
openspec/specs/tasks/spec.md 已经定义了 Task 数据模型、4 个 REST API 和 3 张设计稿(04 / 04a / 04b)。缺失的是执行引擎—— status: proposing → running → awaiting_review → done 和 stage: explore → propose → apply → archive 这些字段被前端 MiniStages 拿来画动画,但没有任何后端代码会真正推进它们。
Task DB 行存在,但 stage 永远是 explore、status 永远是 proposing。
- Task 派发器(主 API → 容器)
- 双部署路径并行:公有云 + 私有化
- Agent SDK + Claude + git + openspec
- 状态与工件回传链路
**本期重要变化(vs 上一版报告):**不再”POC 先公有云、私有化是远期阶段 2”。本期 POC 同时验证 公有云(Fly Machines)和私有化(VPS + Docker)两条部署路径,通过 Sandbank 沙箱中间层(详见 §6.1.1)抽象切换。商业上等于”SaaS + 自托管”双轨上线,技术上等于 day 1 就消除供应商锁定。
§2 影响选型的硬约束
下表所列的每条约束都会拍掉一批候选——选型不应以”功能丰富”为先,而应以”红线不踩”为先。
| 约束 | 描述 | 影响 |
|---|---|---|
| 单任务时长 10–30 min | npm install 30-90s + 4 阶段 Claude 调用串联 | 排除任何 ≤ 5 min 硬上限的方案 |
| 每任务一个干净容器 | 仓库间隔离 + 失败重跑不污染上一次状态 | 排除 reuse 型 long-living 进程 |
| 凭据要安全注入 | GitHub installation token(PR 写权限)+ Anthropic API key | 排除共享容器、可被 sidecar 偷窥的方案 |
| 状态要实时回传 | 前端 MiniStages 要看到 stage 跳变 | 排除”跑完一次返回总结果”的模型 |
| 工件要 commit 到 git | openspec/changes/{date-slug}/proposal.md 进仓库 | 排除不提供出口流量 / 不能装 git 的方案 |
| POC 阶段 | 2-3 周见 demo(双轨 ~13d),不上规模、迭代速度优先 | 排除重平台耦合、要写大量胶水的方案 |
§3 云端容器:7 选 1
速览矩阵 + 每个候选的展开。✩ = 5 分制契合度。
| # | 候选 | 形态 | 冷启动 | 单任务上限 | 计费维度 | 本项目契合 |
|---|---|---|---|---|---|---|
| 1 | Fly Machines POC 首选 | OCI / Firecracker | 7.7s(S8.C 实测 · cpu=1 / 256MB · node:22-slim · cold start) | 无硬上限 | 机器 RAM·秒 + 出口 | ★★★★★ |
| 2 | Vercel Sandbox 备选 1 | Firecracker microVM | 1–2s(snapshot 亚秒) | 默认 300s(Pro 可调) | Active CPU + RAM + 调用 | ★★★★☆ |
| 3 | E2B 备选 2 · 协议宿主 | Firecracker microVM | ~150ms | 24h | $0.000014/vCPU/s + $0.0000045/GiB/s · Hobby Free + $100 credit | ★★★★☆ |
| 4 | Cloudflare Sandbox SDK 排除 | Docker on Durable Object | 秒级(休眠后慢) | 10 min 不活跃睡眠 | Worker 调用 + 容器 | ★★☆☆☆ |
| 5 | Daytona Sandboxes 排除 | Docker 容器 | 秒级 | 小时级 | 按小时 + 存储 | ★★☆☆☆ |
| 6 | Modal 排除 | Firecracker | 1–5s | 长 | 秒级 CPU/GPU | ★☆☆☆☆ |
| 7 | Anthropic Code Execution Tool 排除 | Claude 托管 server-side | 即起 | multi-turn ✓(2026 起 container 可复用) | 包含在 token 费里 | ★☆☆☆☆ |
3.1 Fly Machines(POC 首选)
3 个决定性因素让 Fly 跑赢其他候选:
已经在栈里。 Fly token、Fly Postgres、fly-audit 都已经跑着,再加一个 task-runner app 是熟门熟路。
无时长上限。 4 阶段串联跑 30 min 不会撞红线(对比 Vercel Sandbox 默认 300s)。
同 VPC callback。 容器回写主 API 可走内网,不暴露 internal endpoint。
API 调用形态
# 主 API 调 Fly Machines REST 创建一台短命机器
POST https://api.machines.dev/v1/apps/openspec-task-runner/machines
{
"config": {
"image": "ghcr.io/openspec/task-runner:latest",
"env": {
"TASK_ID": "<uuid>",
"INSTALLATION_TOKEN": "<short-lived>",
"ANTHROPIC_API_KEY": "<key>",
"CALLBACK_URL": "https://api.douglasdong.com/internal/tasks/<id>/events"
},
"auto_destroy": true,
"guest": { "cpu_kind": "shared", "cpus": 4, "memory_mb": 4096 }
}
}劣势
- 没有现成 SDK,要包装 Fly Machines REST API(增量 ~150 行 NestJS service)
- 没有原生 sandbox 抽象(但 microVM 隔离已足够)
- 状态回传要自己实现 HMAC 验签 + callback URL pattern
3.2 备选与排除理由
Vercel Sandbox · 备选 1
**优点:**与前端同栈、OIDC 自动认证、snapshot 机制亚秒冷启动。
**致命点:**默认 300s 超时——一个 30 min 的 4 阶段 task 会撞红线,Pro 可调到多少官方文档未明示。
**触发条件:**若官方文档/支持确认 Pro 可调到 ≥ 1800s,切回首选评估。
E2B · 备选 2 · 协议宿主
双产品形态:
- E2B Cloud(SaaS)— Hobby Free + $100 one-time credit(免信用卡),Pro $150/mo 起 + 用量。E2B 自己运维,客户与 AWS 无关。
- E2B Infra(
github.com/e2b-dev/infra· Apache-2.0 · ★1.1k)— 同一套软件开源版,Terraform 部署到自有 GCP(fully supported)/ AWS(Beta)。
按秒单价(Cloud · 两 tier 同价):
- vCPU $0.000014/s ≈ $0.0504/h
- RAM $0.0000045/GiB/s ≈ $0.0162/h
- 4vCPU+4GB · 15 min task = $0.067(约为 Fly 同配置 ~29×)
- 存储 Hobby 10 GiB / Pro 20 GiB 含在套餐,无 API call / egress 费
**协议宿主地位:**E2B 的 HTTP API 已成事实标准——腾讯 CubeSandbox(§9.8.1)通过反向兼容 E2B 协议实现自托管 microVM。本期 fork sandbank 新增的 E2BAdapter,将统一覆盖 E2B Cloud / E2B Infra / CubeSandbox 三个 backend。
**触发条件:**① Fly Machines 跑不通;② 客户私有化场景需要 E2B 协议兼容的 backend(含 Cube);③ 多 backend 协议层验证(POC 用 Hobby tier 的 free credit)。
Cloudflare Sandbox SDK · 排除
当前栈无任何 CF 资产,POC 阶段引入新平台增量过大。10 min 睡眠超时需要 alarm/heartbeat 维持。
Daytona · 排除
按小时计费——20 min 任务也按 1 小时算,定价模型对 POC 不友好。
Modal · 排除
Python 优先,Node/TS 是二等公民。decorator-based API 与 NestJS 主导的范式不匹配。
Anthropic Code Execution · 排除
2026 起已支持 multi-turn + container 复用,但仍是 Claude 托管 sandbox,不能 git push 外部仓库(Anthropic Files API 输出不直通 GitHub),且费用包含在 token 价里(无独立计量),不适合长 PR 工作流。
§4 Agent SDK:Claude vs Codex
头部 2 个候选并排对照。OpenAI Agents SDK / Vercel ToolLoopAgent / LangGraph 三者契合度 ≤ ★★,本节略去。
4.1 并排对照
Claude Agent SDK
推荐@anthropic-ai/claude-agent-sdk
- 执行模型
- 内含 native Claude Code 二进制作为 optional dependency,无需单独安装 CLI。
- 关键能力
- 内置 Read / Write / Edit / Bash / Glob / Grep / WebFetch / WebSearch / Monitor / AskUserQuestion 等工具循环。
- 本仓库 .claude/skills/openspec-*
- 开箱即用——通过
settingSources: ["user","project"]+skills: "all"自动加载。 - .claude/commands/opsx/*
- 开箱即用——可直接写
/opsx:propose ...调用。 - Hooks(pre/post tool use)
- 有。PostToolUse 监听 Write 即可作为 stage 切换的天然挂点。
- Subagent 程序化定义
- 有 declarative
agents: { "code-reviewer": {...} }。 - 沙箱 OS 级实现
- 无原生,依赖容器隔离。
- 模型 / Provider
- Claude(Anthropic Direct / Bedrock / Vertex / Azure 多 provider)。
- 计费
- API key → token 计费。2026-06-15 起 subscription 走独立 Agent SDK 额度:Pro $20/mo · Max $200/mo。
Codex SDK
@openai/codex-sdk
- 执行模型
- TS SDK wraps codex CLI,spawn 进程后用 JSONL over stdin/stdout 通讯。容器镜像必须额外装 codex CLI 二进制。
- 关键能力
- Codex 类 + startThread + Thread.run / runStreamed + resumeThread。结构化输出走 JSON Schema。
- 本仓库 .claude/skills/openspec-*
- 需手工引导——文件能被 Read 工具读到,但 Codex 没有"按需触发"机制;要在 AGENTS.md 里写引导(详见 §4.3)。
- .claude/commands/opsx/*
- 需手工拼到 prompt——没有等价 slash commands 机制。
- Hooks
- 无。只能轮询 events stream(item.completed / turn.completed)或让 agent 主动调用 report 工具。
- Subagent 程序化定义
- 无 declarative,要手动 spawn sub-thread。
- 沙箱 OS 级实现
- read-only / workspace-write / danger-full-access 三档;macOS Seatbelt + Linux Landlock + seccomp。
- 模型 / Provider
- OpenAI(gpt-5 系、o-系列推理模型)。
- 计费
- OpenAI API token 计费;订阅与 Codex 配额合并(具体费率官方文档未细化)。
4.2 决定性差异速读
| 维度 | Claude Agent SDK | Codex SDK |
|---|---|---|
| 二进制依赖 | 内置 | 必须装 codex CLI |
.claude/skills/openspec-* | 自动按需触发 | 手工引导(git clone 后文件在容器里,agent 能 Read,但不自动) |
.claude/commands/opsx/* | 原生 slash command 调用 | 需手工拼到 prompt 头 |
| Hooks(pre/post tool) | 有 | 无 |
| Subagent declarative 定义 | 有 | 无 |
| OS 级沙箱 | 无原生 | Seatbelt / Landlock |
| POC 实施成本 | 低(复用现有 skills,零搬运) | 中(要在 AGENTS.md 引导 + 部分 prompt 内联) |
| Token 效率(context 占用) | 高(未触发的 skill 全文不进 context) | 低(如全量挂在 AGENTS.md,常驻 ~1K-1.5K 行) |
**修正后的关键判据:**差异不在”能不能跑通”——Codex 也能在容器里通过 git clone + Read 工具访问到这些 markdown。差异在于 实施代码量(Claude 零搬运 vs Codex 需在 AGENTS.md 写引导段)和 token 效率(Claude 按需载入 vs Codex 易全量常驻)。POC 阶段两者都可行,Claude 更省事;规模化后 token 成本差距会放大(token 成本由你独立评估,不在本报告范围)。
4.3 Skill 加载机制再评估(承认上一版表述偏激)
**修正:**上一版报告说 Codex SDK “完全不识别 .claude/skills/openspec-*“——这话技术上不准确。只要容器把仓库 git clone 进来,这些 markdown 文件本身就在文件系统上,Codex agent 同样可以通过 Read 工具看到、按需读取它们。差异不在”能不能”,而在”怎么用”。
| 能力 | Claude Agent SDK | Codex SDK |
|---|---|---|
| SKILL.md 自动按需触发 | 原生支持。Agent 看到任务时自动决定要不要载入 skill 全文 | 需手工:在 prompt / AGENTS.md 里告诉 agent “若任务匹配 X 就读 .claude/skills/X/SKILL.md” |
Slash command 调用 /opsx:propose ... | 原生支持。.claude/commands/opsx/propose.md 直接生效 | 需手工:把 commands/opsx/*.md 内容拼到 prompt 头 |
| Skill 内 frontmatter(trigger keywords 等) | SDK 按 description 字段自动匹配 | 忽略 frontmatter,全靠 agent 自己理解 |
| Token 效率 | 未触发的 skill 全文不进 context(只 metadata) | 如果在 AGENTS.md 写全部 4 个 skill,约 800-1500 行常驻 context |
| 双轨维护成本 | 无:仓库已有的 .claude/ 文件就是 SDK 的输入 | 中:要在 AGENTS.md 写”如何使用 .claude/skills/“的引导段 |
修正后的判定:差异从”原生支持 vs 完全不识别”降级为”自动按需加载 vs 手工引导 + 全量常驻”。Claude 仍占优,但优势主要在 token 效率和实施代码量,不在”能不能跑通”。
4.4 鉴权复杂度并排
| 维度 | Claude Agent SDK | Codex SDK |
|---|---|---|
| 容器内最小鉴权 | ANTHROPIC_API_KEY 一个环境变量 | 两件事:OPENAI_API_KEY + 容器镜像装 codex CLI 二进制 |
| 多 provider 切换 | 环境变量切换:Bedrock / Vertex / Azure / Anthropic Direct | 仅 OpenAI(含 Azure OpenAI) |
| 订阅 vs API key 双账单 | 清晰隔离:API key → 按 token 计费(POC 走这条,永远不变);Pro/Max 订阅 → 2026-06-15 起 SDK 调用走独立月度池(Pro $20 / Max $200),与 Claude.ai 交互额度分开 | 复杂:sign in 方式决定走 ChatGPT plan 额度还是 API key 计费,容易混淆 |
| 容器镜像构建复杂度 | npm i 自带原生 binary,单层 | 需多一层 npm i -g @openai/codex 装 codex CLI |
| 本地 dev 与 CI 走同一路径 | 完全一致 | 本地 dev 可能用 ChatGPT 登录,CI 必须 API key |
4.5 速率限制与并行能力
POC 阶段单任务串行可忽略,但只要规划 ≥ 5 并发就要正视。下表汇总 API 层(不算容器层)的速率限制。
| 维度 | Anthropic(Claude) | OpenAI(Codex / GPT-5) |
|---|---|---|
| 分级体系 | Tier 1–4,预付 + 累计支出 | Tier 1–5,预付 + 累计支出 + 账户年龄 |
| Tier 1 入门门槛 | $5 prepay | $5 prepay + 7 天等待 |
| Tier 4/5 顶层门槛 | $400 + 时间 | $1000 + 30 天 |
| Tier 1 RPM(Sonnet 等) | 50 RPM | 500 RPM(GPT-5 系) |
| Tier 4 RPM | 4000 RPM | 10,000+ RPM |
| 实际节流粒度 | 官方文档说”每分钟”,实际按每秒节流 | 同上 |
| 缓存 token 是否计入 ITPM | 不计入(90% off + 不消耗 ITPM 额度) | 部分计入 |
| POC 推荐 tier | Tier 2($40 prepay → 1000 RPM)足够 5-10 并发 | Tier 2 类似 |
| 本项目实际并发瓶颈 | 不在 API tier,而在主 API 端的”同用户同仓库并发上限”控制(见 §5.5) | — |
**关键洞察:**对 POC 来说,API tier 限制远远高于业务实际需要的并发——5 task 并发 × 平均 30s 一次 API 调用 ≈ 10 RPM,连 Tier 1 都不会触顶。瓶颈不在 SDK / 模型一侧,而在主 API 怎么管”同用户/同仓库的 task 并发”。
4.6 推荐用法示意
import { query } from "@anthropic-ai/claude-agent-sdk";
// 在容器入口 run.js 内执行
for await (const msg of query({
prompt: "/opsx:propose " + task.prompt,
options: {
cwd: "/workspace/repo",
settingSources: ["project"], // ← 容器内 user 级通常为空
skills: "all",
allowedTools: ["Bash", "Edit", "Write", "Read", "Grep", "Glob"],
permissionMode: "bypassPermissions", // ← 容器必须 non-root(S7/S8 实测:claude binary 拒绝 root + bypassPermissions)
maxTurns: 200,
hooks: {
PostToolUse: [{
matcher: "Write",
hooks: [async (input) => {
const fp = input.tool_input?.file_path ?? "";
if (fp.endsWith("/proposal.md")) {
await reportStage("propose", "done", fp);
}
return {};
}],
}],
},
},
})) {
if (msg.type === "result") {
await reportStage("propose", "done", msg);
}
}4.7 何时反悔切回 Codex SDK
- Anthropic API 严重不可用或配额政策大变
- 核心任务在 GPT-5 推理模型上效果显著更好
- 业务需要”双 Agent 互评”(Claude 提案 + Codex review)
前两个是完全切换场景,到那时做一次完整迁移评估更划算;只有第 3 个会让两者并存。POC 阶段不必为这种弹性做投资。
§5 容器机器成本估算(联网校准)
所有数字均为 2026-05 联网拉到的官方公开价。只算基础设施成本,Token 成本是 Agent SDK / 模型选型的独立维度,不在本节范围。
**明确边界:**本节只评估”机器开多久花多少钱”。模型推理 token 成本随 prompt 设计、缓存策略、模型选择剧烈波动,把它放进容器对比里会让基础设施决策失焦。容器钱是容器钱的事,token 钱是 token 钱的事——独立看。
5.1 真实月度账单(按规模档 · 已扣 free tier)
这张表怎么算的(vs 上一版的修正):
- I/O wait 修正:Vercel 按 Active CPU 收费,Claude task 大约 50% 时间在等模型 API 返回。Vercel 数字按 0.5x 利用率算(其他家按墙钟时间,不变)。
- Free tier 已扣:E2B $100 one-time credit、Cloudflare Workers Paid 含 375 vCPU-min/月、Vercel Hobby 5h CPU/月、Vercel Pro $20 credit/月——都已经在计算里扣掉。
- 月费已加:E2B Pro $150/月(> 100 并发要)、Cloudflare $5/月、Vercel Pro $20/月——按规模触发的月费已加入合计。
- 单任务 30 min,4 vCPU + 4-8 GB(按各家最近档位)。
| 候选 | POC 规模 (100 task/月) | 中规模 (1K task/月) | 规模化 (5K task/月) | Free tier / 月费 |
|---|---|---|---|---|
Fly Machines shared-cpu-8x · 4GB(推荐 POC 配置) | $1.85 | $18.5 | $92 | 无 free tier · 无月费 · 按秒 |
Fly Machines shared-cpu-1x · 256MB(最小 · S8.C 实测) | ~$0.05 | ~$0.5 | ~$2.5 | S8.C 实测启动 7.7s · 单次 ~10min · 资源够 alpine/slim base + node 跑 SDK |
Fly Machines performance-2x · 4GB | $4.5 | $45 | $223 | 同上 |
E2B Hobby 4 vCPU · 4GB | $0 (用 credit) | $33 (credit 用完后) | $666 | $100 one-time credit ≈ 750 task |
E2B Pro 100 并发上限 | — | — | $816 (含 $150 Pro) | $150/月 · > 20 并发或 > 1h session 要 |
Cloudflare Containers 4 vCPU · 8GB | $22 ($5 月费 + 超额) | $185 | $905 | Workers Paid $5/月 · 含 375 vCPU-min ≈ 3 task |
Vercel Sandbox Hobby 4 vCPU · 8GB · I/O wait 50% | $0 (在免费额度) | 超 Hobby | 超 Hobby | 5h Active CPU/月 ≈ 10 task |
Vercel Sandbox Pro 4 vCPU · 8GB · I/O wait 50% | $21 ($20 月费包 $1 超额) | $213 | $1,064 | $20/月 base · 含 $20 credit |
5.2 规模化(5K task/月)月度账单可视化
5K task/月真实月度账单 · 已扣 free tier $0 ──────────► $1,064 Fly shared-8x (4GB) ▮▮▮▮▮▮▮▮ $92 (1x) Fly perf-2x (4GB) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ $223 (2.4x) E2B Hobby (4 vCPU·4GB) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ $666 (7.2x) E2B Pro (+$150/月) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ $816 (8.9x) Cloudflare (4 vCPU·8GB) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ $905 (9.8x) Vercel Pro (4 vCPU·8GB) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ $1,064 (11.6x)
修正后的核心结论(vs 上一版):
- POC 规模(100 task/月)下,E2B 和 Vercel Hobby 实际免费——free tier 完全覆盖。Fly $1.85 反而不是最便宜的(虽然差距小到没意义)。
- 规模化(5K/月)Fly 仍领先——比次便宜的 E2B Hobby 便宜 7.2x(不是上一版说的 19x;上一版忽略了 I/O wait 与 free tier)。
- Vercel Pro 在规模化时贵了 11.6x——主要是月费 + 单价两端都贵,Active CPU 模型只在 idle 任务上省钱。
- Cloudflare 的 free tier 几乎可忽略——$5 月费含的容量只够 ~3 个 30min task,规模化后跟 E2B Pro 接近。
5.4 数据精度说明
① 单价来自 2026-05 官方公开 pricing 页面(见 §12 参考资料)。 ② I/O wait 50% 假设是中等估算——Claude task 实际 I/O 占比 30-60%,意味着 Vercel 数字波动范围 $0.6x-$1.4x。 ③ Egress 流量在月度量级下可忽略(150 MB × 5K = 750 GB,Fly NA/EU 区 $0.02/GB ≈ $15 在 $92 容器费上 +16%)。如果跨区域流量大需单独算。 ④ 不含模型推理 token 成本(独立维度,由你评估)。 ⑤ 实际生产成本还有冷启动重试、监控、Postgres、Egress 跨区域等——这些是各家通用的,不影响选型决策。
5.5 死循环 / 账单失控防护(重要)
用户反馈:“避免 Cloudflare 这种由于死循环直接刷 10000 刀以上的案例”——这是基于真实社区报告的合理担忧。下表对各候选的自带防护与必须自建的防护做并列。
| 候选 | 原生 spend cap | 并发上限(默认) | 单容器最长寿命 | 失控风险评级 |
|---|---|---|---|---|
| Vercel Sandbox | Spend Management · 项目级暂停 | Pro 2000 · Hobby 10 | Pro 5h · Hobby 45 min | 低 |
| Fly Machines | 无原生 cap,但 auto_destroy=true 跑完销毁 | 未公开默认,需注册时与支持沟通 | 无硬上限 | 中 |
| E2B | 未明示 | Free 20 · Pro 100 · Enterprise 1100 | Free 1h · Pro 24h | 中 |
| Cloudflare Containers | 无月度 spend cap · 仅单 invocation CPU time(5 min max) | max_instances 自定,但默认无硬上限 | 10 min 不活跃睡眠 | 高 |
POC 必须落地的防护清单(多层)
tasks表加claimed_at+runner_machine_id- 同一 user 同一 24h 内最多 20 个 task
- 同一仓库同时最多 3 个 task 并发
- dispatch 前查并发计数,超限直接拒
- run.js 入口顶级
setTimeout(默认 60 min hard kill) - SDK
query()调用包 try/catch,失败回报失败状态后立刻退出 - S5/S7 实测:4 阶段流转跑在单一
query()内部(SDK skill 自调度),无法精确切分各阶段独立 timeout;顶层 hard kill 已足够防护
- Fly 账户:开启 daily spend alert(Fly 邮件通知)
- GitHub installation token:1h 过期即自然失效
- Token 侧账单(Anthropic / OpenAI console 的 monthly hard cap)属于模型选型决策,由你独立配置
- 主 API 每 10 min 巡检:查询 Fly Machines API,把
created_at > 60 min但仍 running 的机器强制 DELETE - 复用现成
apps/fly-audit做活跃 Machine 监控 - 每日 cron 检查 task_events 表,无新事件 30 min 的 task 标记为 stalled
**结论:**即便选了无原生 spend cap 的 Fly,靠”多层防护清单”已经能把容器侧死循环风险压到极低——POC 阶段最坏情况是单任务 1h hard kill × 3 并发 × 24h = 72 任务/天,容器纯开销 ≈ 72 × $0.037 ≈ $2.7/天。模型 token 侧的失控防护属于另一条线(Anthropic console / OpenAI dashboard 的 monthly spend hard cap),由你独立设置即可。
§6 POC 推荐架构
三层拓扑 + 状态机推进 + 关键接口契约。
6.1 拓扑图 · 可插拔双轨
关键设计:Sandbank 沙箱中间层 隔离”主 API 的派发逻辑”与”具体后端”。POC 同时启用 FlyAdapter 和 BoxLiteAdapter 两个 adapter,容器入口 run.js 完全相同。
┌─────────────────────────────────────────────────────────────────────────┐ │ WEB · VERCEL │ │ ┌───────────────────────────────────────┐ │ │ │ apps/web · Next.js │ │ │ │ POST /tasks │ │ │ │ GET /tasks/:id/events (SSE) │ │ │ └───────────────────────────────────────┘ │ │ │ HTTPS · session │ │ ▼ │ │ API · FLY.IO │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ apps/api · NestJS │ │ │ │ ┌──────────────────────────┐ ┌─────────────────────────┐ │ │ │ │ │ TasksController │→ │ TaskEventsController │ │ │ │ │ │ + POST /tasks/:id/ │ │ POST /internal/tasks/ │ │ │ │ │ │ dispatch │ │ :id/events │ │ │ │ │ │ + GET /tasks/:id/events │ │ HMAC 验签 + SSE 广播 │ │ │ │ │ └──────────────────────────┘ └─────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ │ │ Sandbank · 沙箱中间层(多 backend 抽象) │ │ │ │ │ │ provider.create / exec / destroy │ │ │ │ │ │ 按 env 切换 adapter — 业务代码 99% 共用 │ │ │ │ │ │ — 公有云 / 私有化双轨切换的核心抽象 — │ │ │ │ │ │ ↓ 两个 adapter │ │ │ │ │ │ FlyAdapter(内置) │ │ │ │ │ │ BoxLiteAdapter(内置) │ │ │ │ │ │ (详见 §6.1.2 - §6.1.4) │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ FlyAdapter │ BoxLiteAdapter │ │ ▼ ▼ │ │ ⬢ 公有云 · FLY MACHINE ▣ 私有化 · VPS DOCKER │ │ ┌──────────────────────────────┐ ┌────────────────────────────────┐ │ │ │ 短命 Machine (auto_destroy) │ │ BoxLite microVM (via Sandbank) │ │ │ │ guest: 4 vCPU / 4 GB │ │ host: 普通 Linux VPS (KVM) │ │ │ │ spec: shared-cpu-8x │ │ isolation: microVM (每 task) │ │ │ │ ┌────────────────────────┐ │ │ ┌──────────────────────────┐ │ │ │ │ │ run.js (容器入口) │ │ │ │ run.js (同一份代码) │ │ │ │ │ ├────────────────────────┤ │ │ ├──────────────────────────┤ │ │ │ │ │ 1. git clone + checkout│ │ │ │ 1. git clone + checkout │ │ │ │ │ │ 2. /opsx:explore → │ │ │ │ 2-4. 同公有云路径 │ │ │ │ │ │ propose │ │ │ │ 5. 同公有云路径 │ │ │ │ │ │ 3. /opsx:apply │ │ │ └──────────────────────────┘ │ │ │ │ │ (typecheck+lint) │ │ │ │ │ │ │ │ 4. /opsx:archive + │ │ │ callback: Tailscale tailnet │ │ │ │ │ git push │ │ │ (私有,26ms) 或公网 HTTPS │ │ │ │ │ 5. curl POST /pulls + │ │ │ (239ms · HMAC) │ │ │ │ │ report 完成 │ │ │ │ │ │ │ └────────────────────────┘ │ │ 同一镜像 ghcr.io/openspec/ │ │ │ │ 同一镜像 ghcr.io/openspec/ │ │ task-runner │ │ │ │ task-runner │ │ │ │ │ └──────────────────────────────┘ └────────────────────────────────┘ │ │ ╲ ╱ │ │ ╲ 两条路径的 callback 都打回同一个 events controller ╱ │ │ ╲ ╱ │ │ ◀──── (异步回调 dashed) ◀── │ └─────────────────────────────────────────────────────────────────────────┘ Legend: 主进程/服务 ▢ 抽象接口(虚线)▭ 公有云容器 私有化容器 ── 实时数据流 ┄┄ 异步回调
6.1.1 沙箱中间层 · 用 Sandbank(不自定义 Provider)
**关键决策:**本期 POC 不再自定义 Provider 接口——业界已经有专门做”多 backend 抽象”的开源项目。联网调研发现 3 个候选,其中 chekusu/sandbank 几乎完美匹配本场景——直接内置 Fly.io(公有云)+ BoxLite Docker(私有化)+ Cloudflare 等多个 backend,一个 npm 包同时覆盖本期 POC 的两条部署路径。
Sandbank Provider 接口形态
import { createProvider, FlyAdapter, BoxLiteAdapter } from "sandbank";
// 按 env 切换 — 业务代码 99% 共用
const provider = process.env.TASK_RUNNER_MODE === "private"
? createProvider(new BoxLiteAdapter({ /* ... */ }))
: createProvider(new FlyAdapter({ apiKey: process.env.FLY_API_TOKEN }));
// 派发一个 task — 容器入口由 image 决定
const sandbox = await provider.create({
image: "ghcr.io/openspec/task-runner",
env: {
TASK_ID: task.id,
INSTALLATION_TOKEN: installationToken,
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
CALLBACK_URL: `https://api.douglasdong.com/internal/tasks/${task.id}/events`,
HMAC_SECRET: process.env.TASK_HMAC_SECRET,
REPO_FULL_NAME: branch.repoFullName,
AGENT_BRANCH: agentBranch,
PROMPT: task.prompt,
},
});
// 容器内 run.js 串行跑 4 阶段,结束后 sandbox.destroy()6.1.2 三个中间层候选对比
| 候选 | Stars | 最新版 | TS SDK | Fly.io | 本地 Docker | 本项目契合 |
|---|---|---|---|---|---|---|
| chekusu/sandbank 推荐 | 163 | v0.6.2 · 2026-05 | 完整 | Firecracker 3-5s | BoxLite adapter | ★★★★★ |
| cased/sandboxes | 97 | v0.7.0 · 2026-02 | 偏 CLI | Sprites(Fly 旗下 sandbox 产品) | 无 | ★★☆☆☆ |
| hyperterse/sandboxer | 6 | 不明 | 外置 | Fly Machines API | Docker | ★☆☆☆☆ |
Sandbank 详解
Sandbank · 中间层最佳匹配 ⭐
核心理念:“Unified sandbox SDK for AI agents — write once, run on any cloud”,capability detection 替代假兼容(这个工程态度重要:明确告诉你 provider X 不支持 feature Y,不静默降级)。
内置 provider:
- Daytona · 全 VM · ~10s 冷启动
- Fly.io · Firecracker microVM · ~3-5s ← 本期公有云路径
- Cloudflare · V8 isolate + 容器 · ~1s · 全球 edge
- BoxLite(Docker) ← 本期私有化路径
- db9(PostgreSQL service adapter)
API:
import { createProvider, FlyAdapter, BoxLiteAdapter } from "sandbank";
// 按 env 切换 — 业务代码 99% 共用
const provider = process.env.TASK_RUNNER_MODE === "private"
? createProvider(new BoxLiteAdapter({ dockerHost: '...' }))
: createProvider(new FlyAdapter({ apiKey: process.env.FLY_API_TOKEN }));
const sandbox = await provider.create({ image: "ghcr.io/openspec/task-runner" });
const result = await sandbox.exec("/app/run.js");
await provider.destroy(sandbox.id);**关键工程价值:**省掉自写两个 Provider implementation 的工作量 —— Sandbank 内置 adapter 直接可用,POC 工期落在 ~13d(含双轨)。
Sandbank 的限制(已知)
- 无 E2B provider——E2B 兼容不在 sandbank 范围(如果想未来切到 E2B 还要自己加 adapter)
- 无 streaming 支持——文档明示 “No streaming or snapshot support yet”,长任务的实时日志要走自己的 callback HTTPS(与 §6.3 设计一致)
- 无 git 工作流业务封装——Sandbank 只管容器,不管 git 操作。run.js 自己调 git CLI(clone / commit / push)即可,本场景”每 task 一容器”模型下也够用
- star 数 163 仍属早期——POC 前建议做 1-2 小时 spike 验证 Fly + BoxLite 两个 provider 在 30 min 长任务下的稳定性
修订后的设计决策
| 层 | 选择 | 理由 |
|---|---|---|
| 容器调用抽象 | Sandbank(不自写) | 省 2.5 天工期,且 capability detection 比自写更严谨 |
| 公有云 backend | Sandbank 的 Fly Adapter | 3-5s 冷启动,符合 §3 选型 |
| 私有化 backend | Sandbank 的 BoxLite Adapter | S3 实测:Apple Silicon Mac mini + Hypervisor.framework 等效 KVM,开箱即用 |
| Agent 内部调用 | run.js 用 Claude Agent SDK 直接调 | run.js 本身就是 sandbox 内的入口,无需额外编排层 |
| git 工作流 | run.js 直接调 git CLI | 每 task 一个干净容器已是隔离边界,无需 worktree(详见 §10.7) |
**结论:**引入 Sandbank 后,主 API 不再需要自定义 Provider 接口——直接用 Sandbank 提供的 Provider 抽象即可。§7 任务清单按 接入 Sandbank 1.5d(公有云)+ 1.5d(私有化) 计算,POC 工期落在 ~13d。POC 前要 spike 验证 Sandbank 在 30 min 长任务下的稳定性。
6.1.3 Sandbank 私有化接入完整度 + Fork 策略
用户提出的关键问题:Sandbank 对私有化的接入全吗?能不能 fork 改?深入核实后的事实:
BoxLite Adapter 能力完整度
| 能力 | BoxLite | 本场景需要 | 判定 |
|---|---|---|---|
| Create / Destroy / List | ✓ | ✓ | 对齐 |
| Execute commands | ✓ | ✓ | 对齐 |
| Read/Write files | ✓(via exec base64) | ✓ | 对齐 |
| exec.stream(流式输出) | ✓ | 长任务日志必需 | 对齐 |
| terminal(交互式) | ✓ | POC 不强求 | 富余 |
| port.expose | ✓ | POC 不需要 | 富余 |
| snapshot | ✓ | 未来 task 状态延续可用 | 富余 |
| sleep(休眠/唤醒) | ✓ | 未来 task 状态延续可用 | 富余 |
| volumes(持久卷) | ✗ | 不需要(每 task 一次性容器) | 无影响 |
| services(数据服务绑定) | ✗ | 不需要(DB 在主 API 端) | 无影响 |
核心结论:BoxLite adapter 对本场景的私有化需求是齐全的,没有关键缺失。 所有本场景需要的能力(create/destroy/exec/files/streaming)都对齐,BoxLite 还额外提供了 terminal/snapshot/sleep/port.expose 等富余能力(未来可用)。
来自上游 issue #2 的能力补充(2026-05-16 维护者回复)
调研中发现 chekusu/sandbank #2 维护者 @guo-yu 详述了各 adapter 的 persistence 能力——补充以下事实:
- BoxLite 是为”长期保留沙箱”设计的——配合
auto_remove: false+ snapshot + sleep,维护者原话:“适合本机/自托管的长期保留沙箱”。本场景虽然是”每 task 一次性容器”,但未来如果想做 agent 状态延续(如人工 review 中途暂停 task),能力已现成。 - Fly.io adapter 也支持 volumes——已有集成测试覆盖 volume mount 写入读回。这意味着公有云路径也有持久化能力可选(POC 不用,但未来扩展不需切 backend)。
- Cloudflare adapter 支持 snapshot + volumes(配置 storage 时)。
- E2B adapter 上游仍在 TODO——我们已 fork 自实现:
@douglas-agent/sandbank-e2b提供E2BAdapter+CubeSandboxAdapter(共享 E2BProtocolAdapter 基类)。详见 changeadd-sandbank-fork-aio-e2b。
BoxLite 适用范围
BoxLite adapter 背后用的是 BoxLite 的嵌入式 microVM 库。可跑的硬件覆盖了所有目标场景:
- Apple Silicon Mac(Hypervisor.framework): S3 实测 M4 Mac mini 等效 KVM,PoC demo 推荐硬件
- 裸金属 / 主流云 VM: AWS / GCP / Hetzner / DigitalOcean 等开 nested virt 的环境
极少数仅 OpenVZ 类无虚拟化能力的 VPS 不在 POC 支持范围——这类客户应改选有 nested virt 的 VPS 或自带 Apple Silicon 硬件,不再保留”自写纯 Docker adapter”作为退路(容器内 Docker 没有 microVM 隔离边界,与本项目”每 task 一个独立沙箱”的安全前提冲突)。
Fork 可行性评估
| 指标 | 数据 | 对 fork 决策的影响 |
|---|---|---|
| License | MIT | Fork 友好,可商用闭源修改 |
| 仓库结构 | 每个 adapter 独立 npm 包 @sandbank.dev/boxlite / @sandbank.dev/flyio 等 | 扩展点清晰,新加 adapter 不影响原有 |
| 现有 forks | 13 个 | 已有先行者 |
| 最小 adapter 契约 | 6 个核心方法 | 自写工作量可控 |
| 上游维护响应 | issue #2(2026-03 发起)维护者 @guo-yu 2026-05-16 详细回复 | 修正:上游活跃——issue 2 个月后还得到代码级回复 + 3 个可实现点 + TODO 路线图共享。贡献 PR 比 fork 自维护更现实。 |
| contributor 数 | 至少 @chekusu + @guo-yu 两人活跃 | 不是单人项目 |
| 路线图透明 | docs/TODO.md 已含 E2B adapter 等待办项 | 未来可能要的 adapter 已经在计划中,未必要自己写 |
两个 fork 改造方案
不 fork · 直接用上游
**判断:**BoxLite adapter 对 POC 完全够用。host 选 Apple Silicon Mac mini 或支持 nested virt 的 VPS,BoxLite 直接能跑。
**工作量:**0 额外开发
**触发条件:**本期 POC 默认选这个。E1+E2 真跑通过已证明可行。
Fork + 加 CubeSandboxAdapter
**动机:**把腾讯 CubeSandbox(§10.8)接到 Sandbank。CubeSandbox 已经是 E2B 接口兼容——基本上可以参照 sandbank 的 flyio adapter 风格快速实现。
**额外收益:**VM-level 隔离 + 60ms 冷启动 + 2000+/单机并发
**工作量:**0.5-1 天
**触发条件:**国产化合规场景 / 需要高密度并发。
修订后的 POC 决策
| 阶段 | 私有化栈 | 工作量 |
|---|---|---|
| 本期 POC | Sandbank 上游 + BoxLite adapter | 1d 接入 |
| 规模化阶段(国产化) | Fork Sandbank + 自写 CubeSandboxAdapter | +0.5-1d |
核心判断:
- BoxLite adapter 对 POC 私有化需求是齐全的(功能完整度核实 OK + E2 真跑通过)
- Fork 友好度高(MIT + 13 forks + 独立包结构 + 6 方法契约)
- 本期 POC 选方案 A(不 fork,直接用 BoxLite adapter)
- 未来若有国产化合规需求,CubeSandboxAdapter 是 0.5-1 天的事,不是阻塞性风险
6.1.4 其他私有化 Runtime 的 Sandbank 接入评估
除了 BoxLite,§10 列出的其他私有化 sandbox runtime(AIO Sandbox / Daytona OSS / Microsandbox / CubeSandbox / OpenSandbox / OpenHands / Docker sbx)——Sandbank 能不能接?逐个核实它们的接口形态后,结论是大多数都能在 1 天内接入。
接入难度矩阵(联网核实每个 runtime 的官方接口)
| Runtime | Sandbank 内置 | 接口形态 | 接入路径 | 工作量 | 推荐度 |
|---|---|---|---|---|---|
| BoxLite | ✓ 已内置 | 嵌入式库 | 直接用 | 0d | ★★★★★ |
| Daytona OSS | ✓ DaytonaAdapter | NestJS RESTful API(self-hosted 和 cloud 同套代码) | 改 base URL + OIDC token | 0.5d | ★★★★★ |
| AIO Sandbox(字节) | ✗ | RESTful /v1/* + OpenAPI + 官方 @agent-infra/sandbox npm | 写 AIOSandboxAdapter 包装官方 npm SDK | 1d | ★★★★☆ |
| CubeSandbox(腾讯) | ✓ 已 fork 自实现 | E2B 兼容协议(reverse proxy 实现 E2B SDK 接口) | @douglas-agent/sandbank-e2b 的 CubeSandboxAdapter(与 E2BAdapter 共享基类) | 0-1d | ★★★★★ |
| Microsandbox | ✗ | JSON-RPC 2.0 over HTTP(/api/v1/rpc) | 写 MicrosandboxAdapter(JSON-RPC client) | 1-1.5d | ★★★☆☆ |
| OpenSandbox(阿里) | ✗ | 有官方 npm @alibaba-group/opensandbox | 写 OpenSandboxAdapter 包装官方 SDK | 0.5-1d | ★★★☆☆ |
| OpenHands | ✗ | agent + sandbox 一体(要逆向拆解出 sandbox 部分) | 不划算 | 3-5d | ☆☆☆☆☆ |
| Docker sbx | ✗ | 2026-03 新出 · API 未公开披露 | 观察 3-6 个月 | 未知 | ⚠ 观察 |
关键洞察
Daytona OSS 与 cloud 用同一套 NestJS RESTful 代码,Sandbank 现有 DaytonaAdapter 只需切 base URL + OIDC token——0.5 天就能接入 self-hosted Daytona。
CubeSandbox 是 E2B 协议兼容——我们已 fork sandbank 并实现 E2BProtocolAdapter 基类,E2BAdapter(E2B Cloud/Infra)和 CubeSandboxAdapter(自托管 Cube)共享同一协议层。同一份代码同时覆盖国产化 + 海外公有云。
除了 OpenHands(定位错位)和 Docker sbx(太新),所有候选都能在 1-1.5 天内接入 Sandbank。如果未来要把私有化矩阵铺满,加 5 个 adapter 总工期不到 5 天。
Sandbank 维护者在 issue #2 公开了 docs/TODO.md。意味着未来想要的 adapter 可能不用自己写——贡献 PR 加快上游进度比 fork 自维护更划算。POC 期可以先用 BoxLite,未来根据需要去 follow 上游路线图。
对原来”Sandbank 私有化支持”的修正
原结论:“Sandbank 私有化只有 BoxLite,限于 KVM 环境”——这话只在不写 adapter 且不看上游 TODO 的前提下对。
**修正结论:**Sandbank 的真实私有化能力 = “BoxLite 内置 + Daytona/Fly/CF 现有 adapter 各自的 volumes/snapshot + 上游 TODO 路线图(含 E2B)+ 4 个 1 天可接入的 backend”。Sandbank 是 adapter 模式产品 + 活跃的上游——私有化覆盖面取决于”等多久”和”愿意贡献多少”,不取决于”是否被锁死”。
POC 阶段的最优组合(修订)
| 路径 | 本期 POC 选什么 | 规模化阶段加什么 |
|---|---|---|
| 公有云 | Sandbank + 内置 FlyAdapter | 规模化时加 CubeSandbox(公有云高密度场景) |
| 私有化(默认) | Sandbank + 内置 BoxLite adapter | S3 实测:Apple Silicon Mac mini + Hypervisor.framework 等效 KVM |
| 私有化(国产合规) | 本期不做 · 评估 Sandbank E2BAdapter(同时接 CubeSandbox) | 规模化时 1d 接入 CubeSandbox + 真 E2B 双线 |
| 私有化(成熟方案兼容) | 本期不做 | 未来 0.5d 接入 Daytona OSS(已有 adapter) |
**最终判断:**Sandbank 对私有化的真实支持是足够的——不是因为它内置覆盖广,而是因为它的 adapter 模式让扩展成本压到了 1 天数量级。本期 POC 用 BoxLite adapter 即够,未来需求出现时,每加一个 backend 都在可控工期内。
6.2 状态机推进
proposing ─ dispatch ▶ running / explore ▶ running / propose ▶ running / apply ▶ running / archive ─ PR 创建 ▶ awaiting_review ─ 合并 ▶ done
失败分支:running/* 任何阶段(含 proposing 阶段下游)若抛 SDK ERR / hard kill / API_retry 耗尽,→立刻转 failed,写 tasks.failedReason(max 1KB),SSE 推 type=failed 事件后退出。failed 终态,由 web 端给”重试”按钮(创建新 task)。proposal.md 中标记为 BREAKING change(status enum 加 failed)—— D7 已固化。
6.3 容器 → 主 API 的事件 callback
POST /internal/tasks/{taskId}/events
Content-Type: application/json
X-Task-Hmac: <hex of hmac-sha256(secret, body)>
{
"type": "stage_change", // | "log" | "completed" | "failed"
"stage": "propose",
"status": "running",
"data": {
"additions": 0,
"deletions": 0,
"filesChanged": 0,
"logTail": "..." // 最近几行 stdout,用于 SSE 转发
}
}6.4 前端 SSE 事件流
GET /projects/:r/branches/:b/tasks/:t/events
→ SSE stream
event: stage_change
data: {"stage":"propose","status":"running"}
event: log
data: {"tail":"npm install completed in 47s"}
event: completed
data: {"prUrl":"https://github.com/owner/repo/pull/123"}§7 POC 任务拆解(双轨)
粗粒度时间线 · 单人 ~13 工作日。双轨架构在 day 1 落地,不是远期改造。
公共部分(两条路径共用,9 项)
- 设计
task_events表 + Prisma schema —0.5d - 接入 Sandbank · 配置工厂方法(按 env 切 FlyAdapter / BoxLiteAdapter,见 §6.1.1)—
0.5d - 主 API 加
POST /tasks/:id/dispatch(调 sandbank provider.create)—0.5d - 主 API 加
POST /internal/tasks/:id/events(HMAC 验签)—0.5d - 主 API 加
GET /tasks/:id/events(SSE)—0.5d - 写 task-runner Docker 镜像(
node:22-slim+ bash + non-root + git +@fission-ai/openspec+ Claude Agent SDK,平台无关)—1d - 写
run.js容器入口(git clone 用 x-access-token URL + 单 query() 调用 + PostToolUse hook 触发 stage_change,不依赖任何平台 API)—2d - installation token 短命发放(复用现有 GitHub App 路径)—
0.5d - 前端 task 详情页接 SSE,MiniStages 实时更新 —
1d
公共小计 —
7d
⬢ 公有云路径(Fly Machines,3 项)
- 配置 Sandbank FlyAdapter + Fly token 注入(§6.1.2)—
0.5d - 设置 Fly secrets · 部署到 staging —
0.5d - 真跑一遍 · 公有云路径:真实仓库 + 真 PR —
1d
公有云小计 —
2d
▣ 私有化路径(VPS + Docker,4 项)
- 配置 Sandbank BoxLiteAdapter(详见 §6.1.3)—
1d - 准备一台 4 vCPU 8 GB 演示 VPS(Hetzner / DigitalOcean),装 Docker —
0.5d - 容器 → 主 API 的 callback 走公网 + HMAC(验证防火墙穿透)—
0.5d - 真跑一遍 · 私有化路径:从 VPS 跑通同一个 task —
1d
私有化小计 —
3d
联调与验收(2 项)
- E2E:MSW 模拟两种 provider 的 dispatch + callback 链路 —
0.5d - 双轨切换演示:同一个 task,切换 env 后两条路径都能跑通 —
0.5d
POC 合计 —
~13d
vs 单轨 POC 的工期对比:纯公有云路径 ~9 天,加私有化路径多花 4 天(其中 1 天是 BoxLiteAdapter 配置,1 天是 VPS 准备 + callback,1 天是私有化真跑,1 天是接口/联调)——用 44% 的额外工期换取消除供应商锁定 + 双轨商业模式。关键在于这 4 天必须放在 day 1——等公有云路径全跑通后再追加,工作量会翻倍(adapter 切换重构 + run.js 解耦 + 端到端回归)。引入 Sandbank 后,provider 抽象成本几乎归零——这也是为什么用了现成的沙箱中间层。
§8 POC 验证清单
把前面 §1-§7 的调研结论凝结成可执行的验证矩阵。每条都对应一个具体决策点的不确定性——验证不过就要切换方案。
为什么需要这张清单:报告积累了 30+ 个调研结论(Sandbank capability、CubeSandbox E2B 兼容、I/O wait 50% 修正、BoxLite 长任务等),其中一部分是基于官方文档的事实,另一部分是需要本场景实测才能确认的。这张清单只列后者——给 POC 前期 spike + 实施期 + 真跑期一个明确的”check 列表”。
8.1 高优 spike(POC 启动前完成)· 状态总览
这些验证如果失败,整个 POC 设计要重做。2026-05-18 全部 8 个 spike 通过,详见 docs/spikes/。
| # | 验证项 | 状态 | 实际发现 | 详见 |
|---|---|---|---|---|
| S1 | Claude Agent SDK 加载本仓库 .claude/skills/openspec-* | ✓ 通过 | SDK init message 含 skills 字段,无需进 turn 即枚举出 4 个 openspec skills(不消耗 token) | spikes/s1-claude-agent-sdk-skills.md |
| S1.5 | SDK 鉴权 fallback(OAuth vs API key) | ✓ 通过 | SDK 从 keychain 读 OAuth + 调 /api/oauth/claude_cli/create_api_key 换临时 API key;Max 订阅吸收实际成本。容器内仍必须用 API key(合规边界) | 同上(追加部分) |
| S2 | Sandbank 集成可行性(3 个等价验证) | ✓ 通过 | S2.a Provider capability 契约固化(FlyioAdapter 无 exec.stream 但架构不依赖)· S2.b NestJS dispatch + HMAC 端到端 · S2.c BoxLite local microVM 真启动(独立 Linux 6.12.76 内核) | spikes/s2-sandbank-capabilities.md |
| S3+S4 | 远程 macmini + Tailscale callback(合并验证) | ✓ 通过 | Apple M4 Mac mini 上 BoxLite microVM 真启动 + Tailscale tailnet 直连 26ms RTT callback。原 VPS+KVM 改成 Mac mini+Hypervisor.framework——硬件门槛大幅降低 | spikes/s3-s4-remote-macmini.md |
| S5 | OpenSpec 4 阶段流转 + 长时稳定性 | ✓ 通过 | 4.16 min · 42 turns · $1.15 · 98% cache hit。一个 query() 走完 explore → propose → apply → archive 全程,真改 src/math.ts + tests,跑通 typecheck/test/validate。Agent 还自主修复了 2 个 pre-existing 项目配置问题(缺 @types/node、tsconfig 缺 allowImportingTsExtensions)。S5 spike 本身不含 git push(agent 保守不自做高风险动作),PR 闭环由 S8.B 单独验证 → PR #2 | spikes/s5-four-stages-pipeline.md |
| S6 | microVM 内部 → 主 API 出口验证 | ✓ 通过 | S3+S4 之前 callback 是从 macmini host 发的,未覆盖 microVM 内部出口。本次补:alpine box 内 wget/curl 主 API + HMAC 验签(远端 Python sig 与 NestJS createHmac 一致)。BoxLite 自带 NAT/DNS proxy 0 配置出网。microVM 内 RTT p50 35ms / avg 54ms(vs host 直发 26ms),NAT 一跳 +10ms 可忽略 | spikes/s6-microvm-egress.md |
| S7 | macmini microVM 内 SDK 长时复杂任务 | ✓ 通过 | 合并验证 “SDK 能在 microVM 内跑 + 长时稳定性”。BST 完整实现 + 19 测试,9.66 min · 92 turns · 98.5% cache hit。关键新发现:(a)通过 subapi 中转(ANTHROPIC_BASE_URL+API_KEY)让 SDK 跑通——D11 双轨鉴权多了第三条路径;(b)Claude binary 拒绝 root 用 --dangerously-skip-permissions,容器必须用 non-root user;(c)Agent 在 OpenSpec CLI 缺失时手动 mkdir+mv 模拟 archive,工程灵活性体现 | spikes/s7-microvm-long-task.md |
| S8 | 实施期 must-have gap 验证(A + B + C) | ✓ 通过 | S7 后用户 review 识别的 3 个缺口集中验证:A·openspec CLI 真实包名是 @fission-ai/openspec v1.3.1(不是 npm 上的空包 openspec v0.0.0);B·microVM 内端到端 git push 真 PR PR #2 ——关键技巧 https://x-access-token:$TOKEN@github.com/... 0 配置 credential helper;C·Fly machine 真启动 7.7s · AMD EPYC · 256MB,box→subapi RTT 239ms。sandbank flyio 内部 bash -c 包装,base image 必须含 bash(用 node:22-slim 不是 alpine) | spikes/s8-abc-implementation-gaps.md |
spike 期间识别的额外架构发现
- ESM/CJS blocker · sandbank ESM-only,apps/api 原 CJS。已切 NodeNext ESM(实际 3 小时工作量,比预估 1-2 天快)。详见
docs/task-runner-sandbank-integration.md - D11 双轨鉴权(design.md 新增决策)· 容器内 API key + 本地 dev SDK 自动 OAuth fallback
- Tailscale = 天然 callback 通道 · 跨网段不需要 cloudflared / ngrok
- 非 admin 用户也能私有化 · 用
uv替代 brew 装 Python,全程不需要 sudo - Cache hit rate 98%(S5 实测)· OpenSpec skill 是 stable system prompt,重复 turn 几乎零增量。S5 简单 prompt $1.15、S7 BST 复杂 prompt $3.03——cache 命中让重复 turn 几乎零增量,远低于”每 turn full input 重传”的一般 multi-turn 估算
- Agent 自主修复工程问题(S5 + S7 实测)· S5 typecheck 失败时主动 git stash 验证预存在问题;S7 OpenSpec CLI 缺失时手动 mkdir+mv 模拟 archive、自我反思修测试期望——LLM-as-engineer 真实表现稳定
- subapi 中转作为第三条鉴权路径(S7 实测)· 把
ANTHROPIC_BASE_URL指向用户自管 subapi 实例,ANTHROPIC_API_KEY用 subapi 内部 key——彻底绕开”OAuth 给容器外用”合规风险,但用户得自己运维 subapi。补强 D11 双轨 → 三轨 - 容器必须 non-root(S7 实测)· Claude Code binary 拒绝 root 用
--dangerously-skip-permissions。alpine 默认 root,要用node:22-alpine内置 node user(uid 1000)或 Dockerfile USER 切换 - BoxLite 实施细节(S7 实测)· 默认 disk 太小要
disk_size_gb=10;copy_in()不可靠改用 base64 注入或 box 内 git clone;alpine 默认缺 ca-certificates + bash + ripgrep - openspec 包名是 scoped(S8 实测)· 正确装法
npm install -g @fission-ai/openspecv1.3.1。npm 上的openspec是空占位包 v0.0.0 不要用 - git push 用 x-access-token URL 注入(S8 实测)·
https://x-access-token:$TOKEN@github.com/owner/repo.git— 0 配置 credential helper,token 由 D11 容器内续期机制提供(GitHub App installation token) - Fly base image 必须含 bash(S8 实测)· sandbank flyio adapter 内部
bash -c "<cmd>"包装 exec。推荐node:22-slim(Debian 自带 bash),不要用 alpine 默认 - 公有云 vs 私有路径实测对比(S8 实测)· Fly 启动 7.7s vs BoxLite macmini 1.5s(5x,cloud overhead 合理);callback RTT Fly→subapi 239ms vs LAN 35ms(7x,跨 ocean)。印证 D2 双轨设计:私有低延迟,公有云弹性
8.2 实施期边做边验(POC 13 天中嵌入)
这些不需要前置 spike,但在对应任务完成时必须验证。
| # | 验证项 | 嵌入哪个 §7 任务 | 通过标准 | 失败应对 |
|---|---|---|---|---|
| I1 | 同一镜像在 Fly Machine + 本地 Docker 两端都能跑 | §7 任务 06(写镜像) | 同一 docker pull 后,两端运行 node /app/run.js --self-test 都返回 0 | 把平台特定逻辑拆到 entrypoint,run.js 保持纯净 |
| I2 | Sandbank env 切换在主 API 实际生效 | §7 任务 02(接入 Sandbank) | TASK_RUNNER_MODE=private / =public 切换后,/tasks/:id/dispatch 派发到不同 backend,无需重启进程 | 用工厂方法在 dispatch 调用时实例化 provider(而非 module load 时) |
| I3 | SSE 长连接不被中间代理切断 | §7 任务 05(SSE endpoint) | 前端订阅 SSE 后保持 30 min,期间收到 ≥ 4 个 stage_change 事件(对应 4 阶段) | 检查 Fly proxy buffer / Vercel edge timeout · 加心跳 ping 事件 |
| I4 | HMAC 验签防止 callback 伪造 | §7 任务 04(events controller) | 构造 invalid HMAC 的 POST 返 401 · valid HMAC 但替换 body 返 401 | 检查 HMAC 算法是否对 body 全量签名(不只是 header) |
| I5 | installation token <1h 过期续期机制 | §7 任务 08(token 发放) | 容器跑超过 50 min 时主动调主 API /internal/tasks/:id/token,拿到新 token 后 git push 仍成功 | 把 token 续期内嵌到 run.js 的 git 调用 wrapper |
8.3 真跑验收(POC 完成时一次性 demo · §7 任务 12 + 16)
这是 POC 的”end-to-end 合格判定”——只有这一关过了,才能给团队/客户演示。
| # | 验证项 | 通过标准 |
|---|---|---|
| E1 | 公有云路径端到端 | 从前端 04a 页面 submit prompt → Fly Machine 启动 → 跑 4 阶段 → 生成真 PR → 前端 MiniStages 实时显示 stage 跳变 → 30 min 内完成 |
| E2 | 私有化路径端到端 | 同上,但容器跑在演示 VPS 而非 Fly · 同一份 prompt / 同一个仓库 |
| E3 | 双轨切换不破坏功能 | 把 TASK_RUNNER_MODE env 在两个值之间切换 3 次,每次都能成功派发到对应 backend,且前端体验无差 |
| E4 | 故障容错 | 故意让一个 task 中途失败(如 Anthropic API 报 5xx),容器要把 status=failed 回传,前端正确显示 |
| E5 | 账单防护(§5.5 中的 4 层防护) | 启动一个会”自动循环”的恶意 prompt(如要求 agent 无限递归),容器 60 min hard kill · 主 API 并发计数生效 · 总账单 ≤ $5 |
8.4 验证清单可视化(spike 优先级图)
spike 优先级(从上到下:阻塞性高 → 边做边验) 工期 0h ───► 0.5d S1 Claude SDK + skills (关键支点) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ 1-2h S2 Sandbank 长任务 (新库稳定性) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ 0.5d S3 BoxLite + KVM (私有化前置) ▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮▮ 2h S4 防火墙穿透 (私有化前置) ▮▮▮▮▮▮▮▮ 1h
怎么用这张清单:
- POC 启动前:花 1-2 天跑完 S1-S4 四个 spike。任何一个失败 → 走对应”失败应对”或重新规划。
- POC 13 天实施期:每完成一个 §7 任务,对照 I1-I5 验证项打勾。
- POC 结束 demo:E1-E5 必须全过,才能宣告 POC 完成、向上汇报。
- 把这张表存到 OpenSpec change 的
tasks.md里——每个验证项就是一个 task。
§9 风险与未决问题
POC 落地前需要解的硬骨头。每个风险都对应 §8 验证清单里的一项。
-
Claude Agent SDK 在容器里加载本仓库 .claude/skills/ 的实际行为
官方文档说 settingSources + skills:“all” 能加载,但本仓库
.claude/skills/openspec-*是否 100% 兼容 SDK 期望的 SKILL.md 格式需要 spike 验证。 → 验证项 S1(POC 启动前 1-2h 完成) -
网络出口与 callback 路径
容器要访问 api.github.com / api.anthropic.com;callback 回主 API 走公网或 Fly 内网。POC 阶段建议公网 + HMAC 验签更省事。 → 验证项 S4(私有化路径下额外要测防火墙穿透)+ I4(HMAC 验签)
-
Spec 缺一个 failed 状态值
现有
statusenum 只有 proposing/running/awaiting_review/done,跑失败没地方放。POC 实施前要先扩 spec。 → 验证项 E4(真跑阶段的故障容错演示需要这个状态值存在) -
installation token 1h 过期
GitHub App installation token 默认 1h,容器寿命 > 1h 会失效。需要在主 API 加
/internal/tasks/:id/token端点用于续期。 → 验证项 I5(实施期边做边验,跑超 50 min 时测续期) -
并发与排队
并发上限由 §5.5 列的 4 层防护管(同用户 24h ≤ 20 task / 同 repo ≤ 3 并发 / 全局排队),不另起队列服务——计数走 Postgres
tasks表 + 主 API dispatch 前查询。规模化阶段如出现高并发可换专用队列。 → POC 不验证(推迟到规模化阶段) -
取消 / 强制停止
设计稿 04
task-menu-stop-{id}已设 disabled。未来支持时调 Sandbankprovider.destroy(id)(不直接绑 Fly REST)。 → POC 不验证(前端按钮保持 disabled) -
apply 阶段跑多少测试
POC 阶段只跑 typecheck + lint,避免 30 min 上限。完整 jest/playwright 留给 GitHub Actions CI(PR 创建后自动触发)。 → 验证项 E1/E2(30 min 端到端时间预算的约束)
-
账单失控(死循环 / 恶意调用 / 容器卡死)
Fly Machines 没有原生 spend cap;Cloudflare Containers 有用户实测比 GCP 贵 2.5x 且无月度 hard cap 的反馈。POC 阶段必须同时落 §5.5 列出的 4 层防护:主 API 并发上限 + 容器内 hard timeout + 平台账单告警 + 主 API 巡检 cron。(模型 token 侧的账单防护属于另一条线,由你在 Anthropic / OpenAI console 独立配置。) → 验证项 E5(真跑阶段用恶意 prompt 演示 4 层防护都生效)
§10 私有化部署路径
私有化路径的完整调研(深度大于 §6.1.2-§6.1.4 的 POC 集成讨论)。本期 POC 已经包含私有化栈(Sandbank + BoxLiteAdapter),本节展开未来阶段可能要的扩展方案与 Runtime 矩阵。
10.1 私有化的精确口径
本节口径:“私有化部署” = 能在一台普通 Linux 服务器上通过 docker / docker-compose 启动。不要求云供应商账号、不要求 Kubernetes、不要求 Terraform / Nomad 等复杂 orchestration。一条命令在 VPS / 自建机房 / 任意 Ubuntu 22.04+ 上跑起来才算。
触发私有化需求的真实场景:
- 合规要求代码 / 凭据不出企业网络边界
- 开源 task-runner 平台让客户自己 docker 跑
- 对推理质量有定制需求,要接入自己微调的模型
- 规模化后单月 task 量 ≥ 5000,托管 SaaS 成本超过自托管运维成本
10.2 开源沙箱运行时速览(按 docker-only 可行性分组)
A · 真正 docker-friendly(符合用户口径)
| # | 候选 | 启动命令 | 隔离技术 | License | 本项目契合 |
|---|---|---|---|---|---|
| 1 | AIO Sandbox 单 docker run | docker run -p 8080:8080 ghcr.io/agent-infra/sandbox | 容器级(共享 host kernel) | Apache 2.0 · ★ 4.7k | ★★★★☆ |
| 2 | Daytona OSS docker-compose | docker compose -f docker/docker-compose.yaml up -d | 容器级(Docker,沙箱间网络默认隔离) | AGPL 3.0 | ★★★☆☆ |
| 3 | BoxLite 嵌入式 microVM | 作为库嵌入 + KVM device 透传到 docker | OCI 兼容 microVM(KVM / Hypervisor.framework) | Apache 2.0 · v0.9.5 · ★ 2.1k | ★★★☆☆ |
| 4 | Microsandbox 嵌入式 microVM | 同上(libkrun 路径) | libkrun microVM(320ms 启动) | Apache 2.0 · ★ 4.7k | ★★★☆☆ |
| 5 | OpenHands agent + sandbox 一体 | docker run(默认 sandbox 即 Docker) | Docker 容器(每 session 独立) | MIT · ★ 68.6k | ★★☆☆☆ |
| 6 | Docker Sandboxes (sbx) 2026-03 新出 | sudo apt-get install docker-sbx | microVM(每 sandbox 独立 Docker daemon) | License 未公开披露 | ★★☆☆☆ |
B · 云依赖型自托管(不符合”docker-only”口径,仅供对比记录)
| # | 候选 | 实际部署要求 | 为什么不符合 |
|---|---|---|---|
| 7 | E2B Infra 需 GCP/AWS | Terraform + Nomad + Cloudflare DNS | 只支持 GCP / AWS Beta;Docker Compose 部署仍是 feature request |
| 8 | Google Agent Sandbox 需 K8s | Kubernetes 集群 + gVisor/Kata 节点 | 整个项目就是 K8s CRD,没有 docker-compose 路径 |
| 9 | Firecracker 直接自建 | 从零搭 orchestrator | 3-6 人月起步;docker-friendly 候选已经覆盖此能力 |
| 10 | Cloudflare Sandbox SDK | 必须跑在 Cloudflare 平台 | 不算”私有化” |
**修正声明:**上一版报告把 E2B Infra 列为”优选迁移路径”是误导——它实际上需要 GCP/AWS 账号 + Terraform。按用户的 docker-only 口径,E2B Infra 不符合,AIO Sandbox / Daytona OSS 才符合。
10.3 docker-friendly 候选展开
① AIO Sandbox · 单 docker run
定位:“all-in-one” 单容器沙箱——一条 docker run 即起。
启动:
docker run --security-opt seccomp=unconfined --rm -it \
-p 8080:8080 ghcr.io/agent-infra/sandbox:latest包含: Browser (VNC + CDP) · VSCode Server · Shell · 文件操作 · MCP · Jupyter
**适配本场景:**对 Claude Agent SDK + openspec 4 阶段而言:Shell + 文件操作 + MCP 三块直接对得上;Browser / Jupyter 在 POC 范围内用不到,但不增加部署负担。
缺点:隔离是容器级(共享 host kernel),不是 microVM。若对抗恶意代码不是重点(POC 内场景由 GitHub App 信任边界保护),这够用。
**为什么推荐为 A 类首选:**启动门槛极低(一条命令),生态成熟(4.7k stars),未来如需多机扩展可叠加 docker-compose / swarm。
② Daytona OSS · docker-compose
**定位:**完整的”dev environment 编排平台”自托管版。Daytona 自己不用 K8s/Nomad,直接 docker-compose。
部署:
git clone github.com/daytonaio/daytona
cd daytona
docker compose -f docker/docker-compose.yaml up -d
# 访问 http://localhost:3000 — 无需公网域名包含 11 个服务: API / Proxy / Runner / SSH Gateway / Postgres / Redis / Dex (OIDC) / Registry / MinIO / Jaeger 等
最小配置: 4 GB RAM(推荐 8 GB)· Ubuntu 22.04+ / Debian 12+ / Fedora 39+
沙箱间网络: INTER_SANDBOX_NETWORK_ENABLED=false 默认禁用——强制隔离
致命警告:AGPL 3.0——任何”通过网络给用户访问的修改版”都被强制传染同 license。对商业产品是地雷。
③ Microsandbox · 嵌入式 microVM
**定位:**嵌入式 microVM 库(libkrun),适合写进 task-runner 镜像作为隔离层。
性能: 启动 320ms(精确实测)vs Firecracker 808ms
多 OS: Linux KVM / macOS HVF / Windows WSL2
凭据模型: 真实密钥永不进入 guest,通过 TLS allowlist 主机时才注入
跑在 Docker 里的方式: 需要把 /dev/kvm 透传到容器(--device /dev/kvm),且 host 启用 KVM。
用法:不是独立服务,是库——在 task-runner 入口脚本里调用,给每个 task 拉一个 microVM。隔离强度高于 AIO Sandbox(VM-level)。
④ BoxLite · 嵌入式 microVM
**定位:**与 Microsandbox 同赛道——也是 “SQLite of sandbox” 库。
成熟度: v0.9.5(接近 1.0)· 454 commits · ★ 2.1k
多 SDK: Rust / Python / Node.js / Go / C(比 Microsandbox 多 Go / C)
差异化: 持久化 Box(QCOW2 + snapshot/fork)——install 包/创建文件后下次能接续。规模化后可做”task 状态延续”。
缺点: 底层 microVM 引擎在公开文档里只说”OCI 兼容”,未明示是 libkrun 还是自研——技术栈透明度不如 Microsandbox。
BoxLite vs Microsandbox 二选一: 看成熟度选 BoxLite;看明确底层引擎与精确性能数据选 Microsandbox。
⑤ OpenHands · agent + sandbox 一体
**定位:**前 OpenDevin。完整的”agent 平台 + sandbox 一体”——每个 session 一个独立 Docker 容器,含 SSH + Jupyter + BrowserGym。
部署: docker-compose,需要 Docker socket 访问。
本场景适配度问题: OpenHands 自带 agent loop(PromptHands 风格),而我们已经选了 Claude Agent SDK 作为 agent——OpenHands 的 agent 部分对我们冗余。能不能只用它的 sandbox 部分?理论可以(agent-server Docker 镜像是 MIT),但要逆向拆解,复杂度不低。
判定: 如果未来想换”OpenHands agent + OpenHands sandbox” 整套方案再考虑;本期 POC 不直接用。
⑥ Docker Sandboxes (sbx) · 太新
**定位:**Docker 官方在 2026-03 推出的 microVM sandbox——每个 sandbox 一个独立 Docker daemon。
安装:
# macOS
brew install docker/tap/sbx
# Linux
sudo apt-get install docker-sbx
# 运行
sbx run claude已知支持的 agent: Claude Code / Codex / Gemini CLI / GitHub Copilot CLI
未知点: license 未公开披露 · 完全 self-host 行为未文档化 · POC 阶段稳定性数据少
建议: 观察 3-6 个月,等社区积累生产经验后再评估。
10.4 单机自托管 vs 托管 SaaS 成本
以 Fly Machines(托管中最便宜)为基准 vs 单台 Linux VPS 跑 AIO Sandbox 做盈亏分析。只算容器成本,token 不算(与 §5 边界一致)。
| 每月 task 数 | Fly Machines(按量) | VPS + AIO Sandbox(包月) | 结论 |
|---|---|---|---|
100 | $1.8 | $40(一台 4 vCPU 8GB) | Fly 胜 |
1,000 | $18 | $40 | 接近,Fly 仍胜 |
5,000 | $90 | $80(一台 8 vCPU 16GB) | VPS 胜 |
10,000 | $180 | $160(两台 8 vCPU) | VPS 胜 |
50,000 | $900 | $600(5 台 8 vCPU) | VPS 胜 |
VPS 价按 Hetzner / OVH 一台 4 vCPU 8GB ≈ $40/月、8 vCPU 16GB ≈ $80/月(2026-05 公开价)估。**注意:**① SRE 人月成本未计入——按 0.2 FTE × $8K/月 ≈ $1600/月,真实盈亏点右移到 ≥ 30K task/月;② 上表只看容器成本,token 不算;③ 单台 VPS 无 auto-scaling,并发取决于机器规格。
关键反转:因为不再需要云供应商基础设施常驻成本,VPS + AIO Sandbox 的盈亏点远低于上一版报告说的 E2B Infra 路径——从月 task ≥ 1K 开始就接近,≥ 5K 时 VPS 全面胜出。这就是用户 docker-only 口径的真实价值:用一台普通 VPS 就能搞定的事,不必上 GCP 24 vCPU + 2500GB SSD。
10.5 私有化路径的渐进升级图
阶段 1 POC 双轨 ─ 13 天 ▶ 阶段 2 单机扩容 ─ ≥ 5K task/月 ▶ 阶段 3 多机集群 ─ ≥ 100K task/月 ▶ 阶段 4 K8s
| 阶段 | 私有化栈 | 触发条件 | 切换工作量 |
|---|---|---|---|
阶段 1 | Sandbank + BoxLiteAdapter(POC 双轨私有化路径) | 当前 POC | 3d · 见 §7 |
阶段 2 | Sandbank + CubeSandboxAdapter(自写,E2B 兼容协议) | 需要 microVM VM-level 隔离 / 国产化合规 | +1d · 详见 §6.1.4 |
阶段 3 | 多机 + docker-compose 自建调度 | 单机容量到顶 | 2-3 周 · 写简单 queue + worker |
阶段 4 | K8s + Google Agent Sandbox(gVisor/Kata) | 团队已有 K8s 平台 / task 量 ≥ 100K/月 | 2-3 月 · K8s 基础设施 + 重写 dispatcher |
POC 阶段已经做对的设计(让未来阶段切换成本最小):
- 引入 Sandbank 沙箱中间层——未来切换 backend 只需新加或换 adapter,业务代码不动(详见 §6.1.2)。
- 容器入口
run.js只依赖 stdin/stdout 与 HTTPS callback——不绑任何平台 API,所有 sandbox runtime 都能跑同一个镜像。 - 所有 Fly Machines / VPS Docker 调用走 Sandbank Provider 抽象,主 API 不直接接触平台 REST。
10.6 避坑清单(按 docker-only 口径修订)
- **E2B Infra:**需 GCP/AWS + Terraform,不符合 docker-only 口径。除非已经决定上云做 Nomad 集群,规模化后也不应作为迁移目标。
- **Daytona AGPL:**部署方式(docker-compose)符合口径,但 license 是地雷——商业产品避开,开源社区项目可以用。
- **AIO Sandbox 隔离强度:**容器级(共享 host kernel)。POC 内场景由 GitHub App 信任边界保护够用,但跑不可信代码需要叠 Microsandbox / BoxLite 做 microVM 二次隔离。
- **OpenHands:**是 agent + sandbox 一体方案。已选 Claude Agent SDK 作为 agent,OpenHands 的 agent 部分冗余;要只取 sandbox 需逆向拆解。本期不推荐。
- **Docker Sandboxes (sbx):**2026-03 新出,license 未公开披露,self-host 行为未文档化。观察 3-6 个月。
- **BoxLite vs Microsandbox 二选一:**API 形态几乎一致。看成熟度选 BoxLite(v0.9.5);看明确底层引擎与精确性能选 Microsandbox。
- Cloudflare Sandbox SDK:“开源”≠“可自托管”——必须跑在 CF 平台。
- **Firecracker 直接自建:**不要做。Microsandbox / BoxLite 已经把”嵌入式 microVM”做完且开源。
- **K8s 引入:**除非已经有 K8s 平台,否则不要为 task-runner 单独引入——基础设施投资远超收益。
10.7 Agent 业务编排层(澄清版)
上一版本节命名混乱,已重写。之前把”Sandbox SDK”和”编排层”两个不同的事混在一起,还错把 OpenSandbox / Beam Cloud(属于 Runtime 层)列在这里。本节现在专门讲Agent 业务编排层。
先画清楚三层架构
┌───────────────────────────────────────────────────────────────────────┐ │ LAYER 3 Agent 业务编排层 │ │ 在 sandbox 之上做业务封装:git worktree、agent 多 session、agent 协议适配 │ │ Sandcastle(git worktree 隔离) · rivet-dev/sandbox-agent │ │ 本场景结论:不需要(详见下方分析) │ ├───────────────────────────────────────────────────────────────────────┤ │ LAYER 2 中间层 / 多 backend 抽象 │ │ 统一 API 包装多种 Runtime — “写一次,切换 backend 不改业务代码” │ │ Sandbank(推荐) · cased/sandboxes · sandboxer │ │ 本场景结论:用 Sandbank(见 §6.1.2 / §6.1.3 / §6.1.4) │ ├───────────────────────────────────────────────────────────────────────┤ │ LAYER 1 Runtime(实际跑容器的运行时) │ │ 真正提供隔离 + 执行的实体 │ │ 公有云:Fly Machines · Vercel Sandbox · E2B · Cloudflare Containers │ │ 私有化:BoxLite · AIO Sandbox · Microsandbox · CubeSandbox · OpenSandbox │ │ 本场景结论:POC 用 Fly Machines(公有云)+ BoxLite(私有化) │ └───────────────────────────────────────────────────────────────────────┘
本场景为什么不需要 Layer 3?
引入 Sandbank(Layer 2)+ “每 task 一个干净容器”的设计之后,Layer 3 提供的两大功能在本场景里都用不上:
**Sandcastle 卖点:**同一个容器内,给多个 agent 开多个 git worktree(每个 agent 一个分支),结束后干净 patch 回 host。
本场景不需要原因:我们的设计是每 task 一个全新容器,容器内只跑一个 agent。容器即隔离,不需要在容器内再做 worktree 二次隔离。git push 直接在容器里调 git push origin agentBranch 即可。
**rivet-dev/sandbox-agent 卖点:**统一 API 同时控制 Claude Code / Codex / OpenCode / Cursor / Amp / Pi 等不同 coding agent。
本场景不需要原因:§4 已经决定用 Claude Agent SDK 一种。我们的 run.js 直接 import { query } from "@anthropic-ai/claude-agent-sdk" 调用,不需要一个统一协议来适配多 agent。
Layer 3 什么场景下才需要
| 触发条件 | 需要哪个 Layer 3 项目 | 本场景是否触发 |
|---|---|---|
| 单容器并发跑多个 agent 任务(复用容器节省启动开销) | Sandcastle(git worktree 多任务隔离) | 否 — 每 task 一个容器 |
| 业务上要让用户在 Claude Code / Codex / Gemini CLI 之间切换 agent | rivet-dev/sandbox-agent | 否 — §4 已锁定 Claude Agent SDK |
| 需要让一个 agent session 跨容器/跨重启延续 | Sandcastle / rivet-dev 的 session 管理 | 未来可能 — POC 阶段不做 |
| 本场景的实际需求(每 task 一个容器跑 Claude Agent SDK) | run.js 直接调 SDK,不需要 Layer 3 | 是 |
本节保留是因为…
虽然本场景不用 Layer 3,但这一节保留作为决策记录有两个价值:
- 明确”为什么不用 Sandcastle”——避免后续团队成员重新考虑这件事
- 未来如果业务变化(如要支持多 agent、单容器多任务复用),知道去哪里找方案
联网调研发现的 Layer 3 候选(仅供未来参考):
| # | 候选 | 定位 | License / Stars | 未来触发场景 |
|---|---|---|---|---|
| 1 | Sandcastle | git worktree 隔离 · TS-first | MIT · mattpocock/sandcastle | 单容器多任务复用 |
| 2 | rivet-dev/sandbox-agent | 跑在 sandbox 内的 agent 统一控制 HTTP server | Apache 2.0 · ★ 1.4k | 需要多 agent 协议适配 |
**本节最终结论:**Layer 3 在本场景下不引入——run.js 直接调 Claude Agent SDK,git push 直接在容器里执行。这让架构简化、依赖减少、调试更直接。仅当业务变成”单容器多任务”或”多 agent 切换”时再回头评估 Sandcastle / rivet-dev。
10.8 大厂开源方案专项
把全球主要科技公司开源的 sandbox 方案系统化对比。对国产化 / 合规部署场景尤其重要。
| 厂商 | 项目 | 定位 | License | Stars | 关键卖点 |
|---|---|---|---|---|---|
| 腾讯 | CubeSandbox 2026-04 新出 | microVM sandbox runtime · E2B 接口兼容 | Apache 2.0 | ★ 5.7k | 60ms 冷启动 · 2000+/单机并发 · <5MB 实例开销 |
| 阿里 | OpenSandbox | 通用 sandbox 平台 · 多语言 SDK · CNCF | Apache 2.0 | ★ 10.7k | 5 种语言 SDK · gVisor/Kata/Firecracker 三选一 |
| 字节 | AIO Sandbox | 单容器 all-in-one · UI-TARS 生态 | Apache 2.0 | ★ 4.7k | 一条 docker run · Browser+VSCode+MCP 一站式 |
| 字节 | SandboxFusion | 评估导向 sandbox | Apache 2.0 | — | 10+ 编程评估数据集 · 偏 model benchmark 场景 |
| 字节 | DeerFlow 2.0 | SuperAgent harness(含 sandbox) | Apache 2.0 | ★ 35.3k | 含 LangGraph 集成 · 偏完整 agent 框架 |
| 微软 | AutoGen → MAF | 多 agent 编排 · 含 Docker code executor | MIT | ★ 50k+ | AutoGen 已 maintenance · 新项目 MS Agent Framework |
9.8.1 腾讯 CubeSandbox(重点关注)
CubeSandbox · 2026-04 开源 ⭐
性能数据(官方实测):
- 单并发裸金属:
<60ms冷启动 - 50 并发:平均 67ms · P95 90ms · P99 137ms
- 单 96 核服务器:2000+ sandbox 并发
- 单实例内存开销:
<5MB
隔离: RustVMM + KVM · 每个 agent 独立 Guest OS kernel(VM-level,强于 AIO Sandbox 的容器级)
部署: 一键脚本(不是 docker-compose)
# 普通云 VM(PVM 启用 KVM)/ WSL 2 / 物理机均可
curl -sL https://github.com/tencentcloud/CubeSandbox/raw/master/deploy/one-click/online-install.sh | bashE2B SDK 兼容(关键卖点):
# 改一个环境变量即可,业务代码零修改
export E2B_API_URL=http://localhost:<port>
# 然后用任何 E2B SDK,背后跑的就是 CubeSandboxCubeSandbox 与本场景的契合度
替代 §10.5 阶段 2 的优势:
- 性能远胜 AIO Sandbox:60ms vs 未明示
- 隔离强度:VM-level vs 容器级
- 并发密度:2000+/单机——单台 96 核服务器就够撑 50K task/月
- E2B 兼容意味着:如果未来还要切到托管 E2B Cloud 或自托管 E2B Infra,客户端代码不动。这是非常优雅的”未来不锁死”设计。
已知风险:
- 太新:v0.2.1,2026-04 才开源,生产案例尚未积累
- 没有 TS SDK:官方只展示 Python SDK;E2B TS SDK 是否能直接指向 CubeSandbox 未实测验证(理论上能)
- 需要 KVM 支持:部分廉价 VPS(OpenVZ)不支持 nested virtualization
- 主战场中国:海外社区采用案例少;中文文档优于英文文档
建议: POC 阶段先用 Fly。私有化阶段做对比 spike——AIO Sandbox(成熟)vs CubeSandbox(性能 + 兼容性更优)。
9.8.2 字节生态澄清
之前 §10.2A 列的 AIO Sandbox (agent-infra/sandbox) 实际上是字节生态的一部分——字节的 bytedance/UI-TARS-desktop 项目已经从内部 omni-tars core 迁移到 agent-infra sandbox。字节系完整图谱:
| 项目 | 定位 | 与本场景适配度 |
|---|---|---|
AIO Sandbox agent-infra/sandbox | 单容器 sandbox runtime · UI-TARS 的执行环境 | 已在 §10.2A 推荐 |
SandboxFusion bytedance/SandboxFusion | 多语言代码执行 + 评估 sandbox | 偏 benchmark/eval 场景,不是”长跑 agent task”——与本场景定位错位 |
DeerFlow 2.0 bytedance/deer-flow · ★ 35.3k | SuperAgent harness(含 sandbox-aware execution) | 与 Claude Agent SDK 重叠——是 agent 框架不是 sandbox 工具 |
| Seed-OSS | 字节 Seed Team 的 LLM 系列 | 不在本期 sandbox/agent SDK 选型范围 |
9.8.3 微软方案
AutoGen 已进入 maintenance mode(2026-Q1 起不再添加新特性,社区维护)。新项目 Microsoft Agent Framework (MAF) 是企业级继任者。AutoGen 内置 DockerCommandLineCodeExecutor——但这是 agent 框架自带的代码执行能力,不是独立的 sandbox runtime/SDK 产品,与本场景的”task-runner 跑 Claude Agent SDK”定位错位。
判定: 微软方案与本场景不直接对接。
9.8.4 更新后的推荐栈(含国产备选)
| 场景 | 推荐 | 备选 |
|---|---|---|
| POC(本期) | Fly Machines + Claude Agent SDK | — |
| 私有化阶段 2 · 海外团队 | VPS + Sandbank(BoxLiteAdapter) | VPS + AIO Sandbox(字节系) |
| 私有化阶段 2 · 国产化合规 | VPS + CubeSandbox(腾讯,E2B 兼容) | VPS + OpenSandbox(阿里)/ AIO Sandbox(字节) |
| 需要 microVM 强隔离 | CubeSandbox(VM-level) | Microsandbox / BoxLite(嵌入式库) |
| 规模化 ≥ 50K task/月 | CubeSandbox(单 96 核服务器即可) | K8s + Google Agent Sandbox |
关键洞察:国产大厂的 sandbox 方案在 2026 年集中爆发——腾讯 CubeSandbox(2026-04)、阿里 OpenSandbox、字节 AIO Sandbox/SandboxFusion,都比同期海外开源方案性能更激进(CubeSandbox 的 60ms 冷启动 + 2000 并发数据没有海外同类项目能匹敌)。这对国产化 / 合规场景是意外的红利——不必为了”私有化”牺牲性能。
§11 下一步
双轨 POC 的 3 条可选路径。
直接立双轨 OpenSpec change
把本报告精简为 add-task-runner-poc change,proposal.md 明确双部署目标,§7 任务清单直接落到 tasks.md,开 /opsx:apply 按 13 天工期实施。
适合: 方向已校准(公有云 + 私有化双轨),信心高,接受 13 天投入。
跑完 §8 验证清单的 S1-S4,再立 change
4 个高优 spike 总工期 1-1.5 天,是 13 天 POC 投入前的 risk hedge:
- S1 · Claude Agent SDK 加载
.claude/skills/(1-2h) - S2 · Sandbank 长任务稳定性(0.5d)
- S3 · BoxLite + KVM 在目标 VPS 上能跑(2h)
- S4 · 防火墙穿透 callback(1h)
适合: 避免 13 天 POC 中途遇到根本性阻塞返工——每个 spike 失败都有明确替代方案(见 §8)。
分两期 POC:先公有云,再加私有化
第 1 期(9 天)只做公有云 + Sandbank FlyAdapter;第 2 期(4 天)追加 BoxLiteAdapter + 私有化路径。
适合: 需要尽早 9 天有可演示版本(牺牲一些日 1 双轨同步收益)。注意: 第 1 期必须先接入 Sandbank(不直接调 Fly REST),否则第 2 期会大返工。
**三条路径的核心差异:**A 是”信心拉满,一次到位”;B 是”先验证关键技术假设,避免大返工”;C 是”先有公有云 demo,私有化再追”。三条路径都保留双轨架构的核心 — Sandbank 接入必须在第 1 个工作日就完成,才能让后续切换 adapter 不破坏业务代码。
§12 POC 实施进度 2026-05-19 · E1+E2 真跑通过
本节是 v1(2026-05-17 explore 阶段)后的实施期记录。原 §7 任务清单 ~13 工作日实际工期内完成,含 8 个 spike(S1-S8 + 私有化 S9)+ 双轨真跑生成真实 GitHub PR。
Fly Machines · 真跑通过
- app:
openspec-task-runner(NRT 区域 · shared-cpu-4x 4GB · node:22-slim amd64) - API:
api.douglas-agent.com(Fly appopenspec-api) - image:
registry.fly.io/openspec-task-runner(buildx--platform linux/amd64解决 macOS arm64 vs Fly amd64) - 真实产物:PR #12 — agent SDK 经 subapi 中转 4 阶段跑通 + x-access-token push + curl POST /pulls
- 耗时:dispatch → PR 出 ~12 min · 累计 5 次 dispatch + 1 debug machine $0.012
Mac mini Hypervisor + BoxLite · 真跑通过
- host:
vibe-zlyan(Apple M4 16GB · Hypervisor.framework) - microVM:
boxlite 0.9.5单 binary(含 CLI + Python SDK + serve mode)· node:22-alpine + chown node user - 跨网段: Tailscale tailnet(开发者 100.64.3.43 ↔ macmini 100.101.167.99 · p50 26ms)
- 真实产物:PR #13 — boxlite microVM 内运行 task-runner 等价流程
- 耗时:dispatch → PR 出 ~10 min · 私有化路径 host 已自有,零额外 compute 费
11.1 § 9.4 集成路径解锁 — BoxLite serve = BoxRun
v1 (2026-05-17) Open Questions 中标 “BoxRun daemon 来源未知”,实施期解决:boxlite-ai/boxlite 单 binary 含 boxlite serve REST mode = BoxRun。
# macmini 装单 binary(不需要 Python venv)
curl -fsSL https://github.com/boxlite-ai/boxlite/releases/latest/download/install.sh | sh
# 启 daemon
nohup ~/.local/bin/boxlite serve --host 0.0.0.0 --port 8100 > /tmp/boxlite.log 2>&1 &
# 主 API 集成(Sandbank BoxLiteAdapter remote 模式)
const adapter = new BoxLiteAdapter({
mode: 'remote',
apiUrl: 'http://100.101.167.99:8100', // Tailscale tailnet
prefix: 'default', // ⚠ 必传 - boxlite serve 默认 prefix='default',sandbank 默认 prefix='' 会 404
});
await adapter.listSandboxes(); // 实测返历史 box 列表capability 集 ['exec.stream', 'port.expose', 'sleep', 'snapshot', 'terminal'] 与 S2.c spike 一致。实施期 follow-up:task-runner-provider.factory.ts 在 private 模式下使用此配置(spike 已通,主 API 集成路径已打通 · 见 tasks.md §12.4)。
11.2 实测成本验证(vs §5 估算)
| 项 | §5 估算(2026-05-17) | 实测(2026-05-19) | 差异 |
|---|---|---|---|
| Fly Machine · 单次 30min task | $0.0027(shared-cpu-2x 2GB) | ~$0.0023(shared-cpu-4x 4GB · 实际 ~12 min) | 持平(估算偏高,实际任务比假定的 30 min 短) |
| POC 真跑总成本(5 次 dispatch + 1 debug) | ≤ $0.05(5 次预算) | $0.012(compute)+ $0.04/月(image storage) | 低于预算 4 倍以上 |
| 私有化 Mac mini host 月费 | $0(自有硬件) | $0(vibe-zlyan 已运行其他服务) | 一致 |
| 当前状态(POC 结束后) | — | task-runner app fly scale count 0 + suspended;0 active machine,仅留 image storage | 已经 0 compute 计费 |
11.3 8 个 spike 全部通过
| Spike | 验证内容 | 关键发现 |
|---|---|---|
| S1 | Claude Agent SDK 加载 .claude/skills/openspec-* | init message 携带 skills: string[],4 个 openspec skills 全部识别 |
| S2 | Sandbank ESM + capability 契约 + BoxLite Python SDK | FlyAdapter 无 exec.stream(架构不依赖);BoxLite 在 macOS Hypervisor.framework 真启动 microVM |
| S3 | 远程私有化 host 上 BoxLite microVM | 换路径:原 Linux VPS+KVM 改 Apple Silicon Mac mini + Hypervisor.framework;非 admin 用户 uv 装即可 |
| S4 | 容器→主 API callback 防火墙穿透 | Tailscale tailnet 替代 cloudflared/ngrok;health 26ms RTT;4 个 callback 场景全部通过 |
| S5 | Agent SDK 单 query() vs 多 turn | 单 query() 跑完 4 阶段,maxTurns≥200,PostToolUse hook 推 stage_change |
| S6 | microVM 内 → 主 API 网络延迟 | Tailscale p50 35ms / 公网 239ms(HMAC 加 ~2ms) |
| S7 | Claude binary 拒绝 root | Dockerfile 必须 USER node + chown -R node:node /workspace;bypassPermissions 模式下额外硬约束 |
| S8 | openspec CLI npm 包 + slim/alpine 兼容 | scoped 包 @fission-ai/openspec(裸 openspec 是空占位);slim 必须自带 bash;alpine 无 gh CLI 需 curl POST /pulls |
| S9 | §9.4 BoxLite serve remote mode 集成 | boxlite serve 单 binary = BoxRun;prefix: 'default' 必传;E2 PR #13 真跑通过 |
11.4 实施期遗留 follow-up
- §12.3 提主 PR
add-task-runner-poc(v2 报告 + 实施代码一并) - §12.4
task-runner-provider.factory.ts在 private 模式下用BoxLiteAdapter({ mode: 'remote', apiUrl, prefix: 'default' }) - §12.5 run.js callback completed 一致性 bug(PR #12 真创建但 task 表没切 awaiting_review)
- §12.6 DB ↔ GitHub App install repo 范围 sync gap(connect repo 前主动 reconcile)
- §12.7 spec.md 加
BOXLITE_PREFIX(默认'default')必填 env - §11.1-11.4 E3 双轨切换 demo 脚本 / E4 故障容错 / E5 账单防护 / demo 视频
11.5 后续 change · add-sandbank-fork-aio-e2b 2026-05-20 完成
POC 完成当日,立即启动并完成 sandbank fork + 新增 AIO/E2B adapter 工作:
- Fork repo:
Xeonice/sandbank-douglas-agent(MIT 衍生,weekly auto-merge 上游 main) - npm scope:
@douglas-agent— 13 个包发布(10 个上游 mirror + AIO + E2B + CLI) - 新 adapter:
@douglas-agent/sandbank-aio(AIOSandboxAdapter,dockerode + 可选 readinessProbe)+@douglas-agent/sandbank-e2b(E2BAdapter + CubeSandboxAdapter,共享 E2BProtocolAdapter 基类) TASK_RUNNER_MODE扩展:5 项public | private | e2b | cube | aio
E1/E2 等价真跑验证(B-full hard)
| Backend | 路径 | 结果 |
|---|---|---|
| AIO mode | 主 API 本地起 + AIOSandboxAdapter + 本地 docker | ✅ 完整 E1 等价:PR #18 · 34 秒 4 阶段 · HMAC callback + DB 状态机推进 |
| Cube mode | 主 API + CubeSandboxAdapter + douglas-wsl Tailscale | △ 协议层校准通过(against cube-api/routes.rs 反查),listSandboxes/get/destroy 跨 Tailscale 真跑过;真创 sandbox 被 CubeSandbox upstream v0.2.x 自身 plugin loading bug 阻塞(issue #159 OPEN ),与 fork+adapter 无关 |
Cube upstream 阻塞分析
CubeSandbox 是 Tencent 2026-04-20 开源的早期项目(30 天 4 个 release),v0.2.0 / v0.2.1 / v0.2.2 都存在 cubelet.services.images.v1.Images gRPC service 未注册的系统性 bug:
- 跨 AWS / Tencent CVM / 物理 PVM / WSL2 多个环境复现
- maintainer 5/11 给的 workaround(down/up + cubecli unsafe init)多 reporter 实测仍 fail
- PR #282(在 v0.2.2 中)只修了”v0.2.1 .vm not exist” 另一个 regression,没修 images.v1
- 官方 troubleshooting docs 不覆盖(只列 XFS + 磁盘空间 2 条)
我们 fork 的 CubeSandboxAdapter 协议层已 ground-truth 校准 — 上游修复 #159 出 v0.2.3+ 后,adapter 不需任何改动即可用。
详见 openspec/changes/archive/2026-05-20-add-sandbank-fork-aio-e2b/。
§13 参考资料
本报告所引用方案的官方资源。所有数据点均基于这些来源在 2026-05 的内容。
§3 · 云端容器(托管 SaaS)
- Fly Machines 首选 — 官网 · Docs · Pricing · Machines API
- Vercel Sandbox 备选 1 — 官网 · Docs · Pricing · npm
- E2B 备选 2 — 官网 · Docs · Pricing · GitHub
- Cloudflare Sandbox SDK 排除 — 官网 · Docs · Pricing · GitHub
- Daytona Sandboxes 排除 — 官网 · Docs · GitHub
- Modal 排除 — 官网 · Docs · Pricing
- Anthropic Code Execution Tool 排除 — Docs
§4 · Agent SDK
- Claude Agent SDK 推荐 — Docs · Skills · npm · GitHub TS · GitHub Py
- Codex SDK 对比 — Docs · npm · GitHub · TS README
- Anthropic API · Pricing & Limits — Pricing · Rate Limits
- OpenAI API · Pricing & Limits — Pricing · Rate Limits · Codex Pricing
§10.A · docker-friendly 候选(符合用户口径)
- AIO Sandbox 单 docker run · 推荐 — GitHub
- Daytona OSS docker-compose · AGPL 警告 — OSS Deploy · GitHub
- BoxLite 嵌入式 microVM · v0.9.5 — 官网 · Docs · GitHub · MCP Server
- Microsandbox 嵌入式 microVM · libkrun — 官网 · GitHub
- OpenHands agent + sandbox 一体 · ★ 68.6k — GitHub · Docker Sandbox Docs
- Docker Sandboxes (sbx) Docker 官方 · 2026-03 新出 — Docs
§6.1.2 · 沙箱中间层(multi-backend 抽象,磨平公有云/私有化差异)
- Sandbank MIT · ★ 163 · 推荐 · 中间层最佳匹配 — GitHub · Releases (v0.6.2) · npm · Issue #2(维护者持久化能力详述)
- cased/sandboxes MIT · ★ 97 · 偏 CLI — GitHub
- hyperterse/sandboxer Apache 2.0 · ★ 6 · 较早期 — GitHub
- spring-ai-community/agent-sandbox Java/Spring 生态 — GitHub
- @gitwit/sandbox npm 包形态 — npm
§10.7 · Sandbox SDK / 编排层(重要补充)
- Sandcastle MIT · git worktree 隔离 · 本场景不需要(详见 §10.7) — GitHub · README
- rivet-dev/sandbox-agent Apache 2.0 · ★ 1.4k · Universal Agent API — 官网 · GitHub · npm
- alibaba/OpenSandbox Apache 2.0 · ★ 10.7k · CNCF — 官网 · GitHub
- Beam Cloud / Beta9 AGPL 警告 — 官网 · GitHub (Beta9)
- awesome-sandbox 列表 社区维护的索引 — GitHub · 2026-05 list (gist)
§10.8 · 大厂开源方案专项
- 腾讯 CubeSandbox Apache 2.0 · ★ 5.7k · E2B 兼容 · 60ms 冷启动 — GitHub · Releases
- 阿里 OpenSandbox Apache 2.0 · ★ 10.7k · CNCF — 官网 · GitHub
- 字节 AIO Sandbox Apache 2.0 · ★ 4.7k · UI-TARS 生态 — GitHub · UI-TARS Desktop(生态背景)
- 字节 SandboxFusion Apache 2.0 · 评估导向 — 官网 · GitHub
- 字节 DeerFlow 2.0 Apache 2.0 · ★ 35.3k · SuperAgent harness — GitHub
- 微软 AutoGen MIT · maintenance mode — GitHub · Docs
- 微软 Agent Framework (MAF) AutoGen 继任者 — 介绍文章
§10.B · 云依赖型自托管(仅供对比记录,不符合 docker-only 口径)
- E2B Infra 需 GCP/AWS + Terraform + Nomad — GitHub · Self-host Guide
- Google Agent Sandbox 需 Kubernetes — 官网 · GitHub · 发布文章
- Firecracker 底层引擎 — 官网 · GitHub
隔离技术 / 通用对比
- gVisor userspace kernel — 官网 · GitHub
- Kata Containers VM + OCI — 官网 · GitHub
- libkrun Microsandbox 底层 — GitHub
openspec-agent-platform · docs/task-runner-poc.html · v1 · 2026-05-17 · explore 阶段产物