Project Think:在 Cloudflare 上构建下一代 AI agent
原文:Project Think: building the next generation of AI agents on Cloudflare / 2026-04-15 Source: https://blog.cloudflare.com/project-think/
今天,我们介绍 Project Think:Agents SDK 的下一代。Project Think 是一组用于构建长时运行 agent 的新原语(可靠执行、子 agent、沙箱化代码执行、持久会话),以及一个把它们全部接好的有主张基类。用这些原语精确构建你需要的东西,或者使用基类快速起步。
今年早些时候发生了一件事,改变了我们对 AI 的看法。像 Pi、OpenClaw、Claude Code 和 Codex 这样的工具,证明了一个简单但强大的想法:给 LLM 读文件、写代码、执行代码、记住所学的能力,你得到的就不再像一个开发者工具,而更像一个通用助手。
这些 coding agent 不再只是写代码。人们用它们管理日历、分析数据集、商谈采购、报税以及自动化整个业务流程。模式始终一样:agent 读取上下文、推理、写代码以采取行动、观察结果、迭代。代码是行动的通用媒介。
我们的团队每天都在使用这些 coding agent。我们一次次撞上同样的墙:
-
它们只跑在你的笔记本或一台昂贵的 VPS 上:没有共享、没有协作、没有设备间的接力。
-
闲置时也很贵:无论 agent 是否在工作,都是固定的月度成本。把它扩展到一个团队、一家公司,加起来就很快很多。
-
它们需要管理和手动设置:安装依赖、管理更新、配置身份和密钥。
还有一个更深的结构性问题。传统应用从一个实例服务多个用户。正如我们 Welcome to Agents Week 中提到的,agent 是一对一的。每个 agent 都是一个独特的实例,服务一个用户,运行一个任务。一个餐厅有菜单和一个为大批量出菜优化过的厨房;一个 agent 更像一位私人厨师:每次都用不同的食材、不同的技法、不同的工具。
这从根本上改变了规模化的算式。如果一亿知识工作者每人都使用一个 agent 助手,即便并发率不高,你也需要支撑数千万并发会话的容量。在当前每容器成本下,这是不可持续的。我们需要一个不同的地基。
这就是我们在构建的东西。
介绍 Project Think
Project Think 为 Agents SDK 推出一组新原语:
-
基于 fiber 的可靠执行:崩溃恢复、检查点、自动 keepalive
-
子 agent:拥有自己的 SQLite 和类型化 RPC 的隔离子 agent
-
持久会话:树状消息、分叉、压缩、全文检索
-
沙箱化代码执行:Dynamic Workers、codemode、运行时 npm 解析
-
执行阶梯:workspace、isolate、npm、browser、sandbox
-
自著扩展:在运行时给自己写工具的 agent
每一项都可以直接和 Agent 基类一起使用。用原语构建你恰好需要的东西,或使用 Think 基类快速起步。我们逐项看看每一个能做什么。
长时运行的 agent
Agent 在今天是 ephemeral 的。它们运行一个会话,绑定到单个进程或设备,然后就消失了。一个会因为你笔记本休眠就死掉的 coding agent,那是工具。一个能持续存在的 agent——能按需唤醒、在中断后继续工作、在不依赖你本地运行时的情况下保持状态——那开始看起来像基础设施了。这彻底改变了 agent 的规模化模型。
Agents SDK 构建在 Durable Objects 之上,给每个 agent 一个身份、持久状态以及消息触发的唤醒能力。这是 actor 模型:每个 agent 是一个可寻址的实体,带自己的 SQLite 数据库。休眠时消耗零计算。当事件发生(HTTP 请求、WebSocket 消息、定时 alarm、入站邮件),平台唤醒 agent、加载它的状态,把事件交给它。Agent 完成工作,然后回去睡觉。
| VM / 容器 | Durable Objects | |
|---|---|---|
| 闲置成本 | 永远是完整的计算成本 | 零(休眠) |
| 扩展 | 需要预置和管理容量 | 自动,按 agent |
| 状态 | 需要外部数据库 | 内建 SQLite |
| 恢复 | 你自己构建(进程管理器、健康检查) | 平台重启,状态保留 |
| 身份/路由 | 你自己构建(负载均衡、粘性会话) | 内建(name → agent) |
| 10,000 个 agent,每个活跃 1% 的时间 | 10,000 个常驻实例 | 任意时刻 ~100 个活跃 |
这改变了规模化运行 agent 的经济性。你不再受限于“每个高级用户一个昂贵的 agent“,而可以构建“每个客户一个 agent“或“每个任务一个 agent“或“每个邮件线程一个 agent“。新增一个 agent 的边际成本实际上是零。
撑过崩溃:基于 fiber 的可靠执行
一次 LLM 调用要 30 秒。一个多轮 agent 循环可以跑得更长。在那段时间里的任何一刻,执行环境都可能消失:一次部署、一次平台重启、命中资源限制。与模型 provider 的上游连接被永久切断、内存中状态丢失,连接的客户端看到流停止却没有任何解释。
runFiber() 解决这个问题。Fiber 是一个可靠的函数调用:执行开始前在 SQLite 中注册,可在任意点通过 stash() 设检查点,可在重启后通过 onFiberRecovered 恢复。
import { Agent } from "agents";
export class ResearchAgent extends Agent {
async startResearch(topic: string) {
void this.runFiber("research", async (ctx) => {
const findings = [];
for (let i = 0; i < 10; i++) {
const result = await this.callLLM(`Research step ${i}: ${topic}`);
findings.push(result);
// Checkpoint: if evicted, we resume from here
ctx.stash({ findings, step: i, topic });
this.broadcast({ type: "progress", step: i });
}
return { findings };
});
}
async onFiberRecovered(ctx) {
if (ctx.name === "research" && ctx.snapshot) {
const { topic } = ctx.snapshot;
await this.startResearch(topic);
}
}
}
SDK 在 fiber 执行期间自动让 agent 保持存活,无需特殊配置。对于以分钟计的工作,keepAlive() / keepAliveWhile() 防止活跃工作期间被驱逐。对于更长时间的操作(CI 流水线、设计评审、视频生成),agent 启动工作、持久化 job ID、休眠,并在回调时唤醒。
委派工作:通过 Facets 实现的子 agent
单个 agent 不该自己做所有事。子 agent 是通过 Facets 与父 agent 同地点的子 Durable Object,各自拥有独立的 SQLite 与执行上下文:
import { Agent } from "agents";
export class ResearchAgent extends Agent {
async search(query: string) { /* ... */ }
}
export class ReviewAgent extends Agent {
async analyze(query: string) { /* ... */ }
}
export class Orchestrator extends Agent {
async handleTask(task: string) {
const researcher = await this.subAgent(ResearchAgent, "research");
const reviewer = await this.subAgent(ReviewAgent, "review");
const [research, review] = await Promise.all([
researcher.search(task),
reviewer.analyze(task)
]);
return this.synthesize(research, review);
}
}
子 agent 在存储层面是隔离的。每个都有自己的 SQLite 数据库,它们之间没有隐式数据共享。这由运行时强制,子 agent RPC 延迟相当于一次函数调用。TypeScript 在编译期捕捉误用。
持久化的对话:Session API
跑数天或数周的 agent,需要的不只是典型的扁平消息列表。实验性的 Session API 显式建模了这一点。它在 Agent 基类上可用,对话以树形存储,每条消息都有一个 parent_id。这支持分叉(在不丢失原路径的情况下探索另一种走法)、非破坏性压缩(对旧消息做总结而不是删除)以及通过 FTS5 跨对话历史的全文检索。
import { Agent } from "agents";
import { Session, SessionManager } from "agents/experimental/memory/session";
export class MyAgent extends Agent {
sessions = SessionManager.create(this);
async onStart() {
const session = this.sessions.create("main");
const history = session.getHistory();
const forked = this.sessions.fork(session.id, messageId, "alternative-approach");
}
}
Session 可直接和 Agent 一起使用,也是 Think 基类所基于的存储层。
从工具调用到代码执行
传统的工具调用形态笨拙。模型调一个工具,把结果通过上下文窗口拉回来,再调一个工具,又拉回来,如此往复。随着工具表面增长,这既贵又笨。一百个文件意味着穿过模型一百个来回。
但 模型更擅长写代码使用一个系统,而不是玩工具调用游戏。这就是 @cloudflare/codemode 背后的洞察:LLM 不再做顺序工具调用,而是写一个程序处理整个任务。
// The LLM writes this. It runs in a sandboxed Dynamic Worker.
const files = await tools.find({ pattern: "**/*.ts" });
const results = [];
for (const file of files) {
const content = await tools.read({ path: file });
if (content.includes("TODO")) {
results.push({ file, todos: content.match(/\/\/ TODO:.*/g) });
}
}
return results;
不是 100 次到模型的来回,而只是跑一个程序。这导致使用更少 token、更快执行和更好结果。Cloudflare API MCP server 在规模上演示了这一点。我们只暴露两个工具(search() 和 execute()),消耗约 1,000 token,而朴素的“每 endpoint 一工具“等价物消耗约 117 万 token。这是 99.9% 的削减。
缺失的原语:安全的沙箱
一旦你接受模型应该代表用户写代码,问题就变成:这些代码在哪里跑?不是最终,不是等某个产品团队把它列入路线图,而是现在,为这个用户,针对这个系统,带着严格定义的权限。
Dynamic Workers 就是那个沙箱。一个在运行时拉起的全新 V8 isolate,毫秒级启动,占用几兆内存。这大约比一个容器快 100 倍,内存效率高 100 倍。你可以为每个请求启动一个新的、跑一段代码片段、然后扔掉。
关键的设计选择是能力模型(capability model)。Dynamic Workers 不是从一台通用机器开始再尝试约束它,而是从几乎没有任何环境权限开始(globalOutbound: null,无网络访问),开发者通过 binding 一个一个资源地显式授予能力。我们从问“如何阻止这东西做太多?“变成问“我们到底想让这东西能做什么?”
这正是 agent 基础设施该问的问题。
执行阶梯
这种能力模型自然带来一个计算环境的光谱——一个 agent 按需逐级升级的 执行阶梯:
Tier 0 是 Workspace,一个由 SQLite 和 R2 支撑的可靠虚拟文件系统。读、写、编辑、search、grep、diff。由 @cloudflare/shell 驱动。
Tier 1 是一个 Dynamic Worker:由 LLM 生成的 JavaScript,运行在没有网络访问的沙箱化 isolate 中。由 @cloudflare/codemode 驱动。
Tier 2 加上 npm。@cloudflare/worker-bundler 从 registry 拉包,用 esbuild 打包,把结果加载进 Dynamic Worker。Agent 写 import { z } from "zod",直接就能用。
Tier 3 是通过 Cloudflare Browser Run 的无头浏览器。导航、点击、抽取、截图。当服务还不通过 MCP 或 API 支持 agent 时有用。
Tier 4 是一个 Cloudflare Sandbox,配置了你的工具链、仓库和依赖:git clone、npm test、cargo build,与 Workspace 双向同步。
关键设计原则:agent 应在 Tier 0 单独使用时就已经有用,后续每一层是叠加的。 用户可以一边走一边添加能力。
构件,不是框架
所有这些原语都以独立包形式提供。Dynamic Workers、@cloudflare/codemode、@cloudflare/worker-bundler 和 @cloudflare/shell(一个带工具的可靠文件系统)都可以直接和 Agent 基类一起使用。你可以把它们组合起来,给任何 agent 一个工作区、代码执行和运行时包解析,而不必采纳一个有主张的框架。
平台
下面是构建 Cloudflare 上 agent 的完整栈:
| 能力 | 它做什么 | 由什么支撑 |
|---|---|---|
| 按 agent 隔离 | 每个 agent 是自己的世界 | Durable Objects(DO) |
| 闲置零成本 | agent 唤醒前 $0 | DO Hibernation |
| 持久状态 | 可查询、事务性存储 | DO SQLite |
| 可靠文件系统 | 重启后保留的文件 | Workspace(SQLite + R2) |
| 沙箱化代码执行 | 安全运行 LLM 生成的代码 | Dynamic Workers + @cloudflare/codemode |
| 运行时依赖 | import * from react 直接可用 | @cloudflare/worker-bundler |
| Web 自动化 | 浏览、导航、填表 | Browser Run |
| 完整 OS 访问 | git、编译器、test runner | Sandboxes |
| 定时执行 | 主动而非仅被动 | DO Alarms + Fibers |
| 实时流式输出 | 逐 token 推送到任意客户端 | WebSockets |
| 外部工具 | 连接任意工具 server | MCP |
| Agent 协作 | agent 间的类型化 RPC | 子 agent(Facets) |
| 模型访问 | 接入 LLM 驱动 agent | AI Gateway + Workers AI(或 BYOM) |
每一项都是一个构件。合起来,它们形成一个新东西:一个让任何人都能构建、部署并运行 AI agent 的平台,这些 agent 与今天跑在你本地机器上的同样有能力,但是 serverless 的、可靠的、构造上安全的。
Think 基类
现在你看过原语了,这里看看把它们都接好之后会发生什么。
Think 是一个有主张的脚手架,处理完整的 chat 生命周期:agentic 循环、消息持久化、流式输出、工具执行、流恢复和扩展。你专注于让你的 agent 与众不同的部分。
最小子类长这样:
import { Think } from "@cloudflare/think";
import { createWorkersAI } from "workers-ai-provider";
export class MyAgent extends Think<Env> {
getModel() {
return createWorkersAI({ binding: this.env.AI })(
"@cf/moonshotai/kimi-k2.5"
);
}
}
这就是你拥有一个能用的 chat agent 所需的全部:流式、持久化、abort/cancel、错误处理、可恢复流和内建的工作区文件系统。用 npx wrangler deploy 部署。
Think 替你做出决定。当你需要更多控制时,可以覆盖你关心的项:
| 覆盖 | 目的 |
|---|---|
getModel() | 返回要用的 LanguageModel |
getSystemPrompt() | 系统 prompt |
getTools() | agentic 循环用的、与 AI SDK 兼容的 ToolSet |
maxSteps | 每轮的最大工具调用回合数 |
configureSession() | 上下文块、压缩、搜索、skill |
底层,Think 在每一轮都跑完整的 agentic 循环:它装配上下文(基础指令 + 工具描述 + skill + 记忆 + 对话历史),调用 streamText,执行工具调用(对输出做截断以防上下文爆炸),追加结果,循环直到模型完成或达到步数上限。每轮之后所有消息都会被持久化。
生命周期 hook
Think 在 chat 一轮的每个阶段给你 hook,而不要求你拥有整条流水线:
beforeTurn()
→ streamText()
→ beforeToolCall()
→ afterToolCall()
→ onStepFinish()
→ onChatResponse()
切换到更便宜的模型做后续轮、限制它能用的工具、在每轮传入客户端侧上下文。也可以记录每次工具调用到分析、并在模型完成后自动触发一轮额外的后续——所有这些都不必替换 onChatMessage。
持久记忆与长对话
Think 把 Session API 作为存储层,提供内建分支的树状消息。
在此之上,它通过 context blocks 添加持久记忆。这些是系统 prompt 的结构化片段,模型可以随时间读取和更新,并跨休眠保留。模型看到 “MEMORY (Important facts, use set_context to update) [42%, 462/1100 tokens]”,可以主动记住事情。
configureSession(session: Session) {
return session
.withContext("soul", {
provider: { get: async () => "You are a helpful coding assistant." }
})
.withContext("memory", {
description: "Important facts learned during conversation.",
maxTokens: 2000
})
.withCachedPrompt();
}
会话很灵活。你可以为每个 agent 跑多个对话,并对它们进行分叉以尝试不同的方向而不丢失原本的。
随着上下文增长,Think 用非破坏性压缩处理上限。旧消息被总结而非移除,完整历史仍存放在 SQLite 中。
搜索也是内建的。借助 FTS5,你可以在一个会话内或跨所有会话查询对话历史。Agent 也能通过 search_context 工具搜索自己的过去。
接好整条执行阶梯
Think 在一个 getTools() 返回中集成了整条执行阶梯:
import { Think } from "@cloudflare/think";
import { createWorkspaceTools } from "@cloudflare/think/tools/workspace";
import { createExecuteTool } from "@cloudflare/think/tools/execute";
import { createBrowserTools } from "@cloudflare/think/tools/browser";
import { createSandboxTools } from "@cloudflare/think/tools/sandbox";
import { createExtensionTools } from "@cloudflare/think/tools/extensions";
export class MyAgent extends Think<Env> {
extensionLoader = this.env.LOADER;
getModel() {
/* ... */
}
getTools() {
return {
execute: createExecuteTool({
tools: createWorkspaceTools(this.workspace),
loader: this.env.LOADER
}),
...createBrowserTools(this.env.BROWSER),
...createSandboxTools(this.env.SANDBOX), // configured per-agent: toolchains, repos, snapshots
...createExtensionTools({ manager: this.extensionManager! }),
...this.extensionManager!.getTools()
};
}
}
自著扩展
Think 把代码执行又往前推了一步。Agent 可以编写自己的扩展:在 Dynamic Workers 中运行的 TypeScript 程序,声明对网络访问和工作区操作的权限。
{
"name": "github",
"description": "GitHub integration: PRs, issues, repos",
"tools": ["create_pr", "list_issues", "review_pr"],
"permissions": {
"network": ["api.github.com"],
"workspace": "read-write"
}
}
Think 的 ExtensionManager 打包扩展(可选地通过 @cloudflare/worker-bundler 包含 npm 依赖),把它加载进 Dynamic Worker,并注册新工具。扩展持久存放在 DO 存储中,跨休眠保留。下次用户问到 pull request 时,agent 已经有了一个 github_create_pr 工具——30 秒前它还不存在。
这就是让 agent 随时间真正变得更有用的那种自我改进循环。不是通过微调或 RLHF,而是通过代码。Agent 能给自己写新能力,全部在沙箱化、可审计、可撤销的 TypeScript 中。
子 agent RPC
Think 也作为子 agent 工作,通过父级的 RPC 调用 chat(),通过回调接收流式事件:
const researcher = await this.subAgent(ResearchSession, "research");
const result = await researcher.chat(`Research this: ${task}`, streamRelay);
每个子级有自己的对话树、记忆、工具和模型。父级不需要知道细节。
开始
Project Think 是实验性的。API 表面是稳定的,但会在接下来的日子和几周里继续演化。我们已经在内部用它构建自己的后台 agent 基础设施,我们提前分享出来,以便你可以与我们并肩构建。
npm install @cloudflare/think agents ai @cloudflare/shell zod workers-ai-provider
// src/server.ts
import { Think } from "@cloudflare/think";
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";
export class MyAgent extends Think<Env> {
getModel() {
return createWorkersAI({ binding: this.env.AI })(
"@cf/moonshotai/kimi-k2.5"
);
}
}
export default {
async fetch(request: Request, env: Env) {
return (
(await routeAgentRequest(request, env)) ||
new Response("Not found", { status: 404 })
);
}
} satisfies ExportedHandler<Env>;
// src/client.tsx
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";
function Chat() {
const agent = useAgent({ agent: "MyAgent" });
const { messages, sendMessage, status } = useAgentChat({ agent });
// Render your chat UI
}
Think 说的是与 @cloudflare/ai-chat 同一套 WebSocket 协议,所以现有 UI 组件开箱即用。如果你已经在 AIChatAgent 上构建,你的客户端代码不需要改动。
第三波
我们看到 AI agent 的三波:
第一波是聊天机器人。 它们无状态、被动、脆弱。每次对话都从零开始,没有记忆、没有工具、没有行动能力。这让它们对回答问题有用,但也只能回答问题。
第二波是 coding agent。 这些是有状态的、用工具的、能力强得多的工具,如 Pi、Claude Code、OpenClaw 和 Codex。这些 agent 能读代码库、写代码、执行并迭代。它们证明了一个有合适工具的 LLM 是一台通用机器,但它们跑在你的笔记本上,服务一个用户,没有可靠性保证。
现在我们正进入第三波:agent 作为基础设施。 持久、分布式、结构上安全、serverless。这些是跑在互联网上、能挺过故障、闲置时不花钱、通过架构而非行为强制安全的 agent。任何开发者都能构建并部署给任意数量用户的 agent。
这是我们押注的方向。
Agents SDK 已经在驱动数千个生产 agent。借助 Project Think 及其引入的原语,我们正补齐让这些 agent 戏剧性更有能力的缺失部分:持久工作区、沙箱化代码执行、可靠的长时运行任务、结构性安全、子 agent 协作和自著扩展。
它今天以 preview 形式可用。我们与你一起构建,我们真心想看看你(和你的 coding agent)用它创造什么。
Think 是 Cloudflare Agents SDK 的一部分,以 @cloudflare/think 形式提供。本文描述的功能处于 preview 阶段。API 可能在我们吸收反馈时变化。请查看 文档 和 示例 开始。
– 原文译于 2026-04-30