# AGENTS.md — examples/ Self-contained demo apps that show how to use the Agents SDK. These are user-facing learning material — keep them simple, clear, and consistent. Each example should focus on **one feature or concept** (e.g., MCP servers, email routing, workflows). The exception is `playground/`, which is the kitchen-sink showcase covering the full spread of SDK features in a single app. ## All examples are full-stack Every example has both a frontend and a backend. This makes them immediately runnable and visually demonstrable — users can `npm start` and see the feature in action, not just read server logs. All examples use the [Cloudflare Vite plugin](https://developers.cloudflare.com/workers/vite-plugin/) for development and builds. ## Required structure Every example must have: ``` example-name/ package.json # name, dependencies, scripts vite.config.ts # must use @cloudflare/vite-plugin wrangler.jsonc # Workers config (not .toml) tsconfig.json # must extend ../../tsconfig.base.json index.html # Vite entry point README.md # What this example demonstrates, how to run it public/ favicon.ico # Cloudflare favicon src/ server.ts # Worker entry point client.tsx # React client entry styles.css # Kumo + Tailwind imports ``` ## Conventions ### Scripts Use `start` (not `dev`) for the development server: ```json { "scripts": { "start": "vite dev", "deploy": "vite build && wrangler deploy", "types": "wrangler types env.d.ts --include-runtime false" } } ``` ### wrangler.jsonc - Use `wrangler.jsonc` (not `.toml`) - Include `"$schema": "../../node_modules/wrangler/config-schema.json"` - `compatibility_date: "2026-01-28"`, `compatibility_flags: ["nodejs_compat"]` - Full-stack apps with client routing: add `"assets": { "not_found_handling": "single-page-application" }` - Use `"run_worker_first"` to route API/agent paths to the Worker - Do not set `"directory"` in assets — the Vite plugin handles this ### vite.config.ts Every example must use the React, Cloudflare, and Tailwind Vite plugins: ```ts import { cloudflare } from "@cloudflare/vite-plugin"; import react from "@vitejs/plugin-react"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [react(), cloudflare(), tailwindcss()] }); ``` ### index.html Include the theme flash prevention script and favicon: ```html Example Title
``` ### tsconfig.json Extend the base config: ```json { "extends": "../../tsconfig.base.json" } ``` ### env.d.ts Generated by `npx wrangler types`. Do not hand-edit. Regenerate when bindings change. ### .env.example If the example needs secrets (API keys, etc.), include a `.env.example` showing what keys are needed: ``` OPENAI_API_KEY=your-key-here ``` Never commit actual secrets. Use `.env` / `.env.example` (not `.dev.vars` / `.dev.vars.example`). ### UI — Kumo + agents-ui All examples use [Kumo](https://kumo-ui.com/) (`@cloudflare/kumo`) for components and `@cloudflare/agents-ui` for shared cross-example UI. **Always check agents-ui before building something custom** — if it handles connection status, theme toggling, or branding, use the package. #### Kumo basics - Use Kumo components (`Button`, `Surface`, `Text`, `Badge`, `Empty`, etc.) instead of hand-rolled HTML - Use `@phosphor-icons/react` for icons (Kumo's icon library) - Use Kumo semantic color tokens (`text-kumo-default`, `bg-kumo-base`, `border-kumo-line`, etc.) instead of raw Tailwind colors - `Text` does not accept a `className` prop — wrap in a `` if you need custom classes - Use the `data-mode` attribute for dark mode — no `dark:` Tailwind variants - Set `data-theme="workers"` on `` for the Cloudflare-branded color theme #### CSS imports (in `src/styles.css`) ```css @import "tailwindcss"; @import "@cloudflare/kumo/styles/tailwind"; @import "@cloudflare/agents-ui/theme/workers.css"; @source "../../../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}"; ``` #### `@cloudflare/agents-ui` — required shared components Every example should use these from `@cloudflare/agents-ui`: - **`ThemeProvider`** (from `@cloudflare/agents-ui/hooks`) — wrap your app in `client.tsx` - **`ConnectionIndicator`** — show WebSocket connection state in the header - **`ModeToggle`** — light/dark/system toggle in the header - **`PoweredByAgents`** — footer attribution badge (**required in every example**) Don't re-implement connection indicators, theme toggles, or branding — import them. See `/design/visuals.md` for detailed Kumo usage patterns and known gaps. #### Explainer section Every example should include an info card at the top of the page explaining what the demo shows. Use the consistent pattern: ```tsx
Title Description of what this demo shows and how to use it.
``` ### Agent communication Prefer `@callable` methods + `useAgent`/`agent.call()` over manual `onRequest`/`agentFetch` or raw WebSocket messages: ```typescript // server.ts export class MyAgent extends Agent { @callable() async doSomething(arg: string) { return { result: arg }; } } // client.tsx const agent = useAgent({ agent: "my-agent", name: sessionId }); const result = await agent.call("doSomething", ["hello"]); ``` ### Dependencies - Keep example-specific dependencies minimal — these ship as learning material - Shared dependencies (`react`, `vite`, `wrangler`, `@cloudflare/vite-plugin`, etc.) live in the root `package.json` - Only add dependencies in the example's `package.json` if they're specific to what the example demonstrates ### README.md Every example needs one. Keep it short: 1. One sentence: what this example demonstrates 2. How to run it (`npm install && npm start`) 3. Any required env vars 4. Code snippets showing the key pattern 5. Links to related examples ## Known issues to clean up See `TODO.md` in this folder for the full checklist. - `email-agent/` is worker-only and needs a frontend - `cross-domain/` has a `vite.config.ts` but does not use `@cloudflare/vite-plugin`