cloudflare-agents

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cloudflare Agents SDK

Cloudflare Agents SDK

Status: Production Ready ✅ Last Updated: 2025-11-23 Dependencies: cloudflare-worker-base (recommended) Latest Versions: agents@0.2.23 (Nov 13, 2025), @modelcontextprotocol/sdk@latest Production Tested: Cloudflare's own MCP servers (https://github.com/cloudflare/mcp-server-cloudflare)
Recent Updates (2025):
  • Sept 2025: AI SDK v5 compatibility, automatic message migration
  • April 2025: MCP support (MCPAgent class),
    import { context }
    from agents
  • March 2025: Package rename (agents-sdk → agents)

状态:已就绪可用于生产 ✅ 最后更新:2025-11-23 依赖:cloudflare-worker-base(推荐) 最新版本:agents@0.2.23(2025年11月13日)、@modelcontextprotocol/sdk@latest 生产环境测试:Cloudflare官方MCP服务器(https://github.com/cloudflare/mcp-server-cloudflare)
2025年近期更新:
  • 2025年9月:兼容AI SDK v5,支持消息自动迁移
  • 2025年4月:支持MCP(新增McpAgent类),可从agents中
    import { context }
  • 2025年3月:包重命名(agents-sdk → agents)

What is Cloudflare Agents?

什么是Cloudflare Agents?

The Cloudflare Agents SDK enables building AI-powered autonomous agents that run on Cloudflare Workers + Durable Objects. Agents can:
  • Communicate in real-time via WebSockets and Server-Sent Events
  • Persist state with built-in SQLite database (up to 1GB per agent)
  • Schedule tasks using delays, specific dates, or cron expressions
  • Run workflows by triggering asynchronous Cloudflare Workflows
  • Browse the web using Browser Rendering API + Puppeteer
  • Implement RAG with Vectorize vector database + Workers AI embeddings
  • Build MCP servers implementing the Model Context Protocol
  • Support human-in-the-loop patterns for review and approval
  • Scale to millions of independent agent instances globally
Each agent instance is a globally unique, stateful micro-server that can run for seconds, minutes, or hours.

Cloudflare Agents SDK支持在Cloudflare Workers + Durable Objects上构建由AI驱动的自主Agent。Agent具备以下能力:
  • 实时通信:通过WebSocket和Server-Sent Events(SSE)实现
  • 状态持久化:内置SQLite数据库(每个Agent最多支持1GB存储)
  • 任务调度:支持延迟执行、指定日期执行或cron表达式调度
  • 工作流执行:触发异步Cloudflare Workflows
  • 网页浏览:使用Browser Rendering API + Puppeteer
  • 实现RAG:结合Vectorize向量数据库 + Workers AI嵌入模型
  • 搭建MCP服务器:实现Model Context Protocol
  • 支持人在环中模式:用于审核与审批流程
  • 全球大规模扩展:支持数百万个独立Agent实例在全球运行
每个Agent实例都是全局唯一的有状态微服务,可运行数秒、数分钟或数小时。

Do You Need Agents SDK?

你是否需要Agents SDK?

STOP: Before using Agents SDK, ask yourself if you actually need it.
注意:在使用Agents SDK之前,请先确认你是否真的需要它。

Use JUST Vercel AI SDK (Simpler) When:

仅使用Vercel AI SDK(更简易)的场景:

  • ✅ Building a basic chat interface
  • ✅ Server-Sent Events (SSE) streaming is sufficient (one-way: server → client)
  • ✅ No persistent agent state needed (or you manage it separately with D1/KV)
  • ✅ Single-user, single-conversation scenarios
  • ✅ Just need AI responses, no complex workflows or scheduling
This covers 80% of chat applications. For these cases, use Vercel AI SDK directly on Workers - it's simpler, requires less infrastructure, and handles streaming automatically.
Example (no Agents SDK needed):
typescript
// worker.ts - Simple chat with AI SDK only
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

export default {
  async fetch(request: Request, env: Env) {
    const { messages } = await request.json();

    const result = streamText({
      model: openai('gpt-4o-mini'),
      messages
    });

    return result.toTextStreamResponse(); // Automatic SSE streaming
  }
}

// client.tsx - React with built-in hooks
import { useChat } from 'ai/react';

function ChatPage() {
  const { messages, input, handleSubmit } = useChat({ api: '/api/chat' });
  // Done. No Agents SDK needed.
}
Result: 100 lines of code instead of 500. No Durable Objects setup, no WebSocket complexity, no migrations.

  • ✅ 构建基础聊天界面
  • ✅ Server-Sent Events(SSE)流已满足需求(单向:服务器→客户端)
  • ✅ 不需要持久化Agent状态(或通过D1/KV自行管理状态)
  • ✅ 单用户、单对话场景
  • ✅ 仅需要AI响应,无需复杂工作流或任务调度
80%的聊天应用都属于此类场景。对于这些情况,直接在Workers上使用Vercel AI SDK即可——它更简单,所需基础设施更少,且自动处理流传输。
示例(无需Agents SDK):
typescript
// worker.ts - 仅使用AI SDK的简易聊天应用
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

export default {
  async fetch(request: Request, env: Env) {
    const { messages } = await request.json();

    const result = streamText({
      model: openai('gpt-4o-mini'),
      messages
    });

    return result.toTextStreamResponse(); // 自动SSE流传输
  }
}

// client.tsx - 使用内置钩子的React客户端
import { useChat } from 'ai/react';

function ChatPage() {
  const { messages, input, handleSubmit } = useChat({ api: '/api/chat' });
  // 完成开发,无需Agents SDK
}
结果:仅需100行代码,而非500行。无需配置Durable Objects,无需处理WebSocket复杂度,无需迁移。

Use Agents SDK When You Need:

需要使用Agents SDK的场景:

  • WebSocket connections (true bidirectional real-time communication)
  • Durable Objects (globally unique, stateful agent instances)
  • Built-in state persistence (SQLite storage up to 1GB per agent)
  • Multi-agent coordination (agents calling and communicating with each other)
  • Scheduled tasks (delays, cron expressions, recurring jobs)
  • Human-in-the-loop workflows (approval gates, review processes)
  • Long-running agents (background processing, autonomous workflows)
  • MCP servers with stateful tool execution
This is ~20% of applications - when you need the infrastructure that Agents SDK provides.

  • WebSocket连接(真正的双向实时通信)
  • Durable Objects有状态实例(全局唯一的带持久化记忆的Agent)
  • 内置状态持久化(每个Agent最多1GB的SQLite存储)
  • 多Agent协同(Agent之间可调用与通信)
  • 任务调度(延迟执行、cron表达式、周期性任务)
  • 人在环中工作流(审批闸门、审核流程)
  • 长运行Agent(后台处理、自主工作流)
  • 带状态工具执行的MCP服务器
这类场景约占20%——当你需要Agents SDK提供的基础设施能力时。

Key Understanding: What Agents SDK IS vs IS NOT

核心认知:Agents SDK能做什么与不能做什么

Agents SDK IS:
  • 🏗️ Infrastructure layer for WebSocket connections, Durable Objects, and state management
  • 🔧 Framework for building stateful, autonomous agents
  • 📦 Wrapper around Durable Objects with lifecycle methods
Agents SDK IS NOT:
  • AI inference provider (you bring your own: AI SDK, Workers AI, OpenAI, etc.)
  • Streaming response handler (use AI SDK for automatic parsing)
  • LLM integration (that's a separate concern)
Think of it this way:
  • Agents SDK = The building (WebSockets, state, rooms)
  • AI SDK / Workers AI = The AI brain (inference, reasoning, responses)
You can use them together (recommended for most cases), or use Workers AI directly (if you're willing to handle manual SSE parsing).

Agents SDK能做
  • 🏗️ 基础设施层:管理WebSocket连接、Durable Objects与状态
  • 🔧 开发框架:用于构建有状态的自主Agent
  • 📦 Durable Objects封装:提供生命周期方法
Agents SDK不能做
  • AI推理服务:需自行集成(AI SDK、Workers AI、OpenAI等)
  • 流响应处理器:使用AI SDK自动解析
  • LLM集成:这是独立的功能模块
可以这样理解
  • Agents SDK = 建筑(WebSocket、状态管理、实例房间)
  • AI SDK / Workers AI = AI大脑(推理、决策、响应)
你可以将它们结合使用(大多数场景推荐),也可以直接使用Workers AI(如果你愿意手动处理SSE解析)。

Decision Flowchart

决策流程图

Building an AI application?
├─ Need WebSocket bidirectional communication? ───────┐
│  (Client sends while server streams, agent-initiated messages)
├─ Need Durable Objects stateful instances? ──────────┤
│  (Globally unique agents with persistent memory)
├─ Need multi-agent coordination? ────────────────────┤
│  (Agents calling/messaging other agents)
├─ Need scheduled tasks or cron jobs? ────────────────┤
│  (Delayed execution, recurring tasks)
├─ Need human-in-the-loop workflows? ─────────────────┤
│  (Approval gates, review processes)
└─ If ALL above are NO ─────────────────────────────→ Use AI SDK directly
                                                       (Much simpler approach)

   If ANY above are YES ────────────────────────────→ Use Agents SDK + AI SDK
                                                       (More infrastructure, more power)

是否要构建AI应用?
├─ 是否需要WebSocket双向通信? ───────┐
│  (客户端发送消息时服务器可同时流传输,Agent主动发起消息)
├─ 是否需要Durable Objects有状态实例? ──────────┤
│  (全局唯一、带持久化记忆的Agent)
├─ 是否需要多Agent协同? ────────────────────┤
│  (Agent之间可调用/通信)
├─ 是否需要任务调度或cron任务? ────────────────┤
│  (延迟执行、周期性任务)
├─ 是否需要人在环中工作流? ─────────────────┤
│  (审批闸门、审核流程)
└─ 如果以上全为否 ─────────────────────────────→ 直接使用AI SDK
                                                       (更简易的方案)

   如果以上任意一项为是 ────────────────────────────→ 使用Agents SDK + AI SDK
                                                       (需要更多基础设施,但功能更强大)

Architecture Comparison

架构对比

FeatureAI SDK OnlyAgents SDK + AI SDK
Setup Complexity🟢 Low (npm install, done)🔴 Higher (Durable Objects, migrations, bindings)
Code Volume🟢 ~100 lines🟡 ~500+ lines
Streaming✅ Automatic (SSE)✅ Automatic (AI SDK) or manual (Workers AI)
State Management⚠️ Manual (D1/KV)✅ Built-in (SQLite)
WebSockets❌ Manual setup✅ Built-in
React Hooks✅ useChat, useCompletion⚠️ Custom hooks needed
Multi-agent❌ Not supported✅ Built-in (routeAgentRequest)
Scheduling❌ External (Queue/Workflow)✅ Built-in (this.schedule)
Use CaseSimple chat, completionsComplex stateful workflows

特性仅使用AI SDKAgents SDK + AI SDK
部署复杂度🟢 低(npm安装即可完成)🔴 较高(需配置Durable Objects、迁移、绑定)
代码量🟢 ~100行🟡 ~500+行
流传输✅ 自动处理(SSE)✅ 自动处理(AI SDK)或手动处理(Workers AI)
状态管理⚠️ 手动处理(D1/KV)✅ 内置支持(SQLite)
WebSocket❌ 需手动配置✅ 内置支持
React钩子✅ useChat、useCompletion⚠️ 需自定义钩子
多Agent支持❌ 不支持✅ 内置支持(routeAgentRequest)
任务调度❌ 需依赖外部服务(Queue/Workflow)✅ 内置支持(this.schedule)
适用场景简易聊天、补全功能复杂有状态工作流

Still Not Sure?

仍不确定?

Start with AI SDK. You can always migrate to Agents SDK later if you discover you need WebSockets or Durable Objects. It's easier to add infrastructure later than to remove it.
For most developers: If you're building a chat interface and don't have specific requirements for WebSockets, multi-agent coordination, or scheduled tasks, use AI SDK directly. You'll ship faster and with less complexity.
Proceed with Agents SDK only if you've identified a specific need for its infrastructure capabilities.

从AI SDK开始。如果之后发现需要WebSocket或Durable Objects,再迁移到Agents SDK。后续添加基础设施比移除要容易得多。
对于大多数开发者:如果你正在构建聊天界面,且没有明确的WebSocket、多Agent协同或任务调度需求,请直接使用AI SDK。你将更快交付,且复杂度更低。
仅当你明确需要其基础设施能力时,再使用Agents SDK

Quick Start (10 Minutes)

快速开始(10分钟)

1. Scaffold Project with Template

1. 使用模板初始化项目

bash
npm create cloudflare@latest my-agent -- \
  --template=cloudflare/agents-starter \
  --ts \
  --git \
  --deploy false
What this creates:
  • Complete Agent project structure
  • TypeScript configuration
  • wrangler.jsonc with Durable Objects bindings
  • Example chat agent implementation
  • React client with useAgent hook
bash
npm create cloudflare@latest my-agent -- \
  --template=cloudflare/agents-starter \
  --ts \
  --git \
  --deploy false
该命令会创建
  • 完整的Agent项目结构
  • TypeScript配置
  • 包含Durable Objects绑定的wrangler.jsonc
  • 示例聊天Agent实现
  • 带useAgent钩子的React客户端

2. Or Add to Existing Worker

2. 或添加到现有Worker项目

bash
cd my-existing-worker
npm install agents
Then create an Agent class:
typescript
// src/index.ts
import { Agent, AgentNamespace } from "agents";

export class MyAgent extends Agent {
  async onRequest(request: Request): Promise<Response> {
    return new Response("Hello from Agent!");
  }
}

export default MyAgent;
bash
cd my-existing-worker
npm install agents
然后创建Agent类
typescript
// src/index.ts
import { Agent, AgentNamespace } from "agents";

export class MyAgent extends Agent {
  async onRequest(request: Request): Promise<Response> {
    return new Response("Hello from Agent!");
  }
}

export default MyAgent;

3. Configure Durable Objects Binding

3. 配置Durable Objects绑定

Create or update
wrangler.jsonc
:
jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-agent",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21",
  "compatibility_flags": ["nodejs_compat"],
  "durable_objects": {
    "bindings": [
      {
        "name": "MyAgent",        // MUST match class name
        "class_name": "MyAgent"   // MUST match exported class
      }
    ]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["MyAgent"]  // CRITICAL: Enables SQLite storage
    }
  ]
}
CRITICAL Configuration Rules:
  • name
    and
    class_name
    MUST be identical
  • new_sqlite_classes
    MUST be in first migration (cannot add later)
  • ✅ Agent class MUST be exported (or binding will fail)
  • ✅ Migration tags CANNOT be reused (each migration needs unique tag)
创建或更新
wrangler.jsonc
jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-agent",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21",
  "compatibility_flags": ["nodejs_compat"],
  "durable_objects": {
    "bindings": [
      {
        "name": "MyAgent",        // 必须与类名一致
        "class_name": "MyAgent"   // 必须与导出的类名一致
      }
    ]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["MyAgent"]  // 关键配置:启用SQLite存储
    }
  ]
}
关键配置规则
  • name
    class_name
    必须完全一致
  • new_sqlite_classes
    必须包含在第一个迁移版本中(后续无法添加)
  • ✅ Agent类 必须导出(否则绑定会失败)
  • ✅ 迁移标签 不能重复使用(每个迁移版本需要唯一标签)

