Administrator
Published on 2026-07-23 / 0 Visits
0
0

AI Agent Sandbox 状态模型:什么会留下

同样标注 persistent 或 stateful 的 AI Agent Sandbox,实际可能只保留一个对象 ID,也可能保留文件系统,少数产品还能恢复进程和内存。差异会在环境睡眠、暂停、停止、崩溃或删除时集中暴露。可靠的 Agent 架构需要一份状态合同:每次生命周期转换后,哪层状态还能读取,恢复时以什么形式回来,哪些写入已经越过沙箱边界。

本文基于各厂商一手文档,核验时间为 2026 年 7 月 23 日,覆盖 Azure Container Apps、Cloudflare、Runloop、Vercel、E2B、Blaxel 和 Docker Sandboxes。产品细节会继续变化,五层状态模型和验收方法可以跨产品复用。

在文档和实测共同证明之前,应把 Sandbox 本地状态视为缓存。必须跨越计算生命周期的工作进度,应放进由你掌握生命周期的外部存储。已经发往数据库、Git、队列和第三方 API 的写入,则需要幂等与对账机制,删除沙箱不会撤销这些副作用。

先统一生命周期词典

各家 SDK 使用相似的词,却执行不同的状态转换。

  • Sleep 或 standby 通常由平台在闲置后自动触发。Cloudflare 睡眠后启动全新容器,Blaxel standby 后可以恢复内存、进程与文件。
  • Pause 或 suspend 可能保存完整机器,也可能只保存磁盘。E2B 保存内存和进程,Runloop 只保存磁盘,恢复后需要重新启动 daemon。
  • Stop 或 shutdown 可能触发文件系统快照,也可能终止资源。Vercel 默认在 stop 时快照持久化沙箱,Docker 在 stop 和 restart 之间保留 VM 文件系统。
  • Delete、destroy、kill 或 rm 通常终结厂商托管的计算状态。独立 volume、对象存储、宿主机挂载目录和外部 API 写入仍按各自生命周期存在。

因此,stop 本身无法构成状态模型。真正可验收的问题应具体到:恢复后能否读到原文件,原进程是否仍在,连接是否还能用,外部存储是否保留数据,先前的外部写入到底有没有成功。

稳定的 Sandbox ID 也只能证明控制面还能路由。Cloudflare 的 Durable Object 可以保留同一个身份,背后的容器却可能在睡眠后从干净环境启动。身份和数据持久性需要分别核验。

五层状态模型

把 Agent 环境拆成五层,能够直接看清状态归谁所有,以及删除动作能影响到哪里。

第一层:进程与内存

这一层包括运行中的进程、RAM、已加载变量、shell session、打开的文件描述符和内存数据库。完整内存快照有机会恢复这些对象。磁盘快照只能让新进程从原文件重新启动。

即使厂商保存了内存,外部连接仍应按断线恢复设计。恢复后的本地内核可能还记得一个 socket,数据库、消息队列或 HTTP 服务的另一端却可能已经超时关闭。应用必须重新连接,并判断前一次请求是否已经提交。

第二层:Sandbox 本地可写文件系统

这里包含检出的代码、安装包、构建缓存、/tmp、home 目录和运行时生成的配置。它通常速度快,适合放可重建内容。

风险来自生命周期绑定关系:本地可写层可能属于容器、VM、Sandbox 身份或某个带保留期限的快照。产品页面上的持久化三个字无法说明它属于哪一种。只要归属和保留期限不清楚,本地盘就不适合作为唯一事实源。

第三层:检查点与可复用环境

Snapshot、saved template、disk image 和 blueprint 都能缩短恢复时间,但它们表达不同的合同。

  • Pause/resume 检查点通常继续同一个 Sandbox 身份。
  • Snapshot通常保存某个时点,并允许从它创建一个或多个新环境。
  • Template、image 或 blueprint提供可复用起点,可能来自声明式构建,也可能直接捕获一个已经配置好的文件系统。

这层同时带来秘密残留风险。Snapshot 可能包含运行时文件和内存,saved template 可能把写入磁盘的 token 一起打包。检查点也需要访问控制、保留期限、清理策略和秘密扫描。

第四层:外部持久存储

