Cloudflare 推出的 @cloudflare/computer 指向一个正在变得清晰的运行时需求:Agent 不仅要执行一段代码,还要在低延迟任务与完整 Linux 环境之间持续切换。单独使用容器可以提供兼容性,却未必适合每次轻量调用;只使用 isolate 效率很高,但又无法覆盖系统工具、原生依赖和复杂进程。
这个运行时的核心思路,是动态协调快速、轻量的 isolate 与完整 Linux 容器,让每个 Agent 获得一套更接近“独立电脑”的执行环境。
容器为什么不等于 Agent 的电脑
传统容器擅长封装应用:镜像中包含依赖,进程启动后对外提供服务。但 Agent 的执行模式更零散,也更难预测。一轮任务可能同时包含:
- 解析提示词、验证参数和调用 HTTP API;
- 执行 Python 脚本或带原生扩展的工具;
- 调用 shell、浏览器、编译器或文件转换程序;
- 在多轮交互之间保存工作目录和中间产物;
- 根据模型决策临时启动新的进程。
如果所有步骤都放进完整容器,短小任务也要承担较重的启动、调度和资源成本。如果全部放进 isolate,Agent 又可能遇到系统调用、二进制程序、文件系统语义或运行时兼容性限制。
因此,“电脑”在这里不应理解为一台永久运行的虚拟机,而是一种更高层的执行抽象:Agent 提交任务,运行时判断应该使用轻量执行环境,还是进入完整 Linux 容器。
动态编排的关键是任务边界
根据来源摘要,@cloudflare/computer 会在 isolate 和 Linux 容器之间动态编排。摘要没有公布具体 API,因此不能假定它通过某个固定函数或配置项完成路由。不过,从工程角度看,这类系统至少需要识别三类边界。
能力边界决定任务能否在 isolate 中完成。普通 JSON 处理、网络请求和轻量 JavaScript 逻辑通常不需要完整操作系统;调用 ffmpeg、运行任意 shell 或加载系统级动态库,则需要 Linux 环境。
状态边界决定工作目录能保存多久。Agent 可能在前一步下载仓库,在后一步修改文件并运行测试。运行时需要让后续任务重新找到这些文件,同时避免不同 Agent 之间发生数据串扰。
信任边界决定代码能获得哪些权限。模型生成的命令不能天然视为可信输入。网络出口、环境变量、挂载目录、CPU 时间和子进程数量都需要明确限制。
真正困难的部分并不是“启动一个容器”,而是把这三个边界变成可观测、可审计的调度策略。
可以这样实践:先做一个能力路由器
下面是一个可直接运行的概念验证。它不调用 @cloudflare/computer 的真实 API,而是模拟 Agent 运行时如何根据任务能力选择 isolate 或 Linux 容器。接入正式运行时时,可以保留任务分类和审计结构,再替换两个执行函数。
将以下内容保存为 router.mjs:
const tasks = [
{ id: "t1", kind: "json", input: "{\"name\":\"agent\"}" },
{ id: "t2", kind: "shell", input: "python --version" },
{ id: "t3", kind: "http", input: "https://example.com" },
];
const linuxCapabilities = new Set(["shell", "native-binary", "compiler"]);
function selectRuntime(task) {
return linuxCapabilities.has(task.kind) ? "linux-container" : "isolate";
}
async function runInIsolate(task) {
if (task.kind === "json") {
return JSON.parse(task.input);
}
if (task.kind === "http") {
const response = await fetch(task.input);
return { status: response.status };
}
throw new Error(`Unsupported isolate task: ${task.kind}`);
}
async function runInLinuxContainer(task) {
// 概念占位:生产环境应在受限容器中执行,不能直接拼接到本机 shell。
return {
accepted: true,
command: task.input,
note: "Replace this mock with the official container execution API",
};
}
for (const task of tasks) {
const runtime = selectRuntime(task);
const startedAt = Date.now();
try {
const result = runtime === "isolate"
? await runInIsolate(task)
: await runInLinuxContainer(task);
console.log(JSON.stringify({
taskId: task.id,
runtime,
durationMs: Date.now() - startedAt,
status: "ok",
result,
}));
} catch (error) {
console.error(JSON.stringify({
taskId: task.id,
runtime,
durationMs: Date.now() - startedAt,
status: "error",
error: error.message,
}));
}
}
使用 Node.js 18 或更高版本运行:
node router.mjs
这段代码体现了两个值得保留的设计:模型只描述任务意图,不直接指定最高权限的运行环境;调度器则记录任务最终进入了哪个运行时。生产实现还应加入允许列表,例如只允许声明过的二进制程序、网络域名和工作目录。
可以进一步把策略写成独立配置,避免授权规则散落在 Agent 提示词里:
execution_policy:
default_runtime: isolate
container_required_for:
- shell
- native-binary
- compiler
limits:
cpu_seconds: 30
memory_mb: 512
max_processes: 16
filesystem:
writable_paths:
- /workspace
persistent: true
network:
default: deny
allowed_hosts:
- api.example.com
这份 YAML 是可改造的策略示例,并非 @cloudflare/computer 已公开配置格式。它表达的重点是:容器升级应由能力策略触发,而不是由模型随意请求。
接入前要验证什么
采用混合运行时之前,团队需要先梳理 Agent 的真实负载。若任务只是调用 API 和转换结构化数据,isolate 可能已经足够;如果工作流依赖浏览器、编译器、Python 包或系统命令,Linux 容器的价值会迅速上升。
上线检查可以聚焦以下项目:
- 每种工具需要哪些系统能力,是否真的必须进入容器;
- isolate 与容器之间如何传递文件、日志和任务状态;
- 容器何时创建、暂停、复用和销毁;
- 用户数据、密钥与不同 Agent 的工作目录是否隔离;
- 模型生成的命令是否经过参数校验和权限策略;
- 监控是否能区分排队时间、冷启动时间与实际执行时间;
- 失败重试是否会重复执行带副作用的命令。
@cloudflare/computer 所代表的方向,不是简单地给 Agent 增加更多算力,而是为不同重量的任务选择合适的执行环境。对开发者而言,最重要的采用原则是:默认使用成本更低、权限更小的环境,只在能力确实不足时升级到完整 Linux 容器,并让每一次升级都能被解释和审计。