4. Deploy

4. 部署

bash
npx wrangler@latest deploy
Your agent is now running at:
https://my-agent.<subdomain>.workers.dev

bash
npx wrangler@latest deploy
你的Agent现在已部署在:
https://my-agent.<subdomain>.workers.dev

Architecture Overview: How the Pieces Fit Together

架构概述:各组件如何协作

Understanding what each tool does prevents confusion and helps you choose the right combination.
了解每个工具的作用可避免混淆,帮助你选择合适的组合。

The Stack

技术栈

┌─────────────────────────────────────────────────────────┐
│                    Your Application                      │
│                                                          │
│  ┌────────────────┐         ┌──────────────────────┐   │
│  │  Agents SDK    │         │   AI Inference       │   │
│  │  (Infra Layer) │   +     │   (Brain Layer)      │   │
│  │                │         │                      │   │
│  │ • WebSockets   │         │  Choose ONE:         │   │
│  │ • Durable Objs │         │  • Vercel AI SDK ✅   │   │
│  │ • State (SQL)  │         │  • Workers AI ⚠️      │   │
│  │ • Scheduling   │         │  • OpenAI Direct     │   │
│  │ • Multi-agent  │         │  • Anthropic Direct  │   │
│  └────────────────┘         └──────────────────────┘   │
│         ↓                             ↓                │
│  Manages connections          Generates responses      │
│  and state                    and handles streaming    │
└─────────────────────────────────────────────────────────┘
              Cloudflare Workers + Durable Objects
┌─────────────────────────────────────────────────────────┐
│                    你的应用程序                          │
│                                                          │
│  ┌────────────────┐         ┌──────────────────────┐   │
│  │  Agents SDK    │         │   AI推理层           │   │
│  │ (基础设施层) │   +     │   (大脑层)          │   │
│  │                │         │                      │   │
│  │ • WebSockets   │         │  选择其中一种:       │   │
│  │ • Durable Objs │         │  • Vercel AI SDK ✅   │   │
│  │ • 状态存储(SQL)  │         │  • Workers AI ⚠️      │   │
│  │ • 任务调度   │         │  • 直接调用OpenAI     │   │
│  │ • 多Agent协同  │         │  • 直接调用Anthropic  │   │
│  └────────────────┘         └──────────────────────┘   │
│         ↓                             ↓                │
│  管理连接与状态          生成响应并处理流传输    │
└─────────────────────────────────────────────────────────┘
              Cloudflare Workers + Durable Objects

What Each Tool Provides

各工具提供的能力

1. Agents SDK (This Skill)

1. Agents SDK(当前文档主题)

Purpose: Infrastructure for stateful, real-time agents
Provides:
  • ✅ WebSocket connection management (bidirectional real-time)
  • ✅ Durable Objects wrapper (globally unique agent instances)
  • ✅ Built-in state persistence (SQLite up to 1GB)
  • ✅ Lifecycle methods (
    onStart
    ,
    onConnect
    ,
    onMessage
    ,
    onClose
    )
  • ✅ Task scheduling (
    this.schedule()
    with cron/delays)
  • ✅ Multi-agent coordination (
    routeAgentRequest()
    )
  • ✅ Client libraries (
    useAgent
    ,
    AgentClient
    ,
    agentFetch
    )
Does NOT Provide:
  • ❌ AI inference (no LLM calls)
  • ❌ Streaming response parsing (bring your own)
  • ❌ Provider integrations (OpenAI, Anthropic, etc.)
Think of it as: The building and infrastructure (rooms, doors, plumbing) but NOT the residents (AI).

