| name | building-ai-agent-on-cloudflare |
| description | Builds AI agents on Cloudflare using the Agents SDK with state management,
real-time WebSockets, scheduled tasks, tool integration, and chat capabilities.
Generates production-ready agent code deployed to Workers.
Use when: user wants to "build an agent", "AI agent", "chat agent", "stateful
agent", mentions "Agents SDK", needs "real-time AI", "WebSocket AI", or asks
about agent "state management", "scheduled tasks", or "tool calling".
|
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
}
interface State {
messages: Array<{role: string; content: string}>
preferences: Record<string, string>
}
export class MyAgent extends Agent<Env, State> {
initialState: State = {
messages: [],
preferences: {},
}
async onStart() {
console.log('Agent started with state:', this.state)
}
async onConnect(connection: Connection) {
connection.send(
JSON.stringify({
: ,
: ..,
}),
)
}
() {
data = .(message)
(data. === ) {
.(connection, data.)
}
}
() {
.()
}
() {
.(, source)
}
() {
messages = [
.....,
{: , : userMessage},
]
response = ...(, {
messages,
})
.({
....,
: [...messages, {: , : response.}],
})
connection.(
.({
: ,
: response.,
}),
)
}
}
Entry Point Configuration
import {routeAgentRequest} from 'agents'
import {MyAgent} from './agent'
export default {
async fetch(request: Request, env: Env) {
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
const currentMessages = this.state.messages
const userPrefs = this.state.preferences
Updating State
this.setState({
...this.state,
messages: [...this.state.messages, newMessage],
})
this.setState({
preferences: {...this.state.preferences, theme: 'dark'},
})
SQL Storage
For complex queries, use the embedded SQLite database:
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:
async onMessage(connection: Connection, message: string) {
const data = JSON.parse(message);
if (data.type === "schedule_reminder") {
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 ().(),
});
}
Schedule Options
await this.schedule(60, 'taskMethod', {data})
await this.schedule(new Date('2025-01-01T00:00:00Z'), 'taskMethod', {data})
await this.schedule('0 9 * * *', 'dailyTask', {})
await this.schedule('*/5 * * * *', 'everyFiveMinutes', {})
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<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
}
}
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,
})
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
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
npx wrangler deploy
wrangler tail
curl https://my-agent.workers.dev/agents/MyAgent/test-user
Troubleshooting
See references/troubleshooting.md for common issues.
References