AGENTS.md@examples · diff
git:20260207.c3211d0 to git:20260221.571b1bd
104 added, 15 removed. Audit A to B.
# 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 run dev` and see the feature in action, not just read server logs.
+ 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 both the React and Cloudflare Vite plugins:
+ 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()]
+ plugins: [react(), cloudflare(), tailwindcss()]
});
```
+ ### index.html
+
+ Include the theme flash prevention script and favicon:
+
+ ```html
+ <!doctype html>
+ <html lang="en" data-theme="workers">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="icon" href="/favicon.ico" />
+ <title>Example Title</title>
+ <script>
+ (() => {
+ const stored = localStorage.getItem("theme");
+ const mode = stored || "light";
+ document.documentElement.setAttribute("data-mode", mode);
+ document.documentElement.style.colorScheme = mode;
+ })();
+ </script>
+ </head>
+ <body>
+ <div id="root"></div>
+ <script type="module" src="/src/client.tsx"></script>
+ </body>
+ </html>
+ ```
+
### tsconfig.json
- Extend the base config. Only add overrides when the example genuinely needs them (e.g., JSX for React examples):
+ 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.
- Examples using `worker-configuration.d.ts` instead should be migrated to `env.d.ts`.
-
### .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. Prefer `.env` / `.env.example` over `.dev.vars` / `.dev.vars.example`.
+ 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`, `Input`, `Surface`, `Text`, `Badge`, `Empty`, etc.) instead of hand-rolled HTML
+ - 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 `<span>` if you need custom classes
- Use the `data-mode` attribute for dark mode — no `dark:` Tailwind variants
- Set `data-theme="workers"` on `<html>` 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
+ <Surface className="p-4 rounded-xl ring ring-kumo-line">
+ <div className="flex gap-3">
+ <InfoIcon
+ size={20}
+ weight="bold"
+ className="text-kumo-accent shrink-0 mt-0.5"
+ />
+ <div>
+ <Text size="sm" bold>
+ Title
+ </Text>
+ <span className="mt-1 block">
+ <Text size="xs" variant="secondary">
+ Description of what this demo shows and how to use it.
+ </Text>
+ </span>
+ </div>
+ </div>
+ </Surface>
+ ```
+
+ ### 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 run dev`)
+ 2. How to run it (`npm install && npm start`)
3. Any required env vars
- 4. Link to relevant SDK docs in `/docs` if applicable
+ 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.
- - Several examples are worker-only and need a frontend added: `email-agent/`, `mcp-elicitation/`, `mcp-server/`, `mcp-worker/`, `mcp-worker-authenticated/`, `x402/`, `x402-mcp/`
+ - `email-agent/` is worker-only and needs a frontend
- `cross-domain/` has a `vite.config.ts` but does not use `@cloudflare/vite-plugin`
- - `x402/` is missing README.md
- - `x402/` and `x402-mcp/` use `worker-configuration.d.ts` instead of `env.d.ts`
- - `codemode/` uses `.env.example` instead of `.dev.vars.example`
- - Some full-stack examples set `assets.directory: "public"` — not needed with the Vite plugin