building-ai-agent-on-cloudflare

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Building Cloudflare Agents

构建Cloudflare Agent

Creates AI-powered agents using Cloudflare's Agents SDK with persistent state, real-time communication, and tool integration.
借助Cloudflare的Agents SDK创建具备持久状态、实时通信和工具集成能力的AI驱动型Agent。

When to Use

适用场景

  • User wants to build an AI agent or chatbot
  • User needs stateful, real-time AI interactions
  • User asks about the Cloudflare Agents SDK
  • User wants scheduled tasks or background AI work
  • User needs WebSocket-based AI communication
  • 用户想要构建AI Agent或聊天机器人
  • 用户需要有状态的实时AI交互
  • 用户询问Cloudflare Agents SDK相关内容
  • 用户需要定时任务或后台AI工作
  • 用户需要基于WebSocket的AI通信

Prerequisites

前置条件

  • Cloudflare account with Workers enabled
  • Node.js 18+ and npm/pnpm/yarn
  • Wrangler CLI (
    npm install -g wrangler
    )
  • 已启用Workers的Cloudflare账户
  • Node.js 18+ 以及npm/pnpm/yarn
  • Wrangler CLI(
    npm install -g wrangler

Quick Start

快速开始

bash
npm create cloudflare@latest -- my-agent --template=cloudflare/agents-starter
cd my-agent
npm start
Agent runs at
http://localhost:8787
bash
npm create cloudflare@latest -- my-agent --template=cloudflare/agents-starter
cd my-agent
npm start
Agent运行在
http://localhost:8787

Core Concepts

核心概念

What is an Agent?

什么是Agent?

An Agent is a stateful, persistent AI service that:
  • Maintains state across requests and reconnections
  • Communicates via WebSockets or HTTP
  • Runs on Cloudflare's edge via Durable Objects
  • Can schedule tasks and call tools
  • Scales horizontally (each user/session gets own instance)
Agent是一种有状态的持久化AI服务,具备以下特性:
  • 在请求和重连之间保持状态
  • 通过WebSocket或HTTP进行通信
  • 借助Durable Objects在Cloudflare边缘运行
  • 可调度任务并调用工具
  • 支持水平扩展(每个用户/会话拥有独立实例)

Agent Lifecycle

Agent生命周期

Client connects → Agent.onConnect() → Agent processes messages
                                    → Agent.onMessage()
                                    → Agent.setState() (persists + syncs)
Client disconnects → State persists → Client reconnects → State restored
客户端连接 → Agent.onConnect() → Agent处理消息
                                    → Agent.onMessage()
                                    → Agent.setState()(持久化+同步)
客户端断开连接 → 状态持久化 → 客户端重连 → 状态恢复

Basic Agent Structure

基础Agent结构

typescript
import { Agent, Connection } from "agents";

interface Env {
  AI: Ai;  // Workers AI binding
}

interface State {
  messages: Array<{ role: string; content: string }>;
  preferences: Record<string, string>;
}

export class MyAgent extends Agent<Env, State> {
  // Initial state for new instances
  initialState: State = {
    messages: [],
    preferences: {},
  };

  // Called when agent starts or resumes
  async onStart() {
    console.log("Agent started with state:", this.state);
  }

  // Handle WebSocket connections
  async onConnect(connection: Connection) {
    connection.send(JSON.stringify({
      type: "welcome",
      history: this.state.messages,
    }));
  }

  // Handle incoming messages
  async onMessage(connection: Connection, message: string) {
    const data = JSON.parse(message);

    if (data.type === "chat") {
      await this.handleChat(connection, data.content);
    }
  }

  // Handle disconnections
  async onClose(connection: Connection) {
    console.log("Client disconnected");
  }

  // React to state changes
  onStateUpdate(state: State, source: string) {
    console.log("State updated by:", source);
  }

  private async handleChat(connection: Connection, userMessage: string) {
    // Add user message to history
    const messages = [
      ...this.state.messages,
      { role: "user", content: userMessage },
    ];

    // Call AI
    const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {
      messages,
    });

    // Update state (persists and syncs to all clients)
    this.setState({
      ...this.state,
      messages: [
        ...messages,
        { role: "assistant", content: response.response },
      ],
    });

    // Send response
    connection.send(JSON.stringify({
      type: "response",
      content: response.response,
    }));
  }
}
typescript
import { Agent, Connection } from "agents";

