← CloudflareCONTENT HISTORY

Update to Cloudflare

Snapshot Sep 30, 2026 · 23:18 UTC · version 0.1.2

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "building-ai-agent-on-cloudflare",
  "description": "Builds AI agents on Cloudflare using the Agents SDK with state management,\nreal-time WebSockets, scheduled tasks, tool integration, and chat capabilities.\nGenerates production-ready agent code deployed to Workers.\n\nUse when: user wants to \"build an agent\", \"AI agent\", \"chat agent\", \"stateful\nagent\", mentions \"Agents SDK\", needs \"real-time AI\", \"WebSocket AI\", or asks\nabout agent \"state management\", \"scheduled tasks\", or \"tool calling\".\nBiases towards retrieval from Cloudflare docs over pre-trained knowledge.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 132
    },
    {
      "relative_path": "references/agent-patterns.md",
      "size_in_bytes": 12349
    },
    {
      "relative_path": "references/examples.md",
      "size_in_bytes": 4273
    },
    {
      "relative_path": "references/state-patterns.md",
      "size_in_bytes": 8247
    },
    {
      "relative_path": "references/troubleshooting.md",
      "size_in_bytes": 8032
    }
  ],
  "skill_md_contents": "---\nname: building-ai-agent-on-cloudflare\ndescription: |\n  Builds AI agents on Cloudflare using the Agents SDK with state management,\n  real-time WebSockets, scheduled tasks, tool integration, and chat capabilities.\n  Generates production-ready agent code deployed to Workers.\n\n  Use when: user wants to \"build an agent\", \"AI agent\", \"chat agent\", \"stateful\n  agent\", mentions \"Agents SDK\", needs \"real-time AI\", \"WebSocket AI\", or asks\n  about agent \"state management\", \"scheduled tasks\", or \"tool calling\".\n  Biases towards retrieval from Cloudflare docs over pre-trained knowledge.\n---\n\n# Building Cloudflare Agents\n\nYour knowledge of the Agents SDK may be outdated. **Prefer retrieval over pre-training** for any agent-building task.\n\n## Retrieval Sources\n\n| Source | How to retrieve | Use for |\n|--------|----------------|---------|\n| Agents SDK docs | `https://github.com/cloudflare/agents/tree/main/docs` | SDK API, state, routing, scheduling |\n| Cloudflare Agents docs | `https://developers.cloudflare.com/agents/` | Platform integration, deployment |\n| Workers docs | Search tool or `https://developers.cloudflare.com/workers/` | Runtime APIs, bindings, config |\n\n## When to Use\n\n- User wants to build an AI agent or chatbot\n- User needs stateful, real-time AI interactions\n- User asks about the Cloudflare Agents SDK\n- User wants scheduled tasks or background AI work\n- User needs WebSocket-based AI communication\n\n## Prerequisites\n\n- Cloudflare account with Workers enabled\n- Node.js 18+ and npm/pnpm/yarn\n- Wrangler CLI (`npm install -g wrangler`)\n\n## Quick Start\n\n```bash\nnpm create cloudflare@latest -- my-agent --template=cloudflare/agents-starter\ncd my-agent\nnpm start\n```\n\nAgent runs at `http://localhost:8787`\n\n## Core Concepts\n\n### What is an Agent?\n\nAn Agent is a stateful, persistent AI service that:\n- Maintains state across requests and reconnections\n- Communicates via WebSockets or HTTP\n- Runs on Cloudflare's edge via Durable Objects\n- Can schedule tasks and call tools\n- Scales horizontally (each user/session gets own instance)\n\n### Agent Lifecycle\n\n```\nClient connects → Agent.onConnect() → Agent processes messages\n                                    → Agent.onMessage()\n                                    → Agent.setState() (persists + syncs)\nClient disconnects → State persists → Client reconnects → State restored\n```\n\n## Basic Agent Structure\n\n```typescript\nimport { Agent, Connection } from \"agents\";\n\ninterface Env {\n  AI: Ai;  // Workers AI binding\n}\n\ninterface State {\n  messages: Array<{ role: string; content: string }>;\n  preferences: Record<string, string>;\n}\n\nexport class MyAgent extends Agent<Env, State> {\n  // Initial state for new instances\n  initialState: State = {\n    messages: [],\n    preferences: {},\n  };\n\n  // Called when agent starts or resumes\n  async onStart() {\n    console.log(\"Agent started with state:\", this.state);\n  }\n\n  // Handle WebSocket connections\n  async onConnect(connection: Connection) {\n    connection.send(JSON.stringify({\n      type: \"welcome\",\n      history: this.state.messages,\n    }));\n  }\n\n  // Handle incoming messages\n  async onMessage(connection: Connection, message: string) {\n    const data = JSON.parse(message);\n\n    if (data.type === \"chat\") {\n      await this.handleChat(connection, data.content);\n    }\n  }\n\n  // Handle disconnections\n  async onClose(connection: Connection) {\n    console.log(\"Client disconnected\");\n  }\n\n  // React to state changes\n  onStateUpdate(state: State, source: string) {\n    console.log(\"State updated by:\", source);\n  }\n\n  private async handleChat(connection: Connection, userMessage: string) {\n    // Add user message to history\n    const messages = [\n      ...this.state.messages,\n      { role: \"user\", content: userMessage },\n    ];\n\n    // Call AI\n    const response = await this.env.AI.run(\"@cf/meta/llama-3-8b-instruct\", {\n      messages,\n    });\n\n    // Update state (persists and syncs to all clients)\n    this.setState({\n      ...this.state,\n      messages: [\n        ...messages,\n        { role: \"assistant\", content: response.response },\n      ],\n    });\n\n    // Send response\n    connection.send(JSON.stringify({\n      type: \"response\",\n      content: response.response,\n    }));\n  }\n}\n```\n\n## Entry Point Configuration\n\n```typescript\n// src/index.ts\nimport { routeAgentRequest } from \"agents\";\nimport { MyAgent } from \"./agent\";\n\nexport default {\n  async fetch(request: Request, env: Env) {\n    // routeAgentRequest handles routing to /agents/:class/:name\n    return (\n      (await routeAgentRequest(request, env)) ||\n      new Response(\"Not found\", { status: 404 })\n    );\n  },\n};\n\nexport { MyAgent };\n```\n\nClients connect via: `wss://my-agent.workers.dev/agents/MyAgent/session-id`\n\n## Wrangler Configuration\n\n```toml\nname = \"my-agent\"\nmain = \"src/index.ts\"\ncompatibility_date = \"2024-12-01\"\n\n[ai]\nbinding = \"AI\"\n\n[durable_objects]\nbindings = [{ name = \"AGENT\", class_name = \"MyAgent\" }]\n\n[[migrations]]\ntag = \"v1\"\nnew_classes = [\"MyAgent\"]\n```\n\n## State Management\n\n### Reading State\n\n```typescript\n// Current state is always available\nconst currentMessages = this.state.messages;\nconst userPrefs = this.state.preferences;\n```\n\n### Updating State\n\n```typescript\n// setState persists AND syncs to all connected clients\nthis.setState({\n  ...this.state,\n  messages: [...this.state.messages, newMessage],\n});\n\n// Partial updates work too\nthis.setState({\n  preferences: { ...this.state.preferences, theme: \"dark\" },\n});\n```\n\n### SQL Storage\n\nFor complex queries, use the embedded SQLite database:\n\n```typescript\n// Create tables\nawait this.sql`\n  CREATE TABLE IF NOT EXISTS documents (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    title TEXT NOT NULL,\n    content TEXT,\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n  )\n`;\n\n// Insert\nawait this.sql`\n  INSERT INTO documents (title, content)\n  VALUES (${title}, ${content})\n`;\n\n// Query\nconst docs = await this.sql`\n  SELECT * FROM documents WHERE title LIKE ${`%${search}%`}\n`;\n```\n\n## Scheduled Tasks\n\nAgents can schedule future work:\n\n```typescript\nasync onMessage(connection: Connection, message: string) {\n  const data = JSON.parse(message);\n\n  if (data.type === \"schedule_reminder\") {\n    // Schedule task for 1 hour from now\n    const { id } = await this.schedule(3600, \"sendReminder\", {\n      message: data.reminderText,\n      userId: data.userId,\n    });\n\n    connection.send(JSON.stringify({ type: \"scheduled\", taskId: id }));\n  }\n}\n\n// Called when scheduled task fires\nasync sendReminder(data: { message: string; userId: string }) {\n  // Send notification, email, etc.\n  console.log(`Reminder for ${data.userId}: ${data.message}`);\n\n  // Can also update state\n  this.setState({\n    ...this.state,\n    lastReminder: new Date().toISOString(),\n  });\n}\n```\n\n### Schedule Options\n\n```typescript\n// Delay in seconds\nawait this.schedule(60, \"taskMethod\", { data });\n\n// Specific date\nawait this.schedule(new Date(\"2025-01-01T00:00:00Z\"), \"taskMethod\", { data });\n\n// Cron expression (recurring)\nawait this.schedule(\"0 9 * * *\", \"dailyTask\", {});  // 9 AM daily\nawait this.schedule(\"*/5 * * * *\", \"everyFiveMinutes\", {});  // Every 5 min\n\n// Manage schedules\nconst schedules = await this.getSchedules();\nawait this.cancelSchedule(taskId);\n```\n\n## Chat Agent (AI-Powered)\n\nFor chat-focused agents, extend `AIChatAgent`:\n\n```typescript\nimport { AIChatAgent } from \"agents/ai-chat-agent\";\n\nexport class ChatBot extends AIChatAgent<Env> {\n  // Called for each user message\n  async onChatMessage(message: string) {\n    const response = await this.env.AI.run(\"@cf/meta/llama-3-8b-instruct\", {\n      messages: [\n        { role: \"system\", content: \"You are a helpful assistant.\" },\n        ...this.messages,  // Automatic history management\n        { role: \"user\", content: message },\n      ],\n      stream: true,\n    });\n\n    // Stream response back to client\n    return response;\n  }\n}\n```\n\nFeatures included:\n- Automatic message history\n- Resumable streaming (survives disconnects)\n- Built-in `saveMessages()` for persistence\n\n## Client Integration\n\n### React Hook\n\n```tsx\nimport { useAgent } from \"agents/react\";\n\nfunction Chat() {\n  const { state, send, connected } = useAgent({\n    agent: \"my-agent\",\n    name: userId,  // Agent instance ID\n  });\n\n  const sendMessage = (text: string) => {\n    send(JSON.stringify({ type: \"chat\", content: text }));\n  };\n\n  return (\n    <div>\n      {state.messages.map((msg, i) => (\n        <div key={i}>{msg.role}: {msg.content}</div>\n      ))}\n      <input onKeyDown={(e) => e.key === \"Enter\" && sendMessage(e.target.value)} />\n    </div>\n  );\n}\n```\n\n### Vanilla JavaScript\n\n```javascript\nconst ws = new WebSocket(\"wss://my-agent.workers.dev/agents/MyAgent/user123\");\n\nws.onopen = () => {\n  console.log(\"Connected to agent\");\n};\n\nws.onmessage = (event) => {\n  const data = JSON.parse(event.data);\n  console.log(\"Received:\", data);\n};\n\nws.send(JSON.stringify({ type: \"chat\", content: \"Hello!\" }));\n```\n\n## Common Patterns\n\nSee [references/agent-patterns.md](references/agent-patterns.md) for:\n- Tool calling and function execution\n- Multi-agent orchestration\n- RAG (Retrieval Augmented Generation)\n- Human-in-the-loop workflows\n\n## Deployment\n\n```bash\n# Deploy\nnpx wrangler deploy\n\n# View logs\nwrangler tail\n\n# Test endpoint\ncurl https://my-agent.workers.dev/agents/MyAgent/test-user\n```\n\n## Troubleshooting\n\nSee [references/troubleshooting.md](references/troubleshooting.md) for common issues.\n\n## References\n\n- [references/examples.md](references/examples.md) — Official templates and production examples\n- [references/agent-patterns.md](references/agent-patterns.md) — Advanced patterns\n- [references/state-patterns.md](references/state-patterns.md) — State management strategies\n- [references/troubleshooting.md](references/troubleshooting.md) — Error solutions\n"
}

SHA-256: 3d3faf239ef30e632d35de20bd079db3c5a55de44cb30b62cffda99fddea6b23