Agent 从牢房搬进工位:暂停、恢复,和一笔没人算的账

2026-11-02T07:12:09+08:00 | 7分钟阅读 | 更新于 2026-11-02T07:12:09+08:00

@
Agent 从牢房搬进工位:暂停、恢复,和一笔没人算的账

11 月 1 日的 GitHub 趋势榜上,OpenMausBot 一天涨了 919 星,CopilotKit 的 OpenBot 也上了榜。两个项目卖的是同一个东西:每个 AI 同事一台自己的电脑,独立浏览器、独立文件系统、独立工具链。

这个方向不新。10 月底 NVIDIA 的 OpenShell 和 cua 已经在做隔离,我当时写过一篇,讲的是怎么给 agent 造一间牢房。今天的项目往前挪了一步。牢房是一次性的,工位是要住人的。

住人就有住人的麻烦。你开一台机器给 agent,它干完活回一句"已完成",那台机器还在那儿亮着。上面有它装的依赖、改了一半的配置、登录着的账号、跑到一半的服务。第二天你让它接着干,它得从这台机器上接着,不能从一张白纸开始。这个"接着",就是全部难处。

一次性沙箱和长期工位,差的是状态的所有权

一次性沙箱的逻辑很干净:任务结束,机器删掉,什么都不留。出问题重开一个,反正启动只要几百毫秒。这类设计在评估、跑测试、批量处理代码上很合适,失败成本几乎为零。

工位不一样。工位有历史,而历史在运维上就是负债。三个月前它装过一个特定版本的 node,上个月有人手动改了个配置文件没提交,昨天它为了排查问题往 hosts 里写了一行。这些都真实存在,也都没人记得。等到某天它跑出来的结果跟本地对不上,你得从那台机器上一点一点考古。

所以工位贵,不是因为它占了更多 CPU,是因为它开始有"资产"要管。

恢复有两种语义,差价不在钱

所有做这块的平台都要回答一个问题:agent 明天回来的时候,从哪儿接着。

E2B 的做法是暂停和恢复。暂停时把文件系统和内存一起存下来,运行中的进程、加载过的变量、内存里的数据都保留,恢复大概一秒回到原样。代价是暂停本身不快,按官方说法,每 GiB 内存大约 4 秒,一个 8 GiB 的工位停一次要 32 秒。也可以选择只存磁盘,这种模式恢复等于重启,服务得重新拉起来,速度快一些,内存里的东西全丢。

Fly.io 走的是另一条路。它的 suspend 用 Firecracker 快照,把 CPU 寄存器、内存内容、打开的文件句柄整个存下来,恢复几百毫秒,冷启动要两秒以上。但限制写在文档里:机器内存不能超过 4 GB,不支持 swap,2024 年 6 月 20 日之前创建的机器挂不起来。

方案恢复的是什么回来要多久卡在哪
E2B 暂停(默认)磁盘 + 内存,进程活着约 1 秒暂停本身按每 GiB 约 4 秒算
E2B 暂停(只存磁盘)只有磁盘,恢复即重启一次正常启动内存状态全丢,服务要重拉
Fly suspendFirecracker 整机快照几百毫秒内存 ≤ 4 GB,且不保证恢复成功
Daytona 停止磁盘常驻,VM 可另存内存冷启动停止态继续收磁盘费

更值得看的是 Fly 自己加的那句提醒:suspend 不保证恢复。宿主迁移、平台维护、容量紧张,任何一种都可能把一次挂起变成冷启动,而且没有标志告诉你这次是哪种,只能看首次请求的延迟。原话是把 suspend 当成"更快的 stop",别当成保证。

这就是我想说的第一件事。内存快照是加速手段,不是持久化承诺。你在架构里把它当承诺用,早晚会在某个凌晨掉一次。

快照会骗人

内存里装的东西比文件脆弱得多:TCP 连接、文件锁、系统时钟、进程 ID、外部服务那头的会话。

Fly 的文档提到,恢复之后系统时钟要一两秒才重新同步。E2B 直接写明,暂停期间对外的连接会断,恢复以后客户端得重新连。这些细节单看都很小,凑在一起就是一类经典故障:进程还在,端口还开着,客户端连不上,agent 以为服务活着,一直在等一个永远不来的响应。

E2B 还有一条降级路径,我觉得设计得挺诚实,也挺吓人。自动暂停的时候,如果所在节点还在处理这个沙箱的上一个快照,API 会返回 503,沙箱继续运行并重试,最多重试到超时之后两分钟左右。要是这个窗口里一直被拒,它就降级成只存磁盘。下次恢复就是重启,内存状态没了。事后你能在生命周期事件里看到 pause_mode 是 filesystem,才知道发生过什么。

换个说法:你以为的整机挂起,在容量吃紧的时候会悄悄变成关机重开。而发生的时间,通常是你最不想盯着的时段。

