mcpField
C
cloudflare-agents

cloudflare-agents

github.com/jackspaceAgent 工作流1641 次安装12 周前更新
代码仓库

关于 cloudflare-agents

Cloudflare Agents SDK 用于在 Cloudflare Workers 和 Durable Objects 上构建有状态的 AI Agent,面向开发者。它结合持久化状态、实时通信、任务调度与 MCP 服务构建能力。

主要功能

  1. 01基于 Durable Objects 构建 Agent
  2. 02通过 WebSockets 和 SSE 实时通信
  3. 03使用 SQLite 持久化状态
  4. 04按延迟、日期或 cron 调度任务
  5. 05触发异步 Cloudflare Workflows
  6. 06构建 MCP 服务

适用场景

  1. 01构建实时聊天 Agent
  2. 02安排定时检查或提醒
  3. 03将交互式 Agent 与后台工作流结合
  4. 04实现支持人工审核的流程

MCP 相关

可用于构建实现 Model Context Protocol 的 MCP 服务,供 MCP 客户端连接。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jackspace/claudeskillz --skill cloudflare-agents

安装后在 Claude Code 中输入/cloudflare-agents确认已加载。

附带文件README.mdSKILL.json

详细介绍

Cloudflare Agents SDK

状态:已可用于生产环境 ✅ 最后更新:2025-10-21 依赖项:cloudflare-worker-base(推荐) 最新版本:agents@latest,@modelcontextprotocol/sdk@latest 已通过生产环境测试:Cloudflare 自己的 MCP 服务(https://github.com/cloudflare/mcp-server-cloudflare)


什么是 Cloudflare Agents?

Cloudflare Agents SDK 可用于构建由 AI 驱动、运行在 Cloudflare Workers + Durable Objects 上的自主 Agent。Agent 可以:

  • 实时通信,通过 WebSockets 和 Server-Sent Events
  • 持久化状态,使用内置 SQLite 数据库(每个 Agent 最大 1GB)
  • 安排任务,使用延迟时间、指定日期或 cron 表达式
  • 运行工作流,通过触发异步 Cloudflare Workflows
  • 浏览网页,使用 Browser Rendering API + Puppeteer
  • 实现 RAG,使用 Vectorize 向量数据库 + Workers AI 嵌入
  • 构建 MCP 服务,实现 Model Context Protocol
  • 支持人在回路中的模式,用于审核和批准
  • 扩展到数百万个独立的 Agent 实例,覆盖全球

每个 Agent 实例都是一个全局唯一的有状态微型服务,可运行数秒、数分钟或数小时。


快速开始(10 分钟)

1. 使用模板搭建项目
npm create cloudflare@latest my-agent -- \
  --template=cloudflare/agents-starter \
  --ts \
  --git \
  --deploy false

此操作会创建:

  • 完整的 Agent 项目结构
  • TypeScript 配置
  • 带有 Durable Objects 绑定的 wrangler.jsonc
  • 示例聊天 Agent 实现
  • 带有 useAgent hook 的 React 客户端
2. 或添加到现有 Worker
cd my-existing-worker
npm install agents

然后创建一个 Agent 类:

// 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. 配置 Durable Objects 绑定

创建或更新 wrangler.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
    }
  ]
}

重要配置规则:

  • ✅ name 和 class_name 必须相同
  • ✅ new_sqlite_classes 必须位于第一个迁移中(之后无法添加)
  • ✅ Agent 类必须导出(否则绑定会失败)
  • ✅ 迁移标签不能重复使用(每次迁移都需要唯一标签)
4. 部署
npx wrangler@latest deploy

你的 Agent 现已运行于:https://my-agent.<subdomain>.workers.dev


配置详解

完整的 wrangler.jsonc 示例
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-agent",
  "main": "src/index.ts",
  "account_id": "YOUR_ACCOUNT_ID",
  "compatibility_date": "2025-10-21",
  "compatibility_flags": ["nodejs_compat"],

  // Durable Objects configuration (REQUIRED)
  "durable_objects": {
    "bindings": [
      {
        "name": "MyAgent",
        "class_name": "MyAgent"
      }
    ]
  },

  // Migrations (REQUIRED)
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["MyAgent"]  // Enables state persistence
    }
  ],

  // Optional: Workers AI binding (for AI model calls)
  "ai": {
    "binding": "AI"
  },

  // Optional: Vectorize binding (for RAG)
  "vectorize": {
    "bindings": [
      {
        "binding": "VECTORIZE",
        "index_name": "my-agent-vectors"
      }
    ]
  },

  // Optional: Browser Rendering binding (for web browsing)
  "browser": {
    "binding": "BROWSER"
  },

  // Optional: Workflows binding (for async workflows)
  "workflows": [
    {
      "name": "MY_WORKFLOW",
      "class_name": "MyWorkflow",
      "script_name": "my-workflow-script"  // If in different project
    }
  ],

  // Optional: D1 binding (for additional persistent data)
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "my-agent-db",
      "database_id": "your-database-id"
    }
  ],

  // Optional: R2 binding (for file storage)
  "r2_buckets": [
    {
      "binding": "BUCKET",
      "bucket_name": "my-agent-files"
    }
  ],

  // Optional: Environment variables
  "vars": {
    "ENVIRONMENT": "production"
  },

  // Optional: Secrets (set with: wrangler secret put KEY)
  // OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.

  // Observability
  "observability": {
    "enabled": true
  }
}
迁移最佳实践

