building-ai-agent-on-cloudflare

安装量: 1.7K
排名: #948

安装

npx skills add https://github.com/cloudflare/skills --skill building-ai-agent-on-cloudflare

Building Cloudflare Agents

Creates AI-powered agents using Cloudflare's Agents SDK with persistent state, real-time communication, and tool integration.

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 Prerequisites Cloudflare account with Workers enabled Node.js 18+ and npm/pnpm/yarn Wrangler CLI (npm install -g wrangler) Quick Start npm create cloudflare@latest -- my-agent --template=cloudflare/agents-starter cd my-agent npm start

Agent runs at http://localhost:8787

Core Concepts What is an 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 Lifecycle Client connects → Agent.onConnect() → Agent processes messages → Agent.onMessage() → Agent.setState() (persists + syncs) Client disconnects → State persists → Client reconnects → State restored

Basic Agent Structure import { Agent, Connection } from "agents";

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

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

export class MyAgent extends Agent { // 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,
}));

} }

Entry Point Configuration // 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

Wrangler Configuration 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 // Current state is always available const currentMessages = this.state.messages; const userPrefs = this.state.preferences;

Updating State // 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" }, });

SQL Storage

For complex queries, use the embedded SQLite database:

// Create tables await this.sqlCREATE 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.sqlINSERT INTO documents (title, content) VALUES (${title}, ${content});

// Query const docs = await this.sqlSELECT * FROM documents WHERE title LIKE ${%${search}%};

Scheduled Tasks

Agents can schedule future work:

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(), }); }

Schedule Options // 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);

Chat Agent (AI-Powered)

For chat-focused agents, extend AIChatAgent:

import { AIChatAgent } from "agents/ai-chat-agent";

export class ChatBot extends AIChatAgent { // 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 Client Integration React Hook 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 (

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

Vanilla 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 Deployment

Deploy

npx wrangler deploy

View logs

wrangler tail

Test endpoint

curl https://my-agent.workers.dev/agents/MyAgent/test-user

Troubleshooting

See references/troubleshooting.md for common issues.

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

返回排行榜