building-ai-agent-on-cloudflare
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuilding 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 startAgent runs at
http://localhost:8787bash
npm create cloudflare@latest -- my-agent --template=cloudflare/agents-starter
cd my-agent
npm startAgent运行在
http://localhost:8787Core 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-idtypescript
// 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-idWrangler 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 :
AIChatAgenttypescript
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 for persistence
saveMessages()
对于专注于聊天的Agent,可扩展:
AIChatAgenttypescript
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
undefinedbash
undefinedDeploy
部署
npx wrangler deploy
npx wrangler deploy
View logs
查看日志
wrangler tail
wrangler tail
Test endpoint
测试端点
undefinedundefinedTroubleshooting
故障排除
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 — 错误解决方案