Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

配置

本指南涵盖了为本地开发和生产部署配置 agent 所需的一切,包括 Wrangler 配置文件设置、类型生成、环境变量,以及 Cloudflare 控制台的使用。

项目结构

npm create cloudflare@latest agents-starter -- --template cloudflare/agents-starter 创建的 Agent 项目典型文件结构如下:

  • Directorysrc/
    • index.ts 你的 Agent 定义
  • Directorypublic/
    • index.html
  • Directorytest/
    • index.spec.ts 你的测试
  • package.json
  • tsconfig.json
  • vitest.config.mts
  • worker-configuration.d.ts
  • wrangler.jsonc 你的 Workers 和 Agent 配置

Wrangler 配置文件

wrangler.jsonc 文件用于配置你的 Cloudflare Worker 及其绑定。下面是一个 agent 项目的完整示例:

JSONC


{

  "$schema": "node_modules/wrangler/config-schema.json",

  "name": "my-agent-app",

  "main": "src/server.ts",

  // Set this to today's date

  "compatibility_date": "2026-04-29",

  "compatibility_flags": ["nodejs_compat"],


  // Static assets (optional)

  "assets": {

    "directory": "public",

    "binding": "ASSETS",

  },


  // Durable Object bindings for agents

  "durable_objects": {

    "bindings": [

      {

        "name": "MyAgent",

        "class_name": "MyAgent",

      },

      {

        "name": "ChatAgent",

        "class_name": "ChatAgent",

      },

    ],

  },


  // Required: Enable SQLite storage for agents

  "migrations": [

    {

      "tag": "v1",

      "new_sqlite_classes": ["MyAgent", "ChatAgent"],

    },

  ],


  // AI binding (optional, for Workers AI)

  "ai": {

    "binding": "AI",

  },


  // Observability (recommended)

  "observability": {

    "enabled": true,

  },

}


TOML


"$schema" = "node_modules/wrangler/config-schema.json"

name = "my-agent-app"

main = "src/server.ts"

# Set this to today's date

compatibility_date = "2026-04-29"

compatibility_flags = [ "nodejs_compat" ]


[assets]

directory = "public"

binding = "ASSETS"


[[durable_objects.bindings]]

name = "MyAgent"

class_name = "MyAgent"


[[durable_objects.bindings]]

name = "ChatAgent"

class_name = "ChatAgent"


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "MyAgent", "ChatAgent" ]


[ai]

binding = "AI"


[observability]

enabled = true


关键字段

compatibility_flags

agent 必须启用 nodejs_compat 标志:

JSONC


{

  "compatibility_flags": ["nodejs_compat"],

}


TOML


compatibility_flags = [ "nodejs_compat" ]


这会启用 Node.js 兼容模式,agent 依赖它来使用 crypto、streams 和其他 Node.js API。

durable_objects.bindings

每个 agent 类都需要一个绑定:

JSONC


{

  "durable_objects": {

    "bindings": [

      {

        "name": "Counter",

        "class_name": "Counter",

      },

    ],

  },

}


TOML


[[durable_objects.bindings]]

name = "Counter"

class_name = "Counter"


字段描述
nameenv 上的属性名。在代码中这样使用:env.Counter
class_name必须与导出的类名完全一致

nameclass_name 不一致时

nameclass_name 不同时,按下面的写法配置:

JSONC


{

  "durable_objects": {

    "bindings": [

      {

        "name": "COUNTER_DO",

        "class_name": "CounterAgent",

      },

    ],

  },

}


TOML


[[durable_objects.bindings]]

name = "COUNTER_DO"

class_name = "CounterAgent"


当你想要环境变量风格的命名(COUNTER_DO)但又想用更具描述性的类名(CounterAgent)时,这种写法很有用。

migrations

迁移告诉 Cloudflare 如何为你的 Durable Object 设置存储:

JSONC