原子部署:迁移是原子操作,无法逐步部署。

{
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["MyAgent"]  // Initial: enable SQLite
    },
    {
      "tag": "v2",
      "renamed_classes": [
        {"from": "MyAgent", "to": "MyRenamedAgent"}
      ]
    },
    {
      "tag": "v3",
      "deleted_classes": ["OldAgent"]
    },
    {
      "tag": "v4",
      "transferred_classes": [
        {
          "from": "AgentInOldScript",
          "from_script": "old-worker",
          "to": "AgentInNewScript"
        }
      ]
    }
  ]
}

迁移规则:

  • ✅ 每次迁移都需要唯一的 tag
  • ✅ 无法为已部署的现有类启用 SQLite(必须在第一次迁移中启用)
  • ✅ 部署期间按顺序应用迁移
  • ✅ 无法编辑或移除之前的迁移标签
  • ❌ 切勿逐步部署新迁移(只能原子部署)
特定环境的迁移
{
  "migrations": [{"tag": "v1", "new_sqlite_classes": ["MyAgent"]}],
  "env": {
    "staging": {
      "migrations": [
        {"tag": "v1", "new_sqlite_classes": ["MyAgent"]},
        {"tag": "v2-staging", "renamed_classes": [{"from": "MyAgent", "to": "StagingAgent"}]}
      ]
    }
  }
}

Agent 类 API

Agent 类是 Agents SDK 的基础。继承它即可创建 Agent。

基本 Agent 结构
import { Agent } from "agents";

interface Env {
  // Environment variables and bindings
  OPENAI_API_KEY: string;
  AI: Ai;
  VECTORIZE: Vectorize;
  DB: D1Database;
}

interface State {
  // Your agent's persistent state
  counter: number;
  messages: string[];
  lastUpdated: Date | null;
}

export class MyAgent extends Agent<Env, State> {
  // Optional: Set initial state (first time agent is created)
  initialState: State = {
    counter: 0,
    messages: [],
    lastUpdated: null
  };

  // Optional: Called when agent instance starts or wakes from hibernation
  async onStart() {
    console.log('Agent started:', this.name, 'State:', this.state);
  }

  // Handle HTTP requests
  async onRequest(request: Request): Promise<Response> {
    return Response.json({ message: "Hello from Agent", state: this.state });
  }

  // Handle WebSocket connections (optional)
  async onConnect(connection: Connection, ctx: ConnectionContext) {
    console.log('Client connected:', connection.id);
    // Connections are automatically accepted
  }

  // Handle WebSocket messages (optional)
  async onMessage(connection: Connection, message: WSMessage) {
    if (typeof message === 'string') {
      connection.send(`Echo: ${message}`);
    }
  }

  // Handle WebSocket errors (optional)
  async onError(connection: Connection, error: unknown): Promise<void> {
    console.error('Connection error:', error);
  }

  // Handle WebSocket close (optional)
  async onClose(connection: Connection, code: number, reason: string, wasClean: boolean): Promise<void> {
    console.log('Connection closed:', code, reason);
  }

  // Called when state is updated from any source (optional)
  onStateUpdate(state: State, source: "server" | Connection) {
    console.log('State updated:', state, 'Source:', source);
  }

  // Custom methods (call from any handler)
  async customMethod(data: any) {
    this.setState({
      ...this.state,
      counter: this.state.counter + 1,
      lastUpdated: new Date()
    });
  }
}
访问 Agent 属性

在任何 Agent 方法中:

export class MyAgent extends Agent<Env, State> {
  async someMethod() {
    // Access environment variables and bindings
    const apiKey = this.env.OPENAI_API_KEY;
    const ai = this.env.AI;

    // Access current state (read-only)
    const counter = this.state.counter;

    // Update state (persisted automatically)
    this.setState({ ...this.state, counter: counter + 1 });

    // Access SQL database
    const results = await this.sql`SELECT * FROM users`;

    // Get agent instance name
    const instanceName = this.name;  // e.g., "user-123"

    // Schedule tasks
    await this.schedule(60, "runLater", { data: "example" });

    // Call other methods
    await this.customMethod({ foo: "bar" });
  }
}

HTTP 与 Server-Sent Events

HTTP 请求处理
export class MyAgent extends Agent<Env> {
  async onRequest(request: Request): Promise<Response> {
    const url = new URL(request.url);
    const method = request.method;

    if (method === "POST" && url.pathname === "/increment") {
      const counter = (this.state.counter || 0) + 1;
      this.setState({ ...this.state, counter });
      return Response.json({ counter });
    }

    if (method === "GET" && url.pathname === "/status") {
      return Response.json({ state: this.state, name: this.name });
    }

    return new Response("Not Found", { status: 404 });
  }
}
Server-Sent Events(SSE)流式传输
export class MyAgent extends Agent<Env> {
  async onRequest(request: Request): Promise<Response> {
    const stream = new ReadableStream({
      async start(controller) {
        const encoder = new TextEncoder();

        // Send events to client
        controller.enqueue(encoder.encode('data: {"message": "Starting"}\n\n'));

        await new Promise(resolve => setTimeout(resolve, 1000));

        controller.enqueue(encoder.encode('data: {"message": "Processing"}\n\n'));

        await new Promise(resolve => setTimeout(resolve, 1000));

        controller.enqueue(encoder.encode('data: {"message": "Complete"}\n\n'));

        controller.close();
      }
    });

    return new Response(stream, {
      headers: {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
      }
    });
  }
}

