构建一个 Agent 并不容易。
一年前,我们需要自己管理上下文和记忆,思考 RAG 和向量数据库,还要非常仔细地调整工具调用的准确性。Claude Code / Claude Agent SDK 的出现改变了这一切。现在越来越多的团队开始直接使用 Claude Agent SDK + VM 来构建 Agent。那么问题变简单了吗?并没有。
在虚拟机中运行 Claude Code 依然是一件极具挑战性的事情。
-
每个用户会话都需要一个独立的虚拟机。在某些场景下,虚拟机的持久化能力确实有用,但这也使得虚拟机难以升级和编排。例如,从用户的角度来看,他们希望在虚拟机上安装的软件在几个月后仍然可用。但虚拟机上与编排层通信的部分也需要能够滚动升级。
-
大规模创建和编排虚拟机。单个 k8s 集群大约支持几千个 Pod 的编排,对于应用服务集群来说已经足够。但对于每个会话都需要启动一个 Claude Code Pod 的场景来说,就远远不够了。
-
使用 k8s 方案会面临 k8s 本身带来的延迟,难以实现 1 秒以内的性能。
-
使用 e2b 方案需要自己处理持久化,上传文件和下载文件都非常慢。
-
e2b 方案无法满足特定的网络环境要求,私有化部署也十分繁琐。
我们如何解决这些问题?让我们从历史中寻找答案。把时间拨回十多年前,2012 年,世界上还没有 Serverless,没有 k8s,也没有 Docker。后端工程师需要在物理机上手动维护一个服务进程来运行服务。那时候,ssh 和 ansible 是服务器工程师的标配工具。服务进程严重依赖物理机上的各种工具环境,要在多台物理机之间实现一致的工具环境配置极为困难,大规模扩容是团队需要提前很久就开始准备的大工程。我还记得有一次,一位工程师修改了某台机器的环境,却忘记同步到其他机器,结果在生产环境中引发了一个极难排查的幽灵 Bug。那段时期真是一段痛苦的岁月。
2012 年,Docker 出现了。Docker 将所有工具环境打包进一个镜像,解决了环境不一致的问题。社区逐渐意识到,运行在物理机虚拟机中的服务进程,可以像管理物理机上的进程一样进行管理。但 Docker 的编排仍然需要工程团队自己搭建编排系统。而一旦 Docker 内部的服务进程与物理机的网络和文件系统产生耦合,编排就会变成一件非常痛苦的事情。
2014 年,无状态服务开始成为主流趋势。那一年,Kubernetes 和 AWS Lambda 相继诞生,分别从不同角度描绘了无状态服务的未来。无状态服务意味着服务逻辑避免与网络地址耦合,也不再本地依赖持久化文件系统。
随后迎来了云原生的十年,无状态服务的浪潮催生了大批云原生基础设施,例如:
- 服务网关 Istio/Linkerd/Envoy/Treafik
- CI/CD 平台 Argo CD / Flux
- 可观测性平台 Prometheus/Grafana/ELK Stack
- 调用链分析 Jaeger/Zipkin/OpenTelemetry
- 存储 Rook/MinIO/JuiceFS
而我们现在正站在一个新的起点。十年前,计算单元是一个 Java/Python API 服务进程。从今年开始,这个计算单元已经变成了一个 Coding Agent。
ACFS 就像在物理机上手动维护服务进程的时代,E2B 就像 Docker。没有任务编排平台、可观测性平台和分布式状态持久化存储能力,可扩展性对于 Coding Agent 来说依然是一道难题。而我期望中的 Serverless Agent 基础设施应当具备以下能力:
- 能够适当地持久化 Coding Agent 的会话和工作目录,不丢失上下文。
- 极速响应,能够在 100ms 内让 Coding Agent 开始工作。
- 具备易于人类理解的 Agent 行为 Logging / Metric / Tracing,让人类更容易理解和调整 Agent 的行为模式。
- 开发者不再需要关心虚拟机、容器等运维细节,使大规模编排变得非常简单。
我认为,能够满足这些能力的基础设施其实已经准备就绪——例如 Firecracker 已经验证了 microVM 的性能和稳定性,分布式可观测性平台和文件存储系统也有很多成熟的选择。但作为一个曾经用 e2b 封装 Claude Code 的开发者,将这些整合在一起依然非常困难。比如,当 E2B 中的 Claude Code 因 OOM 意外中断时,工程师很难监控到这一情况,更难获取当时的现场和日志。
我希望 2026 年之后的开发者不必再经历这样痛苦的过程,就像 2026 年的大多数工程师不再需要用 ssh 手动初始化物理机一样。
这是 VM0 的梦想。我希望有一天能通过一个符合人体工学的 API 来驱动一个 Coding Agent,就像这样:
cosnt agent = vm0.run({
framework: 'claude-code',
prompt: 'buy me a coffee'
})