interface Env {
  AI: Ai;  // Workers AI绑定
}

interface State {
  messages: Array<{ role: string; content: string }>;
  preferences: Record<string, string>;
}

export class MyAgent extends Agent<Env, State> {
  // 新实例的初始状态
  initialState: State = {
    messages: [],
    preferences: {},
  };

  // Agent启动或恢复时调用
  async onStart() {
    console.log("Agent started with state:", this.state);
  }

  // 处理WebSocket连接
  async onConnect(connection: Connection) {
    connection.send(JSON.stringify({
      type: "welcome",
      history: this.state.messages,
    }));
  }

  // 处理传入消息
  async onMessage(connection: Connection, message: string) {
    const data = JSON.parse(message);

    if (data.type === "chat") {
      await this.handleChat(connection, data.content);
    }
  }

  // 处理断开连接
  async onClose(connection: Connection) {
    console.log("Client disconnected");
  }

  // 响应状态变更
  onStateUpdate(state: State, source: string) {
    console.log("State updated by:", source);
  }

  private async handleChat(connection: Connection, userMessage: string) {
    // 将用户消息添加到历史记录
    const messages = [
      ...this.state.messages,
      { role: "user", content: userMessage },
    ];

    // 调用AI
    const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {
      messages,
    });

    // 更新状态(持久化并同步到所有客户端)
    this.setState({
      ...this.state,
      messages: [
        ...messages,
        { role: "assistant", content: response.response },
      ],
    });

    // 发送响应
    connection.send(JSON.stringify({
      type: "response",
      content: response.response,
    }));
  }
}

Entry Point Configuration

入口点配置

typescript
// src/index.ts
import { routeAgentRequest } from "agents";
import { MyAgent } from "./agent";

export default {
  async fetch(request: Request, env: Env) {
    // routeAgentRequest handles routing to /agents/:class/:name
    return (
      (await routeAgentRequest(request, env)) ||
      new Response("Not found", { status: 404 })
    );
  },
};

export { MyAgent };
Clients connect via:
wss://my-agent.workers.dev/agents/MyAgent/session-id
typescript
// src/index.ts
import { routeAgentRequest } from "agents";
import { MyAgent } from "./agent";

export default {
  async fetch(request: Request, env: Env) {
    // routeAgentRequest 处理指向 /agents/:class/:name 的路由
    return (
      (await routeAgentRequest(request, env)) ||
      new Response("Not found", { status: 404 })
    );
  },
};

export { MyAgent };
客户端通过以下地址连接:
wss://my-agent.workers.dev/agents/MyAgent/session-id

Wrangler Configuration

Wrangler配置

toml
name = "my-agent"
main = "src/index.ts"
compatibility_date = "2024-12-01"

[ai]
binding = "AI"

[durable_objects]
bindings = [{ name = "AGENT", class_name = "MyAgent" }]

[[migrations]]
tag = "v1"
new_classes = ["MyAgent"]
toml
name = "my-agent"
main = "src/index.ts"
compatibility_date = "2024-12-01"

[ai]
binding = "AI"

[durable_objects]
bindings = [{ name = "AGENT", class_name = "MyAgent" }]

[[migrations]]
tag = "v1"
new_classes = ["MyAgent"]

State Management

状态管理

Reading State

读取状态

typescript
// Current state is always available
const currentMessages = this.state.messages;
const userPrefs = this.state.preferences;
typescript
// 当前状态始终可用
const currentMessages = this.state.messages;
const userPrefs = this.state.preferences;

Updating State

