☰
Cloudflare Agents SDK 开发实战:基于 Durable Objects 构建有状态 AI Agent 的完整 API 指南
2026/10/10 1:46:38 网站建设 项目流程

【免费下载链接】autoskills

One command. Your entire AI skill stack. Installed.

项目地址:https://gitcode.com/gh_mirrors/au/autoskills
点击查看免费下载

本篇技术指南以 Cloudflare Agents SDK API 参考 为核心,系统讲解如何在 Cloudflare Workers 上用 Durable Objects 构建具备持久状态、实时 WebSocket、SQLite 存储、定时调度与 AI 能力的智能体。读完本文你将掌握AIChatAgent与Agent两大核心类的全部生命周期钩子、setState状态同步、@callableRPC 调用、MCP 工具集成、任务队列调度,以及配套的 React 客户端钩子,可直接落地聊天机器人、实时协作、邮件处理与后台任务等场景。

一、SDK 概览:两条构建路径怎么选

Agents SDK 的价值在于:把 Durable Objects 的强一致状态、WebSocket 长连接、SQLite 存储、定时任务与 Workers AI 推理能力封装为一套面向 AI 智能体的编程模型,让你"一次编写、全球分布、持久记忆"。从本仓库的 README 可以看到,它内置两套从属类,对应两类典型需求:

使用场景基类关键能力
AI 聊天界面AIChatAgent自动流式输出、工具调用、自动管理的消息历史、断线续传
MCP 工具提供方Agent+ MCP向 AI 系统暴露工具
自定义逻辑/路由Agent完全控制:WebSocket、Email、SQL
实时协作AgentWebSocket 状态同步、广播
邮件处理AgentonEmail()处理器

包入口方面,服务端使用agents包(Agent 类与生命周期),前端分别使用agents/react(useAgentWebSocket 钩子)与agents/ai-react(useAgentChat聊天 UI 钩子)。安装依赖时,基础 Agent 只需npm install agents,聊天型 Agent 还需npm install @cloudflare/ai-chat ai @ai-sdk/react。

二、AIChatAgent:开箱即用的 AI 聊天智能体

对于绝大多数"对话 + 工具"场景,AIChatAgent是最快路径。它内置自动流式输出(auto-streaming)、消息历史管理、工具调用与可续传流(resumable streaming),你只需要重写一个onChatMessage钩子:

import { AIChatAgent } from "@cloudflare/ai-chat"; import { openai } from "@ai-sdk/openai"; export class ChatAgent extends AIChatAgent<Env> { async onChatMessage(onFinish) { return this.streamText({ model: openai("gpt-4"), messages: this.messages, // Auto-managed message history tools: { getWeather: { description: "Get weather", parameters: z.object({ city: z.string() }), execute: async ({ city }) => `Sunny, 72°F in ${city}` } }, onFinish, // Persist response to this.messages }); } }

几点关键说明:

  • this.messages由框架自动管理:用户消息与模型回复(经onFinish回调)都会自动持久化,无需手动维护数组;
  • streamText返回流式响应,配合AIChatAgent实现"断线后自动续传"——参考 gotchas.md 中"Resumable stream not resuming"条目,续传要求流 ID 确定,而AIChatAgent会自动处理,无需你关心;
  • 消息历史是无限累积的,gotchas.md 明确建议在onChatMessage中定期裁剪,例如只保留最近 50 条,避免 token 超限。

三、Agent 基类与生命周期钩子

当需要完全掌控连接、邮件、SQL 或自定义协议时,使用基础Agent类。它的泛型签名是Agent<Env, State, ConnState>,三个类型参数分别约束环境绑定、智能体状态与单个连接状态:

import { Agent } from "agents"; export class MyAgent extends Agent<Env, State> { // Lifecycle methods below }

onStart:初始化与重启

onStart()在智能体首次创建或(Durable Object 休眠后)重启时执行,适合建表、注册 MCP 服务等一次性初始化:

onStart() { // Init/restart this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT, name TEXT)`; }

onRequest:HTTP 请求入口

async onRequest(req: Request) { // HTTP const {pathname} = new URL(req.url); if (pathname === "/users") return Response.json(this.sql<{id,name}>`SELECT * FROM users`); return new Response("Not found", {status: 404}); }

sql标签模板返回的是参数化查询结果,配合泛型<{id,name}>可得到类型安全的结果集。

onConnect / onMessage:WebSocket 生命周期

async onConnect(conn: Connection<ConnState>, ctx: ConnectionContext) { // WebSocket conn.accept(); conn.setState({userId: ctx.request.headers.get("X-User-ID")}); conn.send(JSON.stringify({type: "connected", state: this.state})); } async onMessage(conn: Connection<ConnState>, msg: WSMessage) { // WS messages const m = JSON.parse(msg as string); this.setState({messages: [...this.state.messages, m]}); this.connections.forEach(c => c.send(JSON.stringify(m))); }

注意conn.accept()是必须的第一步——gotchas.md 将"未调用 accept 导致 WebSocket 超时"列为常见错误。conn.setState只影响单个连接的conn.state,而this.setState影响所有客户端可见的共享状态;this.connections是当前所有活跃连接的集合,天然支持广播。

onEmail:邮件路由

async onEmail(email: AgentEmail) { // Email routing this.sql`INSERT INTO emails (from_addr,subject,body) VALUES (${email.from},${email.headers.get("subject")},${await email.text()})`; }

四、State、SQL 与调度:有状态智能体的三大支柱

状态管理:setState 自动同步

状态基于 SQLite 持久化,setState会自动同步到所有已连接的客户端:

// State this.setState({count: 42}); // Auto-syncs this.setState({...this.state, count: this.state.count + 1});

gotchas.md 反复强调一个反模式:绝不能直接修改this.state.count++,必须用不可变更新this.setState({...this.state, count: this.state.count + 1}),否则状态不会同步。同时建议:大块数据(日志、大列表)存入 SQL 而非 state;无界数组(消息、日志)要周期性裁剪。

SQL:参数化查询防注入

// SQL (parameterized queries prevent injection) this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT)`; this.sql`INSERT INTO users (id,name) VALUES (${userId},${name})`; const users = this.sql<{id,name}>`SELECT * FROM users WHERE id = ${userId}`;

注意${userId}是占位符参数,不是字符串插值——写成sql`...WHERE id = '${userId}'`就是 SQL 注入漏洞(见 gotchas.md)。建表应放在onStart()而非onRequest(),避免每个请求都重复执行 DDL。

调度:一次性、延时与 Cron

// Scheduling await this.schedule(new Date("2026-12-25"), "sendGreeting", {msg:"Hi"}); // Date await this.schedule(60, "checkStatus", {}); // Delay (sec) await this.schedule("0 0 * * *", "dailyCleanup", {}); // Cron await this.cancelSchedule(scheduleId);

schedule支持三种触发方式:绝对时间(Date)、相对延时(秒)、标准 cron 表达式。配套的getSchedules()可枚举已注册任务,用于监控配额(每个智能体最多 1000 个定时任务,见 gotchas.md 的限额表)。

五、@callable RPC:跨 WebSocket 的远程方法调用

用@callable()装饰器声明的方法会被暴露为可通过 WebSocket 调用的 RPC,客户端拿到的是普通的 async 方法:

import { Agent, callable } from "agents"; export class MyAgent extends Agent<Env> { @callable() async processTask(input: {text: string}): Promise<{result: string}> { return { result: await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt: input.text}) }; } } // Client: const result = await agent.processTask({ text: "Hello" }); // Must return JSON-serializable values

两个硬性约束:

  1. 返回值必须可 JSON 序列化——gotchas.md 举例说明返回new Date()这类对象会失败,应返回{ timestamp: Date.now() };
  2. 不要开启 tsconfig 的experimentalDecorators——独立 skill agents-sdk/SKILL.md 明确警告这会破坏@callable解析。

六、连接管理与 Workers AI 集成

连接对象操作

// Connections (type: Agent<Env, State, ConnState>) this.connections.forEach(c => c.send(JSON.stringify(msg))); // Broadcast conn.setState({userId:"123"}); conn.close(1000, "Goodbye");

泛型第三个参数ConnState直接类型化conn.state,让每个连接携带独立的元数据(如用户 ID、玩家 ID)。

Workers AI 推理与手动流式

// Workers AI const r = await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt}); // Manual streaming (prefer AIChatAgent) const stream = await client.chat.completions.create({model: "gpt-4", messages, stream: true}); for await (const chunk of stream) conn.send(JSON.stringify({chunk: chunk.choices[0].delta.content}));

官方建议:聊天场景优先AIChatAgent(自动流式、自动续传),手动流式仅用于自定义协议。AI 调用建议包 try/catch 并准备降级方案(gotchas.md 的 "AI Gateway unavailable" 条目)。

七、MCP 集成:把外部工具暴露给 LLM

Agents SDK 内置 Model Context Protocol(MCP)客户端,注册远程 MCP 服务器后,其工具会转换为 AI SDK 工具直接传给模型:

// Register & use MCP server await this.mcp.registerServer("github", { url: env.MCP_SERVER_URL, auth: { type: "oauth", clientId: env.GITHUB_CLIENT_ID, clientSecret: env.GITHUB_CLIENT_SECRET } }); const tools = await this.mcp.getAITools(["github"]); return this.streamText({ model: openai("gpt-4"), messages: this.messages, tools, onFinish });

配套配置见 configuration.md:OAuth 密钥通过wrangler secret put GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET注入,服务器 URL 通过wrangler.jsonc的vars.MCP_SERVER_URL配置。一个关键坑是MCP 连接不跨休眠存活——应在onStart()中重新注册服务器(见 gotchas.md)。

八、任务队列与清理钩子

内置 FIFO 队列

await this.queue("processVideo", { videoId: "abc123" }); // Add task const tasks = await this.dequeue(10); // Process up to 10

queue()入队、dequeue()批量取出消费,适合与调度配合实现"定时批量处理"(参考 patterns.md 的 TaskQueue 模式:每 5 分钟 cron 调度processQueue,逐个dequeue(10)处理视频转码等长任务)。

上下文与销毁

const agent = getCurrentAgent<MyAgent>(); // Get current instance async destroy() { /* cleanup before agent destroyed */ }

getCurrentAgent用于在任意位置取回当前智能体实例;destroy()在智能体销毁前执行资源清理。

九、React 客户端钩子

useAgent:WebSocket + RPC

// useAgent() - WebSocket connection + RPC import { useAgent } from "agents/react"; const agent = useAgent({ agent: "MyAgent", name: "user-123" }); // name for idFromName const result = await agent.processTask({ text: "Hello" }); // Call @callable methods // agent.readyState: 0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED

name参数对应 Durable Object 的idFromName,实现"同一用户永远路由到同一实例"的确定性寻址。

useAgentChat:完整聊天 UI

// useAgentChat() - AI chat UI import { useAgentChat } from "@cloudflare/ai-chat/react"; const agent = useAgent({ agent: "ChatAgent" }); const { messages, input, handleInputChange, handleSubmit, isLoading, stop, clearHistory } = useAgentChat({ agent, maxSteps: 5, // Max tool iterations resume: true, // Auto-resume on disconnect onToolCall: async (toolCall) => { // Client tools (human-in-the-loop) if (toolCall.toolName === "confirm") return { ok: window.confirm("Proceed?") }; } }); // status: "ready" | "submitted" | "streaming" | "error"

参数语义:maxSteps限制单轮对话中工具循环的最大迭代次数;resume: true在断线后自动恢复流式输出;onToolCall实现人在回路(human-in-the-loop)——服务端把工具execute标记为"client"(见 patterns.md 的 Human-in-the-Loop 模式),客户端通过window.confirm等交互代为执行,把需要人工确认的动作(如扣款、发邮件)留在用户侧。

十、工程化配置与部署

Wrangler 配置

无论是基础 Agent 还是 ChatAgent,wrangler.jsonc都需要声明 Durable Object 绑定与 SQLite 迁移:

{ "name": "my-agents-app", "durable_objects": { "bindings": [ {"name": "MyAgent", "class_name": "MyAgent"} ] }, "migrations": [ {"tag": "v1", "new_sqlite_classes": ["MyAgent"]} ], "ai": { "binding": "AI" } }

来自独立 skill agents-sdk/SKILL.md 的三条硬性提醒:每个 Agent 类都要有独立的 DO 绑定 + migration 条目;永远不要编辑旧的 migrations,只能新增 tag;需要 Workers AI 时记得加"ai": { "binding": "AI" },并在 tsconfig 中加入compatibility_flags: ["nodejs_compat"]。

类型安全的 Env 接口

interface Env { AI?: Ai; // Workers AI MyAgent?: DurableObjectNamespace<MyAgent>; ChatAgent?: DurableObjectNamespace<ChatAgent>; DB?: D1Database; // D1 database KV?: KVNamespace; // KV storage R2?: R2Bucket; // R2 bucket OPENAI_API_KEY?: string; // Secrets GITHUB_CLIENT_ID?: string; // MCP OAuth credentials GITHUB_CLIENT_SECRET?: string; QUEUE?: Queue; // Queues }

configuration.md 的最佳实践是:把所有 DO 绑定都写进 Env 接口以获得编译期类型安全。

路由:routeAgentRequest 与手动路由

推荐直接使用routeAgentRequest辅助函数,它按 URL 模式自动把请求路由到对应智能体:

import { routeAgentRequest } from "agents"; export default { fetch(request: Request, env: Env) { return routeAgentRequest(request, env); } }

多智能体场景按路径前缀分发:

export default { fetch(request: Request, env: Env) { const url = new URL(request.url); if (url.pathname.startsWith("/chat")) { return routeAgentRequest(request, env, "ChatAgent"); } if (url.pathname.startsWith("/task")) { return routeAgentRequest(request, env, "TaskAgent"); } return new Response("Not found", { status: 404 }); } }

高级场景可手动路由:env.MyAgent.idFromName("user-123")得到确定性 ID,或idFromString(url.searchParams.get("id"))从 URL 参数取随机 ID,再get(id)拿到 stub 后stub.fetch(request)。

部署命令

# Local dev npx wrangler dev # Deploy production npx wrangler deploy # Set secrets npx wrangler secret put OPENAI_API_KEY

邮件路由还需在 Cloudflare 控制台配置"Workers with Durable Objects"目标,并在 Worker 入口导出email处理器调用routeAgentEmail(详见 configuration.md)。

十一、典型落地模式与限额参考

五个可复用的生产模式

来自 patterns.md,全部可在仓库中找到完整代码:

  1. AI Chat w/Tools:AIChatAgent+tool()定义getWeather/searchDocs,其中searchDocs直接用this.sql做文档检索(简易 RAG);
  2. Human-in-the-Loop:服务端execute: "client"+ 客户端onToolCall确认;
  3. Task Queue & Scheduled Processing:onStart里注册*/5 * * * *cron,onRequest入队,processQueue批量dequeue(10)消费,dailyCleanup清理过期日志;
  4. Manual WebSocket Chat:onConnect发历史、onMessage追加消息并广播(conn.state.userId记录身份);
  5. Email Processing w/AI:onEmail存库 →generateText摘要 → 广播给在线连接 → 摘要含 "urgent" 时schedule(0, ...)立即触发自动回复。

关键限额(摘自 gotchas.md)

资源/限制数值备注
CPU / 请求30s(标准)/ 300s(最大)在 wrangler.jsonc 中配置
内存 / 实例128MB与 WebSocket 共享
存储 / 智能体10GBSQLite 存储
定时任务每智能体 1000 个用getSchedules()监控
WebSocket 连接数无限制受内存约束
SQL 列数每表 100—
SQL 行大小2MBKey + value
WebSocket 消息32MiB上限
DO 请求速率约 1000 req/s / 实例高流量需限流
MCP 请求取决于服务器建议重试/退避

生产级最佳实践清单

  • 状态:不可变更新、定期裁剪无界数组、大块数据放 SQL;
  • SQL:建表放onStart()、全量参数化查询、高频列建索引;
  • 调度:监控getSchedules()数量、完成即取消、周期性任务用 cron;
  • WebSocket:务必conn.accept()、优雅处理断连、高效广播;
  • AI:聊天用AIChatAgent、裁剪历史防 token 超限、AI 错误 try/catch + 降级;
  • 部署:高流量(>1000 req/s)限流、监控关键错误与存储、MCP 休眠后重注册 + 重试。

结语

Cloudflare Agents SDK 把 Durable Objects 的持久性、SQLite 的查询能力、WebSocket 的实时性与 Workers AI 的推理能力整合为一套面向智能体的统一编程模型。本文以 api.md 的 API 参考为骨架,补齐了 README 的选型指南、configuration.md 的工程配置、patterns.md 的落地模式与 gotchas.md 的避坑清单。在动手编码前,建议先通读本仓库 cloudflare skill 的决策树,确认 Agents SDK 是否是你场景的最优解,再按"Quick Start → 配置 → API → 模式 → 避坑"的顺序推进即可。

【免费下载链接】autoskills

One command. Your entire AI skill stack. Installed.

项目地址:https://gitcode.com/gh_mirrors/au/autoskills
点击查看免费下载
上一篇:Miniflux 2 CI/CD 并行测试:加速测试过程
下一篇:gh_mirrors/sh1/sh的嵌入式部署:最小化解析器的构建配置

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询