跳到正文

Blog

笔记本关机后,agent 的工作区还在

Appaloft 1.4 把 Agent Workspace 做成公共 Sandbox 入口工作流:远程 harness、协作租约、休眠恢复,以及带证据门槛的发布路径。本文讲架构、和 OpenSandbox 等产品的对比,以及哪些门禁还没关完。

AppaloftAIAgentsSandbox架构Agent Workspace

笔记本一合上 agent 就没了,那是 demo。工作区能重连、能冻结证据,却仍然拒绝自己发布——这才更像产品。

今天我们发了 Appaloft 1.4.0。发布说明里有远程 Agent Workspace、Task Run、协作、休眠、可迁移恢复、可复用 Snapshot、远程 terminal attach,以及声明式 Agent Adapter 的第一刀。这篇写这些 bullet 背后的架构:谁拥有什么、Cloud 注入什么、我们停在哪里,以及它和 OpenSandbox、E2B、Modal 一类产品差在哪一层。

如果你读过构建应用的 agent,不该是那个点发布的角色和英文的 How we built the delivery evidence chain,这篇是更底下那一层:东西变成可发布候选之前,agent 真正干活的地方。

一直撞上的问题

本地 agent 循环挂得很无聊:

  • 人合上盖子,agent 进程没了。
  • 两个人想看同一次 run,共享笔记本会话扩不开。
  • agent 给你一个别人打不开的 localhost:3000
  • 活干得差不多了,写文件的那个身份还想顺便部署。

所以我们要的不只是「起一个容器再 exec」。它得能重连、隔离租户、暴露临时预览、扛住计划内的算力释放,再接到一条 agent 主体单独走不通的证据链。

Appaloft 里的 Agent Workspace 是什么

Agent Workspace 不是 Cloud 新建的 aggregate。它是盖在现有 Sandbox 操作之上的公共入口工作流:

Sandbox
  + Agent Runtime(今天是 Pi / OpenCode)
  + 可重连 Terminal Session
  + 会过期的 Sandbox Port 暴露
  + 持久的 Agent Task Run
  + Workspace Collaboration(lane、writer lease、handoff)

身份规则是故意的:workspaceId = sandboxId。自托管、Cloud、未来的 Enterprise 发行版用同一套 CLI、SDK 和 operation catalog。Cloud 不会再造一张 Workspace 表,也不会平行搞一套 REST。

flowchart LR
  subgraph Clients
    CLI["CLI workspace *"]
    SDK["SDK workspaces.*"]
    Console["Console /workspaces"]
  end

  subgraph Public["Public Appaloft"]
    WF["Workspace 入口工作流"]
    SBX["Sandbox<br/>workspaceId = sandboxId"]
    RT["Agent Runtime<br/>Pi / OpenCode"]
    TERM["Terminal Session"]
    PORT["Port Preview<br/>TTL + revoke"]
    TASK["Agent Task Run"]
    COLL["Collaboration<br/>writer lease"]
    DELIVER["Source Artifact → Preview → Promote"]
  end

  subgraph Cloud["Cloud overlay 只注入"]
    AUTH["authz / quota"]
    SERVER["registered Server"]
    GW["gateway / attach"]
    REC["recovery + snapshot policy"]
    ADAPT["Adapter 审批"]
  end

  CLI --> WF
  SDK --> WF
  Console --> WF
  WF --> SBX
  SBX --> RT
  SBX --> TERM
  SBX --> PORT
  SBX --> TASK
  COLL --> SBX
  TASK --> DELIVER
  Cloud -.->|"composition only"| Public

这张图就是产品赌注。客户端只打 Public Appaloft。Cloud 做 composition:registered server、gateway attach、模型访问、quota、recovery mount、snapshot 策略、Adapter 审批。虚线,不是归属。

部件怎么接上

创建路径很机械:

  1. sandboxes.create
  2. 对已注册 harness 调 sandboxes.agents.runtimes.create
  3. 可选 terminal、preview port、task run、collaboration lane

给人用和给 agent 用的 CLI:

