资讯动态

Cloudflare Agents 快速上手:十分钟构建带持久化状态与实时同步的 AI Agent

发布时间:2026/9/18 7:08:54 来源:尧图企业网站定制
Cloudflare Agents 快速上手十分钟构建带持久化状态与实时同步的 AI Agent【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents本篇指南带你用 Cloudflare 官方agents包从零搭建一个计数器CounterAgent它拥有持久化状态、通过 WebSocket 与 React 前端实时同步并能部署到 Cloudflare 全球网络。读完你将掌握项目脚手架、callable()装饰器、useAgent/AgentClient客户端调用以及 Durable Objects SQLite 底层状态机制的完整实战链路。背景什么是 Cloudflare Agentsagents是 Cloudflare 开源的 AI Agent 运行时当前仓库版本为 0.23.0见 packages/agents/package.json。它的核心思路是Agent 运行在 Cloudflare 全球网络上跨请求维持状态并通过 WebSocket 与客户端实时连接。每个 Agent 本质上是一个 Durable Object从源码可见Agent类直接继承自DurableObjectEnv见 packages/agents/src/index.ts#L1150-L1154因此天然具备持久化、休眠hibernation和单点一致性等特性。本教程将构建一个带持久化状态的计数器 Agent并把状态实时同步到 React 前端全程约 10 分钟。创建新项目使用官方脚手架快速初始化npm create cloudflarelatest -- --template cloudflare/agents-starter cd my-agent npm install创建出的项目包含以下文件文件作用src/server.ts你的 Agent 代码服务端src/client.tsxReact 前端wrangler.jsoncCloudflare 配置Durable Object 绑定与迁移tsconfig.json继承agents/tsconfig提供正确的装饰器与模块设置vite.config.ts包含agents/vite插件用于装饰器语法支持手动搭建时必配的两个 SDK 集成callable()装饰器依赖两项编译配置。如果不使用脚手架而是手动配置项目必须同时添加tsconfig.json—— 继承agents/tsconfig它会设置target: ES2021等推荐选项{ extends: agents/tsconfig }vite.config.ts—— 引入agents()插件负责处理 TC39 装饰器转换由于 Vite 8 的 Oxc 转译器尚不支持装饰器这一步是必需的import { cloudflare } from cloudflare/vite-plugin; import react from vitejs/plugin-react; import agents from agents/vite; import { defineConfig } from vite; export default defineConfig({ plugins: [agents(), react(), cloudflare()] });注意agents/vite、agents/tsconfig、agents/react、agents/client等都是agents包通过exports字段暴露的独立子入口见 packages/agents/package.json#L106-L384。启动开发服务器npm run dev打开 http://localhost:5173 即可看到 Agent 在运行。你的第一个 Agent从零编写计数器用下面的代码替换src/server.tsimport { Agent, routeAgentRequest, callable } from agents; // 定义状态结构 type CounterState { count: number; }; // 创建 Agent export class Counter extends AgentEnv, CounterState { // 新实例的初始状态 initialState: CounterState { count: 0 }; // 被 callable 标记的方法可以从客户端调用 callable() increment() { this.setState({ count: this.state.count 1 }); return this.state.count; } callable() decrement() { this.setState({ count: this.state.count - 1 }); return this.state.count; } callable() reset() { this.setState({ count: 0 }); } } // 将请求路由到 Agent export default { async fetch(request: Request, env: Env, ctx: ExecutionContext) { return ( (await routeAgentRequest(request, env)) ?? new Response(Not found, { status: 404 }) ); } };几个关键点AgentEnv, CounterStateAgent泛型接受两个参数——Env环境绑定类型与State状态类型。状态类型决定了this.state、setState()的类型推导也决定了客户端useAgentCounterState()的响应式数据形状。initialState为新建的 Agent 实例提供初始状态。在仓库测试用例 packages/agents/src/tests/agents/state.ts#L17-L21 中可以看到同样的用法TestStateAgent通过initialState初始化count/items/lastUpdated字段。setState()是唯一合法的状态修改途径直接改动this.state不会被持久化、也不会广播给客户端。测试用例中onStateChanged(state, source)钩子会在每次状态变更时被触发见 packages/agents/src/tests/agents/state.ts#L26-L31。callable() 装饰器的底层原理callable()的实现位于 packages/agents/src/callable-decorator.ts。它并不修改被装饰方法的逻辑而是把方法及其元数据注册到一个WeakMap中// callable-decorator.ts源码摘录 export function callable(metadata: CallableMetadata {}) { return function callableDecoratorThis, Args extends unknown[], Return( target: (this: This, ...args: Args) Return, _context: ClassMethodDecoratorContext ) { if (!callableMetadata.has(target)) { callableMetadata.set(target, metadata); } return target; }; }CallableMetadata支持两个可选字段字段含义description方法的可选描述streaming该方法是否支持流式响应服务端在运行时通过decoratedMethods(host)沿原型链扫描所有被装饰的方法子类覆写父类方法时取最近声明将其暴露为 RPC 接口。仓库中另有unstable_callable作为旧别名保留并打印弃用警告官方推荐一律使用callable。注册 Durable Object更新 wrangler.jsoncAgent 依赖 Cloudflare Durable Objects 运行因此必须在配置中声明绑定与迁移{ name: my-agent, main: src/server.ts, compatibility_date: 2025-01-01, compatibility_flags: [nodejs_compat], durable_objects: { bindings: [ { name: Counter, class_name: Counter } ] }, migrations: [ { tag: v1, new_sqlite_classes: [Counter] } ] }要点说明durable_objects.bindings中的class_name必须与服务端导出的 Agent 类名一致migrations.new_sqlite_classes声明这是一个使用 SQLite 存储的新 Durable Object 类——Agent 的持久化状态正是存放在 SQLite 中compatibility_flags: [nodejs_compat]为 Worker 提供 Node.js 兼容运行时能力。从 React 连接 Agent替换src/client.tsximport { useAgent } from agents/react; // 与你的 Agent 状态类型保持一致 type CounterState { count: number; }; export default function App() { // 连接到 Counter Agent const agent useAgentCounterState({ agent: Counter }); return ( div style{{ padding: 2rem, fontFamily: system-ui }} h1Counter Agent/h1 p style{{ fontSize: 3rem }}{agent.state?.count ?? 0}/p div style{{ display: flex, gap: 1rem }} button onClick{() agent.stub.decrement()}-/button button onClick{() agent.stub.reset()}Reset/button button onClick{() agent.stub.increment()}/button /div /div ); }关键 APIuseAgent基于partysocket/react封装见 packages/agents/src/react.tsx通过 WebSocket 建立与 Agent 的连接agent.state是响应式的——状态变化时组件自动重渲染agent.stub.methodName()调用 Agent 上被callable()标记的方法。stub是一个 Proxy 代理对象createStubProxy会在内部把方法调用序列化为 RPC 请求通过 WebSocket 发出。useAgent 的常用配置项从 packages/agents/src/client.ts#L43-L104 的AgentClientOptions可以查看到useAgent/AgentClient支持的完整选项选项类型说明agentstring要连接的 Agent 类名必填namestring具体实例名默认defaultbasePathstring直接指定完整 URL 路径跳过默认的 agent/name 拼接onStateUpdate(state, source) void状态更新回调source区分server或clientonStateUpdateError(error: string) void状态更新失败回调如只读连接onIdentity(name, agent) void连接后服务端下发 Agent 身份时触发defaultCallTimeoutnumber非流式调用的默认超时默认 30 000 ms传0关闭点击按钮后发生了什么当你点击按钮时完整的数据流如下客户端通过 WebSocket 调用agent.stub.increment()Agent执行increment()用setState()更新状态状态自动持久化到 SQLite广播推送给所有已连接的客户端React收到更新用最新的agent.state重渲染。┌─────────────┐ ┌─────────────┐ │ Browser │◄───────►│ Agent │ │ (React) │ WS │ (Counter) │ └─────────────┘ └──────┬──────┘ │ ┌──────▼──────┐ │ SQLite │ │ (State) │ └─────────────┘四个核心概念概念含义Agent 实例每个唯一的名称拥有独立的 Agent 实例。Counter:user-123与Counter:user-456是相互隔离的两个实例持久化状态状态跨重启、跨部署、跨休眠而存活存放在 SQLite 中实时同步连接到同一 Agent 的所有客户端都能即时收到状态更新休眠Hibernation没有客户端连接时 Agent 自动休眠零成本下一次请求到达时自动唤醒从实现角度印证Agent类自身带有完整的 WebSocket 子系统onConnect、onMessage、onClose、onError生命周期钩子见 packages/agents/src/index.ts#L1174-L1209其callable()接口即通过该 WebSocket 能力以 Capn Web 端点 / 原生 JSON RPC 协议对外提供实现了“一份接口、所有线上协议通用”。非 React 场景从 Vanilla JS 连接不使用 React 时可以使用AgentClient实现同样位于 packages/agents/src/client.ts基于partysocket封装import { AgentClient } from agents/client; const agent new AgentClient({ agent: Counter, name: my-counter, // 可选默认为 default host: window.location.host }); await agent.ready; // 调用方法 await agent.call(increment); console.log(Current count:, agent.state?.count); await agent.call(reset);AgentClient与 React 版的useAgent共享同一套连接与 RPC 机制AgentClientOptions与useAgent参数一致因此任何前端框架——Vue、Svelte、原生 JS——都能以同样的方式与 Agent 通信。部署到 Cloudflarenpm run deploy部署完成后你的 Agent 就运行在 Cloudflare 的全球网络上就近服务全球用户。由于状态存放在 SQLite 且绑定为 Durable Object部署、重启都不会丢失状态这也是“持久化”Agent 与普通无状态 Worker 的本质区别。下一步深入方向现在你已经拥有一个可运行的 Agent可以继续探索这些主题State Management—— 深入setState()、initialState与onStateChanged()Client SDK——useAgent与AgentClient完整 API 参考Scheduling—— 延迟、定时或 cron 任务Agent Class—— 生命周期方法、HTTP 处理器与 WebSocket 事件常见模式速查我想...阅读...添加 AI/LLM 能力Chat Agents通过 MCP 暴露工具Creating MCP Servers运行后台任务Scheduling处理邮件Email Service使用 Cloudflare WorkflowsWorkflows故障排查“Agent not found” / 404 错误依次检查Agent 类是否从服务端文件正确导出wrangler.jsonc是否包含 Durable Object 绑定与迁移声明客户端传入的 Agent 名称是否与类名一致大小写不敏感。状态没有同步检查以下几点你调用的是this.setState()而不是直接修改this.state直接修改不会持久化、也不会广播Agent 已定义initialStateAgent 只有在拥有状态时才会在连接时下发状态WebSocket 连接已建立可在浏览器开发者工具的 Network 面板中确认。“Method X is not callable” 错误确保方法被callable()装饰import { callable } from agents; callable() increment() { // ... }agent.stub的类型错误为useAgent同时传入 Agent 类型与状态类型使stub获得完整类型推导const agent useAgentCounter, CounterState({ agent: Counter, onStateUpdate: (state) setCount(state.count) }); // 现在 agent.stub 拥有完整类型 agent.stub.increment(); // ✓ TypeScript 知道这个方法存在类型相关的测试用例如 packages/agents/src/tests-d/typed-use-agent.test-d.ts正是验证这类类型推导行为的说明传入 Agent 泛型后stub的方法签名会被精确推导值得在项目中使用。【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价