报价单的第一行不是单价

E2B 和 Daytona 的 2 vCPU、4 GiB 配置,按文档的单价算下来都是每小时 0.1656 美元。一台一直开着,一个月 730 小时,121 美元。二十个工位,每天开 8 小时,一个月 22 个工作日,五百八十多美元。

数字本身不吓人,吓人的是你在为什么付费。

给 agent 开机器,它大部分时间在等模型返回。Upstash 拿同样的 2 vCPU/4 GiB 算过一笔:一个小时的活里真实 CPU 只忙了 10 分钟,按 wall-clock 收 0.17 美元,按活跃核心收 0.02 美元,差 8 倍。它自己的 Box 产品就按活跃核心计费、内存不计费,摆明了冲着这个差价来的。Daytona 的计费是反过来的,按 wall-clock 对预留的 vCPU 和内存收费,你用不用都算。

所以选底座的时候,报价单第一行不该是单价,是计费口径。同样是 0.16 美元一小时,一种口径下你为等待付钱,另一种口径下等待免费。

idle 的那条尾巴

自动停机的判断标准,比价格更容易踩坑。

Daytona 默认 15 分钟无活动自动停,虚拟机类型要 60 分钟才暂停,在那之前一直按运行计费。它判断"活动"看的是外部调用,不管容器里在干什么。

Fly 把这件事写得更直白。proxy 只看入站流量,看不见容器内部。一个要跑二十分钟的报告任务,接口返回 202 就把连接关了,几分钟后机器被停,报告死在一半。官方说这不算 bug,是照文档工作。

两头都得防。跑长任务的时候,别让平台觉得你闲着;反过来,用 cron 每分钟 ping 一下来防自动停,是最亏的保活方式,你付了全价,机器什么也没算。

清理债

这部分没人愿意写,但账单上一定会有。

E2B 的暂停沙箱永久保留,没有 TTL,不会自动删,只有你主动 kill 才消失。省钱是省了,问题是你再也想不起来它们,控制台里排着队,一个都不占钱,一个都不敢删。

Daytona 的状态多一层:运行、停止、归档、删除。停止状态不收 CPU 和内存,磁盘照收。虚拟机类型不能归档,所以一个暂停的 VM 会一直付磁盘费。从沙箱做出来的快照,在沙箱删掉之后还在计费,费率官方没公开。快照两周不用会失效,得先激活才能再起。

还有身份漂移。Daytona 的 macOS 文档写得很实在:从一个镜像起的新机器是新身份,绑在机器上的东西,iCloud 登录、某些软件授权,都得重新登。工位上的凭证不能指望跟着快照走,这事得单独管。

这几条加起来,默认结果就是"没人删"。工位越多,欠得越多。

机器回来了,对话没回来

最后一点,我觉得比上面所有细节都重要。

工位持久化的是文件系统和内存。模型这边持久化的是上下文窗口。这是两套状态,经常不同步。

机器上有改了一半的代码,模型不记得为什么改。模型的计划里写着"接下来改 auth 模块",机器上的文件已经被回滚了。趋势榜上 claude-mem 一天 1527 星,做的就是把这套对话状态跨会话存下来,说明这块到现在还是空的。

所以一个能用的工位,必须有张交接单:这次改了什么、为什么改、哪些没改完、下次从哪儿接。这张单子不该指望模型自己记住,也不该藏在机器的 shell 历史里。

我会怎么做

一次性沙箱的思路是坏了就扔。长期工位的思路必须变成坏了也得修。这是两种运维模型,多数团队按前者的成本做预算,按后者的方式用产品,差额最后都落在账单和故障单上。

具体到落地,四条:

  • 环境当构建产物。工具链装好就做快照,别让每个工位自己长出一套。E2B 的快照是一对多,一个状态能起很多个沙箱;暂停是一对一,只服务它自己。
  • 恢复只承诺磁盘。内存快照当加速器,业务逻辑不要依赖"进程还活着"这个假设。
  • 每个工位带 owner 和过期时间。平台不一定替你删,那就自己写个每天扫一遍的脚本,这行代码能省下的钱比很多优化都多。
  • 长任务别跟 idle 检测打架。能标忙就标忙,标不了就设最小常驻实例。

趋势榜在卖"给 agent 配一台电脑"。真正决定这东西能不能上生产的,是第二天早上那台电脑还在不在、账单上多了多少、以及你敢不敢让它拿昨天的状态继续干活。

参考来源

  • E2B Docs: Sandbox persistence, snapshots, billing
  • Daytona Docs: sandbox lifecycle, macOS sandboxes, billing
  • Fly.io Docs: Machine suspend and resume, long-running tasks and machine lifecycle
  • Upstash: AI agent sandbox providers compared (2026)
  • GitHub Trending, 2026-11-01
Me

Cut out summary from your post content here.

The remaining content of your post.