appaloft workspace create
appaloft workspace connect
appaloft workspace terminal
appaloft workspace preview
appaloft workspace task run
appaloft workspace pause
appaloft workspace resume

规范操作仍在 sandboxes / terminals / ports / collaborations 下面。workspace 命令是工作流门面,不是第二套领域语言。

协作也是公共且显式的。每个人或 agent 用自己的 Sandbox 身份。lane 里旁观者可以看真实 PTY 输出,写入走带 generation fencing 的可续期 writer lease。我们不会把一队人塞进同一个 checkout,指望大家守 tmux 礼节。

休眠、drain 和 Snapshot

1.4 把生命周期做硬一点,好让你关电脑:

机制 保留什么 明确不承诺什么
process-frozen pause 进程 + 文件系统 更适合短暂停
compute-released hibernation /workspace 与文档约定的持久路径;释放 CPU/内存 任意 PTY 内存、未落盘的模型流
Portable drain 同一 SandboxId 迁到共享 recovery family 里的另一台 Server 从未写入 recovery store 的字节
Reusable Snapshot 策略控制下的一对多 restore 我们不替你运营的 shared mount HA SLA

Resume 会重签 capability。旧的 terminal attach token 和 preview URL 故意作废。烦一次,正确一辈子。

2026-07-26 我们已经做过双 registered Server 验收(Yundu → Hostinger planned drain、同 identity 连续性、snapshot restore、精确 cleanup)。这够发表架构,不够编造 RPO 数字。文档拒绝承诺的地方,这篇也拒绝。

工作区何时变成可发布物

Workspace 可变,发布不可变。交接还是那条证据链:

flowchart LR
  W["1. Workspace<br/>可变 FS + agent run"] --> F["2. Freeze<br/>Source Artifact digest"]
  F --> P["3. Candidate Preview<br/>过期 URL + digest"]
  P --> G["4. Promote / deliver<br/>仅外部 actor"]

  subgraph AgentReachable["agent 可达"]
    W
    F
    P
  end

  subgraph HumanGate["人 / 委托门禁"]
    G
  end

Sandbox 范围内的主体只负责准备,不能 accept promotion。如果这条边界显得严,那正好——见先前的agent 发布边界和英文的证据链

和 OpenSandbox 等怎么比

市场上的 “sandbox” 其实是好几类产品。公平对比要靠轴,不靠感觉。下表依据 2026-07-27 的公开文档与仓库;我们没有横向重跑冷启动。

Appaloft Agent Workspace OpenSandbox E2B Modal Sandboxes
主业 持久 coding workspace + 交付控制面 通用沙箱平台(exec、agent、评测、RL) 给 agent 的隔离 Linux(云) 跑不可信代码的安全容器
身份模型 workspaceId = sandboxId 的公共 ops 工作流 Sandbox lifecycle API + execd 带 pause/snapshot 的 Sandbox 对象 Modal 里的 Sandbox 对象
隔离(文档口径) provider/template 策略;我们栈里有 gVisor 执行路径 默认 Docker/runc;可选 gVisor / Kata / Firecracker Firecracker microVM gVisor
Agent 耦合 Harness adapter(Pi、OpenCode;声明式 Adapter 下一步) harness 无关 SDK / MCP 示例 harness 无关 SDK harness 无关
自托管 公共控制面 + 你的 Server Docker / Kubernetes 一等公民 云 + BYOC Modal 托管
Preview 会过期的 sandbox port + artifact candidate preview port endpoint / proxy sandbox domain / envd Connect token / tunnel
发布路径 Freeze → candidate preview → 外部 promote / deliver 不承担部署控制面 不承担 不承担

架构评审时更有用的几点:

1. 谁拥有生命周期。 OpenSandbox 和 E2B 拥有带 TTL、pause、snapshot 的 sandbox 对象。Appaloft 也拥有 Sandbox——然后在同一身份上叠 workspace、task、collaboration、promotion 工作流。如果你只要「跑一段不可信命令」,纯 sandbox API 更薄,完全够用。如果你要「明天还能重连,而且仍不能自己发布」,就需要工作流层。

