Skip to content

Latest commit

 

History

History
222 lines (166 loc) · 6.91 KB

File metadata and controls

222 lines (166 loc) · 6.91 KB

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 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 agents/tsconfig
  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:

{
  "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. Examples that use @callable() or other decorators must also include the agents() plugin from agents/vite:

import { cloudflare } from "@cloudflare/vite-plugin";
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import agents from "agents/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [agents(), react(), cloudflare(), tailwindcss()]
});

The agents() plugin handles TC39 decorator transforms (Oxc doesn't support them yet). It's safe to include even if the example doesn't use decorators.

index.html

Include the theme flash prevention script and favicon:

<!doctype html>
<html lang="en">
  <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:

{
  "extends": "agents/tsconfig"
}

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

All examples use Kumo (@cloudflare/kumo) for components, with Kumo's default theme (no custom overrides).

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 <span> if you need custom classes
  • Use the data-mode attribute for dark mode — no dark: Tailwind variants

CSS imports (in src/styles.css)

@import "tailwindcss";
@import "@cloudflare/kumo/styles/tailwind";
@source "../../../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}";

Required UI patterns

Every example should include:

  • PoweredByCloudflare (from @cloudflare/kumo) — footer attribution badge (required in every example)
  • A dark mode toggle — inline a simple ModeToggle component using useState/useEffect + localStorage + Kumo Button with sun/moon icons
  • Connection status (for WebSocket-based examples) — inline a simple ConnectionIndicator showing a colored dot + label

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:

<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:

// 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.

  • cross-domain/ has a vite.config.ts but does not use @cloudflare/vite-plugin