用途:为有状态、实时Agent提供基础设施
提供的能力
  • ✅ WebSocket连接管理(双向实时通信)
  • ✅ Durable Objects封装(全局唯一Agent实例)
  • ✅ 内置状态持久化(SQLite最多1GB存储)
  • ✅ 生命周期方法(
    onStart
    onConnect
    onMessage
    onClose
  • ✅ 任务调度(
    this.schedule()
    支持cron/延迟)
  • ✅ 多Agent协同(
    routeAgentRequest()
  • ✅ 客户端库(
    useAgent
    AgentClient
    agentFetch
不提供的能力
  • ❌ AI推理(无LLM调用能力)
  • ❌ 流响应解析(需自行集成)
  • ❌ 服务商集成(OpenAI、Anthropic等)
可以这样理解:它是建筑和基础设施(房间、门、管道),但不是居民(AI)。

2. Vercel AI SDK (Recommended for AI)

2. Vercel AI SDK(推荐用于AI推理)

Purpose: AI inference with automatic streaming
Provides:
  • ✅ Automatic streaming response handling (SSE parsing done for you)
  • ✅ Multi-provider support (OpenAI, Anthropic, Google, etc.)
  • ✅ React hooks (
    useChat
    ,
    useCompletion
    ,
    useAssistant
    )
  • ✅ Unified API across providers
  • ✅ Tool calling / function calling
  • ✅ Works on Cloudflare Workers ✅
Example:
typescript
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = streamText({
  model: openai('gpt-4o-mini'),
  messages: [...]
});

// Returns SSE stream - no manual parsing needed
return result.toTextStreamResponse();
When to use with Agents SDK:
  • ✅ Most chat applications
  • ✅ When you want React hooks
  • ✅ When you use multiple AI providers
  • ✅ When you want clean, abstracted AI calls
Combine with Agents SDK:
typescript
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";

export class MyAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    // Agents SDK provides: WebSocket, state, this.messages
    // AI SDK provides: Automatic streaming, provider abstraction

    return streamText({
      model: openai('gpt-4o-mini'),
      messages: this.messages  // Managed by Agents SDK
    }).toTextStreamResponse();
  }
}

用途:带自动流传输的AI推理
提供的能力
  • ✅ 自动处理流响应(SSE解析已完成)
  • ✅ 多服务商支持(OpenAI、Anthropic、Google等)
  • ✅ React钩子(
    useChat
    useCompletion
    useAssistant
  • ✅ 跨服务商统一API
  • ✅ 工具调用/函数调用
  • ✅ 支持在Cloudflare Workers上运行 ✅
示例
typescript
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = streamText({
  model: openai('gpt-4o-mini'),
  messages: [...]
});

// 返回SSE流 - 无需手动解析
return result.toTextStreamResponse();
与Agents SDK结合使用的场景
  • ✅ 大多数聊天应用
  • ✅ 需要React钩子的场景
  • ✅ 使用多个AI服务商的场景
  • ✅ 需要简洁、抽象的AI调用方式的场景
与Agents SDK结合的示例
typescript
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";

export class MyAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    // Agents SDK提供:WebSocket、状态、this.messages
    // AI SDK提供:自动流传输、服务商抽象

    return streamText({
      model: openai('gpt-4o-mini'),
      messages: this.messages  // 由Agents SDK管理
    }).toTextStreamResponse();
  }
}

3. Workers AI (Alternative for AI)

3. Workers AI(AI推理的替代方案)

Purpose: Cloudflare's on-platform AI inference
Provides:
  • ✅ Cost-effective inference (included in Workers subscription)
  • ✅ No external API keys needed
  • ✅ Models: LLaMA 3, Qwen, Mistral, embeddings, etc.
  • ✅ Runs on Cloudflare's network (low latency)
Does NOT Provide:
  • ❌ Automatic streaming parsing (returns raw SSE format)
  • ❌ React hooks
  • ❌ Multi-provider abstraction
Manual parsing required:
typescript
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
  messages: [...],
  stream: true
});

// Returns raw SSE format - YOU must parse
for await (const chunk of response) {
  const text = new TextDecoder().decode(chunk);  // Uint8Array → string
  if (text.startsWith('data: ')) {              // Check SSE format
    const data = JSON.parse(text.slice(6));     // Parse JSON
    if (data.response) {                        // Extract .response field
      fullResponse += data.response;
    }
  }
}
When to use:
  • ✅ Cost is critical (embeddings, high-volume)
  • ✅ Need Cloudflare-specific models
  • ✅ Willing to handle manual SSE parsing
  • ✅ No external dependencies allowed
Trade-off: Save money, spend time on manual parsing.

用途:Cloudflare平台内置的AI推理服务
提供的能力
  • ✅ 高性价比的推理(包含在Workers订阅中)
  • ✅ 无需外部API密钥
  • ✅ 支持模型:LLaMA 3、Qwen、Mistral、嵌入模型等
  • ✅ 在Cloudflare网络运行(低延迟)
不提供的能力
  • ❌ 自动流解析(返回原始SSE格式)
  • ❌ React钩子
  • ❌ 多服务商抽象
需要手动解析
typescript
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
  messages: [...],
  stream: true
});

// 返回原始SSE格式 - 你必须手动解析
for await (const chunk of response) {
  const text = new TextDecoder().decode(chunk);  // Uint8Array → 字符串
  if (text.startsWith('data: ')) {              // 检查SSE格式
    const data = JSON.parse(text.slice(6));     // 解析JSON
    if (data.response) {                        // 提取.response字段
      fullResponse += data.response;
    }
  }
}
适用场景
  • ✅ 成本敏感(嵌入模型、高流量场景)
  • ✅ 需要Cloudflare特定模型
  • ✅ 愿意手动处理SSE解析
  • ✅ 不允许外部依赖
** trade-off **:节省成本,但需要编写更多手动解析代码。

Recommended Combinations

推荐组合

Option A: Agents SDK + Vercel AI SDK (Recommended ⭐)

方案A:Agents SDK + Vercel AI SDK(推荐 ⭐)

Use when: You need WebSockets/state AND want clean AI integration
typescript
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    return streamText({
      model: openai('gpt-4o-mini'),
      messages: this.messages,  // Agents SDK manages history
      onFinish
    }).toTextStreamResponse();
  }
}
Pros:
  • ✅ Best developer experience
  • ✅ Automatic streaming
  • ✅ WebSockets + state from Agents SDK
  • ✅ Clean, maintainable code
Cons:
  • ⚠️ Requires external API keys
  • ⚠️ Additional cost for AI provider

适用场景:需要WebSocket/状态管理,同时希望获得简洁的AI集成体验
typescript
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    return streamText({
      model: openai('gpt-4o-mini'),
      messages: this.messages,  // 由Agents SDK管理历史消息
      onFinish
    }).toTextStreamResponse();
  }
}
优点
  • ✅ 最佳开发者体验
  • ✅ 自动流传输
  • ✅ Agents SDK提供WebSocket + 状态管理
  • ✅ 代码简洁、易维护
缺点
  • ⚠️ 需要外部API密钥
  • ⚠️ 需支付AI服务商费用

Option B: Agents SDK + Workers AI

方案B:Agents SDK + Workers AI

Use when: You need WebSockets/state AND cost is critical
typescript
import { Agent } from "agents";

export class BudgetAgent extends Agent<Env> {
  async onMessage(connection, message) {
    const response = await this.env.AI.run('@cf/meta/llama-3-8b-instruct', {
      messages: [...],
      stream: true
    });

    // Manual SSE parsing required (see Workers AI section above)
    for await (const chunk of response) {
      // ... manual parsing ...
    }
  }
}
Pros:
  • ✅ Cost-effective
  • ✅ No external dependencies
  • ✅ WebSockets + state from Agents SDK
Cons:
  • ❌ Manual SSE parsing complexity
  • ❌ Limited model selection
  • ❌ More code to maintain

适用场景:需要WebSocket/状态管理,同时对成本敏感
typescript
import { Agent } from "agents";

export class BudgetAgent extends Agent<Env> {
  async onMessage(connection, message) {
    const response = await this.env.AI.run('@cf/meta/llama-3-8b-instruct', {
      messages: [...],
      stream: true
    });

    // 需要手动解析SSE(参见上方Workers AI章节)
    for await (const chunk of response) {
      // ... 手动解析代码 ...
    }
  }
}
优点
  • ✅ 成本低廉
  • ✅ 无外部依赖
  • ✅ Agents SDK提供WebSocket + 状态管理
缺点
  • ❌ 手动解析SSE复杂度高
  • ❌ 模型选择有限
  • ❌ 需维护更多代码

Option C: Just Vercel AI SDK (No Agents)

方案C:仅使用Vercel AI SDK(无需Agents)

Use when: You DON'T need WebSockets or Durable Objects
typescript
// worker.ts - Simple Workers route
export default {
  async fetch(request: Request, env: Env) {
    const { messages } = await request.json();

    const result = streamText({
      model: openai('gpt-4o-mini'),
      messages
    });

    return result.toTextStreamResponse();
  }
}

// client.tsx - Built-in React hooks
import { useChat } from 'ai/react';

function Chat() {
  const { messages, input, handleSubmit } = useChat({ api: '/api/chat' });
  return <form onSubmit={handleSubmit}>...</form>;
}
Pros:
  • ✅ Simplest approach
  • ✅ Least code
  • ✅ Fast to implement
  • ✅ Built-in React hooks
Cons:
  • ❌ No WebSockets (only SSE)
  • ❌ No Durable Objects state
  • ❌ No multi-agent coordination
Best for: 80% of chat applications

适用场景:不需要WebSocket或Durable Objects
typescript
// worker.ts - 简易Workers路由
export default {
  async fetch(request: Request, env: Env) {
    const { messages } = await request.json();

    const result = streamText({
      model: openai('gpt-4o-mini'),
      messages
    });

    return result.toTextStreamResponse();
  }
}

// client.tsx - 使用内置React钩子
import { useChat } from 'ai/react';

function Chat() {
  const { messages, input, handleSubmit } = useChat({ api: '/api/chat' });
  return <form onSubmit={handleSubmit}>...</form>;
}
优点
  • ✅ 最简单的方案
  • ✅ 代码量最少
  • ✅ 实现速度快
  • ✅ 内置React钩子
缺点
  • ❌ 无WebSocket支持(仅SSE)
  • ❌ 无Durable Objects状态管理
  • ❌ 无多Agent协同
最适合:80%的聊天应用

Decision Matrix

决策矩阵

Your NeedsRecommended StackComplexityCost
Simple chat, no stateAI SDK only🟢 Low$$ (AI provider)
Chat + WebSockets + stateAgents SDK + AI SDK🟡 Medium$$$ (infra + AI)
Chat + WebSockets + budgetAgents SDK + Workers AI🔴 High$ (infra only)
Multi-agent workflowsAgents SDK + AI SDK🔴 High$$$ (infra + AI)
MCP server with toolsAgents SDK (McpAgent)🟡 Medium$ (infra only)

你的需求推荐技术栈复杂度成本
简易聊天,无状态仅使用AI SDK🟢 低$$(AI服务商费用)
聊天 + WebSocket + 状态Agents SDK + AI SDK🟡 中$$$(基础设施+AI费用)
聊天 + WebSocket + 低成本Agents SDK + Workers AI🔴 高$(仅基础设施费用)
多Agent工作流Agents SDK + AI SDK🔴 高$$$(基础设施+AI费用)
带工具调用的MCP服务器Agents SDK(McpAgent)🟡 中$(仅基础设施费用)