2. 默认隔离 vs 可配置隔离。 E2B / Modal 把强默认写进产品(Firecracker / gVisor)。OpenSandbox 让 API 保持中立,由运维选 secure_runtime。Appaloft 更接近后者:隔离是 provider/template 属性,不是 Workspace 类型上的营销词。别把 “workspace” 读成「我们发明了新的 microVM」。

3. 凭证叙事。 OpenSandbox 的 Credential Vault 一类出站注入,尽量让 guest 看不到真密钥。我们关心同一失败模式,但当前发布硬线不同:密钥不能进不可变 Source Artifact,sandbox 主体也不能 promote。guest 密钥注入和 artifact 密钥扫描解决相邻问题,威胁模型里两样都要。

4. 产品层别混。 Cloudflare Sandbox SDK(Linux 容器 + preview URL)和 Dynamic Workers(V8 isolate)很容易被当成一类。只有前者才和 coding workspace 同场。DevPod / Codespaces 在人用 IDE 轴。OpenHands 的 sandbox 和 agent 绑死。跨层比功能清单没有意义。

5. 开源路径。 OpenSandbox 是 Apache-2.0、偏自托管。E2B 开源 SDK,BYOC 另讲。Daytona 公开仓在 2026-06 停更、核心迁私有——读旧 README 时别把「开源自托管」当成现状。Appaloft 的 Workspace 真相源在 public core;Cloud 是 overlay。

我们不宣称自己是唯一可 pause 的沙箱、唯一的 gVisor 选项,或唯一友好 MCP 的 exec API。那些已经存在。我们的主张更窄:一个远程 agent workspace,仍然说部署证据那一套操作语言。

门禁未齐,架构先正确

1.4 有些面已经收口,有些没有。没收口的部分,方向我们打算继续守。

形状已经可以说清楚、不必再对产品形状打补丁的

  • Pi / OpenCode 的远程 Workspace 入口
  • Task Run 过程管理器(taskRunId = runId
  • Collaboration 的 writer lease / observer / handoff
  • compute-released 休眠、capability 重签、planned drain、可复用 Snapshot(双 Server 验收已有记录)

方向已定、退出门禁还在关的

  • 托管环境对 test-owned GitHub 仓做真实 PR write go-live(幂等重试 + 精确 cleanup)。Task Run 架构在,验收未关。
  • 开放 Adapter / Workspace Profile:声明式 manifest、租户安装审批、profile pin、credential grant。契约已是公共的(appaloft.agent-adapter/v1appaloft.agent-workspace-profile/v1)。完整的 Codex-on-registered-server smoke 和任何 marketplace 故事是后面章节,不是今天的主张。
flowchart TD
  A["Declarative Adapter / Profile"] --> B["Harness 解析<br/>不执行租户上传的控制面代码"]
  B --> C["Pinned Workspace 实例<br/>digest + installation id"]
  C --> D["同一套 Sandbox / Task / Collaboration / Promote ops"]

这是故意未完成的产品,不是空气。Cloud 会审批和审计安装,不会执行租户上传的控制面包。哪天这条线糊了,这篇就成了我们写错的证据。

正在承受的取舍

  • Workspace 和 Sandbox 同身份让 ops 和 cleanup 简单。每个 Workspace 功能也必须服从 Sandbox 过期、网络策略和 provider 限额——没有逃逸 aggregate。
  • Harness adapter 而不是唯一钦定 agent让控制面保持诚实。每个新 runtime 都要付 conformance 成本。
  • 文件系统优先的休眠可运维。承诺完整 TUI 内存复活则不可。
  • 先证据再发布拖慢 demo。这也是我们愿意让 agent 靠近交付的唯一理由。

自己摸一摸

如果你在做相近或互补的沙箱,我们想听具体反馈:workspaceId = sandboxId 帮没帮上忙?密钥你更想放 guest vault、host 注入,还是 artifact 门禁?Codex 验收路径绿灯之后,Adapter profile 下一个该接哪个 harness?