SSE 与 WebSockets 对比:

特性SSEWebSockets
方向仅服务器 → 客户端双向
协议HTTPws:// 或 wss://
重新连接自动手动
二进制数据有限完全支持
使用场景流式响应、通知聊天、实时协作

建议:大多数 Agent 应用都使用 WebSockets(全双工,更适合长会话)。


WebSockets

完整的 WebSocket 示例
import { Agent, Connection, ConnectionContext, WSMessage } from "agents";

interface ChatState {
  messages: Array<{ id: string; text: string; sender: string; timestamp: number }>;
  participants: string[];
}

export class ChatAgent extends Agent<Env, ChatState> {
  initialState: ChatState = {
    messages: [],
    participants: []
  };

  async onConnect(connection: Connection, ctx: ConnectionContext) {
    // Access original HTTP request for auth
    const authHeader = ctx.request.headers.get('Authorization');
    const userId = ctx.request.headers.get('X-User-ID') || 'anonymous';

    // Connections are automatically accepted
    // Optionally close connection if unauthorized:
    // if (!authHeader) {
    //   connection.close(401, "Unauthorized");
    //   return;
    // }

    // Add to participants
    this.setState({
      ...this.state,
      participants: [...this.state.participants, userId]
    });

    // Send welcome message
    connection.send(JSON.stringify({
      type: 'welcome',
      message: 'Connected to chat',
      participants: this.state.participants
    }));
  }

  async onMessage(connection: Connection, message: WSMessage) {
    if (typeof message === 'string') {
      try {
        const data = JSON.parse(message);

        if (data.type === 'chat') {
          // Add message to state
          const newMessage = {
            id: crypto.randomUUID(),
            text: data.text,
            sender: data.sender || 'anonymous',
            timestamp: Date.now()
          };

          this.setState({
            ...this.state,
            messages: [...this.state.messages, newMessage]
          });

          // Broadcast to this connection (state sync will broadcast to all)
          connection.send(JSON.stringify({
            type: 'message_added',
            message: newMessage
          }));
        }
      } catch (e) {
        connection.send(JSON.stringify({ type: 'error', message: 'Invalid message format' }));
      }
    }
  }

  async onError(connection: Connection, error: unknown): Promise<void> {
    console.error('WebSocket error:', error);
    // Optionally log to external monitoring
  }

  async onClose(connection: Connection, code: number, reason: string, wasClean: boolean): Promise<void> {
    console.log(`Connection ${connection.id} closed:`, code, reason, wasClean);
    // Clean up connection-specific state if needed
  }
}
连接管理
export class MyAgent extends Agent {
  async onMessage(connection: Connection, message: WSMessage) {
    // Connection properties
    const connId = connection.id;  // Unique connection ID
    const connState = connection.state;  // Connection-specific state

    // Update connection state (not agent state)
    connection.setState({ ...connection.state, lastActive: Date.now() });

    // Send to this connection only
    connection.send("Message to this client");

    // Close connection programmatically
    connection.close(1000, "Goodbye");
  }
}

状态管理

使用 setState()
interface UserState {
  name: string;
  email: string;
  preferences: { theme: string; notifications: boolean };
  loginCount: number;
  lastLogin: Date | null;
}

export class UserAgent extends Agent<Env, UserState> {
  initialState: UserState = {
    name: "",
    email: "",
    preferences: { theme: "dark", notifications: true },
    loginCount: 0,
    lastLogin: null
  };

  async onRequest(request: Request): Promise<Response> {
    if (request.method === "POST" && new URL(request.url).pathname === "/login") {
      // Update state
      this.setState({
        ...this.state,
        loginCount: this.state.loginCount + 1,
        lastLogin: new Date()
      });

      // State is automatically persisted and synced to connected clients
      return Response.json({ success: true, state: this.state });
    }

    return Response.json({ state: this.state });
  }

  onStateUpdate(state: UserState, source: "server" | Connection) {
    console.log('State updated:', state);
    console.log('Source:', source);  // "server" or Connection object

    // React to state changes
    if (state.loginCount > 10) {
      console.log('Frequent user!');
    }
  }
}

状态规则:

  • ✅ 状态可序列化为 JSON(对象、数组、字符串、数字、布尔值、null)
  • ✅ Agent 重启后状态仍会保留
  • ✅ Agent 内部的状态可立即保持一致
  • ✅ 状态会自动同步到已连接的 WebSocket 客户端
  • ❌ 状态不能包含函数或循环引用
  • ❌ 状态总大小受数据库大小限制(每个 Agent 最大 1GB)
使用 SQL 数据库