{

  "migrations": [

    {

      "tag": "v1",

      "new_sqlite_classes": ["MyAgent"],

    },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "MyAgent" ]


字段描述
tag版本标识符(例如 “v1”、“v2”)。必须唯一
new_sqlite_classes使用 SQLite 存储(状态持久化)的 agent 类
deleted_classes被删除的类
renamed_classes被重命名的类

assets

用于提供静态文件(HTML、CSS、JS):

JSONC


{

  "assets": {

    "directory": "public",

    "binding": "ASSETS",

  },

}


TOML


[assets]

directory = "public"

binding = "ASSETS"


加上绑定后,你可以以编程方式提供资源:

JavaScript


export default {

  async fetch(request, env) {

    // Static assets are served by the worker automatically by default


    // Route the request to the appropriate agent

    const agentResponse = await routeAgentRequest(request, env);

    if (agentResponse) return agentResponse;


    // Add your own routing logic here

    return new Response("Not found", { status: 404 });

  },

};


TypeScript


export default {

  async fetch(request: Request, env: Env) {

    // Static assets are served by the worker automatically by default


    // Route the request to the appropriate agent

    const agentResponse = await routeAgentRequest(request, env);

    if (agentResponse) return agentResponse;


    // Add your own routing logic here

    return new Response("Not found", { status: 404 });

  },

} satisfies ExportedHandler<Env>;


ai

用于 Workers AI 集成:

JSONC


{

  "ai": {

    "binding": "AI",

  },

}


TOML


[ai]

binding = "AI"


在 agent 中访问:

JavaScript


const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {

  prompt: "Hello!",

});


TypeScript


const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {

  prompt: "Hello!",

});


TypeScript 配置

Agents SDK 提供了一个共享的 tsconfig.json,它设置了 agent 项目所需的所有编译器选项——包括 @callable() 装饰器需要的 ES2021 target、严格模式、bundler 模块解析以及 Workers 类型。

在你的 tsconfig.json 中继承它:


{

  "extends": "agents/tsconfig"

}


它等价于:


{

  "compilerOptions": {

    "target": "ES2021",

    "lib": ["ES2022", "DOM", "DOM.Iterable"],

    "jsx": "react-jsx",

    "module": "ES2022",

    "moduleResolution": "bundler",

    "types": ["node", "@cloudflare/workers-types", "vite/client"],

    "allowImportingTsExtensions": true,

    "noEmit": true,

    "isolatedModules": true,

    "verbatimModuleSyntax": true,

    "esModuleInterop": true,

    "forceConsistentCasingInFileNames": true,

    "strict": true,

    "skipLibCheck": true

  }

}


你可以根据需要覆盖单个选项:


{

  "extends": "agents/tsconfig",

  "compilerOptions": {

    "jsx": "preserve"

  }

}


警告

不要设置 "experimentalDecorators": true。Agents SDK 使用 TC39 标准装饰器 ↗,而不是 TypeScript 的旧版装饰器。启用 experimentalDecorators 会应用一个不兼容的转换,在运行时悄悄破坏 @callable()

Vite 配置

Agents SDK 提供了一个 Vite 插件,处理 TC39 装饰器的转换。Vite 8 使用 Oxc 进行转译,Oxc 目前还不支持 TC39 装饰器——没有这个插件,@callable() 和其他装饰器在运行时会失败。

将插件添加到你的 vite.config.ts:

JavaScript


import { cloudflare } from "@cloudflare/vite-plugin";

import react from "@vitejs/plugin-react";

import agents from "agents/vite";

import { defineConfig } from "vite";


export default defineConfig({

  plugins: [agents(), react(), cloudflare()],

});


TypeScript


import { cloudflare } from "@cloudflare/vite-plugin";

import react from "@vitejs/plugin-react";

import agents from "agents/vite";

import { defineConfig } from "vite";


export default defineConfig({

  plugins: [agents(), react(), cloudflare()],

});


即使你的项目不使用装饰器,加上 agents() 插件也是安全的。它只会对包含 @ 语法的文件运行转换。

starter 模板和所有示例都默认包含了这个插件。如果你在使用装饰器时遇到 SyntaxError: Invalid or unexpected token,请参考 可调用方法 — 故障排查