Key Takeaway

核心要点

Agents SDK is infrastructure, not AI. You combine it with AI inference tools:
  • For best DX: Agents SDK + Vercel AI SDK ⭐
  • For cost savings: Agents SDK + Workers AI (accept manual parsing)
  • For simplicity: Just AI SDK (if you don't need WebSockets/state)
The rest of this skill focuses on Agents SDK (the infrastructure layer). For AI inference patterns, see the
ai-sdk-core
or
cloudflare-workers-ai
skills.

Agents SDK是基础设施,不是AI。你需要将它与AI推理工具结合使用:
  • 最佳开发者体验:Agents SDK + Vercel AI SDK ⭐
  • 节省成本:Agents SDK + Workers AI(需接受手动解析)
  • 最简单方案:仅使用AI SDK(如果不需要WebSocket/状态)
本文档剩余部分将聚焦于Agents SDK(基础设施层)。关于AI推理模式,请参考
ai-sdk-core
cloudflare-workers-ai
文档。

Configuration (wrangler.jsonc)

配置(wrangler.jsonc)

Critical Required Configuration:
jsonc
{
  "durable_objects": {
    "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
  },
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["MyAgent"] }  // MUST be in first migration
  ]
}
Common Optional Bindings:
ai
,
vectorize
,
browser
,
workflows
,
d1_databases
,
r2_buckets
CRITICAL Migration Rules:
  • new_sqlite_classes
    MUST be in tag "v1" (cannot add SQLite to existing deployed class)
  • name
    and
    class_name
    MUST match exactly
  • ✅ Migrations are atomic (all instances updated simultaneously)
  • ✅ Each tag must be unique, cannot edit/remove previous tags

关键必填配置
jsonc
{
  "durable_objects": {
    "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
  },
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["MyAgent"] }  // 必须包含在第一个迁移版本中
  ]
}
常见可选绑定
ai
vectorize
browser
workflows
d1_databases
r2_buckets
关键迁移规则
  • new_sqlite_classes
    必须在"v1"标签中(无法为已部署的类添加SQLite支持)
  • name
    class_name
    必须完全匹配
  • ✅ 迁移是原子操作(所有实例同时更新)
  • ✅ 每个标签必须唯一,无法编辑/删除之前的标签

Core Agent Patterns

核心Agent模式

Agent Class Basics - Extend
Agent<Env, State>
with lifecycle methods:
  • onStart()
    - Agent initialization
  • onRequest()
    - Handle HTTP requests
  • onConnect/onMessage/onClose()
    - WebSocket handling
  • onStateUpdate()
    - React to state changes
Key Properties:
  • this.env
    - Environment bindings (AI, DB, etc.)
  • this.state
    - Current agent state (read-only)
  • this.setState()
    - Update persisted state
  • this.sql
    - Built-in SQLite database
  • this.name
    - Agent instance identifier
  • this.schedule()
    - Schedule future tasks

Agent类基础 - 继承
Agent<Env, State>
并实现生命周期方法:
  • onStart()
    - Agent初始化
  • onRequest()
    - 处理HTTP请求
  • onConnect/onMessage/onClose()
    - WebSocket处理
  • onStateUpdate()
    - 响应状态变化
关键属性
  • this.env
    - 环境绑定(AI、数据库等)
  • this.state
    - 当前Agent状态(只读)
  • this.setState()
    - 更新持久化状态
  • this.sql
    - 内置SQLite数据库
  • this.name
    - Agent实例标识符
  • this.schedule()
    - 调度未来任务

WebSockets & Real-Time Communication

WebSocket与实时通信

Agents support WebSockets for bidirectional real-time communication. Use when you need:
  • Client can send messages while server streams
  • Agent-initiated messages (notifications, updates)
  • Long-lived connections with state
Basic Pattern:
typescript
export class ChatAgent extends Agent<Env, State> {
  async onConnect(connection: Connection, ctx: ConnectionContext) {
    // Auth check, add to participants, send welcome
  }

  async onMessage(connection: Connection, message: WSMessage) {
    // Process message, update state, broadcast response
  }
}
SSE Alternative: For one-way server → client streaming (simpler, HTTP-based), use Server-Sent Events instead of WebSockets.

Agents支持WebSocket双向实时通信。适用于以下场景:
  • 客户端发送消息时服务器可同时流传输
  • Agent主动发起消息(通知、更新)
  • 带状态的长连接
基础模式
typescript
export class ChatAgent extends Agent<Env, State> {
  async onConnect(connection: Connection, ctx: ConnectionContext) {
    // 权限校验、添加参与者、发送欢迎消息
  }

  async onMessage(connection: Connection, message: WSMessage) {
    // 处理消息、更新状态、广播响应
  }
}
SSE替代方案:对于单向服务器→客户端流传输(更简易、基于HTTP),使用Server-Sent Events而非WebSocket。

State Management

状态管理

Two State Mechanisms:
  1. this.setState(newState)
    - JSON-serializable state (up to 1GB)
    • Automatically persisted, syncs to WebSocket clients
    • Use for: User preferences, session data, small datasets
  2. this.sql
    - Built-in SQLite database (up to 1GB)
    • Tagged template literals prevent SQL injection
    • Use for: Relational data, large datasets, complex queries
State Rules:
  • ✅ JSON-serializable only (objects, arrays, primitives, null)
  • ✅ Persists across restarts, immediately consistent
  • ❌ No functions or circular references
  • ❌ 1GB total limit (state + SQL combined)
SQL Pattern:
typescript
await this.sql`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, email TEXT)`
await this.sql`INSERT INTO users (email) VALUES (${userEmail})`  // ← Prepared statement
const users = await this.sql`SELECT * FROM users WHERE email = ${email}`  // ← Returns array

两种状态机制
  1. this.setState(newState)
    - JSON可序列化状态(最多1GB)
    • 自动持久化,同步到WebSocket客户端
    • 适用场景:用户偏好、会话数据、小型数据集
  2. this.sql
    - 内置SQLite数据库(最多1GB)
    • 标签模板字符串可防止SQL注入
    • 适用场景:关系型数据、大型数据集、复杂查询
状态规则
  • ✅ 仅支持JSON可序列化类型(对象、数组、基本类型、null)
  • ✅ 重启后状态仍保留,即时一致
  • ❌ 不支持函数或循环引用
  • ❌ 每个Agent总状态上限为1GB(状态+SQL)
SQL使用模式
typescript
await this.sql`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, email TEXT)`
await this.sql`INSERT INTO users (email) VALUES (${userEmail})`  // ← 预编译语句
const users = await this.sql`SELECT * FROM users WHERE email = ${email}`  // ← 返回数组

Schedule Tasks

任务调度

Agents can schedule tasks to run in the future using
this.schedule()
.
Agents可使用
this.schedule()
调度未来任务。

Delay (Seconds)

延迟执行(秒)

typescript
export class MyAgent extends Agent {
  async onRequest(request: Request): Promise<Response> {
    // Schedule task to run in 60 seconds
    const { id } = await this.schedule(60, "checkStatus", { requestId: "123" });

    return Response.json({ scheduledTaskId: id });
  }

  // This method will be called in 60 seconds
  async checkStatus(data: { requestId: string }) {
    console.log('Checking status for request:', data.requestId);
    // Perform check, update state, send notification, etc.
  }
}
typescript
export class MyAgent extends Agent {
  async onRequest(request: Request): Promise<Response> {
    // 调度60秒后执行的任务
    const { id } = await this.schedule(60, "checkStatus", { requestId: "123" });

    return Response.json({ scheduledTaskId: id });
  }

  // 该方法将在60秒后被调用
  async checkStatus(data: { requestId: string }) {
    console.log('检查请求状态:', data.requestId);
    // 执行检查、更新状态、发送通知等
  }
}

Specific Date

指定日期执行

typescript
export class MyAgent extends Agent {
  async scheduleReminder(reminderDate: string) {
    const date = new Date(reminderDate);

    const { id } = await this.schedule(date, "sendReminder", {
      message: "Time for your appointment!"
    });

    return id;
  }

  async sendReminder(data: { message: string }) {
    console.log('Sending reminder:', data.message);
    // Send email, push notification, etc.
  }
}
typescript
export class MyAgent extends Agent {
  async scheduleReminder(reminderDate: string) {
    const date = new Date(reminderDate);

    const { id } = await this.schedule(date, "sendReminder", {
      message: "你的预约时间到了!"
    });

    return id;
  }

  async sendReminder(data: { message: string }) {
    console.log('发送提醒:', data.message);
    // 发送邮件、推送通知等
  }
}

Cron Expressions

Cron表达式

typescript
export class MyAgent extends Agent {
  async setupRecurringTasks() {
    // Every 10 minutes
    await this.schedule("*/10 * * * *", "checkUpdates", {});

    // Every day at 8 AM
    await this.schedule("0 8 * * *", "dailyReport", {});

    // Every Monday at 9 AM
    await this.schedule("0 9 * * 1", "weeklyReport", {});

    // Every hour on the hour
    await this.schedule("0 * * * *", "hourlyCheck", {});
  }

  async checkUpdates(data: any) {
    console.log('Checking for updates...');
  }

  async dailyReport(data: any) {
    console.log('Generating daily report...');
  }

  async weeklyReport(data: any) {
    console.log('Generating weekly report...');
  }

  async hourlyCheck(data: any) {
    console.log('Running hourly check...');
  }
}
typescript
export class MyAgent extends Agent {
  async setupRecurringTasks() {
    // 每10分钟执行一次
    await this.schedule("*/10 * * * *", "checkUpdates", {});

    // 每天早上8点执行
    await this.schedule("0 8 * * *", "dailyReport", {});

    // 每周一早上9点执行
    await this.schedule("0 9 * * 1", "weeklyReport", {});

    // 每小时整点执行
    await this.schedule("0 * * * *", "hourlyCheck", {});
  }

  async checkUpdates(data: any) {
    console.log('检查更新...');
  }

  async dailyReport(data: any) {
    console.log('生成日报...');
  }