每个 Agent 都内置了一个可通过 this.sql 访问的 SQLite 数据库:

export class MyAgent extends Agent {
  async onStart() {
    // Create tables on first start
    await this.sql`
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `;

    await this.sql`
      CREATE INDEX IF NOT EXISTS idx_email ON users(email)
    `;
  }

  async addUser(name: string, email: string) {
    // Insert with prepared statement (prevents SQL injection)
    const result = await this.sql`
      INSERT INTO users (name, email)
      VALUES (${name}, ${email})
    `;

    return result;
  }

  async getUser(email: string) {
    // Query returns array of results
    const users = await this.sql`
      SELECT * FROM users WHERE email = ${email}
    `;

    return users[0] || null;
  }

  async getAllUsers() {
    const users = await this.sql`
      SELECT * FROM users ORDER BY created_at DESC
    `;

    return users;
  }

  async updateUser(id: number, name: string) {
    await this.sql`
      UPDATE users SET name = ${name} WHERE id = ${id}
    `;
  }

  async deleteUser(id: number) {
    await this.sql`
      DELETE FROM users WHERE id = ${id}
    `;
  }
}

SQL 最佳实践:

  • ✅ 使用带标签的模板字面量(可防止 SQL 注入)
  • ✅ 为频繁查询的列创建索引
  • ✅ 对多个相关操作使用事务
  • ✅ 查询结果始终是数组(即使只有一行)
  • ❌ 不要手动构造 SQL 字符串
  • ❌ 注意数据库大小上限为 1GB

计划任务

Agent 可以使用 this.schedule() 安排未来运行的任务。

延迟(秒)
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.
  }
}
指定日期
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.
  }
}
Cron 表达式
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...');
  }
}
管理计划任务
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" });
  }
}

计划任务限制:

  • 每个任务对应一行 SQL 数据库记录(每个任务最大为 2 MB)
  • 任务总数受限于:(task_size * count) + other_state < 1GB
  • Cron 任务会持续运行,直到被明确取消
  • 回调方法必须存在于 Agent 类中(若不存在则会抛出错误)

严重错误:如果回调方法不存在:

// ❌ BAD: Method doesn't exist
await this.schedule(60, "nonExistentMethod", {});

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

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

运行工作流

Agent 可以触发异步 Cloudflare Workflows。

工作流绑定配置

wrangler.jsonc:

{
  "workflows": [
    {
      "name": "MY_WORKFLOW",
      "class_name": "MyWorkflow"
    }
  ]
}

如果 Workflow 位于其他脚本中:

{
  "workflows": [
    {
      "name": "EMAIL_WORKFLOW",
      "class_name": "EmailWorkflow",
      "script_name": "email-workflows"  // Different project
    }
  ]
}
触发工作流
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;
  }
}
Agent 与 Workflow
特性AgentWorkflow
用途交互式,面向用户后台处理
持续时间几秒到几小时几分钟到几小时
状态SQLite 数据库基于步骤的检查点
交互方式WebSockets、HTTP无直接交互
重试手动每个步骤自动重试
使用场景聊天、实时 UIETL、批处理

最佳实践:使用 Agent 协调多个 Workflow。Agent 可以触发、监控 Workflow,并响应其结果,同时保持与用户的交互。


浏览网页

Agent 可以使用 Browser Rendering 浏览网页。

Browser Rendering 绑定

wrangler.jsonc:

{
  "browser": {
    "binding": "BROWSER"
  }
}
安装
npm install @cloudflare/puppeteer
网页抓取示例
import { Agent } from "agents";
import puppeteer from "@cloudflare/puppeteer";

interface Env {
  BROWSER: Fetcher;
  OPENAI_API_KEY: string;
}

export class BrowserAgent extends Agent<Env> {
  async browse(urls: string[]) {
    const responses = [];

    for (const url of urls) {
      const browser = await puppeteer.launch(this.env.BROWSER);
      const page = await browser.newPage();

      await page.goto(url);
      await page.waitForSelector("body");

      const bodyContent = await page.$eval("body", el => el.innerHTML);

      // Extract data with AI
      const data = await this.extractData(bodyContent);
      responses.push({ url, data });

      await browser.close();
    }

    return responses;
  }

  async extractData(html: string): Promise<any> {
    // Use OpenAI or Workers AI to extract structured data
    const response = await fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.env.OPENAI_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        model: 'gpt-4o-mini',
        messages: [{
          role: 'user',
          content: `Extract product info from HTML: ${html.slice(0, 4000)}`
        }],
        response_format: { type: "json_object" }
      })
    });

    const result = await response.json();
    return JSON.parse(result.choices[0].message.content);
  }

  async onRequest(request: Request): Promise<Response> {
    const url = new URL(request.url).searchParams.get('url');
    if (!url) {
      return new Response("Missing url parameter", { status: 400 });
    }

    const results = await this.browse([url]);
    return Response.json(results);
  }
}
截图
export class ScreenshotAgent extends Agent<Env> {
  async captureScreenshot(url: string): Promise<Buffer> {
    const browser = await puppeteer.launch(this.env.BROWSER);
    const page = await browser.newPage();

    await page.goto(url);
    const screenshot = await page.screenshot({ fullPage: true });

    await browser.close();

    return screenshot;
  }
}