Volume、drive、对象存储挂载和宿主机 bind mount 的生命周期独立于 Sandbox。需要跨计算实例保存的数据,通常应该落在这一层。

删除语义也在这里发生变化。Docker Sandbox 删除后,直挂的宿主机工作区仍然存在。Blaxel Sandbox 终止后,volume 可以交给新环境继续使用。Cloudflare 容器销毁后,已经写入 R2 的对象仍由 R2 管理。

第五层:外部系统与副作用

Agent 可能推送 Git commit、更新数据库、发送消息、创建云资源、确认队列任务或发起支付。这些动作已经穿过 Sandbox 边界。回滚快照或删除环境都不会自动撤销它们。

这一层决定了恢复是否安全。生产系统需要在第一次请求前生成幂等键,把操作意图和结果记录到外部耐久存储,在恢复后先对账,再决定重试还是补偿。

产品事实表:核验于 2026 年 7 月 23 日

下面这张表是带日期的事实快照,不是长期排名。预览、Early Access 和 private beta 能力均保留其成熟度标签。

产品 生命周期动作 本地文件系统 内存与进程 独立持久层 时效与成熟度边界
Azure Container Apps Dynamic Sessions 冷却期结束或 Stop Session 后销毁 丢失 丢失 不提供持久存储 与 Azure Container Apps Sandboxes 是两个产品
Azure Container Apps Sandboxes Memory 或 Disk suspend;支持显式 snapshot 两种模式都可保留磁盘 Memory 模式保留;Disk 模式重启进程 Blob、Data Disk volume Preview,API 与预览实例可能变化
Cloudflare Sandbox SDK 默认闲置 10 分钟后 sleep 容器停止后丢失 丢失 可挂载 R2、S3、GCS,支持只读 Durable Object 身份保留,容器状态不保留
Runloop Devbox Suspend 时保存磁盘,resume 保留 Devbox ID 保留 丢失,daemon 需重启 独立 disk snapshot;Blueprint 生命周期页明确为 disk only
Vercel Sandbox 默认 persistent;stop 时自动快照 在新 session 中恢复 进程重启 Snapshot;Drive 支持只读或读写 Persistence 已 GA;Drive 为 private beta
E2B Pause 后通过 connect 恢复;kill 为终态 保留 保留 内存与文件系统 snapshot;Volume Volume 为 private beta
Blaxel 闲置后自动进入 standby Sandbox 存续期间保留 保留;外部连接会关闭 Volume 跨 Sandbox 删除保留,可只读挂载 保留期限可能受配额层级影响
Docker Sandboxes Stop/restart 保留 VM;sbx rm 删除 VM VM 内状态保留到 rm;宿主工作区独立存在 按重启恢复设计 宿主工作区;saved template Template 为 Early Access,kit 为 experimental

Azure 的两个产品采用两套状态合同

Azure Container Apps Dynamic Sessions 面向托管的短时执行。相同 identifier 在 session 存活期间会路由到原环境。冷却期结束后,平台销毁 session 并清理资源。之后再次使用同一 identifier,只会分配一个新 session。官方对比表还明确写出 Dynamic Sessions 没有持久存储。

Azure Container Apps Sandboxes 是另一项预览能力。它提供可编程生命周期、Memory 与 Disk 两种 suspend 模式、独立 snapshot,以及 Blob 和 Data Disk volume。把二者合并为 Azure Sandbox 会直接抹掉最关键的选型差异。

Cloudflare 的持久身份和临时容器需要分开理解

Cloudflare 使用 Durable Object 持有 Sandbox 身份并负责路由。生命周期文档同时明确说明:默认闲置 10 分钟后容器停止,下一次请求启动干净容器,本地文件、进程、shell 状态和代码解释器上下文全部清除。

keepAlive 通过持续占用活动资源来避免睡眠,它解决运行连续性,不提供独立耐久存储。需要保存数据时,可使用 R2、S3 或 GCS 挂载,并可按挂载点配置只读。

Runloop 将工作进度落到磁盘

Runloop 的 Devbox 生命周期文档规定 suspend/resume 只保存磁盘,内存状态消失,daemon 与其他进程需要重新启动。Devbox ID 和 SSH key 可以延续。独立 disk snapshot能够创建新 Devbox,Blueprint 则用于构建可重复的基础环境。