生成类型

Wrangler 可以为你的绑定生成 TypeScript 类型。

自动生成

运行 types 命令:

Terminal window


npx wrangler types


这会创建或更新 worker-configuration.d.ts,包含你的 Env 类型。

自定义输出路径

指定一个自定义路径:

Terminal window


npx wrangler types env.d.ts


不包含运行时类型

为了得到更干净的输出(对 agent 项目推荐):

Terminal window


npx wrangler types env.d.ts --include-runtime false


这只会生成你的绑定,不带 Cloudflare 运行时类型。

生成的输出示例

TypeScript


// env.d.ts (generated)

declare namespace Cloudflare {

  interface Env {

    OPENAI_API_KEY: string;

    Counter: DurableObjectNamespace;

    ChatAgent: DurableObjectNamespace;

  }

}

interface Env extends Cloudflare.Env {}


手动定义类型

你也可以手动定义类型:

JavaScript


// env.d.ts


TypeScript


// env.d.ts

import type { Counter } from "./src/agents/counter";

import type { ChatAgent } from "./src/agents/chat";


interface Env {

  // Secrets

  OPENAI_API_KEY: string;

  WEBHOOK_SECRET: string;


  // Agent bindings

  Counter: DurableObjectNamespace<Counter>;

  ChatAgent: DurableObjectNamespace<ChatAgent>;


  // Other bindings

  AI: Ai;

  ASSETS: Fetcher;

  MY_KV: KVNamespace;

}


添加到 package.json

加一个脚本以便随时重新生成:


{

  "scripts": {

    "types": "wrangler types env.d.ts --include-runtime false"

  }

}


环境变量与 Secret

本地开发(.env)

创建一个 .env 文件来存放本地 secret(将其加入 .gitignore):

Terminal window


# .env

OPENAI_API_KEY=sk-...

GITHUB_WEBHOOK_SECRET=whsec_...

DATABASE_URL=postgres://...


在 agent 中访问:

JavaScript


class MyAgent extends Agent {

  async onStart() {

    const apiKey = this.env.OPENAI_API_KEY;

  }

}


TypeScript


class MyAgent extends Agent {

  async onStart() {

    const apiKey = this.env.OPENAI_API_KEY;

  }

}


生产环境 secret

生产环境使用 wrangler secret:

Terminal window


# Add a secret

npx wrangler secret put OPENAI_API_KEY

# Enter value when prompted


# List secrets

npx wrangler secret list


# Delete a secret

npx wrangler secret delete OPENAI_API_KEY


非 secret 变量

对于非敏感配置,在 Wrangler 配置文件中使用 vars:

JSONC


{

  "vars": {

    "API_BASE_URL": "https://api.example.com",

    "MAX_RETRIES": "3",

    "DEBUG_MODE": "false",

  },

}


TOML


[vars]

API_BASE_URL = "https://api.example.com"

MAX_RETRIES = "3"

DEBUG_MODE = "false"


所有值都必须是字符串。在代码中解析数字和布尔值:

JavaScript


const maxRetries = parseInt(this.env.MAX_RETRIES, 10);

const debugMode = this.env.DEBUG_MODE === "true";


TypeScript


const maxRetries = parseInt(this.env.MAX_RETRIES, 10);

const debugMode = this.env.DEBUG_MODE === "true";


按环境区分变量

使用 env 区块为不同环境(例如 staging、production)配置变量:

JSONC


{

  "name": "my-agent",

  "vars": {

    "API_URL": "https://api.example.com",

  },


  "env": {

    "staging": {

      "vars": {

        "API_URL": "https://staging-api.example.com",

      },

    },

    "production": {

      "vars": {

        "API_URL": "https://api.example.com",

      },

    },

  },

}


TOML


name = "my-agent"


[vars]

API_URL = "https://api.example.com"


[env.staging.vars]

API_URL = "https://staging-api.example.com"


[env.production.vars]

API_URL = "https://api.example.com"


部署到指定环境:

Terminal window