检索增强生成(RAG)

使用 Vectorize + Workers AI 嵌入实现 RAG。

Vectorize 绑定

wrangler.jsonc:

{
  "ai": {
    "binding": "AI"
  },
  "vectorize": {
    "bindings": [
      {
        "binding": "VECTORIZE",
        "index_name": "my-agent-vectors"
      }
    ]
  }
}
创建索引
npx wrangler vectorize create my-agent-vectors \
  --dimensions=768 \
  --metric=cosine
完整的 RAG 实现
import { Agent } from "agents";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

interface Env {
  AI: Ai;
  VECTORIZE: Vectorize;
  OPENAI_API_KEY: string;
}

export class RAGAgent extends Agent<Env> {
  // Ingest documents
  async ingestDocuments(documents: Array<{ id: string; text: string; metadata: any }>) {
    const vectors = [];

    for (const doc of documents) {
      // Generate embedding with Workers AI
      const { data } = await this.env.AI.run('@cf/baai/bge-base-en-v1.5', {
        text: [doc.text]
      });

      vectors.push({
        id: doc.id,
        values: data[0],
        metadata: { ...doc.metadata, text: doc.text }
      });
    }

    // Insert into Vectorize
    await this.env.VECTORIZE.upsert(vectors);

    return { ingested: vectors.length };
  }

  // Query knowledge base
  async queryKnowledge(userQuery: string, topK: number = 5) {
    // Generate query embedding
    const { data } = await this.env.AI.run('@cf/baai/bge-base-en-v1.5', {
      text: [userQuery]
    });

    // Search Vectorize
    const results = await this.env.VECTORIZE.query(data[0], { topK });

    // Extract relevant documents
    const context = results.matches.map(match => match.metadata.text).join('\n\n');

    return context;
  }

  // RAG Chat
  async chat(userMessage: string) {
    // Retrieve relevant context
    const context = await this.queryKnowledge(userMessage);

    // Generate response with context
    const { text } = await generateText({
      model: openai('gpt-4o-mini'),
      messages: [
        {
          role: 'system',
          content: `You are a helpful assistant. Use the following context to answer questions:\n\n${context}`
        },
        {
          role: 'user',
          content: userMessage
        }
      ]
    });

    return { response: text, context };
  }

  async onRequest(request: Request): Promise<Response> {
    const { message } = await request.json();
    const result = await this.chat(message);
    return Response.json(result);
  }
}
元数据筛选
// Create metadata indexes BEFORE inserting vectors
await this.env.VECTORIZE.createMetadataIndex("category");
await this.env.VECTORIZE.createMetadataIndex("language");

// Query with filters
const results = await this.env.VECTORIZE.query(queryVector, {
  topK: 10,
  filter: {
    category: { $eq: "documentation" },
    language: { $eq: "en" }
  }
});

参见:cloudflare-vectorize skill,了解完整的 Vectorize 指南。


使用 AI 模型

AI SDK(Vercel)
npm install ai @ai-sdk/openai @ai-sdk/anthropic
import { Agent } from "agents";
import { generateText, streamText } from "ai";
import { openai } from "@ai-sdk/openai";
import { anthropic } from "@ai-sdk/anthropic";

export class AIAgent extends Agent {
  // Simple text generation
  async generateResponse(prompt: string) {
    const { text } = await generateText({
      model: openai('gpt-4o-mini'),
      prompt
    });

    return text;
  }

  // Streaming response
  async streamResponse(prompt: string): Promise<Response> {
    const result = streamText({
      model: anthropic('claude-sonnet-4-5'),
      prompt
    });

    return result.toTextStreamResponse();
  }

  // Structured output
  async extractData(text: string) {
    const { object } = await generateObject({
      model: openai('gpt-4o-mini'),
      schema: z.object({
        name: z.string(),
        email: z.string().email(),
        age: z.number().optional()
      }),
      prompt: `Extract user info from: ${text}`
    });

    return object;
  }
}
Workers AI
interface Env {
  AI: Ai;
}

export class WorkersAIAgent extends Agent<Env> {
  async generateText(prompt: string) {
    const response = await this.env.AI.run('@cf/meta/llama-3-8b-instruct', {
      messages: [{ role: 'user', content: prompt }]
    });

    return response;
  }

  async generateImage(prompt: string) {
    const response = await this.env.AI.run('@cf/black-forest-labs/flux-1-schnell', {
      prompt
    });

    return response;
  }
}

参见:cloudflare-workers-ai skill,了解完整的 Workers AI 指南。


调用 Agent

使用 routeAgentRequest

根据 URL 模式 /agents/:agent/:name 自动将请求路由到 Agent:

import { Agent, AgentNamespace, routeAgentRequest } from 'agents';

interface Env {
  MyAgent: AgentNamespace<MyAgent>;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Routes to: /agents/my-agent/user-123
    const response = await routeAgentRequest(request, env);

    if (response) {
      return response;
    }

    return new Response("Not Found", { status: 404 });
  }
} satisfies ExportedHandler<Env>;