  async weeklyReport(data: any) {
    console.log('生成周报...');
  }

  async hourlyCheck(data: any) {
    console.log('执行每小时检查...');
  }
}

Managing Scheduled Tasks

管理调度任务

typescript
export class MyAgent extends Agent {
  async manageSchedules() {
    // Get all scheduled tasks
    const allTasks = this.getSchedules();
    console.log('Total tasks:', allTasks.length);

    // Get specific task by ID
    const taskId = "some-task-id";
    const task = await this.getSchedule(taskId);

    if (task) {
      console.log('Task:', task.callback, 'at', new Date(task.time));
      console.log('Payload:', task.payload);
      console.log('Type:', task.type);  // "scheduled" | "delayed" | "cron"

      // Cancel the task
      const cancelled = await this.cancelSchedule(taskId);
      console.log('Cancelled:', cancelled);
    }

    // Get tasks in time range
    const upcomingTasks = this.getSchedules({
      timeRange: {
        start: new Date(),
        end: new Date(Date.now() + 24 * 60 * 60 * 1000)  // Next 24 hours
      }
    });

    console.log('Upcoming tasks:', upcomingTasks.length);

    // Filter by type
    const cronTasks = this.getSchedules({ type: "cron" });
    const delayedTasks = this.getSchedules({ type: "delayed" });
  }
}
Scheduling Constraints:
  • Each task maps to a SQL database row (max 2 MB per task)
  • Total tasks limited by:
    (task_size * count) + other_state < 1GB
  • Cron tasks continue running until explicitly cancelled
  • Callback method MUST exist on Agent class (throws error if missing)
CRITICAL ERROR: If callback method doesn't exist:
typescript
// ❌ BAD: Method doesn't exist
await this.schedule(60, "nonExistentMethod", {});

// ✅ GOOD: Method exists
await this.schedule(60, "existingMethod", {});

async existingMethod(data: any) {
  // Implementation
}

typescript
export class MyAgent extends Agent {
  async manageSchedules() {
    // 获取所有调度任务
    const allTasks = this.getSchedules();
    console.log('总任务数:', allTasks.length);

    // 根据ID获取特定任务
    const taskId = "some-task-id";
    const task = await this.getSchedule(taskId);

    if (task) {
      console.log('任务:', task.callback, '执行时间:', new Date(task.time));
      console.log('负载:', task.payload);
      console.log('类型:', task.type);  // "scheduled" | "delayed" | "cron"

      // 取消任务
      const cancelled = await this.cancelSchedule(taskId);
      console.log('已取消:', cancelled);
    }

    // 获取指定时间范围内的任务
    const upcomingTasks = this.getSchedules({
      timeRange: {
        start: new Date(),
        end: new Date(Date.now() + 24 * 60 * 60 * 1000)  // 未来24小时
      }
    });

    console.log('即将执行的任务数:', upcomingTasks.length);

    // 按类型筛选
    const cronTasks = this.getSchedules({ type: "cron" });
    const delayedTasks = this.getSchedules({ type: "delayed" });
  }
}
调度约束
  • 每个任务对应SQL数据库中的一行(单个任务最大2MB)
  • 总任务数限制:
    (任务大小 * 数量) + 其他状态 < 1GB
  • Cron任务会持续运行,直到显式取消
  • 回调方法必须存在于Agent类中(不存在会抛出错误)
关键错误:如果回调方法不存在:
typescript
// ❌ 错误:方法不存在
await this.schedule(60, "nonExistentMethod", {});

// ✅ 正确:方法已存在
await this.schedule(60, "existingMethod", {});

async existingMethod(data: any) {
  // 实现代码
}

Run Workflows

运行工作流

Agents can trigger asynchronous Cloudflare Workflows.
Agents可触发异步Cloudflare Workflows

Workflow Binding Configuration

工作流绑定配置

wrangler.jsonc
:
jsonc
{
  "workflows": [
    {
      "name": "MY_WORKFLOW",
      "class_name": "MyWorkflow"
    }
  ]
}
If Workflow is in a different script:
jsonc
{
  "workflows": [
    {
      "name": "EMAIL_WORKFLOW",
      "class_name": "EmailWorkflow",
      "script_name": "email-workflows"  // Different project
    }
  ]
}
wrangler.jsonc
jsonc
{
  "workflows": [
    {
      "name": "MY_WORKFLOW",
      "class_name": "MyWorkflow"
    }
  ]
}
如果工作流在其他脚本中:
jsonc
{
  "workflows": [
    {
      "name": "EMAIL_WORKFLOW",
      "class_name": "EmailWorkflow",
      "script_name": "email-workflows"  // 不同项目
    }
  ]
}

Triggering a Workflow

触发工作流

typescript
import { Agent } from "agents";
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers";

interface Env {
  MY_WORKFLOW: Workflow;
  MyAgent: AgentNamespace<MyAgent>;
}

export class MyAgent extends Agent<Env> {
  async onRequest(request: Request): Promise<Response> {
    const userId = new URL(request.url).searchParams.get('userId');

    // Trigger a workflow immediately
    const instance = await this.env.MY_WORKFLOW.create({
      id: `user-${userId}`,
      params: { userId, action: "process" }
    });

    // Or schedule a delayed workflow trigger
    await this.schedule(300, "runWorkflow", { userId });

    return Response.json({ workflowId: instance.id });
  }

  async runWorkflow(data: { userId: string }) {
    const instance = await this.env.MY_WORKFLOW.create({
      id: `delayed-${data.userId}`,
      params: data
    });

    // Monitor workflow status periodically
    await this.schedule("*/5 * * * *", "checkWorkflowStatus", { id: instance.id });
  }

  async checkWorkflowStatus(data: { id: string }) {
    // Check workflow status (see Workflows docs for details)
    console.log('Checking workflow:', data.id);
  }
}

// Workflow definition (can be in same or different file/project)
export class MyWorkflow extends WorkflowEntrypoint<Env> {
  async run(event: WorkflowEvent<{ userId: string }>, step: WorkflowStep) {
    // Workflow implementation
    const result = await step.do('process-data', async () => {
      return { processed: true };
    });

    return result;
  }
}
typescript
import { Agent } from "agents";
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers";

interface Env {
  MY_WORKFLOW: Workflow;
  MyAgent: AgentNamespace<MyAgent>;
}

export class MyAgent extends Agent<Env> {
  async onRequest(request: Request): Promise<Response> {
    const userId = new URL(request.url).searchParams.get('userId');

    // 立即触发工作流
    const instance = await this.env.MY_WORKFLOW.create({
      id: `user-${userId}`,
      params: { userId, action: "process" }
    });

    // 或调度延迟触发的工作流
    await this.schedule(300, "runWorkflow", { userId });

    return Response.json({ workflowId: instance.id });
  }

  async runWorkflow(data: { userId: string }) {
    const instance = await this.env.MY_WORKFLOW.create({
      id: `delayed-${data.userId}`,
      params: data
    });

    // 定期监控工作流状态
    await this.schedule("*/5 * * * *", "checkWorkflowStatus", { id: instance.id });
  }

  async checkWorkflowStatus(data: { id: string }) {
    // 检查工作流状态(参考Workflows文档)
    console.log('检查工作流:', data.id);
  }
}

// 工作流定义(可在同一文件/项目或不同文件/项目中)
export class MyWorkflow extends WorkflowEntrypoint<Env> {
  async run(event: WorkflowEvent<{ userId: string }>, step: WorkflowStep) {
    // 工作流实现
    const result = await step.do('process-data', async () => {
      return { processed: true };
    });

    return result;
  }
}

Agents vs Workflows

Agents vs Workflows

FeatureAgentsWorkflows
PurposeInteractive, user-facingBackground processing
DurationSeconds to hoursMinutes to hours
StateSQLite databaseStep-based checkpoints
InteractionWebSockets, HTTPNo direct interaction
RetryManualAutomatic per step
Use CaseChat, real-time UIETL, batch processing
Best Practice: Use Agents to coordinate multiple Workflows. Agents can trigger, monitor, and respond to Workflow results while maintaining user interaction.

特性AgentsWorkflows
用途交互式、面向用户后台处理
持续时间秒到小时分钟到小时
状态SQLite数据库基于步骤的检查点
交互性WebSocket、HTTP无直接交互
重试手动实现按步骤自动重试
适用场景聊天、实时UIETL、批处理
最佳实践:使用Agents来协调多个Workflows。Agents可触发、监控Workflows并响应其结果,同时保持用户交互。

Browse the Web

网页浏览

Agents can use Browser Rendering for web scraping and automation:
Binding: Add
"browser": { "binding": "BROWSER" }
to wrangler.jsonc Package:
@cloudflare/puppeteer
Use Case: Web scraping, screenshots, automated browsing within agent workflows
See:
cloudflare-browser-rendering
skill for complete Puppeteer + Workers integration guide.

Agents可使用Browser Rendering进行网页抓取与自动化:
绑定配置:在wrangler.jsonc中添加
"browser": { "binding": "BROWSER" }
依赖包
@cloudflare/puppeteer
适用场景:网页抓取、截图、Agent工作流中的自动化浏览
参考
cloudflare-browser-rendering
文档获取完整的Puppeteer + Workers集成指南。

Retrieval Augmented Generation (RAG)

检索增强生成(RAG)

Agents can implement RAG using Vectorize (vector database) + Workers AI (embeddings):
Pattern: Ingest docs → generate embeddings → store in Vectorize → query → retrieve context → pass to AI
Bindings:
  • "ai": { "binding": "AI" }
    - Workers AI for embeddings
  • "vectorize": { "bindings": [{ "binding": "VECTORIZE", "index_name": "my-vectors" }] }
    - Vector search
Typical Workflow:
  1. Generate embeddings with Workers AI (
    @cf/baai/bge-base-en-v1.5
    )
  2. Upsert vectors to Vectorize (
    this.env.VECTORIZE.upsert(vectors)
    )
  3. Query similar vectors (
    this.env.VECTORIZE.query(queryVector, { topK: 5 })
    )
  4. Use retrieved context in AI prompt
See:
cloudflare-vectorize
skill for complete RAG implementation guide.