这套语义要求 Agent 在 suspend 前把进度序列化到磁盘,并让启动脚本具备幂等性。某些教程使用过更宽泛的过程保存表述,正式生命周期页给出了更精确的边界,本文以它为准。

Vercel 默认保存文件系统

Vercel 于 2026 年 5 月 26 日宣布 Sandbox persistence GA。当前持久化指南说明 persistence 默认开启。Stop 会自动快照文件系统,后续操作从最近快照启动一个新的 VM session。设置 persistent: false 后,session 停止时直接丢弃文件系统。

显式 snapshot 保存文件与安装包。默认保留期限为最后一次使用后的 30 天,Vercel 于 2026 年 6 月 26 日调整了计时规则。Vercel Drive拥有独立生命周期,也支持只读挂载,但在本文核验时仍属 private beta。

E2B 与 Blaxel 保存内存,连接仍需恢复

E2B persistence在 pause 时保存文件系统和内存,包括进程与已加载变量。其文档同时说明,pause 期间外部客户端会断开。Resume 后服务进程可能仍在,客户端依然需要重连。

Blaxel 的 Sandbox 生命周期在进入 standby 时保存进程、内存与内存文件系统,同时明确排除数据库连接、消息队列连接和 HTTP connection pool 的连续性。Blaxel Volume可跨 Sandbox 销毁与重建保留,并支持只读挂载。

Docker 的工作区属于宿主机

Docker Sandboxes 把 Agent 放进独立 microVM,但默认工作区采用宿主机目录直挂。Agent 默认可以读取、修改和删除其中的文件。Stop 后,VM 内安装包、镜像与配置继续存在。执行 sbx rm 后 VM 内容被删除,宿主机工作区的变更仍然保留。

这个反例说明,路径显示在 Sandbox 内,并不代表数据归 Sandbox 所有。所有权由 mount 决定。Docker 还明确警告,把运行中的 Sandbox 保存为 template会捕获整个文件系统,其中可能包含秘密。

外部连接和副作用才是恢复难点

内存恢复会让进程看起来连续,外部世界却可能已经前进。假设 Agent 更新数据库后,还没把成功状态写入本地检查点,环境就暂停或崩溃:

  1. 数据库已经提交更新。
  2. Sandbox 本地仍停留在请求前或请求中的状态。
  3. 恢复后 Agent 认为操作尚未完成。
  4. Agent 再次发送同一更新。

外部 API 支持幂等时,可以返回同一个业务结果。普通非幂等接口可能重复创建订单、消息、资源或支付。

Git push、队列确认、对象上传和 webhook 都有同样的问题。恢复设计需要落到外部边界:请求前生成幂等键,把意图和结果写入外部日志,恢复后先查询真实结果,对不确定操作执行对账,对无法事务化的动作准备补偿路径。

Agent 的持久协调也应与代码执行分层。Agent Cloud 架构解析讨论了更完整的编排基础设施。协调器可以持久记录任务,而执行 Sandbox 可以按任务启动、暂停或重建。

一套真正有用的生命周期测试

厂商表格适合做初筛。生产可信度来自同一套餐、区域、SDK 版本、镜像和生命周期策略下的实测。

先准备五个探针:

探针 生命周期动作前 恢复后检查
进程 启动 heartbeat,记录 PID 与内存计数器 判断原进程继续、重启还是消失
本地盘 向 Sandbox 自有目录写入随机值 读取并核对 checksum
检查点 创建厂商提供的 suspend 或 snapshot 工件 分别测试同身份 resume 与新环境 fork
外部存储 向 volume 或 bucket 写入另一随机值 脱离 Sandbox 恢复流程独立核验
外部副作用 向测试服务发送带幂等键的写请求 重试前先查询服务端,确认业务效果只发生一次

然后覆盖系统实际会经历的状态转换:

create -> sleep -> resume
create -> pause/suspend -> resume
create -> stop/shutdown -> start
create -> crash/timeout -> recover
create -> snapshot -> fork
create -> delete/kill/rm -> verify external state

测试结果应成为版本化合同:

provider: example
verified_at: 2026-07-23
sdk_version: 1.2.3
transition: suspend_resume
same_identity: true
process_memory: lost
local_filesystem: preserved
checkpoint: disk_only
external_volume: preserved
connections: reconnect_required
external_effects: reconciled_by_idempotency_key

SDK 升级、套餐变化、镜像重建或厂商调整默认生命周期后,重新执行同一组测试。这套探针就是状态架构的验证接口。

持久化和写控制要分成两条轴

持久化回答一次变更保留多久,写控制回答谁能改变哪层状态。生产系统需要同时评估两条轴。

Cloudflare、Blaxel 和 Vercel 可以把部分外部挂载设为只读。Docker 默认宿主工作区可写。E2B secure access 解决 Sandbox controller 的 API 鉴权,它不等同于目录级写入白名单。Runloop 提供文件系统操作和网络策略。Azure Dynamic Sessions 保护管理端点并隔离不同 session,但单个 session 内的文件和环境变量对该 session 的使用者可见。

写控制至少要检查四个边界:

  1. 管理面: 谁可以创建、暂停、快照和删除环境。
  2. 运行身份: Agent 生成的代码以哪个 OS 用户和权限执行。
  3. 存储路径: 哪些本地目录和外部挂载只读,哪些可写。
  4. 网络与凭据: Agent 可以向哪里发送数据,秘密以什么方式进入运行时。

关于 OS 身份、ACL、可写目录和网络边界的具体实现,可以继续阅读 Codex Windows 沙箱架构。更早一层的准入问题,也就是哪些依赖有资格开始执行,见 AI Coding Agent 的安装前信任边界

六条可以跨产品复用的架构规则

产品表会过期,下面六条规则更稳定。

  1. 把厂商动词映射为内部状态合同。 每个动作都按五层状态记录实测结果。
  2. 本地盘只保存可重建内容。 代码副本、依赖、缓存和临时产物最适合放在这里。
  3. 耐久进度交给独立存储。 必须跨计算删除保留的任务状态,应写入 volume、对象存储、数据库或持久协调器。
  4. 把 resume 当作故障恢复。 重连 socket,重启带健康检查的服务,刷新凭据,对账所有结果不确定的外部操作。
  5. 把延续性和可重复性分开。 Snapshot 延续某个具体状态,声明式 image 与 blueprint 创建已知起点。成熟系统通常两者都需要。
  6. 显式测试删除。 确认厂商托管状态已经清除,外部数据只在预期位置保留,snapshot 和 template 没有残留凭据。

最终的选型问题会从哪家 Sandbox 更强,收敛为一组可验证的系统问题:当前工作负载需要哪种执行隔离、恢复工件、耐久存储和写入边界?当厂商改名、升级 SDK 或调整默认值时,这组问题仍然成立。

常见问题

什么是持久化 AI Agent Sandbox?

它至少能让一层状态跨越计算生命周期。完整定义必须写明具体层级:文件系统、内存、进程、snapshot 还是外部 volume。只写 persistent 无法支撑架构决策。

Snapshot 一定能保存运行中的进程吗?

取决于快照类型。E2B snapshot 包含内存和进程,Runloop 明确为 disk only,Vercel snapshot 保存文件系统与安装包。最终应以当前官方文档和进程探针共同确认。

删除 Sandbox 后还会留下什么?

厂商托管的计算状态通常被清除。独立 volume、对象存储、宿主机挂载目录、显式 snapshot 工件和外部系统副作用可能继续存在。删除验收需要逐个查询这些真正的数据所有者。

Template、snapshot 和 volume 有什么区别?

Template 或 blueprint 提供可复用起点,snapshot 捕获某个运行时点并用于恢复或分叉,volume 在独立于计算的生命周期里保存文件。各家 API 名称不同,架构上应按这三种职责分类。

保存内存后,数据库连接能直接继续用吗?

远端数据库可能已经关闭连接。恢复后应重新连接,验证事务结果,并用幂等键保证重试不会重复产生业务效果。

选 AI Agent Sandbox 时应该比较什么?

先列出隔离强度、本地盘、进程连续性、恢复时间、外部存储、写控制、保留期限和删除语义,再用同一套状态合同测试候选产品。价格与启动速度应在状态和安全合同满足需求之后比较。

参考资料


Comment