export class MyAgent extends Agent<Env> {
  async onRequest(request: Request): Promise<Response> {
    return Response.json({ agent: this.name });
  }
}

URL 模式:/agents/my-agent/user-123

  • my-agent = kebab-case 格式的类名
  • user-123 = Agent 实例名称
使用 getAgentByName

用于自定义路由,或从 Workers 调用 Agent:

import { Agent, AgentNamespace, getAgentByName } from 'agents';

interface Env {
  MyAgent: AgentNamespace<MyAgent>;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const userId = new URL(request.url).searchParams.get('userId') || 'anonymous';

    // Get or create agent instance
    const agent = getAgentByName<Env, MyAgent>(env.MyAgent, `user-${userId}`);

    // Pass request to agent
    return (await agent).fetch(request);
  }
} satisfies ExportedHandler<Env>;

export class MyAgent extends Agent<Env> {
  // Agent implementation
}
直接调用 Agent 方法
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const agent = getAgentByName<Env, MyAgent>(env.MyAgent, 'user-123');

    // Call custom methods on agent using RPC
    const result = await (await agent).customMethod({ data: "example" });

    return Response.json({ result });
  }
}

export class MyAgent extends Agent<Env> {
  async customMethod(params: { data: string }): Promise<any> {
    return { processed: params.data };
  }
}
多 Agent 通信
interface Env {
  AgentA: AgentNamespace<AgentA>;
  AgentB: AgentNamespace<AgentB>;
}

export class AgentA extends Agent<Env> {
  async processData(data: any) {
    // Call another agent
    const agentB = getAgentByName<Env, AgentB>(this.env.AgentB, 'processor-1');
    const result = await (await agentB).analyze(data);

    return result;
  }
}

export class AgentB extends Agent<Env> {
  async analyze(data: any) {
    return { analyzed: true, data };
  }
}
身份验证模式
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Authenticate BEFORE invoking agent
    const authHeader = request.headers.get('Authorization');
    if (!authHeader) {
      return new Response("Unauthorized", { status: 401 });
    }

    const userId = await verifyToken(authHeader);
    if (!userId) {
      return new Response("Forbidden", { status: 403 });
    }

    // Only create/access agent for authenticated users
    const agent = getAgentByName<Env, MyAgent>(env.MyAgent, `user-${userId}`);
    return (await agent).fetch(request);
  }
}

严重提示:始终在 Worker 中进行身份验证,不要在 Agent 中进行。Agent 应假定调用方已获授权。


客户端 API

AgentClient(浏览器)
import { AgentClient } from "agents/client";

// Connect to agent instance
const client = new AgentClient({
  agent: "chat-agent",        // Class name in kebab-case
  name: "room-123",           // Instance name
  host: window.location.host
});

client.onopen = () => {
  console.log("Connected");
  client.send(JSON.stringify({ type: "join", user: "alice" }));
};

client.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log("Received:", data);
};

client.onclose = () => {
  console.log("Disconnected");
};
agentFetch(HTTP 请求)
import { agentFetch } from "agents/client";

async function getData() {
  const response = await agentFetch(
    { agent: "my-agent", name: "user-123" },
    {
      method: "GET",
      headers: { "Authorization": `Bearer ${token}` }
    }
  );

  const data = await response.json();
  return data;
}
useAgent Hook(React)
import { useAgent } from "agents/react";
import { useState } from "react";

function ChatUI() {
  const [messages, setMessages] = useState([]);

  const connection = useAgent({
    agent: "chat-agent",
    name: "room-123",
    onMessage: (event) => {
      const data = JSON.parse(event.data);
      if (data.type === 'message') {
        setMessages(prev => [...prev, data.message]);
      }
    },
    onOpen: () => console.log("Connected"),
    onClose: () => console.log("Disconnected")
  });

  const sendMessage = (text: string) => {
    connection.send(JSON.stringify({ type: 'chat', text }));
  };

  return (
    <div>
      {messages.map((msg, i) => <div key={i}>{msg.text}</div>)}
      <button onClick={() => sendMessage("Hello")}>Send</button>
    </div>
  );
}
状态同步
import { useAgent } from "agents/react";
import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  const agent = useAgent({
    agent: "counter-agent",
    name: "my-counter",
    onStateUpdate: (newState) => {
      setCount(newState.counter);
    }
  });

  const increment = () => {
    agent.setState({ counter: count + 1 });
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
useAgentChat Hook
import { useAgentChat } from "agents/ai-react";

function ChatInterface() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useAgentChat({
    agent: "ai-chat-agent",
    name: "chat-session-123"
  });

  return (
    <div>
      <div>
        {messages.map((msg, i) => (
          <div key={i}>
            <strong>{msg.role}:</strong> {msg.content}
          </div>
        ))}
      </div>

      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Type a message..."
          disabled={isLoading}
        />
        <button type="submit" disabled={isLoading}>
          {isLoading ? "Thinking..." : "Send"}
        </button>
      </form>
    </div>
  );
}

模型上下文协议(MCP)

使用 Agents SDK 构建 MCP 服务。