更新状态

typescript
// setState persists AND syncs to all connected clients
this.setState({
  ...this.state,
  messages: [...this.state.messages, newMessage],
});

// Partial updates work too
this.setState({
  preferences: { ...this.state.preferences, theme: "dark" },
});
typescript
// setState 会持久化并同步到所有已连接客户端
this.setState({
  ...this.state,
  messages: [...this.state.messages, newMessage],
});

// 部分更新同样有效
this.setState({
  preferences: { ...this.state.preferences, theme: "dark" },
});

SQL Storage

SQL存储

For complex queries, use the embedded SQLite database:
typescript
// Create tables
await this.sql`
  CREATE TABLE IF NOT EXISTS documents (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`;

// Insert
await this.sql`
  INSERT INTO documents (title, content)
  VALUES (${title}, ${content})
`;

// Query
const docs = await this.sql`
  SELECT * FROM documents WHERE title LIKE ${`%${search}%`}
`;
对于复杂查询,使用内置的SQLite数据库:
typescript
// 创建表
await this.sql`
  CREATE TABLE IF NOT EXISTS documents (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`;

// 插入数据
await this.sql`
  INSERT INTO documents (title, content)
  VALUES (${title}, ${content})
`;

// 查询数据
const docs = await this.sql`
  SELECT * FROM documents WHERE title LIKE ${`%${search}%`}
`;

Scheduled Tasks

定时任务

Agents can schedule future work:
typescript
async onMessage(connection: Connection, message: string) {
  const data = JSON.parse(message);

  if (data.type === "schedule_reminder") {
    // Schedule task for 1 hour from now
    const { id } = await this.schedule(3600, "sendReminder", {
      message: data.reminderText,
      userId: data.userId,
    });

    connection.send(JSON.stringify({ type: "scheduled", taskId: id }));
  }
}

// Called when scheduled task fires
async sendReminder(data: { message: string; userId: string }) {
  // Send notification, email, etc.
  console.log(`Reminder for ${data.userId}: ${data.message}`);

  // Can also update state
  this.setState({
    ...this.state,
    lastReminder: new Date().toISOString(),
  });
}
Agent可以调度未来的工作:
typescript
async onMessage(connection: Connection, message: string) {
  const data = JSON.parse(message);

  if (data.type === "schedule_reminder") {
    // 调度1小时后执行的任务
    const { id } = await this.schedule(3600, "sendReminder", {
      message: data.reminderText,
      userId: data.userId,
    });

    connection.send(JSON.stringify({ type: "scheduled", taskId: id }));
  }
}

// 定时任务触发时调用
async sendReminder(data: { message: string; userId: string }) {
  // 发送通知、邮件等
  console.log(`Reminder for ${data.userId}: ${data.message}`);

  // 也可以更新状态
  this.setState({
    ...this.state,
    lastReminder: new Date().toISOString(),
  });
}

Schedule Options

调度选项

typescript
// Delay in seconds
await this.schedule(60, "taskMethod", { data });

// Specific date
await this.schedule(new Date("2025-01-01T00:00:00Z"), "taskMethod", { data });

// Cron expression (recurring)
await this.schedule("0 9 * * *", "dailyTask", {});  // 9 AM daily
await this.schedule("*/5 * * * *", "everyFiveMinutes", {});  // Every 5 min

// Manage schedules
const schedules = await this.getSchedules();
await this.cancelSchedule(taskId);
typescript
// 延迟(秒)
await this.schedule(60, "taskMethod", { data });

// 指定日期
await this.schedule(new Date("2025-01-01T00:00:00Z"), "taskMethod", { data });

// Cron表达式(重复执行)
await this.schedule("0 9 * * *", "dailyTask", {});  // 每天上午9点
await this.schedule("*/5 * * * *", "everyFiveMinutes", {});  // 每5分钟

// 管理调度任务
const schedules = await this.getSchedules();
await this.cancelSchedule(taskId);

Chat Agent (AI-Powered)