npx wrangler deploy --env staging

npx wrangler deploy --env production


本地开发

启动开发服务器

使用 Vite(全栈应用推荐):

Terminal window


npx vite dev


不使用 Vite:

Terminal window


npx wrangler dev


本地状态持久化

Durable Object 状态在本地持久化在 .wrangler/state/:

  • Directory.wrangler/
    • Directorystate/ * Directoryv3/ * Directoryd1/ * Directoryminiflare-D1DatabaseObject/ * … (SQLite files)

清除本地状态

要重置所有本地 Durable Object 状态:

Terminal window


rm -rf .wrangler/state


或者用全新状态重启:

Terminal window


npx wrangler dev --persist-to=""


检查本地 SQLite

你可以直接检查 agent 状态:

Terminal window


# Find the SQLite file

ls .wrangler/state/v3/d1/


# Open with sqlite3

sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite


控制台设置

自动创建的资源

部署时,Cloudflare 会自动创建:

  • Worker - 你部署的代码
  • Durable Object 命名空间 - 每个 agent 类对应一个
  • SQLite 存储 - 附加到每个命名空间

查看 Durable Object

登录 Cloudflare 控制台,然后进入 Durable Objects。

进入 Durable Objects

在这里你可以:

  • 查看所有 Durable Object 命名空间
  • 查看单个对象实例
  • 检查存储(键值对)
  • 删除对象

实时日志

查看 agent 的实时日志:

Terminal window


npx wrangler tail


或在控制台中:

  1. 进入你的 Worker。
  2. 选择 Observability 标签页。
  3. 启用实时日志。

可按以下条件过滤:

  • 状态(成功、错误)
  • 搜索文本
  • 采样率

生产部署

基础部署

Terminal window


npx wrangler deploy


它会:

  1. 打包你的代码
  2. 上传到 Cloudflare
  3. 应用迁移
  4. *.workers.dev 上线

自定义域名

在 Wrangler 配置文件中添加路由:

JSONC


{

  "routes": [

    {

      "pattern": "agents.example.com/*",

      "zone_name": "example.com",

    },

  ],

}


TOML


[[routes]]

pattern = "agents.example.com/*"

zone_name = "example.com"


或者使用自定义域名(更简单):

JSONC


{

  "routes": [

    {

      "pattern": "agents.example.com",

      "custom_domain": true,

    },

  ],

}


TOML


[[routes]]

pattern = "agents.example.com"

custom_domain = true


预览部署

不影响生产环境的部署:

Terminal window


npx wrangler deploy --dry-run    # See what would be uploaded

npx wrangler versions upload     # Upload new version

npx wrangler versions deploy     # Gradually roll out


回滚

回滚到上一个版本:

Terminal window


npx wrangler rollback


多环境配置

环境配置

在 Wrangler 配置文件中定义环境:

JSONC


{

  "name": "my-agent",

  "main": "src/server.ts",


  // Base configuration (shared)

  // Set this to today's date

  "compatibility_date": "2026-04-29",

  "compatibility_flags": ["nodejs_compat"],

  "durable_objects": {

    "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }],

  },

  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }],


  // Environment overrides

  "env": {

    "staging": {

      "name": "my-agent-staging",

      "vars": {

        "ENVIRONMENT": "staging",

      },

    },

    "production": {

      "name": "my-agent-production",

      "vars": {

        "ENVIRONMENT": "production",

      },

    },

  },

}


TOML


name = "my-agent"

main = "src/server.ts"

# Set this to today's date

compatibility_date = "2026-04-29"

compatibility_flags = [ "nodejs_compat" ]


[[durable_objects.bindings]]

name = "MyAgent"

class_name = "MyAgent"


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "MyAgent" ]


[env.staging]

name = "my-agent-staging"


  [env.staging.vars]

  ENVIRONMENT = "staging"


[env.production]

name = "my-agent-production"


  [env.production.vars]

  ENVIRONMENT = "production"


部署到不同环境

Terminal window


# Deploy to staging

npx wrangler deploy --env staging


