RepoCloudflare (Workers AI)Cloudflare (Workers AI)published Feb 21, 2025seen 5d

cloudflare/agents-starter

TypeScript

Open original ↗

Captured source

source ↗
published Feb 21, 2025seen 5dcaptured 8hhttp 200method plain

cloudflare/agents-starter

Description: A starter kit for building ai agents on Cloudflare

Language: TypeScript

License: MIT

Stars: 1269

Forks: 260

Open issues: 16

Created: 2025-02-21T00:58:55Z

Pushed: 2026-06-02T11:26:00Z

Default branch: main

Fork: no

Archived: no

README:

Agent Starter

![npm i agents command](./npm-agents-banner.svg)

A starter template for building AI chat agents on Cloudflare, powered by the Agents SDK.

Uses Workers AI (no API key required), with tools for weather, timezone detection, calculations with approval, task scheduling, and vision (image input).

Quick start

npx create-cloudflare@latest --template cloudflare/agents-starter
cd agents-starter
npm install
npm run dev

Open http://localhost:5173 to see your agent in action.

Try these prompts to see the different features:

  • "What's the weather in Paris?" — server-side tool (runs automatically)
  • "What timezone am I in?" — client-side tool (browser provides the answer)
  • **"Calculate 5000 \* 3"** — approval tool (asks you before running)
  • "Remind me in 5 minutes to take a break" — scheduling
  • Drop an image and ask "What's in this image?" — vision (image understanding)

Project structure

src/
server.ts # Chat agent with tools and scheduling
app.tsx # Chat UI built with Kumo components
client.tsx # React entry point
styles.css # Tailwind + Kumo styles

What's included

  • AI Chat — Streaming responses powered by Workers AI via AIChatAgent
  • Image input — Drag-and-drop, paste, or click to attach images for vision-capable models
  • Three tool patterns — server-side auto-execute, client-side (browser), and human-in-the-loop approval
  • Scheduling — one-time, delayed, and recurring (cron) tasks
  • Reasoning display — shows model thinking as it streams, collapses when done
  • Debug mode — toggle in the header to inspect raw message JSON for each message
  • Kumo UI — Cloudflare's design system with dark/light mode
  • Real-time — WebSocket connection with automatic reconnection and message persistence

Making it your own

Name your project

Update the name in package.json and wrangler.jsonc — the name in wrangler.jsonc becomes your deployed Worker's URL (..workers.dev).

Change the system prompt

Edit the system string in server.ts to give your agent a different personality or focus area. This is the most impactful single change you can make.

Replace the demo tools with real ones

The starter ships with demo tools (getWeather returns random data, calculate does basic arithmetic). Replace them with real implementations:

// In server.ts, replace a demo tool with a real API call:
getWeather: tool({
description: "Get the current weather for a city",
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => {
const res = await fetch(`https://api.weather.example/${city}`);
return res.json();
}
}),

Add your own tools

Add new tools to the tools object in server.ts. There are three patterns:

// Auto-execute: runs on the server, no user interaction
myTool: tool({
description: "...",
inputSchema: z.object({ /* ... */ }),
execute: async (input) => { /* return result */ }
}),

// Client-side: no execute function, browser provides the result
// Handle it in app.tsx via the onToolCall callback
browserTool: tool({
description: "...",
inputSchema: z.object({ /* ... */ })
}),

// Approval: add needsApproval to gate execution
sensitiveTool: tool({
description: "...",
inputSchema: z.object({ /* ... */ }),
needsApproval: async (input) => true, // or conditional logic
execute: async (input) => { /* runs after approval */ }
}),

Customize scheduled task behavior

When a scheduled task fires, executeTask runs on the server. It does its work and then uses this.broadcast() to notify connected clients (shown as a toast notification in the UI). Replace it with your own logic:

async executeTask(description: string, task: Schedule) {
// Do the actual work
await sendEmail({ to: "user@example.com", subject: description });

// Notify connected clients
this.broadcast(
JSON.stringify({ type: "scheduled-task", description, timestamp: new Date().toISOString() })
);
}

> Why `broadcast()` instead of `saveMessages()`? Injecting into chat history can cause the AI to see the notification as new context and re-trigger the same task in a loop. broadcast() sends a one-off event that the client displays separately from the conversation.

Remove scheduling

If you don't need scheduling, remove scheduleTask, getScheduledTasks, and cancelScheduledTask from the tools object, the executeTask method, and the schedule-related imports (getSchedulePrompt, scheduleSchema, Schedule, generateId).

Add state beyond chat messages

Use this.setState() and this.state for real-time state that syncs to all connected clients. See Store and sync state.

Add callable methods

Expose agent methods as typed RPC that your client can call directly:

import { callable } from "agents";

export class ChatAgent extends AIChatAgent {
@callable()
async getStats() {
return { messageCount: this.messages.length };
}
}

// Client-side:
const stats = await agent.call("getStats");

See Callable methods.

Connect to MCP servers

Add external tools from MCP servers:

async onChatMessage(onFinish, options) {
// Connect to an MCP server
await this.mcp.connect("https://my-mcp-server.example/sse");

const result = streamText({
// ...
tools: {
...myTools,
...this.mcp.getAITools() // Include MCP tools
}
});
}

See MCP Client API.

Use a different AI model provider

The starter uses Workers AI by default (no API key needed). To use a different provider:

OpenAI

npm install @ai-sdk/openai
// In server.ts, replace the model:
import { openai } from "@ai-sdk/openai";

// Inside onChatMessage:
const result = streamText({
model: openai("gpt-5.2")
// ...
});

Create a .env file with your API key:

OPENAI_API_KEY=your-key-here

Anthropic

npm install…

Excerpt shown — open the source for the full document.

Notability

notability 6.0/10

New starter repo with solid traction