聊天Agent(AI驱动)

For chat-focused agents, extend
AIChatAgent
:
typescript
import { AIChatAgent } from "agents/ai-chat-agent";

export class ChatBot extends AIChatAgent<Env> {
  // Called for each user message
  async onChatMessage(message: string) {
    const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        ...this.messages,  // Automatic history management
        { role: "user", content: message },
      ],
      stream: true,
    });

    // Stream response back to client
    return response;
  }
}
Features included:
  • Automatic message history
  • Resumable streaming (survives disconnects)
  • Built-in
    saveMessages()
    for persistence
对于专注于聊天的Agent,可扩展
AIChatAgent
typescript
import { AIChatAgent } from "agents/ai-chat-agent";

export class ChatBot extends AIChatAgent<Env> {
  // 每条用户消息触发时调用
  async onChatMessage(message: string) {
    const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {
      messages: [
        { role: "system", content: "You are a helpful assistant." },
        ...this.messages,  // 自动历史管理
        { role: "user", content: message },
      ],
      stream: true,
    });

    // 将响应流式返回给客户端
    return response;
  }
}
包含的特性:
  • 自动消息历史管理
  • 可恢复的流式传输(断开重连后仍可继续)
  • 内置
    saveMessages()
    用于持久化

Client Integration

客户端集成

React Hook

React Hook

tsx
import { useAgent } from "agents/react";

function Chat() {
  const { state, send, connected } = useAgent({
    agent: "my-agent",
    name: userId,  // Agent instance ID
  });

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

  return (
    <div>
      {state.messages.map((msg, i) => (
        <div key={i}>{msg.role}: {msg.content}</div>
      ))}
      <input onKeyDown={(e) => e.key === "Enter" && sendMessage(e.target.value)} />
    </div>
  );
}
tsx
import { useAgent } from "agents/react";

function Chat() {
  const { state, send, connected } = useAgent({
    agent: "my-agent",
    name: userId,  // Agent实例ID
  });

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

  return (
    <div>
      {state.messages.map((msg, i) => (
        <div key={i}>{msg.role}: {msg.content}</div>
      ))}
      <input onKeyDown={(e) => e.key === "Enter" && sendMessage(e.target.value)} />
    </div>
  );
}

Vanilla JavaScript

原生JavaScript

javascript
const ws = new WebSocket("wss://my-agent.workers.dev/agents/MyAgent/user123");

ws.onopen = () => {
  console.log("Connected to agent");
};

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

ws.send(JSON.stringify({ type: "chat", content: "Hello!" }));
javascript
const ws = new WebSocket("wss://my-agent.workers.dev/agents/MyAgent/user123");

ws.onopen = () => {
  console.log("Connected to agent");
};

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

ws.send(JSON.stringify({ type: "chat", content: "Hello!" }));

Common Patterns

常见模式

See references/agent-patterns.md for:
  • Tool calling and function execution
  • Multi-agent orchestration
  • RAG (Retrieval Augmented Generation)
  • Human-in-the-loop workflows
查看 references/agent-patterns.md 了解:
  • 工具调用与函数执行
  • 多Agent编排
  • RAG(检索增强生成)
  • 人机协同工作流

Deployment

部署

bash
undefined
bash
undefined

Deploy

部署

npx wrangler deploy
npx wrangler deploy

View logs

查看日志

wrangler tail
wrangler tail

Test endpoint

测试端点

Troubleshooting

故障排除

See references/troubleshooting.md for common issues.
查看 references/troubleshooting.md 了解常见问题。

References

参考资料

  • references/examples.md — Official templates and production examples
  • references/agent-patterns.md — Advanced patterns
  • references/state-patterns.md — State management strategies
  • references/troubleshooting.md — Error solutions
  • references/examples.md — 官方模板和生产示例
  • references/agent-patterns.md — 进阶模式
  • references/state-patterns.md — 状态管理策略
  • references/troubleshooting.md — 错误解决方案