# Deploy to production

npx wrangler deploy --env production


# Set secrets per environment

npx wrangler secret put OPENAI_API_KEY --env staging

npx wrangler secret put OPENAI_API_KEY --env production


独立的 Durable Object

每个环境有自己的 Durable Object。staging 的 agent 不会与 production 的 agent 共享状态。

如要显式分离:

JSONC


{

  "env": {

    "staging": {

      "durable_objects": {

        "bindings": [

          {

            "name": "MyAgent",

            "class_name": "MyAgent",

            "script_name": "my-agent-staging",

          },

        ],

      },

    },

  },

}


TOML


[[env.staging.durable_objects.bindings]]

name = "MyAgent"

class_name = "MyAgent"

script_name = "my-agent-staging"


迁移

迁移用于管理 Durable Object 存储的 schema 变更。

添加新的 agent

在新的迁移中加到 new_sqlite_classes:

JSONC


{

  "migrations": [

    {

      "tag": "v1",

      "new_sqlite_classes": ["ExistingAgent"],

    },

    {

      "tag": "v2",

      "new_sqlite_classes": ["NewAgent"],

    },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "ExistingAgent" ]


[[migrations]]

tag = "v2"

new_sqlite_classes = [ "NewAgent" ]


重命名 agent 类

使用 renamed_classes:

JSONC


{

  "migrations": [

    {

      "tag": "v1",

      "new_sqlite_classes": ["OldName"],

    },

    {

      "tag": "v2",

      "renamed_classes": [

        {

          "from": "OldName",

          "to": "NewName",

        },

      ],

    },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "OldName" ]


[[migrations]]

tag = "v2"


  [[migrations.renamed_classes]]

  from = "OldName"

  to = "NewName"


同时要更新:

  1. 代码中的类名
  2. 绑定中的 class_name
  3. export 语句

删除 agent 类

使用 deleted_classes:

JSONC


{

  "migrations": [

    {

      "tag": "v1",

      "new_sqlite_classes": ["AgentToDelete", "AgentToKeep"],

    },

    {

      "tag": "v2",

      "deleted_classes": ["AgentToDelete"],

    },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "AgentToDelete", "AgentToKeep" ]


[[migrations]]

tag = "v2"

deleted_classes = [ "AgentToDelete" ]


警告

这会永久删除该类的所有数据。

迁移最佳实践

  1. 永远不要修改已有迁移 - 总是新增。
  2. 使用顺序的 tag - v1、v2、v3(或用日期:2025-01-15)。
  3. 先在本地测试 - 迁移会在部署时执行。
  4. 备份生产数据 - 在重命名或删除之前。

故障排查

No such Durable Object class

类没有出现在迁移中:

JSONC


{

  "migrations": [

    {

      "tag": "v1",

      "new_sqlite_classes": ["MissingClassName"],

    },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "MissingClassName" ]


Cannot find module in types

重新生成类型:

Terminal window


npx wrangler types env.d.ts --include-runtime false


本地无法加载 secret

检查 .env 是否存在并包含该变量:

Terminal window


cat .env

# Should show: MY_SECRET=value


迁移 tag 冲突

迁移的 tag 必须唯一。如果遇到冲突:

JSONC


{

  // Wrong - duplicate tags

  "migrations": [

    { "tag": "v1", "new_sqlite_classes": ["A"] },

    { "tag": "v1", "new_sqlite_classes": ["B"] },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "A" ]


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "B" ]


JSONC


{

  // Correct - sequential tags

  "migrations": [

    { "tag": "v1", "new_sqlite_classes": ["A"] },

    { "tag": "v2", "new_sqlite_classes": ["B"] },

  ],

}


TOML


[[migrations]]

tag = "v1"

new_sqlite_classes = [ "A" ]


[[migrations]]

tag = "v2"

new_sqlite_classes = [ "B" ]


下一步

Agents API Agents SDK 的完整 API 参考。

路由 将请求路由到你的 agent 实例。

调度任务 通过延迟和 cron 任务进行后台处理。