このガイドでは、ローカル開発と本番デプロイ向けのエージェント設定を扱います。Wrangler 設定ファイル、型生成、環境変数、Cloudflare ダッシュボードです。
npm create cloudflare@latest agents-starter -- --template cloudflare/agents-starter から作った Agent プロジェクトの典型的なファイル構成は次のとおりです。
- src/
- index.ts エージェント定義
- public/
- index.html
- test/
- index.spec.ts テスト
- package.json
- tsconfig.json
- vitest.config.mts
- worker-configuration.d.ts
- wrangler.jsonc Workers と Agent の設定
wrangler.jsonc は Cloudflare Worker とそのバインディングを設定します。Agents プロジェクトの完全な例です。
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-agent-app",
"main": "src/server.ts",
// Set this to today's date
"compatibility_date": "2026-09-20",
"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",
},
],
},
// Provision storage for each agent class
"exports": {
"MyAgent": {
"type": "durable-object",
"storage": "sqlite",
},
"ChatAgent": {
"type": "durable-object",
"storage": "sqlite",
},
},
// AI binding (optional, for Workers AI)
"ai": {
"binding": "AI",
},
// Observability (recommended)
"observability": {
"enabled": true,
},
}"$schema" = "node_modules/wrangler/config-schema.json"
name = "my-agent-app"
main = "src/server.ts"
# Set this to today's date
compatibility_date = "2026-09-20"
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"
[exports.MyAgent]
type = "durable-object"
storage = "sqlite"
[exports.ChatAgent]
type = "durable-object"
storage = "sqlite"
[ai]
binding = "AI"
[observability]
enabled = trueエージェントには nodejs_compat フラグが必要です。
{
"compatibility_flags": ["nodejs_compat"],
}compatibility_flags = [ "nodejs_compat" ]これにより Node.js 互換モードが有効になります。エージェントは crypto、streams、その他の Node.js API に依存します。
エージェントクラスごとにバインディングが必要です。
{
"durable_objects": {
"bindings": [
{
"name": "Counter",
"class_name": "Counter",
},
],
},
}[[durable_objects.bindings]]
name = "Counter"
class_name = "Counter"| フィールド | 説明 |
|---|---|
name |
env 上のプロパティ名。コードでは env.Counter として使います |
class_name |
エクスポートしたクラス名と正確に一致させる必要があります |
exports フィールドは、Worker がエクスポートする各 Agent クラスと、Cloudflare が使うストレージバックエンドを宣言します。
{
"exports": {
"MyAgent": {
"type": "durable-object",
"storage": "sqlite",
},
},
}[exports.MyAgent]
type = "durable-object"
storage = "sqlite"| フィールド | 説明 |
|---|---|
type |
エクスポートの種類。Agent では常に "durable-object" です。 |
storage |
ストレージバックエンド。新しい Agent では "sqlite" を使います(推奨)。 |
クラスの名前変更、削除、移譲の詳細は Durable Object class exports を参照してください。レガシーの migrations 配列を使う既存 Worker は引き続き動きます。Durable Object class migrations (legacy) を参照してください。
静的ファイル(HTML、CSS、JS)の配信です。
{
"assets": {
"directory": "public",
"binding": "ASSETS",
},
}[assets]
directory = "public"
binding = "ASSETS"バインディングがあると、プログラムからアセットを配信できます。
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 });
},
};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>;Workers AI 連携です。
{
"ai": {
"binding": "AI",
},
}[ai]
binding = "AI"エージェント内でのアクセスです。
const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {
prompt: "Hello!",
});const response = await this.env.AI.run("@cf/meta/llama-3-8b-instruct", {
prompt: "Hello!",
});Agents SDK は、エージェントプロジェクトに必要なコンパイラオプションをまとめた共有 tsconfig.json を同梱します。@callable() デコレーターに必要な ES2021 ターゲット、strict モード、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"
}
}Agents SDK は、TC39 デコレーター変換を扱う Vite プラグインを提供します。Vite 8 はトランスパイルに Oxc を使い、まだ TC39 デコレーターをサポートしません。このプラグインが無いと、@callable() などのデコレーターは実行時に失敗します。
vite.config.ts にプラグインを追加します。
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()],
});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() プラグインは、プロジェクトがデコレーターを使わなくても入れて問題ありません。@ 構文を含むファイルに対してだけ変換を実行します。
スターターテンプレートとすべての例は、デフォルトでこのプラグインを含みます。デコレーターで SyntaxError: Invalid or unexpected token が出る場合は 呼び出し可能なメソッド — トラブルシューティング を参照してください。
Wrangler は、バインディング向けの TypeScript 型を生成できます。
types コマンドを実行します。
npx wrangler typesこれにより、Env 型を含む worker-configuration.d.ts が作成または更新されます。
カスタムパスを指定します。
npx wrangler types env.d.tsよりきれいな出力です(エージェント向けに推奨)。
npx wrangler types env.d.ts --include-runtime falseCloudflare のランタイム型なしで、バインディングだけを生成します。
// env.d.ts (generated)
declare namespace Cloudflare {
interface Env {
OPENAI_API_KEY: string;
Counter: DurableObjectNamespace;
ChatAgent: DurableObjectNamespace;
}
}
interface Env extends Cloudflare.Env {}型を手動で定義することもできます。
// env.d.ts// 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;
}再生成しやすいよう、スクリプトを追加します。
{
"scripts": {
"types": "wrangler types env.d.ts --include-runtime false"
}
}ローカルシークレット用に .env ファイルを作成します(.gitignore に追加します)。
# .env
OPENAI_API_KEY=sk-...
GITHUB_WEBHOOK_SECRET=whsec_...
DATABASE_URL=postgres://...エージェント内でのアクセスです。
class MyAgent extends Agent {
async onStart() {
const apiKey = this.env.OPENAI_API_KEY;
}
}class MyAgent extends Agent {
async onStart() {
const apiKey = this.env.OPENAI_API_KEY;
}
}本番では wrangler secret を使います。
# 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機密でない設定には、Wrangler 設定ファイルの vars を使います。
{
"vars": {
"API_BASE_URL": "https://api.example.com",
"MAX_RETRIES": "3",
"DEBUG_MODE": "false",
},
}[vars]
API_BASE_URL = "https://api.example.com"
MAX_RETRIES = "3"
DEBUG_MODE = "false"値はすべて文字列である必要があります。数値と真偽値はコードで解析します。
const maxRetries = parseInt(this.env.MAX_RETRIES, 10);
const debugMode = this.env.DEBUG_MODE === "true";const maxRetries = parseInt(this.env.MAX_RETRIES, 10);
const debugMode = this.env.DEBUG_MODE === "true";環境ごとに異なる値には env セクションを使います(staging、production など)。
{
"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",
},
},
},
}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"特定の環境へデプロイします。
npx wrangler deploy --env staging
npx wrangler deploy --env productionVite を使う場合(フルスタックアプリ向けに推奨):
npx vite devVite なしの場合:
npx wrangler devDurable Object の状態は .wrangler/state/ にローカル保存されます。
- .wrangler/
- state/
- v3/
- d1/
- miniflare-D1DatabaseObject/
- ... (SQLite files)
- miniflare-D1DatabaseObject/
- d1/
- v3/
- state/
ローカルの Durable Object 状態をすべてリセットします。
rm -rf .wrangler/stateまたは、新しい状態で再起動します。
npx wrangler dev --persist-to=""エージェント状態を直接確認できます。
# Find the SQLite file
ls .wrangler/state/v3/d1/
# Open with sqlite3
sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqliteデプロイすると、Cloudflare が次を自動作成します。
- Worker - デプロイしたコード
- Durable Object 名前空間 - エージェントクラスごとに 1 つ
- SQLite ストレージ - 各名前空間に付与
Cloudflare ダッシュボードにログインし、Durable Objects を開きます。
Durable Objects を開く ↗ここでは次ができます。
- すべての Durable Object 名前空間を見る
- 個々のオブジェクトインスタンスを見る
- ストレージ(キーと値)を確認する
- オブジェクトを削除する
エージェントのライブログを表示します。
npx wrangler tailまたはダッシュボードで次を行います。
- Worker を開きます。
- Observability タブを選びます。
- リアルタイムログを有効にします。
次で絞り込みます。
- ステータス(success、error)
- 検索テキスト
- サンプリングレート
npx wrangler deployこれは次を行います。
- コードをバンドルします
- Cloudflare にアップロードします
- Agent の Durable Object 名前空間ストレージをプロビジョニングします
*.workers.dev上で公開します
Wrangler 設定ファイルにルートを追加します。
{
"routes": [
{
"pattern": "agents.example.com/*",
"zone_name": "example.com",
},
],
}[[routes]]
pattern = "agents.example.com/*"
zone_name = "example.com"または、より簡単なカスタムドメインを使います。
{
"routes": [
{
"pattern": "agents.example.com",
"custom_domain": true,
},
],
}[[routes]]
pattern = "agents.example.com"
custom_domain = true本番に影響せずにデプロイします。
npx wrangler deploy --dry-run # See what would be uploaded
npx wrangler versions upload # Upload new version
npx wrangler versions deploy # Gradually roll out以前のバージョンへ戻します。
npx wrangler rollbackWrangler 設定ファイルで環境を定義します。
{
"name": "my-agent",
"main": "src/server.ts",
// Base configuration (shared)
// Set this to today's date
"compatibility_date": "2026-09-20",
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }],
},
"exports": {
"MyAgent": { "type": "durable-object", "storage": "sqlite" },
},
// Environment overrides
"env": {
"staging": {
"name": "my-agent-staging",
"durable_objects": {
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }],
},
"vars": {
"ENVIRONMENT": "staging",
},
},
"production": {
"name": "my-agent-production",
"durable_objects": {
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }],
},
"vars": {
"ENVIRONMENT": "production",
},
},
},
}name = "my-agent"
main = "src/server.ts"
# Set this to today's date
compatibility_date = "2026-09-20"
compatibility_flags = [ "nodejs_compat" ]
[[durable_objects.bindings]]
name = "MyAgent"
class_name = "MyAgent"
[exports.MyAgent]
type = "durable-object"
storage = "sqlite"
[env.staging]
name = "my-agent-staging"
[[env.staging.durable_objects.bindings]]
name = "MyAgent"
class_name = "MyAgent"
[env.staging.vars]
ENVIRONMENT = "staging"
[env.production]
name = "my-agent-production"
[[env.production.durable_objects.bindings]]
name = "MyAgent"
class_name = "MyAgent"
[env.production.vars]
ENVIRONMENT = "production"# 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 Objects を持ちます。staging のエージェントは production のエージェントと状態を共有しません。
明示的に分離するには次です。
{
"env": {
"staging": {
"durable_objects": {
"bindings": [
{
"name": "MyAgent",
"class_name": "MyAgent",
"script_name": "my-agent-staging",
},
],
},
},
},
}[[env.staging.durable_objects.bindings]]
name = "MyAgent"
class_name = "MyAgent"
script_name = "my-agent-staging"各 Agent は Durable Object クラスに対応します。クラスのライフサイクル(作成、名前変更、削除、移譲)は、Wrangler 設定ファイルの exports フィールドで管理します。
exports に新しいクラスを宣言します。
{
"exports": {
"NewAgent": { "type": "durable-object", "storage": "sqlite" },
},
}[exports.NewAgent]
type = "durable-object"
storage = "sqlite"旧名のエントリを renamed tombstone に置き換え、新名のライブエントリを追加します。
{
"exports": {
"OldName": {
"type": "durable-object",
"state": "renamed",
"renamed_to": "NewName",
},
"NewName": { "type": "durable-object", "storage": "sqlite" },
},
}[exports.OldName]
type = "durable-object"
state = "renamed"
renamed_to = "NewName"
[exports.NewName]
type = "durable-object"
storage = "sqlite"あわせて次も更新します。
- コード内のクラス名。
- バインディングの
class_name。 - export 文。
エントリを deleted tombstone に置き換えます。
{
"exports": {
"AgentToKeep": { "type": "durable-object", "storage": "sqlite" },
"AgentToDelete": { "type": "durable-object", "state": "deleted" },
},
}[exports.AgentToKeep]
type = "durable-object"
storage = "sqlite"
[exports.AgentToDelete]
type = "durable-object"
state = "deleted"exportsをコードと同期させます。 Worker がエクスポートするすべての Agent クラスにエントリが必要です。- tombstone を使い、黙って削除しません。 クラスを退役させるときは、
exportsにdeleted/renamed/transferredの tombstone を残し、Cloudflare が変更を明示的に突き合わせられるようにします。 - 先にローカルでテストします。 ライフサイクル変更は
wrangler deployで適用されます。 - 名前変更や削除の前に 本番データをバックアップします。
レガシーの migrations 配列を使う既存 Worker は引き続き動きます。レガシーリファレンスは Durable Object class migrations (legacy) を、exports への移行は Migrate from the legacy migrations flow を参照してください。
クラスが exports にありません。クラスとそのストレージを宣言します。
{
"exports": {
"MissingClassName": { "type": "durable-object", "storage": "sqlite" },
},
}[exports.MissingClassName]
type = "durable-object"
storage = "sqlite"型を再生成します。
npx wrangler types env.d.ts --include-runtime false.env が存在し、変数が含まれていることを確認します。
cat .env
# Should show: MY_SECRET=valueWorker がレガシーの migrations 配列を使う場合、各エントリの tag は一意である必要があります。
{
// Wrong - duplicate tags
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["A"] },
{ "tag": "v1", "new_sqlite_classes": ["B"] },
],
}[[migrations]]
tag = "v1"
new_sqlite_classes = [ "A" ]
[[migrations]]
tag = "v1"
new_sqlite_classes = [ "B" ]{
// Correct - sequential tags
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["A"] },
{ "tag": "v2", "new_sqlite_classes": ["B"] },
],
}[[migrations]]
tag = "v1"
new_sqlite_classes = [ "A" ]
[[migrations]]
tag = "v2"
new_sqlite_classes = [ "B" ]宣言的な exports フィールドへの移行を検討できます。