diff --git a/src/content/docs/agents/getting-started/add-to-existing-project.mdx b/src/content/docs/agents/getting-started/add-to-existing-project.mdx
index 6322b0ec7e645a..df0743b51393da 100644
--- a/src/content/docs/agents/getting-started/add-to-existing-project.mdx
+++ b/src/content/docs/agents/getting-started/add-to-existing-project.mdx
@@ -3,6 +3,7 @@ title: Add to existing project
pcx_content_type: how-to
sidebar:
order: 2
+description: Add agents with persistent state and real-time sync to an existing Cloudflare Workers project.
---
import {
@@ -12,7 +13,7 @@ import {
LinkCard,
} from "~/components";
-This guide shows how to add agents to an existing Cloudflare Workers project. If you are starting fresh, refer to [Building a chat agent](/agents/getting-started/build-a-chat-agent/) instead.
+This guide shows how to add agents to an existing Cloudflare Workers project. If you are starting a new project, refer to [Quick start](/agents/getting-started/quick-start/) instead.
## Prerequisites
@@ -36,7 +37,7 @@ Create a new file for your agent (for example, `src/agents/counter.ts`):
```ts
-import { Agent } from "agents";
+import { Agent, callable } from "agents";
export type CounterState = {
count: number;
@@ -45,11 +46,13 @@ export type CounterState = {
export class CounterAgent extends Agent {
initialState: CounterState = { 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;
@@ -69,7 +72,7 @@ Add the Durable Object binding and migration:
{
"name": "my-existing-project",
"main": "src/index.ts",
- "compatibility_date": "2025-01-01",
+ "compatibility_date": "$today",
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
@@ -143,7 +146,7 @@ export default {
return new Response("Not found", { status: 404 });
},
-};
+} satisfies ExportedHandler;
```
@@ -191,7 +194,7 @@ export default {
return new Response("Not found", { status: 404 });
},
-};
+} satisfies ExportedHandler;
```
@@ -210,28 +213,17 @@ Configure assets in the Wrangler configuration file:
-## 6. Add TypeScript types
+## 6. Generate TypeScript types
+
+Do not hand-write your `Env` interface. Run [`wrangler types`](/workers/wrangler/commands/#types) to generate a type definition file that matches your Wrangler configuration. This catches mismatches between your config and code at compile time instead of at deploy time.
-You can generate types automatically from your Wrangler configuration file:
+Re-run `wrangler types` whenever you add or rename a binding.
```sh
-npx wrangler types env.d.ts
+npx wrangler types
```
-This creates an `env.d.ts` file with all your bindings typed. Alternatively, you can manually update your `Env` type to include the agent namespace:
-
-```ts
-import type { CounterAgent } from "./agents/counter";
-
-interface Env {
- // Your existing bindings
- MY_KV: KVNamespace;
- MY_DB: D1Database;
-
- // Add agent bindings
- CounterAgent: DurableObjectNamespace;
-}
-```
+This creates a type definition file with all your bindings typed, including your agent Durable Object namespaces. The `Agent` class defaults to using the generated `Env` type, so you do not need to pass it as a type parameter — `extends Agent` is sufficient unless you need to pass a second type parameter for state (for example, `Agent`).
Refer to [Configuration](/agents/api-reference/configuration/#generating-types) for more details on type generation.
@@ -295,11 +287,15 @@ Add more agents by extending the configuration:
```ts
// src/agents/chat.ts
+import { Agent } from "agents";
+
export class Chat extends Agent {
// ...
}
// src/agents/scheduler.ts
+import { Agent } from "agents";
+
export class Scheduler extends Agent {
// ...
}
@@ -367,7 +363,7 @@ export default {
// ... rest of routing
},
-};
+} satisfies ExportedHandler;
```
@@ -409,7 +405,7 @@ export default {
}
// ...
},
-};
+} satisfies ExportedHandler;
```
diff --git a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx b/src/content/docs/agents/getting-started/build-a-chat-agent.mdx
index 23cd3f8b879fc1..f8f55e743f3f17 100644
--- a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx
+++ b/src/content/docs/agents/getting-started/build-a-chat-agent.mdx
@@ -7,7 +7,7 @@ head: []
description: Build a streaming AI chat agent with tool integration using Cloudflare Workers and the Agents framework.
---
-import { TypeScriptExample, WranglerConfig } from "~/components";
+import { TypeScriptExample, WranglerConfig, LinkCard } from "~/components";
A complete guide to building a streaming AI chat agent with tool integration using Cloudflare Workers and the Agents framework.
@@ -34,9 +34,9 @@ npm install
You have two options for setting up your OpenAI API key:
-**Option A: Using `.dev.vars` (recommended for development)**
+**Option A: Using `.env` (recommended for development)**
-Create a `.dev.vars` file in your project root:
+Create a `.env` file in your project root (and make sure it is in your `.gitignore`):
```txt
OPENAI_API_KEY=your-key-here
@@ -50,13 +50,19 @@ For production deployments, use Cloudflare secrets instead of putting API keys i
wrangler secret put OPENAI_API_KEY
```
-## Step 3: Test the agent locally
+You can also upload all secrets from your `.env` file to production at once:
+
+```bash
+wrangler secret bulk .env
+```
+
+## Step 3: Run the dev server
```bash
npm start
```
-The server will be available at `http://localhost:5174`. Open your browser and start chatting.
+Open your browser and start chatting. Check the terminal output for the correct URL.
## Understanding the code
@@ -82,10 +88,14 @@ The main agent class that handles chat interactions:
```ts
-import { AIChatAgent } from "agents/ai-chat-agent";
+import { AIChatAgent } from "@cloudflare/ai-chat";
+import { streamText, type StreamTextOnFinishCallback, type ToolSet } from "ai";
export class Chat extends AIChatAgent {
- async onChatMessage(onFinish, options) {
+ async onChatMessage(
+ onFinish: StreamTextOnFinishCallback,
+ options?: { abortSignal?: AbortSignal },
+ ) {
// Handles incoming messages and manages streaming responses
// Processes tool calls and generates AI responses
}
@@ -102,12 +112,12 @@ Define what actions your agent can perform:
```ts
import { tool } from "ai";
-import { z } from "zod";
+import { z } from "zod/v3";
// Automatic execution (no confirmation needed)
const getLocalTime = tool({
description: "get the local time for a specified location",
- parameters: z.object({ location: z.string() }),
+ inputSchema: z.object({ location: z.string() }),
execute: async ({ location }) => {
return "10am";
},
@@ -116,7 +126,7 @@ const getLocalTime = tool({
// Requires confirmation (no execute function)
const getWeatherInformation = tool({
description: "show the weather in a given city to the user",
- parameters: z.object({ city: z.string() }),
+ inputSchema: z.object({ city: z.string() }),
// Omitting execute function makes this tool require human confirmation
});
```
@@ -133,9 +143,11 @@ const getWeatherInformation = tool({
```ts
// In src/tools.ts
+import { z } from "zod/v3";
+
const getWeather = tool({
description: "Get current weather for a location",
- parameters: z.object({
+ inputSchema: z.object({
location: z.string().describe("The city name"),
}),
execute: async ({ location }) => {
@@ -161,7 +173,7 @@ export const tools = {
// In src/tools.ts
const sensitiveAction = tool({
description: "Perform a sensitive action",
- parameters: z.object({
+ inputSchema: z.object({
action: z.string().describe("The action to perform"),
reason: z.string().describe("Reason for the action"),
}),
@@ -187,14 +199,17 @@ export const executions = {
### Customizing the system prompt
-Edit the system prompt in `src/server.ts`:
+Edit the system prompt in `src/server.ts`. You can use the `getSchedulePrompt` helper from `agents/schedule` to include scheduling context:
```ts
+import { getSchedulePrompt } from "agents/schedule";
+
+// Inside your onChatMessage method:
system: `You are a helpful assistant specializing in software development.
You can help with coding questions, debugging, and best practices.
Always provide clear, actionable advice.
-${unstable_getSchedulePrompt({ date: new Date() })}
+${getSchedulePrompt({ date: new Date() })}
If the user asks to schedule a task, use the schedule tool to schedule the task.
`,
@@ -202,20 +217,14 @@ If the user asks to schedule a task, use the schedule tool to schedule the task.
## Deploy to Cloudflare Workers
+Before deploying, make sure your production secrets are set (refer to Step 2, Option B).
+
```bash
npm run deploy
```
Your agent will be available at `https://your-project-name.your-subdomain.workers.dev`.
-### Environment variables in production
-
-For production deployment, set your OpenAI API key as a secret:
-
-```bash
-wrangler secret put OPENAI_API_KEY
-```
-
## Features
- **Streaming Responses**: Real-time AI responses with typing indicators.
@@ -231,17 +240,12 @@ wrangler secret put OPENAI_API_KEY
**"OPENAI_API_KEY is not set"**
-- Make sure you have set the API key in `.dev.vars` for local development.
-- For production, use `wrangler secret put OPENAI_API_KEY`.
-
-**"npm run dev" not found**
-
-- Use `npm start` instead (the script is named `start`).
+- Make sure you have set the API key in a `.env` file in your project root for local development.
+- For production, use `wrangler secret put OPENAI_API_KEY` or `wrangler secret bulk .env`.
**Server not accessible**
-- Check that the server is running on port 5174 (not 8787).
-- Look for the correct URL in the terminal output.
+- Look for the correct URL in the terminal output when you run `npm start` or `npm run dev`.
**Tool execution errors**
@@ -253,3 +257,29 @@ wrangler secret put OPENAI_API_KEY
- Use the browser developer tools to view detailed error messages.
- Check the terminal output for server logs.
- The debug mode in the UI shows detailed message processing.
+
+## Next steps
+
+
+
+
+
+
+
+
diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx
index 517fea2c51fc8a..0a0af27b618dd6 100644
--- a/src/content/docs/agents/getting-started/quick-start.mdx
+++ b/src/content/docs/agents/getting-started/quick-start.mdx
@@ -24,7 +24,7 @@ Build AI agents that persist, think, and act. Agents run on Cloudflare's global
Then install dependencies and start the dev server:
@@ -89,7 +89,7 @@ export default {
new Response("Not found", { status: 404 })
);
},
-};
+} satisfies ExportedHandler;
```
@@ -102,7 +102,7 @@ Update `wrangler.jsonc` to register the agent:
{
"name": "my-agent",
"main": "src/server.ts",
- "compatibility_date": "2025-01-01",
+ "compatibility_date": "$today",
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
"bindings": [
@@ -179,12 +179,12 @@ flowchart LR
### Key concepts
-| Concept | What it means |
-| -------------------- | ------------------------------------------------------------------------------------------- |
+| Concept | What it means |
+| -------------------- | ----------------------------------------------------------------------------------------------------- |
| **Agent instance** | Each unique name gets its own agent. `CounterAgent:user-123` is separate from `CounterAgent:user-456` |
-| **Persistent state** | State survives restarts, deploys, and hibernation. It is stored in SQLite |
-| **Real-time sync** | All clients connected to the same agent receive state updates instantly |
-| **Hibernation** | When no clients are connected, the agent hibernates (no cost). It wakes on the next request |
+| **Persistent state** | State survives restarts, deploys, and hibernation. It is stored in SQLite |
+| **Real-time sync** | All clients connected to the same agent receive state updates instantly |
+| **Hibernation** | When no clients are connected, the agent hibernates (no cost). It wakes on the next request |
## Connect from vanilla JavaScript
@@ -283,13 +283,13 @@ Now that you have a working agent, explore these topics:
### Common patterns
-| Learn how to | Refer to |
-| ------------------------ | ------------------------------------------------------------ |
-| Add AI/LLM capabilities | [Using AI models](/agents/api-reference/using-ai-models/) |
-| Expose tools via MCP | [MCP servers](/agents/api-reference/mcp-agent-api/) |
-| Run background tasks | [Schedule tasks](/agents/api-reference/schedule-tasks/) |
-| Handle emails | [Email routing](/agents/api-reference/email/) |
-| Use Cloudflare Workflows | [Run Workflows](/agents/api-reference/run-workflows/) |
+| Learn how to | Refer to |
+| ------------------------ | --------------------------------------------------------- |
+| Add AI/LLM capabilities | [Using AI models](/agents/api-reference/using-ai-models/) |
+| Expose tools via MCP | [MCP servers](/agents/api-reference/mcp-agent-api/) |
+| Run background tasks | [Schedule tasks](/agents/api-reference/schedule-tasks/) |
+| Handle emails | [Email routing](/agents/api-reference/email/) |
+| Use Cloudflare Workflows | [Run Workflows](/agents/api-reference/run-workflows/) |
### Explore more
@@ -315,4 +315,4 @@ Now that you have a working agent, explore these topics:
title="Schedule tasks"
href="/agents/api-reference/schedule-tasks/"
description="Run tasks on a delay, schedule, or cron."
-/>
\ No newline at end of file
+/>
diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx
index 39d1a7928e9fda..d556e27a6f778f 100644
--- a/src/content/docs/agents/getting-started/testing-your-agent.mdx
+++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx
@@ -1,11 +1,17 @@
---
title: Testing your Agents
-pcx_content_type: get-started
+pcx_content_type: how-to
sidebar:
order: 3
+description: Write and run tests for your Cloudflare Agents using Vitest and the Workers test pool.
---
-import { Render, PackageManagers, WranglerConfig } from "~/components";
+import {
+ Render,
+ PackageManagers,
+ WranglerConfig,
+ LinkCard,
+} from "~/components";
Because Agents run on Cloudflare Workers and Durable Objects, they can be tested using the same tools and techniques as Workers and Durable Objects.
@@ -15,7 +21,7 @@ Because Agents run on Cloudflare Workers and Durable Objects, they can be tested
:::note
-The `agents-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.js` file.
+The `agents-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.ts` file.
:::
@@ -26,9 +32,9 @@ npm install vitest@~3.0.0 --save-dev --save-exact
npm install @cloudflare/vitest-pool-workers --save-dev
```
-Ensure that your `vitest.config.js` file is identical to the following:
+Ensure that your `vitest.config.ts` file is identical to the following:
-```js
+```ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
@@ -44,9 +50,9 @@ export default defineWorkersConfig({
### Add the Agent configuration
-Add a `durableObjects` configuration to `vitest.config.js` with the name of your Agent class:
+Add a `durableObjects` configuration to `vitest.config.ts` with the name of your Agent class:
-```js
+```ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
@@ -99,13 +105,13 @@ describe("make a request to my Agent", () => {
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx);
- expect(await response.text()).toMatchObject({ hello: "from your agent" });
+ expect(await response.json()).toMatchObject({ hello: "from your agent" });
});
it("also responds with state", async () => {
const request = new Request("http://example.com/agent/my-agent/agent-123");
const response = await SELF.fetch(request);
- expect(await response.text()).toMatchObject({ hello: "from your agent" });
+ expect(await response.json()).toMatchObject({ hello: "from your agent" });
});
});
```
@@ -115,12 +121,12 @@ describe("make a request to my Agent", () => {
Running tests is done using the `vitest` CLI:
```sh
-$ npm run test
+npm run test
# or run vitest directly
-$ npx vitest
+npx vitest
```
-```sh output
+```txt
MyAgent
✓ should return a greeting (1 ms)
@@ -134,10 +140,10 @@ Review the [documentation on testing](/workers/testing/vitest-integration/write-
You can also run an Agent locally using the `wrangler` CLI:
```sh
-$ npx wrangler dev
+npx wrangler dev
```
-```sh output
+```txt
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.
Your worker has access to the following bindings:
@@ -149,4 +155,24 @@ Your worker has access to the following bindings:
This spins up a local development server that runs the same runtime as Cloudflare Workers, and allows you to iterate on your Agent's code and test it locally without deploying it.
-Visit the [`wrangler dev`](https://developers.cloudflare.com/workers/wrangler/commands/#dev) docs to review the CLI flags and configuration options.
+Visit the [`wrangler dev`](/workers/wrangler/commands/#dev) docs to review the CLI flags and configuration options.
+
+## Next steps
+
+
+
+
+
+