1. Project Overview & Quickstart (cloudflare/agents)
File: README.md
Cloudflare Agents
Agents are persistent, stateful execution environments for agentic workloads, powered by Cloudflare Durable Objects. Each agent has its own state, storage, and lifecycle โ with built-in support for real-time communication, scheduling, AI model calls, MCP, workflows, and more.
Agents hibernate when idle and wake on demand. You can run millions of them โ one per user, per session, per game room โ each costs nothing when inactive.
npm create cloudflare@latest -- --template cloudflare/agents-starterOr add to an existing project:
npm install agentsRead the docs โ getting started, API reference, guides, and more.
Quick Example
A counter agent with persistent state, callable methods, and real-time sync to a React frontend:
// server.ts
import { Agent, routeAgentRequest, callable } from "agents";
export type CounterState = { count: number };
export class CounterAgent extends Agent<Env, CounterState> {
initialState = { count: 0 };
@callable()
increment() {
this.setState({ count: this.state.count + 1 });
return this.state.count;
}
@callable()
decrement() {
this.setState({ count: this.state.count - 1 });
return this.state.count;
}
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
return (
(await routeAgentRequest(request, env)) ??
new Response("Not found", { status: 404 })
);
}
};// client.tsx
import { useAgent } from "agents/react";
import { useState } from "react";
import type { CounterAgent, CounterState } from "./server";
function Counter() {
const [count, setCount] = useState(0);
const agent = useAgent<CounterAgent, CounterState>({
agent: "CounterAgent",
onStateUpdate: (state) => setCount(state.count)
});
return (
{count}
agent.stub.increment()}>+
agent.stub.decrement()}>-
);
}State changes sync to all connected clients automatically. Call methods like they're local functions.
The agent is a Durable Object, so it needs a binding and a SQLite migration in wrangler.jsonc:
{
"name": "counter",
"main": "server.ts",
"compatibility_date": "2026-06-11",
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
"bindings": [{ "name": "CounterAgent", "class_name": "CounterAgent" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["CounterAgent"] }]
}Features
| Feature | Description |
|---|---|
| Persistent State | Syncs to all connected clients, survives restarts |
| Callable Methods | Type-safe RPC via the @callable() decorator |
| Sub-agents | Parent/child DO composition via facets, nested routing, and typed parent lookup |
| Agent Tools | Run chat-capable sub-agents as tools with streaming child timelines |
| Scheduling | One-time, recurring, and cron-based tasks |
| WebSockets | Real-time bidirectional communication with lifecycle hooks |
| AI Chat | Message persistence, resumable streaming, server/client tool execution |
| MCP | Act as MCP servers or connect as MCP clients (HTTP, SSE, RPC, elicitation) |
| WebMCP | Expose page-local tools or bridge remote MCP tools to browser agents |
| Workflows | Durable multi-step tasks with human-in-the-loop approval |
| Send, receive, and reply via Cloudflare Email Service | |
| Voice | Continuous STT, streaming TTS, VAD, interruption, SFU utilities |
| Browser Agents | Run agents in the browser tab with agents/browser |
| Code Mode | LLMs generate executable TypeScript instead of individual tool calls |
| Sandboxed Execution | Run generated code inside an isolated Worker with a virtual filesystem |
| x402 Payments | Pay-per-call APIs and tools via the x402 protocol |
| Observability | Built-in tracing, metrics, and structured logs |
| SQL | Direct SQLite queries via Durable Objects |
| React Hooks | useAgent, useAgentChat, useVoiceAgent for frontend integration |
| Vanilla JS Client | AgentClient and VoiceClient for non-React environments |
Packages
| Package | Description |
|---|---|
agents |
Core SDK โ Agent class, routing, state, scheduling, MCP, email, workflows, x402, browser agents |
@cloudflare/ai-chat |
Higher-level AI chat โ persistent messages, resumable streaming, tool execution |
@cloudflare/think |
Opinionated chat agent base โ agentic loop, stream resumption, client tools, workspace tools |
@cloudflare/codemode |
LLMs write executable code that calls your tools, instead of one tool call at a time |
@cloudflare/shell |
Sandboxed JS execution + virtual filesystem (Workspace) for agents |
@cloudflare/voice |
Voice pipeline โ STT, TTS, VAD, streaming, SFU utilities |
@cloudflare/worker-bundler |
Build and bundle Workers at runtime, for use with the Worker Loader binding |
hono-agents |
Hono middleware for adding agents to Hono apps |
AI-chat modules used to live in
agents/ai-chat-agent,agents/chat,agents/ai-react, andagents/ai-types. Those entry points still re-export, but they're deprecated โ import from@cloudflare/ai-chatdirectly. New chat-from-scratch projects should look at@cloudflare/think.
Examples
The examples/ directory has 30+ self-contained demos. A non-exhaustive tour:
- Showcase โ
playground/is the kitchen-sink app: state, callable methods, scheduling, chat, tools, MCP, workflows, email, voice โ all in one UI - Chat & assistants โ
assistant/,agents-as-tools/,agent-skills/,workspace-chat/,resumable-stream-chat/,structured-input/,dynamic-tools/,multi-ai-chat/,context-overflow-recovery/ - MCP โ
mcp/,mcp-client/,mcp-server/,mcp-worker/,mcp-worker-authenticated/,mcp-elicitation-mrtr/,mcp-elicitation/,mcp-rpc-transport/,webmcp/,webmcp-react/ - Code Mode & sandboxes โ
codemode/,codemode-mcp/,codemode-mcp-openapi/,dynamic-workers/,dynamic-workers-playground/,worker-bundler-playground/ - Voice โ
voice-agent/is the unified voice pipeline example with Workers AI, AssemblyAI, Telnyx, and ElevenLabs STT;voice-input/covers dictation;telnyx-voice-agent/covers phone transport;elevenlabs-starter/covers broader ElevenLabs media APIs - Workflows & approvals โ
workflows/,a2a/ - Auth, payments, comms โ
auth-agent/,cross-domain/,x402/,x402-mcp/,email-agent/,github-webhook/,push-notifications/ - Game & misc โ
tictactoe/,ai-chat/
Examples using the OpenAI Agents SDK live in openai-sdk/. Work-in-progress experiments live in experimental/ (no stability guarantees).
Run any example locally:
cd examples/playground
npm startDocumentation
- Full docs on developers.cloudflare.com
docs/directory in this repo (synced upstream)- Anthropic Patterns guide โ sequential, routing, parallel, orchestrator, evaluator
- Human-in-the-Loop guide โ approval workflows with pause/resume
design/โ architecture and design decision records (chat API, sub-agents, agent tools, workspace, voice, browser tools, retries, and more)
Repository Structure
| Directory | Description |
|---|---|
packages/agents/ |
Core SDK |
packages/ai-chat/ |
AI chat layer |
packages/think/ |
Opinionated chat agent base |
packages/codemode/ |
Code Mode |
packages/shell/ |
Sandboxed execution + filesystem |
packages/voice/ |
Voice pipeline |
packages/worker-bundler/ |
Runtime Workers bundler |
packages/hono-agents/ |
Hono integration |
examples/ |
Self-contained demo apps |
experimental/ |
Work-in-progress experiments (not published) |
openai-sdk/ |
Examples using the OpenAI Agents SDK |
guides/ |
In-depth pattern tutorials |
docs/ |
Markdown docs synced to developers.cloudflare.com |
site/ |
Deployed websites (agents.cloudflare.com, AI playground) |
design/ |
Architecture and design decision records |
scripts/ |
Repo-wide tooling |
Development
Node 24+ required. pnpm workspaces with Nx for task orchestration, caching, and affected detection.
pnpm install # install all workspaces
pnpm run build # build all packages (Nx, cached, dependency-ordered)
pnpm run check # sherif + export checks + oxfmt + oxlint + typecheck
pnpm run test # vitest + vitest-pool-workers (Workers runtime)
pnpm run test:react # Playwright-based React hook tests
pnpm exec nx affected -t build # build only what changed
pnpm exec nx affected -t test # test only what changedChanges to packages/ need a changeset:
pnpm exec changesetSee AGENTS.md for deeper contributor guidance.
Contributing
We are not accepting external pull requests at this time โ the SDK is evolving quickly and we want to keep the surface area manageable. That said, we'd love to hear from you:
- Bug reports & feature requests โ open an issue
- Questions & ideas โ start a discussion
License
File: docs/index.md
Cloudflare Agents SDK Documentation
Documentation is grouped by the package that owns it:
agentsโ Durable Object agents, state, routing, scheduling, sessions, MCP, and shared primitives@cloudflare/thinkโ opinionated agent harness built on Agents, Codemode, and Shell@cloudflare/codemodeโ sandboxed code execution, tool providers, connectors, approvals, and snippets@cloudflare/shellโ durable workspaces and filesystem tools@cloudflare/voiceโ voice agents, clients, audio pipelines, and provider contracts
Each package listed above includes its own documentation under docs/. Other published packages use their package README as their documentation entry point. Package indexes name relevant dependency documentation by package path, for example agents/docs/index.md or @cloudflare/codemode/docs/index.md.
File: examples/tictactoe/README.md
Tic Tac Toe
A simple demo showing a smart agent playing Tic Tac Toe against a human. The AI opponent uses GPT-4o to make strategic moves.
Quick Start
Copy .env.example to .env and fill in your OpenAI API key.
npm i && npm startVisit http://localhost:5174 to play against the agent.
File: examples/playground/README.md
Agents SDK Playground
An interactive demo application showcasing the major feature areas of the Cloudflare Agents SDK. Use it to learn the SDK, test features, and understand how agents work.
Getting Started
# Install dependencies
npm install
# Start the development server
npm startVisit http://localhost:5173 to explore the playground.
Features
The playground is organized into feature categories, each with interactive demos:
Core
| Demo | Description |
|---|---|
| State | Real-time state synchronization with setState() and onStateChanged() |
| Callable | RPC methods using the @callable decorator |
| Streaming | Streaming responses with StreamingResponse |
| Schedule | One-time and recurring task scheduling |
| Connections | WebSocket lifecycle, client tracking, and broadcasting |
| SQL | Direct SQLite queries using this.sql template literal |
| Routing | Agent naming strategies (per-user, shared, per-session) |
| Readonly | Read-only agent access |
| Retry | Retry with backoff and shouldRetry |
Durable Execution
| Demo | Description |
|---|---|
| Fibers | Long-running work with checkpoints and recovery hooks |
Multi-Agent
| Demo | Description |
|---|---|
| Supervisor | Manager-child agent pattern using getAgentByName() for RPC |
| Chat Rooms | Lobby with room agents for multi-user chat |
| Workers | Fan-out parallel processing |
| Pipeline | Chain of responsibility pattern |
AI
| Demo | Description |
|---|---|
| Chat | AIChatAgent with message persistence and streaming |
| Tools | Client-side tool execution with confirmation flows |
| Codemode | AI code generation and editing |
| Agent Tools | Delegate chat work to child agents with inline timelines |
| Think + Shell | Assistant runtime with durable workspace and state tools |
MCP (Model Context Protocol)
| Demo | Description |
|---|---|
| Server | Creating MCP servers with tools, resources, and prompts |
| Client | Connecting to external MCP servers |
| OAuth | OAuth authentication for MCP connections |
| Advanced MCP | Transports, elicitation, codemode, and x402 patterns |
Workflows
| Demo | Description |
|---|---|
| Basic | Interactive multi-step workflow simulation with progress |
| Approval | Human-in-the-loop approval/rejection patterns |
| Demo | Description |
|---|---|
| Receive | Receive real emails via Cloudflare Email Routing |
| Secure Replies | Send HMAC-signed replies for secure routing back to the agent |
Note: Email demos require deployment to Cloudflare. A warning banner is shown when running locally.
Product Integrations
| Demo | Description |
|---|---|
| Integration Stories | Email, webhooks, push, A2A, x402, and browser-tool stories |
Project Structure
playground/
โโโ src/
โ โโโ demos/ # Demo pages and agent definitions
โ โ โโโ core/ # State, callable, streaming, schedule, etc.
โ โ โโโ ai/ # Chat, tools, codemode
โ โ โโโ durable/ # Fibers and durable execution
โ โ โโโ mcp/ # Server, client, OAuth
โ โ โโโ multi-agent/ # Supervisor, chat rooms, workers, pipeline
โ โ โโโ workflow/ # Basic, approval
โ โ โโโ email/ # Receive, secure replies
โ โ โโโ integrations/ # Product integration explainers
โ โโโ components/ # Shared UI components
โ โโโ layout/ # App layout (sidebar, wrapper)
โ โโโ hooks/ # React hooks (theme, userId, logs)
โ โโโ pages/ # Home page
โ โโโ client.tsx # Client entry point
โ โโโ server.ts # Worker entry point
โ โโโ styles.css # Tailwind styles
โโโ testing.md # Manual testing guide
โโโ TODO.md # Planned improvements
โโโ wrangler.jsonc # Cloudflare configurationTesting
See testing.md for a comprehensive guide on manually testing every feature.
Configuration
Each demo has its own Durable Object agent. The full list of agents and workflows is defined in wrangler.jsonc.
Environment Variables
For the email demos, set EMAIL_SECRET for HMAC-signed replies:
# Production
wrangler secret put EMAIL_SECRETFor local development, add it to a .env file:
EMAIL_SECRET=your-secret-for-email-signingEmail Routing Setup
To test the email demos with real emails:
- Deploy to Cloudflare:
npm run deploy - Go to Cloudflare Dashboard โ Email โ Email Routing
- Add a routing rule to forward emails to your Worker
- Send emails to:
[email protected]โ ReceiveEmailAgent[email protected]โ SecureEmailAgent
Dark Mode
Click the theme toggle in the sidebar footer to switch between Light and Dark themes.
File: examples/mcp-client/README.md
MCP Client
An Agent that acts as an MCP client โ dynamically connects to remote MCP servers, handles OAuth authentication, and aggregates tools, prompts, and resources from all connected servers.
What it demonstrates
addMcpServer/removeMcpServerโ managing MCP server connections from an AgentonMcpUpdateโ real-time state updates pushed to the React frontend via WebSocketthis.mcp.configureElicitationHandlersโ handles both Stateless Elicitation (input_requiredthrough MRTR) and Legacy Elicitation (pushedelicitation/create); the Agent broadcasts requests to the browser and the human's answer resolves the pending operation via a@callablemethod- OAuth popup flow โ
configureOAuthCallbackwith a custom handler that closes the popup after auth agentFetchโ making HTTP requests to the Agent's custom endpoints from the client
Running
npm install
npm run startThe UI lets you add MCP server URLs, see their connection state, browse their tools, prompts, and resources, and run tools. If a tool call triggers an elicitation, a card appears asking for your input.
To test with an authenticated server, run mcp-worker-authenticated alongside this example and add its URL. For Stateless Elicitation, run mcp-elicitation-mrtr and call increase-counter. To test pushed form- and URL-mode Legacy Elicitation, run mcp-elicitation. Each endpoint is /mcp (for example, http://localhost:8787/mcp).
Environment variables
Copy .env.example to .env if you need to override the OAuth callback host:
cp .env.example .envHow it works
Server side
The Agent manages MCP connections via the built-in mcp property:
export class MyAgent extends Agent {
onStart() {
this.mcp.configureOAuthCallback({
customHandler: (result) => {
if (result.authSuccess) {
return new Response("<script>window.close();</script>", {
headers: { "content-type": "text/html" }
});
}
return new Response(`Auth failed: ${result.authError}`, {
status: 400
});
}
});
}
async onRequest(request) {
// Custom endpoints for the frontend
if (url.pathname.endsWith("add-mcp")) {
const { name, url } = await request.json();
await this.addMcpServer(name, url);
return new Response("Ok");
}
}
}Client side
The React frontend uses useAgent with onMcpUpdate to receive real-time server state:
const agent = useAgent({
agent: "my-agent",
name: sessionId,
onMcpUpdate: (mcpServers) => setMcpState(mcpServers),
onOpen: () => setConnected(true)
});Related examples
mcpโ stateful MCP server (good target to connect to)mcp-worker-authenticatedโ authenticated server (tests the OAuth flow)
File: examples/mcp/README.md
Stateful MCP Server
A deprecated, feature-frozen stateful MCP server retained only for existing deployments during migration. State persists across requests through McpAgent and a Durable Object. New servers should use the stateless SDK v2 createMcpHandler path.
What it demonstrates
McpAgentโ the Agents SDK class for building MCP servers with persistent state- Tools โ registering an
addtool that modifies the counter - Resources โ exposing the counter value as an MCP resource
- State management โ
setStateandonStateChangedfor durable state - Streamable HTTP transport โ the default transport for
McpAgent
Running
pnpm install
pnpm startOpen the browser to see the built-in tool tester. You can also connect with the MCP Inspector โ set the transport to Streamable HTTP and URL to http://localhost:5173/mcp.
How it works
The McpAgent class extends Agent with MCP protocol support. Define your tools and resources in the init() method:
export class MyMCP extends McpAgent<Env, State, {}> {
server = new McpServer({ name: "Demo", version: "1.0.0" });
initialState: State = { counter: 1 };
async init() {
this.server.resource("counter", "mcp://resource/counter", (uri) => ({
contents: [{ text: String(this.state.counter), uri: uri.href }]
}));
this.server.registerTool(
"add",
{ description: "Add to the counter", inputSchema: { a: z.number() } },
async ({ a }) => {
this.setState({ ...this.state, counter: this.state.counter + a });
return {
content: [{ type: "text", text: `Total: ${this.state.counter}` }]
};
}
);
}
}
export default MyMCP.serve("/mcp", { binding: "MyMCP" });Related examples
mcp-workerโ simplest stateless MCP server usingcreateMcpHandlermcp-worker-authenticatedโ adding OAuth to an MCP servermcp-clientโ connecting to MCP servers as a client
File: examples/cross-domain/README.md
Cross-Domain Communication Demo
A simple demo showing WebSocket and HTTP communication between a React client and Cloudflare Worker server, when running on different domains. tl;dr - make sure you pass cors: true to routeAgentRequest.
Quick Start
Run the front end and agents server:
npm i && npm startFile: guides/human-in-the-loop/README.md
Human in the Loop with Cloudflare Agents
This guide demonstrates human-in-the-loop patterns using AIChatAgent from @cloudflare/ai-chat. Tools can require user approval before executing, and tools that need browser APIs are handled client-side.
Key Patterns
needsApproval-- Server-side tools that pause for user approval before executingonToolCall-- Client-side tool execution for tools that need browser APIsaddToolApprovalResponse-- Client responds to approval requests
Server
Tools are defined on the server. Use needsApproval for tools requiring human confirmation:
import { AIChatAgent } from "@cloudflare/ai-chat";
import { streamText, convertToModelMessages, tool } from "ai";
import { z } from "zod";
export class HumanInTheLoop extends AIChatAgent {
async onChatMessage() {
const result = streamText({
model: openai("gpt-4o"),
messages: await convertToModelMessages(this.messages),
tools: {
// Requires approval -- needsApproval: true
getWeather: tool({
inputSchema: z.object({ city: z.string() }),
needsApproval: true,
execute: async ({ city }) => `The weather in ${city} is sunny.`
}),
// Client-side tool -- no execute function
getLocalTime: tool({
inputSchema: z.object({ location: z.string() })
}),
// Automatic -- no approval, runs server-side
getNews: tool({
inputSchema: z.object({ location: z.string() }),
execute: async ({ location }) => `${location} news: all good!`
})
},
maxSteps: 5
});
return result.toUIMessageStreamResponse();
}
}Client
Handle approvals with addToolApprovalResponse and client-side tools with onToolCall:
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";
function Chat() {
const agent = useAgent({ agent: "human-in-the-loop" });
const { messages, sendMessage, addToolApprovalResponse } = useAgentChat({
agent,
onToolCall: async ({ toolCall, addToolOutput }) => {
if (toolCall.toolName === "getLocalTime") {
const time = new Date().toLocaleTimeString();
addToolOutput({ toolCallId: toolCall.toolCallId, output: time });
}
}
});
return (
{messages.map((msg) => (
{msg.parts.map((part, i) => {
if (part.type === "text") return {part.text};
// Tool approval request
if ("approval" in part && part.state === "approval-requested") {
return (
Approve {getToolName(part)}?
addToolApprovalResponse({
id: part.approval.id,
approved: true
})
}
>
Approve
addToolApprovalResponse({
id: part.approval.id,
approved: false
})
}
>
Reject
);
}
return null;
})}
))}
);
}Running
npm install
npm run devRequires OPENAI_API_KEY in .env.
Learn More
File: guides/anthropic-patterns/README.md
Agent Patterns Demo
This project demonstrates different patterns for building AI agents, based on Anthropic's research, implemented using Cloudflare's Durable Objects and the AI SDK.
Overview
The demo showcases five fundamental patterns for building AI agents:
- Prompt Chaining: Sequential processing where each step builds on the previous
- Routing: Intelligent classification and routing of tasks
- Parallelization: Concurrent execution of multiple subtasks
- Orchestrator-Workers: Dynamic task breakdown and delegation
- Evaluator-Optimizer: Iterative improvement through feedback loops
Each pattern is implemented as a Durable Object, providing persistence, real-time updates, and scalability.
Architecture
Frontend
- React application with TypeScript
- Real-time WebSocket connections to Durable Objects (powered by PartySocket, a reconnecting websocket library with a react hook)
- Dark mode support
- Responsive design
Backend
- Cloudflare Durable Objects + PartyServer for agent state management
- WebSocket connections for live updates
- OpenAI integration via AI SDK
- AI SDK for defining agent workflows
- AI Gateway for caching and rate limiting
Features
- Live Agent Interaction: Test each pattern with real inputs
- Real-time Updates: See agent progress as it happens
- Persistent State: Agents continue running even if you close the browser
- Global Scaling: Runs on Cloudflare's edge network
- Bonus: Dark Mode: Supports system preferences and manual toggle
Getting Started
Clone the repository
Install dependencies:
bashnpm installCreate a
.envfile with your API keys:textOPENAI_API_KEY=your_key_here AI_GATEWAY_TOKEN=your_key_hereEdit
wrangler.jsonto set your account ID and ai gateway ID details:json"account_id": "your_account_id_here" "vars": { "AI_GATEWAY_ACCOUNT_ID": "your_account_id_here", "AI_GATEWAY_ID": "your_gateway_id_here" }Run the development server:
bashnpm start
Deployment
The application is designed to be deployed to Cloudflare Workers:
npm run deployImplementation Details
Durable Objects
We have an createAgent factory function that creates a new Durable Object class for a given pattern/workflow. The template for the class includes basic state management and websocket communication. So by calling createAgent(async () => {/* run the pattern */}) we get a new Durable Object class that can be used to create an instance. We create the 5 types of agents and export them from the worker, and wire them up as bindings in wrangler.jsonc.
WebSocket Communication
The frontend maintains WebSocket connections to each Durable Object instance. The websocket sends state updates to the frontend.
const socket = usePartySocket({
party: type,
room: "default-room",
onMessage: (e) => {
const data = JSON.parse(e.data);
switch (data.type) {
case "state":
setWorkflowState(data.state);
break;
}
}
});The frontend also triggers the workflow by sending a run message to the websocket with initial input.
State Management
Each Durable Object maintains its own state:
state: {
isRunning: boolean;
output: any;
} = {
isRunning: false,
output: undefined,
};Read more in the source code.
Why Durable Objects?
Durable Objects provide several key benefits for hosting AI agents:
- Persistence: Agents continue running even when clients disconnect
- Real-time Updates: WebSocket connections enable live progress streaming
- Global Scale: Automatic distribution across Cloudflare's network
- Flexible Triggers: Can be activated by HTTP, cron jobs, or other events
- Memory Isolation: Each agent runs in its own environment
- Cost Effective: Pay only for actual compute time used
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests.
License
MIT License - feel free to use this code in your own projects.
Acknowledgments
- Based on research by Anthropic
- Uses AI SDK
- Built on Cloudflare Workers and Durable Objects
File: packages/hono-agents/README.md
hono-agents
๐ฅ Hono โจ ๐ง Cloudflare Agents
Add intelligent, stateful AI agents to your Hono app. Create persistent AI agents that can think, communicate, and evolve over time, all integrated seamlessly with your Hono application.
Installation
npm install agents hono hono-agentsUsage
import { Hono } from "hono";
import { Agent } from "agents";
import { agentsMiddleware } from "hono-agents";
// Define your agent classes
export class ChatAgent extends Agent {
async onRequest(_request: Request) {
return new Response("Ready to assist with chat.");
}
}
export class AssistantAgent extends Agent {
async onRequest(_request: Request) {
return new Response("I'm your AI assistant.");
}
}
// Basic setup
const app = new Hono();
app.use("*", agentsMiddleware());
export default app;Authentication
Replace the basic middleware registration with one that authenticates both
WebSocket connections and HTTP requests:
const authorizeAgentRequest = async (req: Request) => {
const token = req.headers.get("authorization");
// Validate token
if (!token) return new Response("Unauthorized", { status: 401 });
};
app.use(
"*",
agentsMiddleware({
options: {
onBeforeConnect: authorizeAgentRequest,
onBeforeRequest: authorizeAgentRequest
}
})
);Error handling
Replace the basic middleware registration to add an error handler:
app.use("*", agentsMiddleware({ onError: (error) => console.error(error) }));Custom routing
Replace the basic middleware registration to customize routing:
app.use(
"*",
agentsMiddleware({
options: {
prefix: "agents" // Handles /agents/* routes only
}
})
);Configuration
To properly configure your Cloudflare Workers project to use agents, add bindings to your wrangler.jsonc file:
{
"durable_objects": {
"bindings": [
{ "name": "ChatAgent", "class_name": "ChatAgent" },
{ "name": "AssistantAgent", "class_name": "AssistantAgent" }
]
},
"migrations": [
{
"tag": "v1",
"new_sqlite_classes": ["ChatAgent", "AssistantAgent"]
}
]
}How It Works
The agentsMiddleware function:
- Detects whether the incoming request is a WebSocket connection or standard HTTP request
- Routes the request to the appropriate agent
- Handles WebSocket upgrades for persistent connections
- Provides error handling and custom routing options
Requests that do not match an Agent route continue through later Hono middleware
and routes. Once an Agent route matches, its responseโincluding an HTTP
rejectionโis returned without invoking later handlers. Mount agentsMiddleware
on a narrower path or configure a distinct prefix if the app has other WebSocket
routes under the same URL prefix.
Agents can:
- Maintain state across requests
- Handle both HTTP and WebSocket connections
- Schedule tasks for future execution
- Communicate with AI services
- Integrate seamlessly with React applications
License
Learn more about Cloudflare Agents at https://www.npmjs.com/package/agents
ISC
2. Official Technical Reference & Guides (cloudflare/docs)
AMPProject.org [](https://travis-ci.org/ampproject/docs)
You're looking at the source code of the official website of the AMP Project.
Even if you don't plan on contributing, explore how we've built the site for
a good example of how to build a canonical, responsive standalone AMP site.
How to build the site
Install
Install Grow and npm dependencies:
$ curl https://install.growsdk.org | bash
$ npm installGet a GitHub token or app id/secret
The docs in the reference section of the AMP Project site are not part of this repository; instead they are read from the amphtml GitHub repository "source of truth." When building the site these docs are fetched via GitHub.
Due to GitHub quotas this fetching will quickly fail unless additional information is provided in the request. This can be either a personal access token or an application id/secret.
Personal access token
- Request a GitHub personal access token. Since the docs are fetched from a public repository you only need to select the "public_repo" scope when creating the token. (It's a good practice to limit the token to the scope you need.)
- In your shell export the generated personal access token as
AMP_DOC_TOKEN
Application client id and secret
If you prefer not to use a personal access token, you can also create a GitHub application and use its id and secret.
- Register for a GitHub application
- In your shell export the application client id as
AMP_DOC_IDand the client secret asAMP_DOC_SECRET
Build
$ grow buildThis will generate a static, complete build of the site into the *build folder.
Develop
Note: Be sure to run grow build at least once to pull in reference docs before running the following command.
$ grow runYou can now open http://localhost:8080/ and continue working on the source files, then reload the page to see changes appear.
Support
If you've found an error or inconsistency, please file an issue:
https://github.com/ampproject/docs/issues
Patches are encouraged, and may be submitted by forking this project and
submitting a pull request through GitHub.
License
All image and audio files except in folders "source/img/partners",
"source/img/publishers" and "source/img/quotes" (including *.png, *.jpg, *.svg,
*.mp3, *.wav and *.ogg) are licensed under the CC-BY-NC license. Images in the
excluded folders are not licensed.
All other files are licensed under the Apache 2 license.
Copyright 2015 Google, Inc.
Licensed to the Apache Software Foundation (ASF) under one or more contributor
license agreements. See the NOTICE file distributed with this work for
additional information regarding copyright ownership. The ASF licenses this
file to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.