今天,我们隆重推出 Project Think:也就是新一代 Agents SDK。Project Think 为构建长时间运行的智能体提供一套新原语,包括持久化执行、子智能体、沙箱代码执行和持续会话,以及将这些基础组件集成在一起的有明确设计理念的基类。可以利用这些原语准确构建所需功能,也可以使用基类快速入门。
今年年初发生的一件事改变了我们对 AI 的认知。Pi、OpenClaw、Claude Code 和 Codex 等工具证明了一个简单而强大的理念:赋予 LLM 如下四项能力:读取文件、编写代码、执行代码、记住所学知识,用户就能得到看起来更像是通用助手的工具,而不是开发人员工具。
这些编码智能体的功能不再局限于编写代码。人们使用它们来管理日历、分析数据集、洽谈采购合同、提交税务申报,以及自动化整个业务工作流程。运行模式始终相同:智能体读取上下文,对上下文进行推理,编写代码来执行操作,观察结果,然后迭代。代码是智能体将意图转化为行动的通用媒介。
Cloudflare 团队每天都在使用这些编码智能体。而且我们不断遇到同样的难题:
它们只能在笔记本电脑或昂贵的 VPS 上运行:无法共享、协作,也无法在不同设备之间切换。
闲置成本较高:无论智能体是否工作,需要支付固定的月费。如果扩展到团队或全公司,闲置成本迅速增加。
需要管理和手动设置:安装依赖项、管理更新、配置身份和密钥。
此外,还有更深层次的结构性问题。传统应用通过单个实例为许多用户提供服务。正如我们在“欢迎参加 Agents Week”博客文章中提到的,智能体是一对一服务。每个智能体都是一个独立实例,服务一个用户,运行一项任务。餐馆有菜单和优化的厨房,可以高效批量出餐。智能体更像是私人厨师:每次使用的食材、烹饪技巧和工具都各不相同。
这从根本上改变了扩展的计算方式。如果一亿知识工作者每人使用一个智能助手,则即使并发率适中,也需要足够支持数千万个并发会话的容量。按照目前每个容器的成本,这种方法难以为继。我们需要不同的基础架构。
这正是 Cloudflare 一直在努力构建的解决方案。
Project Think 为 Agents SDK 提供一套新原语:
持久化执行(使用纤程):崩溃恢复、检查点、自动确保持续存在
子智能体:隔离的子智能体,具有各自的 SQLite 数据库和类型化 RPC
持续会话:树状结构信息、分叉、压缩、全文检索
沙箱代码执行:Dynamic Workers、codemode 执行模式、runtime npm 解析
执行层级:工作区、隔离区、npm、浏览器、沙箱
自主编写扩展:在运行时自主编写工具的智能体
这些基础组件均可直接与 Agent 基类搭配使用。可以利用这些原语准确构建所需功能,也可以使用 Think 基类快速入门。接下来,我们将逐一介绍它们的作用。
目前存在的智能体都是短暂运行。它们只在单个会话期间运行,绑定到单个进程或设备,随后便终止。在笔记本电脑进入睡眠模式后即终止的编码智能体,只能算是一个工具。而一个持久运行的智能体(可以按需唤醒,在中断后继续工作,且不依赖本地运行时即可保持状态)则更像是基础设施。并且它会彻底改变智能体的扩展模式。
Agents SDK 基于 Durable Objects 构建,为每个智能体赋予身份、持续状态以及收到消息时唤醒的功能。这就是 actor 模型:每个智能体都是可寻址的实体,且拥有自己的 SQLite 数据库。当它处于休眠状态时,不会消耗任何计算资源。如果发生了某件事(HTTP 请求、WebSocket 消息、计划的警报、入站电子邮件),平台会唤醒智能体,加载其状态,并将事件传递给它。智能体完成其工作,然后再次进入休眠状态。
| 虚拟机/容器 | Durable Objects |
|---|
闲置成本 | 始终收取计算成本 | 零(休眠) |
扩展 | 配置和管理容量 | 全自动、按智能体 |
状态 | 需要外部数据库 | 内置 SQLite 数据库 |
恢复 | 自行构建(进程管理器、运行状况检查) | 平台重启,状态保留 |
身份/路由 | 自行构建(负载均衡器、粘性会话) | 内置(名称 → 智能体) |
10000 个智能体,每个处理活跃状态的时间占 1% | 10000 个始终在线的实例 | 约 100 个随时活跃的实例 |
这将改变大规模运行智能体的成本。您可以构建“每个客户一个智能体”、“每个任务一个智能体”或“每个电子邮件线程一个智能体”,而不是构建“每个高级用户一个昂贵的智能体”。创建新智能体的边际成本几乎为零。
一个 LLM 调用需要耗费 30 秒。多回合智能体的运行时间可能更长。在此期间,执行环境可能会消失:例如一次部署、平台重启或达到资源限制,与模型提供商的上游连接被永久断开,内存状态丢失,以及连接的客户端发现数据流被无故中断。
runFiber() 可以解决这个问题。纤程是一种持久化函数调用实例:执行前先在 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 会自动维持智能体处于活动状态,无需任何特殊配置。对于以分钟为单位的工作,keepAlive()/keepAliveWhile() 可防止在执行任务期间被清理。对于耗时更长的操作(例如 CI 管道、设计评审、视频生成),智能体会启动工作、持久化作业 ID、进入休眠状态,以及在回调时唤醒。
单一智能体不应包揽所有工作。子智能体是通过 Facets 与父智能体在同一物理/虚拟节点上运行的子 Durable Objects,每个子智能体都有各自独立的 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);
}
}
子智能体在存储层面彼此隔离。每个子智能体都有自己的 SQLite 数据库,它们之间不存在隐式数据共享。运行时会强制执行这一隔离规则,其中子智能体 RPC 延迟是一个函数调用。TypeScript 在编译时会发现误用行为。
运行数日或数周的智能体,需要比典型的扁平消息列表更丰富的存储方式。实验性 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 基类构建的存储层。
传统工具的调用方式非常繁琐。模型调用一个工具,通过上下文窗口拉取结果;随后调用另一个工具,以同样的方式再次拉取结果,如此循环往复。随着工具数量的增加,这种做法既耗时又笨拙。100 个文件意味着需要经过模型完成 100 次往返通信。
但是,模型更擅长编写代码以调用系统的代码,而不是进行繁琐的工具调用。这正是 @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 次往返通信,只需运行单个程序即可。这可以减少词元使用量,加快执行速度,以及改善结果。Cloudflare API MCP 服务器在规模上证明了这一点。我们只暴露两个通用工具(search() 和 execute()),它们消耗了大约 1000 个词元,而天真的“一个端点一个工具”方法则消耗将近 117 万个词元。这相当于词元使用量减少了 99.9%。
接受模型应该代表用户编写代码这一理念后,接着面临的问题就是:这些代码在哪里运行?不是最终,也不是等候产品团队将其纳入路线图。而是现在,针对当前用户,针对当前系统,且拥有严格定义的权限。
Dynamic Workers 就是那种安全沙箱。它会在运行时在数毫秒内启动一个全新的 V8 隔离区,仅占用几兆字节内存。与容器相比,启动速度大约加快 100 倍,内存效率也至多提高 100 倍。您可以为每个请求启动一个新隔离区,运行一段代码,然后将其丢弃。
关键的设计选择是能力模型。Dynamic Workers 并非从通用机器开始并试尝试对其限制,而是开始时几乎没有任何环境权限(globalOutbound: null,没有网络访问权限),开发人员通过绑定,逐个资源地明确授予其访问特定能力的权限。我们思考的问题从“如何阻止模型生成过多内容?”变成“我们希望模型能够做到什么?”。
关于智能体基础设施,这才是合适的问题。
这种能力模型自然而然地引出了一系列计算环境,也就是执行层级,智能体根据需要在这些计算环境中逐步提升权限:
第 0 级是工作区,它是由 SQLite 和 R2 提供支持的持久化虚拟文件系统。可执行读取、写入、编辑、搜索、grep、diff 操作。由 @cloudflare/shell 提供支持。
第 1 级是 Dynamic Worker:由 LLM 生成的 JavaScript 在沙箱隔离环境中运行,没有网络访问权限。由 @cloudflare/codemode 提供支持。
第 2 级添加了 npm。@cloudflare/worker-bundler 从注册表中获取软件包,使用 esbuild 对其进行打包,然后将结果加载到 Dynamic Worker 中。智能体只需写入 import { z } from “zod” 即可正常运行。
第 3 级是通过 Cloudflare Browser Run 提供的无头浏览器。可执行导航、点击、提取、截屏操作。当服务尚不支持通过 MCP 或 API 使用智能体时,这个层级非常有用。
第 4 级是 Cloudflare 沙箱,其中配置了用户自定义的工具链、代码存储库和依赖项:git clone、npm test、cargo build,与工作区双向同步。
关键设计原则:智能体应仅在第 0 级有用处,每一级的权限逐步添加。用户可以根据需要随时添加功能。
所有这些基础组件都以独立包的形式提供。Dynamic Workers、@cloudflare/codemode、@cloudflare/worker-bundler 和 @cloudflare/shell(包含工具的持久化文件系统)均可直接与 Agent 基类搭配使用。您可以组合利用它们,为智能体提供工作区、代码执行和运行时包解析功能,而无需采用任何预设框架。
以下是在 Cloudflare 上构建智能体的完整技术栈:
这些都是构建块。它们共同构成一个全新的平台:可供任何用户构建、部署和运行 AI 智能体,其功能与目前在本地计算机上运行的智能体一样强大,但从设计上来说,它具有无服务器、持久和安全的特性。
现在您已了解这些基础组件,接下来我们将介绍如何将它们集成在一起。
Think 是一个具有明确设计理念的框架,它负责处理完整的聊天生命周期:智能体逻辑循环、消息持久化、流式传输、工具执行、流恢复以及扩展。您只需聚焦智能体的核心功能。
最小子类如下所示:
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"
);
}
}
如此一来,您便可以轻松创建一个工作聊天智能体,它具有流式传输、持久化、中止/取消、错误处理、可恢复的工作流,以及内置工作区文件系统。使用 npx wrangler deploy 进行部署。
Think 会为您做出决策。如果您需要加强控制,则可以覆盖自己关注的各项决策:
覆盖 | 目的 |
getModel()
| 返回要使用的 LanguageModel |
getSystemPrompt()
| 系统提示词 |
getTools()
| 兼容 AI SDK 的 ToolSet,以支持智能体逻辑循环 |
maxSteps
| 单个对话轮次的最大工具调用次数 |
configureSession()
| 上下文块、压缩、搜索、技能 |
其实从底层机制来说,Think 在每个轮次执行完整的智能体逻辑循环:组装上下文(基本指令 + 工具描述 + 技能 + 内存 + 对话历史记录),调用 streamText,执行工具调用(使用输出截断以防止上下文膨胀),附加结果,然后循环直到模型完成或达到步数限制。每个轮次结束后,所有消息会被持久化。
Think 为用户在对话轮次的每个阶段提供 hook 接口,而无须拥有整个管道:
beforeTurn()
→ streamText()
→ beforeToolCall()
→ afterToolCall()
→ onStepFinish()
→ onChatResponse()
切换到成本更低的模型来处理后续轮次,限制其可以使用的工具,以及在每个轮次对话中传递客户端上下文。此外,将每个工具调用记录到分析,并在模型完成后自动触发一个后续轮次,所有这些都无需替换 onChatMessage 函数。
Think 以 Session API 作为其存储层而构建,提供内置分支的树状结构化消息。
除此之外,它还通过上下文块添加持久性内存。这些是系统提示词的结构化部分,可供模型读取并随时间更新,且在休眠后仍然保留。模型会看到“MEMORY(重要信息,请使用 set_context 进行更新)[42%,462/1100 个词元]”,且可以主动记住信息。
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();
}
会话非常灵活。每个智能体可以运行多个对话,并且可以分叉这些对话以尝试不同的方向,而不会丢失原始对话。
随着上下文的增加,Think 会使用非破坏性压缩方法来解决限制。总结较早的消息而不是删除,同时完整的历史记录仍然存储在 SQLite 中。
还内置了搜索功能。使用 FTS5,可以查询会话内或所有会话的对话历史记录。智能体还能够利用 search_context 工具,搜索自己的历史记录。
将完整的执行层级集成到单个 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 将代码执行功能提升到全新的层次。智能体可以编写自己的扩展:在 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 存储中,并且在休眠后仍然有效。用户下次询问拉取请求时,智能体会拥有一个 30 秒前尚不存在的 github_create_pr 工具。
这种自我改进的循环,让 AI 智能体随着时间的推移变得越来越实用。不是通过微调或 RLHF,而是通过代码本身实现改进。智能体能够自行编写新功能,所有代码均采用沙盒化、可审核且可撤销的 TypeScript 编写。
Think 也可以充当子智能体,由父智能体通过 RPC 发起 chat() 调用,通过回调函数接收流式传输事件:
const researcher = await this.subAgent(ResearchSession, "research");
const result = await researcher.chat(`Research this: ${task}`, streamRelay);
每个子智能体都拥有自己的对话树、记忆、工具和模型。父智能体无需了解具体细节。
Project Think 目前处于实验阶段。虽然 API 接口稳定,但会在未来几天和几周内持续改进。Cloudflare 内部已将其用于构建自己的后台智能体基础设施,现在提前发布,便于用户可以与我们一起开发。
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 智能体发展的三个时期:
第一个时期主要是聊天机器人。它们无状态、被动响应且比较脆弱。每次对话都是从头开始,没有记忆、没有工具,也无法执行任何操作。这让它们能够回答问题,但也将它们的功能限制在只能回答问题。
第二个时期是编码智能体。它们有状态、会使用工具,且功能远比聊天机器人更强大,例如 Pi、Claude Code、OpenClaw 和 Codex。这些智能体可以读取代码库、编写代码、执行代码并进行迭代。这证明,配备适当工具的 LLM 可以成为一台通用计算机,但它们只能在笔记本电脑上运行,供单个用户使用,且无法保证持久性。
如今,我们进入到第三个时期:智能体作为基础设施。它们具备持久化、分布式、结构安全、无服务器的特点。这些智能体运行在互联网上,经历故障后仍可运行,闲置时不产生任何成本,并通过架构而非行为来确保安全性。任何开发人员均可构建并部署智能体,服务于任意数量的用户。
这是我们看好的发展方向。
目前,Agents SDK 已为数千个生产环境智能体提供支持。凭借 Project Think 及其引入的基础组件,我们将添加缺失的组件,从而显著提高这些智能体的功能:持久工作区、沙箱代码执行、持久的长时间运行任务、结构化安全性、子智能体协调,以及自主编写扩展。
现已推出预览版。我们将与您一同构建,并真切地期待看到您(以及您的编码智能体)使用它来创作哪些精彩的作品。
Think 是 Cloudflare Agents SDK 的一部分,提供 @cloudflare/think 供选择。本博客文章所述的这些功能处于预览阶段。我们会根据用户反馈,不断改进 API。请查看文档和示例,开始使用。