Agents可使用Vectorize(向量数据库)+ Workers AI(嵌入模型)实现RAG:
模式:导入文档→生成嵌入向量→存储到Vectorize→查询→检索上下文→传入AI
绑定配置
  • "ai": { "binding": "AI" }
    - Workers AI用于生成嵌入向量
  • "vectorize": { "bindings": [{ "binding": "VECTORIZE", "index_name": "my-vectors" }] }
    - 向量搜索
典型工作流
  1. 使用Workers AI生成嵌入向量(
    @cf/baai/bge-base-en-v1.5
  2. 将向量插入Vectorize(
    this.env.VECTORIZE.upsert(vectors)
  3. 查询相似向量(
    this.env.VECTORIZE.query(queryVector, { topK: 5 })
  4. 在AI提示词中使用检索到的上下文
参考
cloudflare-vectorize
文档获取完整的RAG实现指南。

Using AI Models

使用AI模型

Agents can call AI models using:
  • Vercel AI SDK (recommended): Multi-provider, automatic streaming, tool calling
  • Workers AI: Cloudflare's on-platform inference (cost-effective, manual parsing)
Architecture Note: Agents SDK provides infrastructure (WebSockets, state, scheduling). AI inference is a separate layer - use AI SDK for the "brain".
See:
  • ai-sdk-core
    skill for complete AI SDK integration patterns
  • cloudflare-workers-ai
    skill for Workers AI streaming parsing

Agents可通过以下方式调用AI模型:
  • Vercel AI SDK(推荐):多服务商支持、自动流传输、工具调用
  • Workers AI:Cloudflare平台内置推理(成本低廉,需手动解析)
架构说明:Agents SDK提供基础设施(WebSocket、状态、调度)。AI推理是独立的层——使用AI SDK作为"大脑"。
参考
  • ai-sdk-core
    文档获取完整的AI SDK集成模式
  • cloudflare-workers-ai
    文档获取Workers AI流解析方法

Calling Agents

调用Agent

Two Main Patterns:
  1. routeAgentRequest(request, env)
    - Auto-route via URL pattern
    /agents/:agent/:name
    • Example:
      /agents/my-agent/user-123
      routes to MyAgent instance "user-123"
  2. getAgentByName<Env, T>(env.AgentBinding, instanceName)
    - Custom routing
    • Returns agent stub for calling methods or passing requests
    • Example:
      const agent = getAgentByName(env.MyAgent, 'user-${userId}')
Multi-Agent Communication:
typescript
export class AgentA extends Agent<Env> {
  async processData(data: any) {
    const agentB = getAgentByName<Env, AgentB>(this.env.AgentB, 'processor-1');
    return await (await agentB).analyze(data);
  }
}
CRITICAL Security: Always authenticate in Worker BEFORE creating/accessing agents. Agents should assume the caller is authorized.

两种主要模式
  1. routeAgentRequest(request, env)
    - 通过URL模式
    /agents/:agent/:name
    自动路由
    • 示例:
      /agents/my-agent/user-123
      路由到MyAgent实例"user-123"
  2. getAgentByName<Env, T>(env.AgentBinding, instanceName)
    - 自定义路由
    • 返回Agent存根,用于调用方法或传递请求
    • 示例:
      const agent = getAgentByName(env.MyAgent, 'user-${userId}')
多Agent通信
typescript
export class AgentA extends Agent<Env> {
  async processData(data: any) {
    const agentB = getAgentByName<Env, AgentB>(this.env.AgentB, 'processor-1');
    return await (await agentB).analyze(data);
  }
}
关键安全注意事项:始终在Worker中完成身份验证后,再创建/访问Agent。Agent应假设调用者已通过授权。

Client APIs

客户端API

Browser/React Integration:
  • AgentClient
    (from
    agents/client
    ) - WebSocket client for browser
  • agentFetch
    (from
    agents/client
    ) - HTTP requests to agents
  • useAgent
    (from
    agents/react
    ) - React hook for WebSocket connections + state sync
  • useAgentChat
    (from
    agents/ai-react
    ) - Pre-built chat UI hook
All client libraries automatically handle: WebSocket connections, state synchronization, reconnection logic.

浏览器/React集成
  • AgentClient
    (来自
    agents/client
    )- 浏览器端WebSocket客户端
  • agentFetch
    (来自
    agents/client
    )- 向Agent发送HTTP请求
  • useAgent
    (来自
    agents/react
    )- WebSocket连接+状态同步的React钩子
  • useAgentChat
    (来自
    agents/ai-react
    )- 预构建的聊天UI钩子
所有客户端库自动处理:WebSocket连接、状态同步、重连逻辑。

Model Context Protocol (MCP)

模型上下文协议(MCP)

Build MCP servers using the Agents SDK.
使用Agents SDK构建MCP服务器。

MCP Server Setup

MCP服务器设置

bash
npm install @modelcontextprotocol/sdk agents
bash
npm install @modelcontextprotocol/sdk agents

Basic MCP Server

基础MCP服务器

typescript
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export class MyMCP extends McpAgent {
  server = new McpServer({ name: "Demo", version: "1.0.0" });

  async init() {
    // Define a tool
    this.server.tool(
      "add",
      "Add two numbers together",
      {
        a: z.number().describe("First number"),
        b: z.number().describe("Second number")
      },
      async ({ a, b }) => ({
        content: [{ type: "text", text: String(a + b) }]
      })
    );
  }
}
typescript
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export class MyMCP extends McpAgent {
  server = new McpServer({ name: "Demo", version: "1.0.0" });

  async init() {
    // 定义工具
    this.server.tool(
      "add",
      "将两个数字相加",
      {
        a: z.number().describe("第一个数字"),
        b: z.number().describe("第二个数字")
      },
      async ({ a, b }) => ({
        content: [{ type: "text", text: String(a + b) }]
      })
    );
  }
}

Stateful MCP Server

有状态MCP服务器

typescript
type State = { counter: number };

export class StatefulMCP extends McpAgent<Env, State> {
  server = new McpServer({ name: "Counter", version: "1.0.0" });

  initialState: State = { counter: 0 };

  async init() {
    // Resource
    this.server.resource(
      "counter",
      "mcp://resource/counter",
      (uri) => ({
        contents: [{ uri: uri.href, text: String(this.state.counter) }]
      })
    );

    // Tool
    this.server.tool(
      "increment",
      "Increment the counter",
      { amount: z.number() },
      async ({ amount }) => {
        this.setState({
          ...this.state,
          counter: this.state.counter + amount
        });

        return {
          content: [{
            type: "text",
            text: `Counter is now ${this.state.counter}`
          }]
        };
      }
    );
  }
}
typescript
type State = { counter: number };

export class StatefulMCP extends McpAgent<Env, State> {
  server = new McpServer({ name: "Counter", version: "1.0.0" });

  initialState: State = { counter: 0 };

  async init() {
    // 资源
    this.server.resource(
      "counter",
      "mcp://resource/counter",
      (uri) => ({
        contents: [{ uri: uri.href, text: String(this.state.counter) }]
      })
    );

    // 工具
    this.server.tool(
      "increment",
      "递增计数器",
      { amount: z.number() },
      async ({ amount }) => {
        this.setState({
          ...this.state,
          counter: this.state.counter + amount
        });

        return {
          content: [{
            type: "text",
            text: `计数器当前值为 ${this.state.counter}`
          }]
        };
      }
    );
  }
}

MCP Transport Configuration

MCP传输配置

typescript
import { Hono } from 'hono';

const app = new Hono();

// Modern streamable HTTP transport (recommended)
app.mount('/mcp', MyMCP.serve('/mcp').fetch, { replaceRequest: false });

// Legacy SSE transport (deprecated)
app.mount('/sse', MyMCP.serveSSE('/sse').fetch, { replaceRequest: false });

export default app;
Transport Comparison:
  • /mcp: Streamable HTTP (modern, recommended)
  • /sse: Server-Sent Events (legacy, deprecated)
typescript
import { Hono } from 'hono';

const app = new Hono();

// 现代可流传输HTTP传输(推荐)
app.mount('/mcp', MyMCP.serve('/mcp').fetch, { replaceRequest: false });

// 遗留SSE传输(已废弃)
app.mount('/sse', MyMCP.serveSSE('/sse').fetch, { replaceRequest: false });

export default app;
传输对比
  • /mcp:可流传输HTTP(现代、推荐)
  • /sse:Server-Sent Events(遗留、已废弃)

MCP with OAuth

带OAuth的MCP

typescript
import { OAuthProvider } from '@cloudflare/workers-oauth-provider';

export default new OAuthProvider({
  apiHandlers: {
    '/sse': MyMCP.serveSSE('/sse'),
    '/mcp': MyMCP.serve('/mcp')
  },
  // OAuth configuration
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  // ... other OAuth settings
});
typescript
import { OAuthProvider } from '@cloudflare/workers-oauth-provider';

export default new OAuthProvider({
  apiHandlers: {
    '/sse': MyMCP.serveSSE('/sse'),
    '/mcp': MyMCP.serve('/mcp')
  },
  // OAuth配置
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  // ... 其他OAuth设置
});

Testing MCP Server

测试MCP服务器

bash
undefined
bash
undefined

Run MCP inspector

运行MCP检查器

npx @modelcontextprotocol/inspector@latest
npx @modelcontextprotocol/inspector@latest

**Cloudflare's MCP Servers**: See [reference](https://developers.cloudflare.com/agents/model-context-protocol/mcp-servers-for-cloudflare/) for production examples.

---

**Cloudflare官方MCP服务器**:查看[参考示例](https://developers.cloudflare.com/agents/model-context-protocol/mcp-servers-for-cloudflare/)获取生产环境示例。

---

Critical Rules

关键规则

Always Do ✅

必须遵循 ✅

  1. Export Agent class - Must be exported for binding to work
  2. Include new_sqlite_classes in v1 migration - Cannot add SQLite later
  3. Match binding name to class name - Prevents "binding not found" errors
  4. Authenticate in Worker, not Agent - Security best practice
  5. Use tagged template literals for SQL - Prevents SQL injection
  6. Handle WebSocket disconnections - State persists, connections don't
  7. Verify scheduled task callback exists - Throws error if method missing
  8. Use global unique instance names - Same name = same agent globally
  9. Check state size limits - Max 1GB total per agent
  10. Monitor task payload size - Max 2MB per scheduled task
  11. Use workflow bindings correctly - Must be configured in wrangler.jsonc
  12. Create Vectorize indexes before inserting - Required for metadata filtering
  13. Close browser instances - Prevent resource leaks
  14. Use setState() for persistence - Don't just modify this.state
  15. Test migrations locally first - Migrations are atomic, can't rollback
  1. 导出Agent类 - 必须导出才能完成绑定
  2. 在v1迁移中包含new_sqlite_classes - 后续无法添加SQLite支持
  3. 绑定名称与类名匹配 - 避免"binding not found"错误
  4. 在Worker中完成身份验证,而非Agent - 安全最佳实践
  5. 使用标签模板字符串编写SQL - 防止SQL注入
  6. 处理WebSocket断开连接 - 状态会保留,但连接不会
  7. 验证调度任务的回调方法存在 - 方法缺失会抛出错误
  8. 使用全局唯一的实例名称 - 相同名称对应同一个全局Agent
  9. 检查状态大小限制 - 每个Agent总状态最大1GB
  10. 监控任务负载大小 - 单个调度任务最大2MB
  11. 正确配置工作流绑定 - 必须在wrangler.jsonc中配置
  12. 插入向量前创建Vectorize索引 - 元数据过滤需要索引
  13. 关闭浏览器实例 - 防止资源泄漏
  14. 使用setState()持久化状态 - 不要直接修改this.state
  15. 先在本地测试迁移 - 迁移是原子操作,无法回滚

Never Do ❌

禁止操作 ❌

  1. Don't add SQLite to existing deployed class - Must be in first migration
  2. Don't gradually deploy migrations - Atomic only
  3. Don't skip authentication in Worker - Always auth before agent access
  4. Don't construct SQL strings manually - Use tagged templates
  5. Don't exceed 1GB state per agent - Hard limit
  6. Don't schedule tasks with non-existent callbacks - Runtime error
  7. Don't assume same name = different agent - Global uniqueness
  8. Don't use SSE for MCP - Deprecated, use /mcp transport
  9. Don't forget browser binding - Required for web browsing
  10. Don't modify this.state directly - Use setState() instead

  1. 不要为已部署的类添加SQLite支持 - 必须在第一个迁移版本中添加
  2. 不要逐步部署迁移 - 仅支持原子部署
  3. 不要在Worker中跳过身份验证 - 访问Agent前必须完成身份验证
  4. 不要手动拼接SQL字符串 - 使用标签模板字符串
  5. 不要超过每个Agent 1GB状态限制 - 硬限制
  6. 不要调度不存在回调方法的任务 - 运行时会出错
  7. 不要假设相同名称对应不同Agent - 全局唯一
  8. 不要为MCP使用SSE传输 - 已废弃,使用/mcp传输
  9. 不要忘记配置浏览器绑定 - 网页浏览需要该绑定
  10. 不要直接修改this.state - 使用setState()替代

Known Issues Prevention

已知问题预防

This skill prevents 16+ documented issues:
本文档可预防**16+**个已记录的问题:

Issue 1: Migrations Not Atomic

问题1:迁移非原子

Error: "Cannot gradually deploy migration" Source: https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/ Why: Migrations apply to all instances simultaneously Prevention: Deploy migrations independently of code changes, use
npx wrangler versions deploy
错误信息:"Cannot gradually deploy migration" 来源https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/ 原因:迁移会同时应用到所有实例 预防方案:独立于代码变更部署迁移,使用
npx wrangler versions deploy

Issue 2: Missing new_sqlite_classes

问题2:缺少new_sqlite_classes

Error: "Cannot enable SQLite on existing class" Source: https://developers.cloudflare.com/agents/api-reference/configuration/ Why: SQLite must be enabled in first migration Prevention: Include
new_sqlite_classes
in tag "v1" migration
错误信息:"Cannot enable SQLite on existing class" 来源https://developers.cloudflare.com/agents/api-reference/configuration/ 原因:必须在第一个迁移版本中启用SQLite 预防方案:在"v1"迁移标签中包含
new_sqlite_classes

Issue 3: Agent Class Not Exported

问题3:Agent类未导出

Error: "Binding not found" or "Cannot access undefined" Source: https://developers.cloudflare.com/agents/api-reference/agents-api/ Why: Durable Objects require exported class Prevention:
export class MyAgent extends Agent
(with export keyword)
错误信息:"Binding not found"或"Cannot access undefined" 来源https://developers.cloudflare.com/agents/api-reference/agents-api/ 原因:Durable Objects要求类必须导出 预防方案
export class MyAgent extends Agent
(包含export关键字)

Issue 4: Binding Name Mismatch

问题4:绑定名称不匹配

Error: "Binding 'X' not found" Source: https://developers.cloudflare.com/agents/api-reference/configuration/ Why: Binding name must match class name exactly Prevention: Ensure
name
and
class_name
are identical in wrangler.jsonc
错误信息:"Binding 'X' not found" 来源https://developers.cloudflare.com/agents/api-reference/configuration/ 原因:绑定名称必须与类名完全一致 预防方案:确保wrangler.jsonc中的
name
class_name
完全相同

Issue 5: Global Uniqueness Not Understood

问题5:未理解全局唯一性

Error: Unexpected behavior with agent instances Source: https://developers.cloudflare.com/agents/api-reference/agents-api/ Why: Same name always returns same agent instance globally Prevention: Use unique identifiers (userId, sessionId) for instance names
错误信息:Agent实例行为不符合预期 来源https://developers.cloudflare.com/agents/api-reference/agents-api/ 原因:相同名称始终对应同一个全局Agent实例 预防方案:使用唯一标识符(用户ID、会话ID)作为实例名称

Issue 6: WebSocket State Not Persisted

问题6:WebSocket状态未持久化

Error: Connection state lost after disconnect Source: https://developers.cloudflare.com/agents/api-reference/websockets/ Why: WebSocket connections don't persist, but agent state does Prevention: Store important data in agent state via setState(), not connection state
错误信息:断开连接后连接状态丢失 来源https://developers.cloudflare.com/agents/api-reference/websockets/ 原因:WebSocket连接不会持久化,但Agent状态会 预防方案:将重要数据通过setState()存储到Agent状态中,而非连接状态

Issue 7: Scheduled Task Callback Doesn't Exist

问题7:调度任务的回调方法不存在

Error: "Method X does not exist on Agent" Source: https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ Why: this.schedule() calls method that isn't defined Prevention: Ensure callback method exists before scheduling
错误信息:"Method X does not exist on Agent" 来源https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ 原因:this.schedule()调用了未定义的方法 预防方案:调度前确保回调方法已存在

Issue 8: State Size Limit Exceeded

问题8:状态大小超出限制

Error: "Maximum database size exceeded" Source: https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/ Why: Agent state + scheduled tasks exceed 1GB Prevention: Monitor state size, use external storage (D1, R2) for large data
错误信息:"Maximum database size exceeded" 来源https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/ 原因:Agent状态+调度任务超出1GB 预防方案:监控状态大小,使用外部存储(D1、R2)存储大型数据

Issue 9: Scheduled Task Too Large

问题9:调度任务过大

Error: "Task payload exceeds 2MB" Source: https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ Why: Each task maps to database row with 2MB limit Prevention: Keep task payloads minimal, store large data in agent state/SQL
错误信息:"Task payload exceeds 2MB" 来源https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ 原因:每个任务对应数据库中的一行,最大2MB 预防方案:保持任务负载最小,将大型数据存储到Agent状态/SQL中

Issue 10: Workflow Binding Missing

问题10:工作流绑定缺失

Error: "Cannot read property 'create' of undefined" Source: https://developers.cloudflare.com/agents/api-reference/run-workflows/ Why: Workflow binding not configured in wrangler.jsonc Prevention: Add workflow binding before using this.env.WORKFLOW
错误信息:"Cannot read property 'create' of undefined" 来源https://developers.cloudflare.com/agents/api-reference/run-workflows/ 原因:未在wrangler.jsonc中配置工作流绑定 预防方案:使用this.env.WORKFLOW前添加工作流绑定

Issue 11: Browser Binding Required

问题11:缺少浏览器绑定

Error: "BROWSER binding undefined" Source: https://developers.cloudflare.com/agents/api-reference/browse-the-web/ Why: Browser Rendering requires explicit binding Prevention: Add
"browser": { "binding": "BROWSER" }
to wrangler.jsonc
错误信息:"BROWSER binding undefined" 来源https://developers.cloudflare.com/agents/api-reference/browse-the-web/ 原因:Browser Rendering需要显式绑定 预防方案:在wrangler.jsonc中添加
"browser": { "binding": "BROWSER" }

Issue 12: Vectorize Index Not Found

问题12:Vectorize索引不存在

Error: "Index does not exist" Source: https://developers.cloudflare.com/agents/api-reference/rag/ Why: Vectorize index must be created before use Prevention: Run
wrangler vectorize create
before deploying agent
错误信息:"Index does not exist" 来源https://developers.cloudflare.com/agents/api-reference/rag/ 原因:使用前必须创建Vectorize索引 预防方案:部署Agent前运行
wrangler vectorize create

Issue 13: MCP Transport Confusion

问题13:MCP传输混淆

Error: "SSE transport deprecated" Source: https://developers.cloudflare.com/agents/model-context-protocol/transport/ Why: SSE transport is legacy, streamable HTTP is recommended Prevention: Use
/mcp
endpoint with
MyMCP.serve('/mcp')
, not
/sse
错误信息:"SSE transport deprecated" 来源https://developers.cloudflare.com/agents/model-context-protocol/transport/ 原因:SSE传输是遗留方案,推荐使用可流传输HTTP 预防方案:使用
MyMCP.serve('/mcp')
的/mcp端点,而非/sse

Issue 14: Authentication Bypass

问题14:身份验证绕过

Error: Security vulnerability Source: https://developers.cloudflare.com/agents/api-reference/calling-agents/ Why: Authentication done in Agent instead of Worker Prevention: Always authenticate in Worker before calling getAgentByName()
错误信息:安全漏洞 来源https://developers.cloudflare.com/agents/api-reference/calling-agents/ 原因:在Agent中而非Worker中完成身份验证 预防方案:调用getAgentByName()前始终在Worker中完成身份验证

Issue 15: Instance Naming Errors

问题15:实例命名错误

Error: Cross-user data leakage Source: https://developers.cloudflare.com/agents/api-reference/calling-agents/ Why: Poor instance naming allows access to wrong agent Prevention: Use namespaced names like
user-${userId}
, validate ownership
错误信息:跨用户数据泄露 来源https://developers.cloudflare.com/agents/api-reference/calling-agents/ 原因:实例命名不当导致访问错误的Agent 预防方案:使用命名空间名称如
user-${userId}
,验证所有权

Issue 16: Workers AI Streaming Requires Manual Parsing

问题16:Workers AI流需要手动解析

Error: "Cannot read property 'response' of undefined" or empty AI responses Source: https://developers.cloudflare.com/workers-ai/platform/streaming/ Why: Workers AI returns streaming responses as
Uint8Array
in Server-Sent Events (SSE) format, not plain objects Prevention: Use
TextDecoder
+ SSE parsing pattern (see "Workers AI (Alternative for AI)" section above)
The problem - Attempting to access stream chunks directly fails:
typescript
const response = await env.AI.run(model, { stream: true });
for await (const chunk of response) {
  console.log(chunk.response);  // ❌ undefined - chunk is Uint8Array, not object
}
The solution - Parse SSE format manually:
typescript
const response = await env.AI.run(model, { stream: true });
for await (const chunk of response) {
  const text = new TextDecoder().decode(chunk);  // Step 1: Uint8Array → string
  if (text.startsWith('data: ')) {              // Step 2: Check SSE format
    const jsonStr = text.slice(6).trim();       // Step 3: Extract JSON from "data: {...}"
    if (jsonStr === '[DONE]') break;            // Step 4: Handle termination
    const data = JSON.parse(jsonStr);           // Step 5: Parse JSON
    if (data.response) {                        // Step 6: Extract .response field
      fullResponse += data.response;
    }
  }
}
Better alternative: Use Vercel AI SDK which handles this automatically:
typescript
import { streamText } from 'ai';
import { createCloudflare } from '@ai-sdk/cloudflare';

const cloudflare = createCloudflare();
const result = streamText({
  model: cloudflare('@cf/meta/llama-3-8b-instruct', { binding: env.AI }),
  messages
});
// No manual parsing needed ✅
When to accept manual parsing:
  • Cost is critical (Workers AI is cheaper)
  • No external dependencies allowed
  • Willing to maintain SSE parsing code
When to use AI SDK instead:
  • Value developer time over compute cost
  • Want automatic streaming
  • Need multi-provider support

错误信息:"Cannot read property 'response' of undefined"或AI响应为空 来源https://developers.cloudflare.com/workers-ai/platform/streaming/ 原因:Workers AI以Server-Sent Events(SSE)格式返回
Uint8Array
流响应,而非普通对象 预防方案:使用
TextDecoder
+ SSE解析模式(参见上方"Workers AI(AI推理的替代方案)"章节)
问题表现 - 直接访问流块会失败:
typescript
const response = await env.AI.run(model, { stream: true });
for await (const chunk of response) {
  console.log(chunk.response);  // ❌ undefined - chunk是Uint8Array,不是对象
}
解决方案 - 手动解析SSE格式:
typescript
const response = await env.AI.run(model, { stream: true });
for await (const chunk of response) {
  const text = new TextDecoder().decode(chunk);  // 步骤1:Uint8Array → 字符串
  if (text.startsWith('data: ')) {              // 步骤2:检查SSE格式
    const jsonStr = text.slice(6).trim();       // 步骤3:从"data: {...}"中提取JSON
    if (jsonStr === '[DONE]') break;            // 步骤4:处理终止信号
    const data = JSON.parse(jsonStr);           // 步骤5:解析JSON
    if (data.response) {                        // 步骤6:提取.response字段
      fullResponse += data.response;
    }
  }
}
更好的替代方案:使用Vercel AI SDK自动处理:
typescript
import { streamText } from 'ai';
import { createCloudflare } from '@ai-sdk/cloudflare';

const cloudflare = createCloudflare();
const result = streamText({
  model: cloudflare('@cf/meta/llama-3-8b-instruct', { binding: env.AI }),
  messages
});
// 无需手动解析 ✅
适合手动解析的场景
  • 成本敏感(Workers AI更便宜)
  • 不允许外部依赖
  • 愿意维护SSE解析代码
适合使用AI SDK的场景
  • 更看重开发时间而非计算成本
  • 需要自动流传输
  • 需要多服务商支持

Dependencies

依赖

Required

必填

  • cloudflare-worker-base - Foundation (Hono, Vite, Workers setup)
  • cloudflare-worker-base - 基础框架(Hono、Vite、Workers配置)

Optional (by feature)

可选(按功能分类)

  • cloudflare-workers-ai - For Workers AI model calls
  • cloudflare-vectorize - For RAG with Vectorize
  • cloudflare-d1 - For additional persistent storage beyond agent state
  • cloudflare-r2 - For file storage
  • cloudflare-queues - For message queues
  • cloudflare-workers-ai - 用于调用Workers AI模型
  • cloudflare-vectorize - 用于使用Vectorize实现RAG
  • cloudflare-d1 - 用于Agent状态之外的额外持久化存储
  • cloudflare-r2 - 用于文件存储
  • cloudflare-queues - 用于消息队列

NPM Packages

NPM包

  • agents
    - Agents SDK (required)
  • @modelcontextprotocol/sdk
    - For building MCP servers
  • @cloudflare/puppeteer
    - For web browsing
  • ai
    - AI SDK for model calls
  • @ai-sdk/openai
    - OpenAI models
  • @ai-sdk/anthropic
    - Anthropic models

  • agents
    - Agents SDK(必填)
  • @modelcontextprotocol/sdk
    - 用于构建MCP服务器
  • @cloudflare/puppeteer
    - 用于网页浏览
  • ai
    - 用于调用AI模型的AI SDK
  • @ai-sdk/openai
    - OpenAI模型支持
  • @ai-sdk/anthropic
    - Anthropic模型支持

Official Documentation

官方文档

Bundled Resources

捆绑资源

Templates (templates/)

模板(templates/)

  • wrangler-agents-config.jsonc
    - Complete configuration example
  • basic-agent.ts
    - Minimal HTTP agent
  • websocket-agent.ts
    - WebSocket handlers
  • state-sync-agent.ts
    - State management patterns
  • scheduled-agent.ts
    - Task scheduling
  • workflow-agent.ts
    - Workflow integration
  • browser-agent.ts
    - Web browsing
  • rag-agent.ts
    - RAG implementation
  • chat-agent-streaming.ts
    - Streaming chat
  • calling-agents-worker.ts
    - Agent routing
  • react-useagent-client.tsx
    - React client
  • mcp-server-basic.ts
    - MCP server
  • hitl-agent.ts
    - Human-in-the-loop
  • wrangler-agents-config.jsonc
    - 完整配置示例
  • basic-agent.ts
    - 极简HTTP Agent
  • websocket-agent.ts
    - WebSocket处理器
  • state-sync-agent.ts
    - 状态管理模式
  • scheduled-agent.ts
    - 任务调度
  • workflow-agent.ts
    - 工作流集成
  • browser-agent.ts
    - 网页浏览
  • rag-agent.ts
    - RAG实现
  • chat-agent-streaming.ts
    - 流传输聊天
  • calling-agents-worker.ts
    - Agent路由
  • react-useagent-client.tsx
    - React客户端
  • mcp-server-basic.ts
    - MCP服务器
  • hitl-agent.ts
    - 人在环中模式

References (references/)

参考文档(references/)

  • agent-class-api.md
    - Complete Agent class reference
  • client-api-reference.md
    - Browser client APIs
  • state-management-guide.md
    - State and SQL deep dive
  • websockets-sse.md
    - WebSocket vs SSE comparison
  • scheduling-api.md
    - Task scheduling details
  • workflows-integration.md
    - Workflows guide
  • browser-rendering.md
    - Web browsing patterns
  • rag-patterns.md
    - RAG best practices
  • mcp-server-guide.md
    - MCP server development
  • mcp-tools-reference.md
    - MCP tools API
  • hitl-patterns.md
    - Human-in-the-loop workflows
  • best-practices.md
    - Production patterns
  • agent-class-api.md
    - 完整Agent类参考
  • client-api-reference.md
    - 浏览器客户端API
  • state-management-guide.md
    - 状态与SQL深度指南
  • websockets-sse.md
    - WebSocket vs SSE对比
  • scheduling-api.md
    - 任务调度详情
  • workflows-integration.md
    - 工作流指南
  • browser-rendering.md
    - 网页浏览模式
  • rag-patterns.md
    - RAG最佳实践
  • mcp-server-guide.md
    - MCP服务器开发
  • mcp-tools-reference.md
    - MCP工具API
  • hitl-patterns.md
    - 人在环中工作流
  • best-practices.md
    - 生产环境模式

Examples (examples/)

示例(examples/)

  • chat-bot-complete.md
    - Full chat agent
  • multi-agent-workflow.md
    - Agent orchestration
  • scheduled-reports.md
    - Recurring tasks
  • browser-scraper-agent.md
    - Web scraping
  • rag-knowledge-base.md
    - RAG system
  • mcp-remote-server.md
    - Production MCP server

Last Verified: 2025-10-21 Package Versions: agents@latest Compliance: Cloudflare Agents SDK official documentation
  • chat-bot-complete.md
    - 完整聊天Agent
  • multi-agent-workflow.md
    - Agent编排
  • scheduled-reports.md
    - 周期性任务
  • browser-scraper-agent.md
    - 网页抓取
  • rag-knowledge-base.md
    - RAG知识库
  • mcp-remote-server.md
    - 生产环境MCP服务器

最后验证:2025-10-21 包版本:agents@latest 合规性:符合Cloudflare Agents SDK官方文档