MCP 服务设置
npm install @modelcontextprotocol/sdk agents
基本 MCP 服务
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) }]
      })
    );
  }
}
有状态 MCP 服务
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}`
          }]
        };
      }
    );
  }
}
MCP 传输配置
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;

传输方式比较:

  • /mcp:可流式传输的 HTTP(现代、推荐)
  • /sse:服务器发送事件(旧版,已弃用)
使用 OAuth 的 MCP
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
});
测试 MCP 服务
# Run MCP inspector
npx @modelcontextprotocol/inspector@latest

# Connect to: http://localhost:8788/mcp

Cloudflare 的 MCP 服务:生产环境示例请参阅参考资料。


模式与概念

聊天 Agent(AIChatAgent)
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";

export class MyChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    const result = streamText({
      model: openai('gpt-4o-mini'),
      messages: this.messages,
      onFinish
    });

    return result.toTextStreamResponse();
  }

  // Optional: Customize message persistence
  async onStateUpdate(state, source) {
    console.log('Chat state updated:', this.messages.length, 'messages');
  }
}
人类参与环节(HITL)
export class ApprovalAgent extends Agent {
  async processRequest(data: any) {
    // Process automatically
    const processed = await this.autoProcess(data);

    // If confidence low, request human review
    if (processed.confidence < 0.8) {
      this.setState({
        ...this.state,
        pendingReview: {
          data: processed,
          requestedAt: Date.now(),
          status: 'pending'
        }
      });

      // Send notification to human
      await this.notifyHuman(processed);

      return { status: 'pending_review', id: processed.id };
    }

    // High confidence, proceed automatically
    return this.complete(processed);
  }

  async approveReview(id: string, approved: boolean) {
    const pending = this.state.pendingReview;

    if (approved) {
      await this.complete(pending.data);
    } else {
      await this.reject(pending.data);
    }

    this.setState({
      ...this.state,
      pendingReview: null
    });
  }
}
工具概念

工具使 Agent 能够与外部服务交互:

export class ToolAgent extends Agent {
  // Tool: Search flights
  async searchFlights(from: string, to: string, date: string) {
    const response = await fetch(`https://api.flights.com/search`, {
      method: 'POST',
      body: JSON.stringify({ from, to, date })
    });
    return response.json();
  }

  // Tool: Book flight
  async bookFlight(flightId: string, passengers: any[]) {
    const response = await fetch(`https://api.flights.com/book`, {
      method: 'POST',
      body: JSON.stringify({ flightId, passengers })
    });
    return response.json();
  }

  // Tool: Send confirmation email
  async sendEmail(to: string, subject: string, body: string) {
    // Use email service
    return { sent: true };
  }

  // Orchestrate tools
  async bookTrip(params: any) {
    const flights = await this.searchFlights(params.from, params.to, params.date);
    const booking = await this.bookFlight(flights[0].id, params.passengers);
    await this.sendEmail(params.email, "Booking Confirmed", `Booking ID: ${booking.id}`);

    return booking;
  }
}
多 Agent 编排
interface Env {
  ResearchAgent: AgentNamespace<ResearchAgent>;
  WriterAgent: AgentNamespace<WriterAgent>;
  EditorAgent: AgentNamespace<EditorAgent>;
}

export class OrchestratorAgent extends Agent<Env> {
  async createArticle(topic: string) {
    // 1. Research agent gathers information
    const researcher = getAgentByName<Env, ResearchAgent>(
      this.env.ResearchAgent,
      `research-${topic}`
    );
    const research = await (await researcher).research(topic);

    // 2. Writer agent creates draft
    const writer = getAgentByName<Env, WriterAgent>(
      this.env.WriterAgent,
      `writer-${topic}`
    );
    const draft = await (await writer).write(research);

    // 3. Editor agent reviews
    const editor = getAgentByName<Env, EditorAgent>(
      this.env.EditorAgent,
      `editor-${topic}`
    );
    const final = await (await editor).edit(draft);

    return final;
  }
}

关键规则

始终要做 ✅
  1. 导出 Agent 类 - 必须导出才能使绑定生效
  2. 在 v1 迁移中包含 new_sqlite_classes - 之后无法再添加 SQLite
  3. 使绑定名称与类名一致 - 避免出现“找不到绑定”错误
  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. 先在本地测试迁移 - 迁移是原子操作,无法回滚
绝不要做 ❌
  1. 不要向已部署的类添加 SQLite - 必须在首次迁移中添加
  2. 不要逐步部署迁移 - 只能原子部署
  3. 不要在 Worker 中跳过身份验证 - 访问 Agent 前始终先进行身份验证
  4. 不要手动构造 SQL 字符串 - 使用带标签的模板字面量
  5. 不要让每个 Agent 的状态超过 1GB - 硬性限制
  6. 不要使用不存在的回调来安排任务 - 会导致运行时错误
  7. 不要以为相同名称表示不同 Agent - 名称全局唯一
  8. 不要将 SSE 用于 MCP - 已弃用,请使用 /mcp 传输
  9. 不要忘记浏览器绑定 - 网页浏览所必需
  10. 不要直接修改 this.state - 改用 setState()

已知问题预防

此技能可预防 15+ 个已记录的问题:

问题 1:迁移不是原子操作

错误:“无法逐步部署迁移” 来源:https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/ 原因:迁移会同时应用到所有实例 预防措施:独立于代码更改部署迁移,使用 npx wrangler versions deploy

问题 2:缺少 new_sqlite_classes

错误:“无法在现有类上启用 SQLite” 来源:https://developers.cloudflare.com/agents/api-reference/configuration/ 原因:必须在首次迁移中启用 SQLite 预防措施:在标记为 "v1" 的迁移中包含 new_sqlite_classes

问题 3:未导出 Agent 类

错误:“找不到绑定”或“无法访问 undefined” 来源:https://developers.cloudflare.com/agents/api-reference/agents-api/ 原因:Durable Objects 要求类必须导出 预防措施:export class MyAgent extends Agent(使用 export 关键字)

问题 4:绑定名称不匹配

错误:“找不到绑定 'X'” 来源:https://developers.cloudflare.com/agents/api-reference/configuration/ 原因:绑定名称必须与类名完全一致 预防措施:确保 wrangler.jsonc 中的 name 和 class_name 完全相同

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

错误:Agent 实例出现意外行为 来源:https://developers.cloudflare.com/agents/api-reference/agents-api/ 原因:相同名称始终会返回同一个全局 Agent 实例 预防措施:使用唯一标识符(userId、sessionId)作为实例名称

问题 6:WebSocket 状态未持久化

错误:断开连接后连接状态丢失 来源:https://developers.cloudflare.com/agents/api-reference/websockets/ 原因:WebSocket 连接不会持久化,但 Agent 状态会 预防措施:使用 setState() 将重要数据存储在 Agent 状态中,而非连接状态中

问题 7:计划任务回调不存在

错误:"Method X does not exist on Agent" 来源:https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ 原因:this.schedule() 调用了未定义的方法 预防措施:安排任务前,确保回调方法已存在

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

错误:"Maximum database size exceeded" 来源:https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/ 原因:Agent 状态和计划任务总计超过 1GB 预防措施:监控状态大小,大型数据使用外部存储(D1、R2)

问题 9:计划任务过大

错误:"Task payload exceeds 2MB" 来源:https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ 原因:每个任务都映射到一个数据库行,大小上限为 2MB 预防措施:尽量精简任务负载,将大型数据存储在 Agent 状态或 SQL 中

问题 10:缺少工作流绑定

错误:"Cannot read property 'create' of undefined" 来源:https://developers.cloudflare.com/agents/api-reference/run-workflows/ 原因:未在 wrangler.jsonc 中配置工作流绑定 预防措施:使用 this.env.WORKFLOW 前,先添加工作流绑定

问题 11:需要浏览器绑定

错误:"BROWSER binding undefined" 来源:https://developers.cloudflare.com/agents/api-reference/browse-the-web/ 原因:Browser Rendering 需要显式绑定 预防措施:在 wrangler.jsonc 中添加 "browser": { "binding": "BROWSER" }

问题 12:未找到 Vectorize 索引

错误:"Index does not exist" 来源:https://developers.cloudflare.com/agents/api-reference/rag/ 原因:必须先创建 Vectorize 索引才能使用 预防措施:部署 Agent 前运行 wrangler vectorize create

问题 13:MCP 传输方式混淆

错误:"SSE transport deprecated" 来源:https://developers.cloudflare.com/agents/model-context-protocol/transport/ 原因:SSE 传输方式已过时,推荐使用可流式传输的 HTTP 预防措施:使用 /mcp 端点和 MyMCP.serve('/mcp'),而非 /sse

问题 14:绕过身份验证

错误:安全漏洞 来源:https://developers.cloudflare.com/agents/api-reference/calling-agents/ 原因:在 Agent 中而非 Worker 中执行身份验证 预防措施:调用 getAgentByName() 前,务必在 Worker 中进行身份验证

问题 15:实例命名错误

错误:用户间数据泄漏 来源:https://developers.cloudflare.com/agents/api-reference/calling-agents/ 原因:实例命名不当,可能导致访问错误的 Agent 预防措施:使用带命名空间的名称,例如 user-${userId},并验证所有权


依赖项

必需
  • cloudflare-worker-base - 基础环境(Hono、Vite、Workers 设置)
可选(按功能)
  • cloudflare-workers-ai - 用于 Workers AI 模型调用
  • cloudflare-vectorize - 用于使用 Vectorize 实现 RAG
  • cloudflare-d1 - 用于 Agent 状态之外的额外持久化存储
  • cloudflare-r2 - 用于文件存储
  • cloudflare-queues - 用于消息队列
NPM 包
  • agents - Agents SDK(必需)
  • @modelcontextprotocol/sdk - 用于构建 MCP 服务
  • @cloudflare/puppeteer - 用于网页浏览
  • ai - 用于模型调用的 AI SDK
  • @ai-sdk/openai - OpenAI 模型
  • @ai-sdk/anthropic - Anthropic 模型

官方文档


附带资源

模板(templates/)
  • 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/)
  • agent-class-api.md - 完整的 Agent 类参考
  • client-api-reference.md - 浏览器客户端 API
  • state-management-guide.md - 深入了解状态与 SQL
  • websockets-sse.md - WebSocket 与 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/)
  • 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 官方文档

评论

支持 Markdown