cloudflare-agents について
Cloudflare Agents SDKは、Cloudflare WorkersとDurable Objects上でステートフルなリアルタイムAIエージェントを構築するフレームワークです。状態保持、タスク実行、多エージェント連携が必要な開発者向けで、AI推論自体は提供しません。
主な機能
- 01WebSocket双方向通信
- 02SQLiteによる状態保持
- 03スケジュール・Cronタスク
- 04複数エージェントの連携
- 05人による確認ワークフロー
- 06MCPサーバーの実装
活用シーン
- 01エージェント間で状態を保持
- 02複数エージェントを連携
- 03遅延・定期タスクを実行
- 04人の承認を経て操作
MCP 対応
MCPAgentを備え、ステートフルなツール実行を含むMCPサーバーを実装できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ovachiever/ droid-tings --skill cloudflare-agentsインストール後、Claude Code で/cloudflare-agentsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsontemplates/basic-agent.tsbrowser-agent.tscalling-agents-worker.tschat-agent-streaming.tshitl-agent.tsmcp-server-basic.tsrag-agent.tsreact-useagent-client.tsxscheduled-agent.tssimple-chat-no-agents-sdk.tsstate-sync-agent.tswebsocket-agent.tsworkflow-agent.tswrangler-agents-config.jsonc詳細
Cloudflare Agents SDK
ステータス:本番環境で利用可能 ✅ 最終更新日:2025-11-23 依存関係:cloudflare-worker-base(推奨) 最新バージョン:[email protected](2025年11月13日)、@modelcontextprotocol/sdk@latest 本番環境でのテスト済み:Cloudflare 独自の MCP サーバー(https://github.com/cloudflare/mcp-server-cloudflare)
最近の更新(2025年):
- 2025年9月:AI SDK v5 との互換性、自動メッセージ移行
- 2025年4月:MCP のサポート(MCPAgent クラス)、agents からの
import { context } - 2025年3月:パッケージ名の変更(agents-sdk → agents)
Cloudflare Agents とは?
Cloudflare Agents SDK を使うと、Cloudflare Workers + Durable Objects 上で動作する、AI を活用した自律型エージェントを構築できます。エージェントでは、次のことができます。
- WebSocket と Server-Sent Events を介したリアルタイム通信
- 組み込み SQLite データベースを使った状態の永続化(エージェントごとに最大 1GB)
- 遅延、特定の日付、cron 式を使ったタスクのスケジュール設定
- Cloudflare Workflows を非同期で起動するワークフローの実行
- Browser Rendering API + Puppeteer を使ったウェブの閲覧
- Vectorize ベクトルデータベース + Workers AI エンベディングを使った RAG の実装
- Model Context Protocol を実装する MCP サーバーの構築
- Human-in-the-loop パターンによるレビューと承認のサポート
- グローバルに数百万の独立したエージェントインスタンスへのスケーリング
各エージェントインスタンスは、数秒、数分、または数時間にわたって動作できる、グローバルに一意なステートフルマイクロサーバーです。
Agents SDK は必要ですか?
停止:Agents SDK を使う前に、本当に必要かどうかを確認してください。
次の場合は Vercel AI SDK のみを使用します(よりシンプルです)。
- ✅ 基本的なチャットインターフェースを構築する
- ✅ Server-Sent Events(SSE)によるストリーミングで十分である(単方向:サーバー → クライアント)
- ✅ エージェントの状態を永続化する必要がない(または D1/KV で別途管理する)
- ✅ 単一ユーザー、単一会話のシナリオである
- ✅ AI の応答だけが必要で、複雑なワークフローやスケジュール設定は必要ない
チャットアプリケーションの 80% はこれに該当します。 このような場合は、Workers 上で Vercel AI SDK を直接使用してください。よりシンプルで、必要なインフラストラクチャが少なく、ストリーミングも自動的に処理されます。
例(Agents SDK は不要):
// worker.ts - Simple chat with AI SDK only
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
export default {
async fetch(request: Request, env: Env) {
const { messages } = await request.json();
const result = streamText({
model: openai('gpt-4o-mini'),
messages
});
return result.toTextStreamResponse(); // Automatic SSE streaming
}
}
// client.tsx - React with built-in hooks
import { useChat } from 'ai/react';
function ChatPage() {
const { messages, input, handleSubmit } = useChat({ api: '/api/chat' });
// Done. No Agents SDK needed.
}
結果:コードは 500 行ではなく 100 行になります。Durable Objects のセットアップ、WebSocket の複雑さ、移行は必要ありません。
次の機能が必要な場合は Agents SDK を使用します。
- ✅ WebSocket 接続(双方向のリアルタイム通信)
- ✅ Durable Objects(グローバルに一意なステートフルエージェントインスタンス)
- ✅ 組み込みの状態永続化(エージェントごとに最大 1GB の SQLite ストレージ)
- ✅ マルチエージェント連携(エージェント同士の呼び出しと通信)
- ✅ スケジュールされたタスク(遅延、cron 式、定期的なジョブ)
- ✅ Human-in-the-loop ワークフロー(承認ゲート、レビューのプロセス)
- ✅ 長時間実行されるエージェント(バックグラウンド処理、自律型ワークフロー)
- ✅ ステートフルなツール実行を行う MCP サーバー
アプリケーションの約 20% がこれに該当します。Agents SDK が提供するインフラストラクチャが必要な場合に使用します。
重要なポイント:Agents SDK ができることと、できないこと
Agents SDK ができること:
- 🏗️ WebSocket 接続、Durable Objects、状態管理のためのインフラストラクチャレイヤー
- 🔧 ステートフルな自律型エージェントを構築するためのフレームワーク
- 📦 ライフサイクルメソッドを備えた Durable Objects のラッパー
Agents SDK ができないこと:
- ❌ AI 推論プロバイダー(AI SDK、Workers AI、OpenAI などは独自に用意してください)
- ❌ ストリーミング応答ハンドラー(自動解析には AI SDK を使用してください)
- ❌ LLM との統合(これは別の役割です)
次のように考えてください:
- Agents SDK = 建物(WebSocket、状態、ルーム)
- AI SDK / Workers AI = AI の頭脳(推論、推論処理、応答)
両者を組み合わせて使用することも(ほとんどの場合に推奨)、Workers AI を直接使用することもできます(SSE の解析を手動で処理する必要があります)。
選択フローチャート
Building an AI application?
│
├─ Need WebSocket bidirectional communication? ───────┐
│ (Client sends while server streams, agent-initiated messages)
│
├─ Need Durable Objects stateful instances? ──────────┤
│ (Globally unique agents with persistent memory)
│
├─ Need multi-agent coordination? ────────────────────┤
│ (Agents calling/messaging other agents)
│
├─ Need scheduled tasks or cron jobs? ────────────────┤
│ (Delayed execution, recurring tasks)
│
├─ Need human-in-the-loop workflows? ─────────────────┤
│ (Approval gates, review processes)
│
└─ If ALL above are NO ─────────────────────────────→ Use AI SDK directly
(Much simpler approach)
If ANY above are YES ────────────────────────────→ Use Agents SDK + AI SDK
(More infrastructure, more power)
アーキテクチャの比較
| 機能 | AI SDK のみ | Agents SDK + AI SDK |
|---|---|---|
| セットアップの複雑さ | 🟢 低い(npm install で完了) | 🔴 高い(Durable Objects、マイグレーション、バインディング) |
| コード量 | 🟢 約100行 | 🟡 約500行以上 |
| ストリーミング | ✅ 自動(SSE) | ✅ 自動(AI SDK)または手動(Workers AI) |
| 状態管理 | ⚠️ 手動(D1/KV) | ✅ 組み込み(SQLite) |
| WebSocket | ❌ 手動でセットアップ | ✅ 組み込み |
| React フック | ✅ useChat、useCompletion | ⚠️ カスタムフックが必要 |
| マルチエージェント | ❌ 非対応 | ✅ 組み込み(routeAgentRequest) |
| スケジューリング | ❌ 外部(Queue/Workflow) | ✅ 組み込み(this.schedule) |
| 用途 | シンプルなチャット、補完 | 複雑なステートフルワークフロー |
まだ迷っていますか?
AI SDK から始めましょう。 WebSocket や Durable Objects が必要だと分かった場合は、後から Agents SDK に移行できます。後からインフラを追加するほうが、削除するより簡単です。
ほとんどの開発者の場合:チャットインターフェースを構築していて、WebSocket、マルチエージェントの連携、スケジュールされたタスクに関する具体的な要件がない場合は、AI SDK を直接使いましょう。より速く、複雑さを抑えてリリースできます。
Agents SDK を使うのは、そのインフラ機能が必要な具体的な理由がある場合に限ってください。
クイックスタート(10分)
1. テンプレートでプロジェクトをスキャフォールドする
npm create cloudflare@latest my-agent -- \
--template=cloudflare/agents-starter \
--ts \
--git \
--deploy false
この操作で作成されるもの:
- 完全な Agent プロジェクト構成
- TypeScript の設定
- Durable Objects のバインディングを含む wrangler.jsonc
- Agent のチャット実装例
- useAgent フックを使った React クライアント
2. または既存の Worker に追加する
cd my-existing-worker
npm install agents
次に、Agent クラスを作成します:
// src/index.ts
import { Agent, AgentNamespace } from "agents";
export class MyAgent extends Agent {
async onRequest(request: Request): Promise<Response> {
return new Response("Hello from Agent!");
}
}
export default MyAgent;
3. Durable Objects のバインディングを設定する
wrangler.jsonc を作成または更新します:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-agent",
"main": "src/index.ts",
"compatibility_date": "2025-10-21",
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
"bindings": [
{
"name": "MyAgent", // MUST match class name
"class_name": "MyAgent" // MUST match exported class
}
]
},
"migrations": [
{
"tag": "v1",
"new_sqlite_classes": ["MyAgent"] // CRITICAL: Enables SQLite storage
}
]
}
重要な設定ルール:
- ✅
nameとclass_nameは必ず同一にしてください - ✅
new_sqlite_classesは最初のマイグレーションに必ず含めてください(後から追加できません) - ✅ Agent クラスは必ずエクスポートしてください(そうしないとバインディングに失敗します)
- ✅ マイグレーションタグは再利用できません(各マイグレーションには一意のタグが必要です)
4. デプロイする
npx wrangler@latest deploy
エージェントは https://my-agent.<subdomain>.workers.dev で稼働しています。
アーキテクチャの概要:各要素の連携
各ツールの役割を理解すると、混乱を避け、適切な組み合わせを選べます。
スタック
┌─────────────────────────────────────────────────────────┐
│ Your Application │
│ │
│ ┌────────────────┐ ┌──────────────────────┐ │
│ │ Agents SDK │ │ AI Inference │ │
│ │ (Infra Layer) │ + │ (Brain Layer) │ │
│ │ │ │ │ │
│ │ • WebSockets │ │ Choose ONE: │ │
│ │ • Durable Objs │ │ • Vercel AI SDK ✅ │ │
│ │ • State (SQL) │ │ • Workers AI ⚠️ │ │
│ │ • Scheduling │ │ • OpenAI Direct │ │
│ │ • Multi-agent │ │ • Anthropic Direct │ │
│ └────────────────┘ └──────────────────────┘ │
│ ↓ ↓ │
│ Manages connections Generates responses │
│ and state and handles streaming │
└─────────────────────────────────────────────────────────┘
↓
Cloudflare Workers + Durable Objects
各ツールが提供するもの
1. Agents SDK(このスキル)
目的:ステートフルでリアルタイムなエージェントのインフラ
提供するもの:
- ✅ WebSocket 接続管理(双方向リアルタイム通信)
- ✅ Durable Objects ラッパー(一意のグローバルエージェントインスタンス)
- ✅ 組み込みの状態永続化(最大1GBの SQLite)
- ✅ ライフサイクルメソッド(
onStart、onConnect、onMessage、onClose) - ✅ タスクのスケジューリング(cron/遅延を使った
this.schedule()) - ✅ マルチエージェント連携(
routeAgentRequest()) - ✅ クライアントライブラリ(
useAgent、AgentClient、agentFetch)
提供しないもの:
- ❌ AI 推論(LLM 呼び出しなし)
- ❌ ストリーミングレスポンスの解析(独自に用意してください)
- ❌ プロバイダーとの連携(OpenAI、Anthropic など)
イメージとしては:建物とインフラ(部屋、ドア、配管)であり、居住者(AI)ではありません。
2. Vercel AI SDK(AI に推奨)
目的:自動ストリーミングに対応した AI 推論
提供するもの:
- ✅ ストリーミングレスポンスの自動処理(SSE の解析を代行)
- ✅ 複数プロバイダーのサポート(OpenAI、Anthropic、Google など)
- ✅ React フック(
useChat、useCompletion、useAssistant) - ✅ プロバイダー間で統一された API
- ✅ ツール呼び出し/関数呼び出し
- ✅ Cloudflare Workers で動作 ✅
例:
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = streamText({
model: openai('gpt-4o-mini'),
messages: [...]
});
// Returns SSE stream - no manual parsing needed
return result.toTextStreamResponse();
Agents SDK と組み合わせて使う場合:
- ✅ ほとんどのチャットアプリケーション
- ✅ React フックを使いたい場合
- ✅ 複数の AI プロバイダーを使う場合
- ✅ シンプルで抽象化された AI 呼び出しを利用したい場合
Agents SDK と組み合わせる:
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";
export class MyAgent extends AIChatAgent<Env> {
async onChatMessage(onFinish) {
// Agents SDK provides: WebSocket, state, this.messages
// AI SDK provides: Automatic streaming, provider abstraction
return streamText({
model: openai('gpt-4o-mini'),
messages: this.messages // Managed by Agents SDK
}).toTextStreamResponse();
}
}
3. Workers AI(AI の代替手段)
目的:Cloudflare のプラットフォーム上での AI 推論
提供内容:
- ✅ コスト効率の高い推論(Workers サブスクリプションに含まれます)
- ✅ 外部 API キーは不要です
- ✅ モデル:LLaMA 3、Qwen、Mistral、埋め込みなど
- ✅ Cloudflare のネットワーク上で実行(低レイテンシー)
提供しないもの:
- ❌ ストリーミングの自動パース(生の SSE 形式を返します)
- ❌ React フック
- ❌ マルチプロバイダーの抽象化
手動でのパースが必要です:
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [...],
stream: true
});
// Returns raw SSE format - YOU must parse
for await (const chunk of response) {
const text = new TextDecoder().decode(chunk); // Uint8Array → string
if (text.startsWith('data: ')) { // Check SSE format
const data = JSON.parse(text.slice(6)); // Parse JSON
if (data.response) { // Extract .response field
fullResponse += data.response;
}
}
}
使用する場合:
- ✅ コストが重要な場合(埋め込み、大量処理)
- ✅ Cloudflare 固有のモデルが必要な場合
- ✅ SSE の手動パースに対応できる場合
- ✅ 外部依存関係を許容できない場合
トレードオフ:コストを節約する代わりに、手動パースに時間をかけます。
おすすめの組み合わせ
オプション A:Agents SDK + Vercel AI SDK(推奨 ⭐)
使用する場面:WebSocket/状態管理が必要で、AI との統合もシンプルにしたい場合
import { AIChatAgent } from "agents/ai-chat-agent";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
export class ChatAgent extends AIChatAgent<Env> {
async onChatMessage(onFinish) {
return streamText({
model: openai('gpt-4o-mini'),
messages: this.messages, // Agents SDK manages history
onFinish
}).toTextStreamResponse();
}
}
メリット:
- ✅ 最良の開発者体験
- ✅ ストリーミングを自動処理
- ✅ Agents SDK による WebSocket と状態管理
- ✅ シンプルで保守しやすいコード
デメリット:
- ⚠️ 外部 API キーが必要です
- ⚠️ AI プロバイダーの追加費用がかかります
オプション B:Agents SDK + Workers AI
使用する場面:WebSocket/状態管理が必要で、コストが重要な場合
import { Agent } from "agents";
export class BudgetAgent extends Agent<Env> {
async onMessage(connection, message) {
const response = await this.env.AI.run('@cf/meta/llama-3-8b-instruct', {
messages: [...],
stream: true
});
// Manual SSE parsing required (see Workers AI section above)
for await (const chunk of response) {
// ... manual parsing ...
}
}
}
メリット:
- ✅ コスト効率が高い
- ✅ 外部依存関係が不要
- ✅ Agents SDK による WebSocket と状態管理
デメリット:
- ❌ SSE の手動パースが複雑
- ❌ 選択できるモデルが限られる
- ❌ 保守するコードが増える
オプション C:Vercel AI SDK のみ(Agents なし)
使用する場面:WebSocket や Durable Objects が不要な場合
// worker.ts - Simple Workers route
export default {
async fetch(request: Request, env: Env) {
const { messages } = await request.json();
const result = streamText({
model: openai('gpt-4o-mini'),
messages
});
return result.toTextStreamResponse();
}
}
// client.tsx - Built-in React hooks
import { useChat } from 'ai/react';
function Chat() {
const { messages, input, handleSubmit } = useChat({ api: '/api/chat' });
return <form onSubmit={handleSubmit}>...</form>;
}
メリット:
- ✅ 最もシンプルな方法
- ✅ コードが最も少ない
- ✅ すばやく実装できる
- ✅ React フックを内蔵
デメリット:
- ❌ WebSocket なし(SSE のみ)
- ❌ Durable Objects の状態管理なし
- ❌ マルチエージェントの連携なし
最適な用途:チャットアプリケーションの 80%
判断マトリックス
| ニーズ | 推奨スタック | 複雑さ | コスト |
|---|---|---|---|
| シンプルなチャット、状態管理なし | AI SDK のみ | 🟢 低 | $$(AI プロバイダー) |
| チャット + WebSocket + 状態管理 | Agents SDK + AI SDK | 🟡 中 | $$$(インフラ + AI) |
| チャット + WebSocket + 予算重視 | Agents SDK + Workers AI | 🔴 高 | $(インフラのみ) |
| マルチエージェントのワークフロー | Agents SDK + AI SDK | 🔴 高 | $$$(インフラ + AI) |
| ツールを備えた MCP サーバー | Agents SDK(McpAgent) | 🟡 中 | $(インフラのみ) |
要点
Agents SDK はインフラストラクチャであり、AI ではありません。 AI 推論ツールと組み合わせて使用します。
- 開発者体験を重視する場合:Agents SDK + Vercel AI SDK ⭐
- コストを抑える場合:Agents SDK + Workers AI(手動パースが必要です)
- シンプルさを重視する場合:AI SDK のみ(WebSocket/状態管理が不要であれば)
このスキルの以降の部分では、Agents SDK(インフラストラクチャ層)に焦点を当てます。AI 推論のパターンについては、ai-sdk-core または cloudflare-workers-ai のスキルを参照してください。
設定(wrangler.jsonc)
必須の重要な設定:
{
"durable_objects": {
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
},
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] } // MUST be in first migration
]
}
よく使われるオプションのバインディング:ai、vectorize、browser、workflows、d1_databases、r2_buckets
重要な移行ルール:
- ✅
new_sqlite_classesはタグ「v1」に含める必要があります(デプロイ済みのクラスに SQLite を追加することはできません) - ✅
nameとclass_nameは完全に一致する必要があります - ✅ 移行はアトミックです(すべてのインスタンスが同時に更新されます)
- ✅ 各タグは一意である必要があります。以前のタグは編集・削除できません
参照先:https://developers.cloudflare.com/agents/api-reference/configuration/
コアエージェントパターン
Agent クラスの基本 - ライフサイクルメソッドを持つ Agent<Env, State> を拡張します。
onStart()- エージェントの初期化onRequest()- HTTP リクエストの処理onConnect/onMessage/onClose()- WebSocket の処理onStateUpdate()- 状態の変更への対応
主なプロパティ:
this.env- 環境バインディング(AI、DB など)this.state- 現在のエージェントの状態(読み取り専用)this.setState()- 永続化する状態の更新this.sql- 組み込みの SQLite データベースthis.name- エージェントインスタンスの識別子this.schedule()- 将来のタスクのスケジュール設定
参照:公式の Agent API ドキュメント:https://developers.cloudflare.com/agents/api-reference/agents-api/
WebSocket とリアルタイム通信
エージェントは双方向のリアルタイム通信に WebSocket を使用できます。次の場合に使用します。
- サーバーがストリーミングしている間に、クライアントからメッセージを送信できる
- エージェントが開始するメッセージ(通知、更新)がある
- 状態を維持する長時間接続が必要
基本パターン:
export class ChatAgent extends Agent<Env, State> {
async onConnect(connection: Connection, ctx: ConnectionContext) {
// Auth check, add to participants, send welcome
}
async onMessage(connection: Connection, message: WSMessage) {
// Process message, update state, broadcast response
}
}
SSE の代替手段:一方向のサーバー → クライアントのストリーミング(よりシンプルで、HTTP ベース)には、WebSocket の代わりに Server-Sent Events を使用します。
参照:https://developers.cloudflare.com/agents/api-reference/websockets/
状態管理
2 つの状態管理方法:
-
this.setState(newState)- JSON シリアライズ可能な状態(最大 1GB)- 自動的に永続化され、WebSocket クライアントと同期されます
- 用途:ユーザー設定、セッションデータ、小規模なデータセット
-
this.sql- 組み込みの SQLite データベース(最大 1GB)- タグ付きテンプレートリテラルにより、SQL インジェクションを防ぎます
- 用途:リレーショナルデータ、大規模なデータセット、複雑なクエリ
状態のルール:
- ✅ JSON シリアライズ可能な値のみ(オブジェクト、配列、プリミティブ、null)
- ✅ 再起動後も保持され、即座に一貫性が保たれます
- ❌ 関数や循環参照は使用できません
- ❌ 合計上限は 1GB(状態と SQL の合計)
SQL パターン:
await this.sql`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, email TEXT)`
await this.sql`INSERT INTO users (email) VALUES (${userEmail})` // ← Prepared statement
const users = await this.sql`SELECT * FROM users WHERE email = ${email}` // ← Returns array
参照:https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/
タスクのスケジュール設定
エージェントは this.schedule() を使用して、将来実行するタスクをスケジュールできます。
遅延(秒)
export class MyAgent extends Agent {
async onRequest(request: Request): Promise<Response> {
// Schedule task to run in 60 seconds
const { id } = await this.schedule(60, "checkStatus", { requestId: "123" });
return Response.json({ scheduledTaskId: id });
}
// This method will be called in 60 seconds
async checkStatus(data: { requestId: string }) {
console.log('Checking status for request:', data.requestId);
// Perform check, update state, send notification, etc.
}
}
特定の日付
export class MyAgent extends Agent {
async scheduleReminder(reminderDate: string) {
const date = new Date(reminderDate);
const { id } = await this.schedule(date, "sendReminder", {
message: "Time for your appointment!"
});
return id;
}
async sendReminder(data: { message: string }) {
console.log('Sending reminder:', data.message);
// Send email, push notification, etc.
}
}
Cron 式
export class MyAgent extends Agent {
async setupRecurringTasks() {
// Every 10 minutes
await this.schedule("*/10 * * * *", "checkUpdates", {});
// Every day at 8 AM
await this.schedule("0 8 * * *", "dailyReport", {});
// Every Monday at 9 AM
await this.schedule("0 9 * * 1", "weeklyReport", {});
// Every hour on the hour
await this.schedule("0 * * * *", "hourlyCheck", {});
}
async checkUpdates(data: any) {
console.log('Checking for updates...');
}
async dailyReport(data: any) {
console.log('Generating daily report...');
}
async weeklyReport(data: any) {
console.log('Generating weekly report...');
}
async hourlyCheck(data: any) {
console.log('Running hourly check...');
}
}
スケジュール済みタスクの管理
export class MyAgent extends Agent {
async manageSchedules() {
// Get all scheduled tasks
const allTasks = this.getSchedules();
console.log('Total tasks:', allTasks.length);
// Get specific task by ID
const taskId = "some-task-id";
const task = await this.getSchedule(taskId);
if (task) {
console.log('Task:', task.callback, 'at', new Date(task.time));
console.log('Payload:', task.payload);
console.log('Type:', task.type); // "scheduled" | "delayed" | "cron"
// Cancel the task
const cancelled = await this.cancelSchedule(taskId);
console.log('Cancelled:', cancelled);
}
// Get tasks in time range
const upcomingTasks = this.getSchedules({
timeRange: {
start: new Date(),
end: new Date(Date.now() + 24 * 60 * 60 * 1000) // Next 24 hours
}
});
console.log('Upcoming tasks:', upcomingTasks.length);
// Filter by type
const cronTasks = this.getSchedules({ type: "cron" });
const delayedTasks = this.getSchedules({ type: "delayed" });
}
}
スケジュールの制約:
- 各タスクは SQL データベースの 1 行に対応します(タスクあたり最大 2 MB)
- タスクの合計数は、
(task_size * count) + other_state < 1GBによって制限されます - Cron タスクは明示的にキャンセルされるまで実行され続けます
- コールバックメソッドは Agent クラスに存在する必要があります(存在しない場合はエラーが発生します)
重大なエラー:コールバックメソッドが存在しない場合:
// ❌ BAD: Method doesn't exist
await this.schedule(60, "nonExistentMethod", {});
// ✅ GOOD: Method exists
await this.schedule(60, "existingMethod", {});
async existingMethod(data: any) {
// Implementation
}
ワークフローの実行
エージェントは非同期の Cloudflare Workflows を起動できます。
ワークフローバインディングの設定
wrangler.jsonc:
{
"workflows": [
{
"name": "MY_WORKFLOW",
"class_name": "MyWorkflow"
}
]
}
Workflow が別のスクリプトにある場合:
{
"workflows": [
{
"name": "EMAIL_WORKFLOW",
"class_name": "EmailWorkflow",
"script_name": "email-workflows" // Different project
}
]
}
ワークフローの起動
import { Agent } from "agents";
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers";
interface Env {
MY_WORKFLOW: Workflow;
MyAgent: AgentNamespace<MyAgent>;
}
export class MyAgent extends Agent<Env> {
async onRequest(request: Request): Promise<Response> {
const userId = new URL(request.url).searchParams.get('userId');
// Trigger a workflow immediately
const instance = await this.env.MY_WORKFLOW.create({
id: `user-${userId}`,
params: { userId, action: "process" }
});
// Or schedule a delayed workflow trigger
await this.schedule(300, "runWorkflow", { userId });
return Response.json({ workflowId: instance.id });
}
async runWorkflow(data: { userId: string }) {
const instance = await this.env.MY_WORKFLOW.create({
id: `delayed-${data.userId}`,
params: data
});
// Monitor workflow status periodically
await this.schedule("*/5 * * * *", "checkWorkflowStatus", { id: instance.id });
}
async checkWorkflowStatus(data: { id: string }) {
// Check workflow status (see Workflows docs for details)
console.log('Checking workflow:', data.id);
}
}
// Workflow definition (can be in same or different file/project)
export class MyWorkflow extends WorkflowEntrypoint<Env> {
async run(event: WorkflowEvent<{ userId: string }>, step: WorkflowStep) {
// Workflow implementation
const result = await step.do('process-data', async () => {
return { processed: true };
});
return result;
}
}
エージェントとワークフローの比較
| 機能 | エージェント | ワークフロー |
|---|---|---|
| 目的 | 対話型、ユーザー向け | バックグラウンド処理 |
| 実行時間 | 数秒から数時間 | 数分から数時間 |
| 状態 | SQLite データベース | ステップ単位のチェックポイント |
| インタラクション | WebSocket、HTTP | 直接のインタラクションなし |
| 再試行 | 手動 | ステップごとに自動 |
| 用途 | チャット、リアルタイム UI | ETL、バッチ処理 |
ベストプラクティス:複数のワークフローを調整するためにエージェントを使用します。エージェントは、ユーザーとのインタラクションを維持しながらワークフローを起動、監視し、結果に応答できます。
Web の閲覧
エージェントはウェブスクレイピングと自動化に Browser Rendering を使用できます。
バインディング:"browser": { "binding": "BROWSER" } を wrangler.jsonc に追加します
パッケージ:@cloudflare/puppeteer
用途:ウェブスクレイピング、スクリーンショット、エージェントのワークフロー内での自動ブラウジング
参照:Puppeteer と Workers の連携に関する完全ガイドは、cloudflare-browser-rendering スキルをご覧ください。
Retrieval Augmented Generation(RAG)
エージェントは、Vectorize(ベクトルデータベース)と Workers AI(埋め込み)を使って RAG を実装できます。
パターン:ドキュメントを取り込む → 埋め込みを生成する → Vectorize に保存する → クエリする → コンテキストを取得する → AI に渡す
バインディング:
"ai": { "binding": "AI" }- 埋め込み用の Workers AI"vectorize": { "bindings": [{ "binding": "VECTORIZE", "index_name": "my-vectors" }] }- ベクトル検索
一般的なワークフロー:
- Workers AI(
@cf/baai/bge-base-en-v1.5)で埋め込みを生成する - ベクトルを Vectorize にアップサートする(
this.env.VECTORIZE.upsert(vectors)) - 類似するベクトルをクエリする(
this.env.VECTORIZE.query(queryVector, { topK: 5 })) - 取得したコンテキストを AI のプロンプトで使用する
参照:RAG の完全な実装ガイドについては、cloudflare-vectorize スキルを参照してください。
AI モデルの使用
エージェントは、次の方法で AI モデルを呼び出せます。
- Vercel AI SDK(推奨):複数のプロバイダー、自動ストリーミング、ツール呼び出しに対応
- Workers AI:Cloudflare のプラットフォーム内推論(コスト効率に優れていますが、解析は手動)
アーキテクチャに関する注意:Agents SDK はインフラストラクチャ(WebSocket、状態、スケジューリング)を提供します。AI 推論は別のレイヤーです。「頭脳」には AI SDK を使用してください。
参照:
- AI SDK の完全な統合パターンについては、
ai-sdk-coreスキルを参照してください - Workers AI のストリーミング解析については、
cloudflare-workers-aiスキルを参照してください
エージェントの呼び出し
主なパターンは 2 つです:
-
routeAgentRequest(request, env)- URL パターン/agents/:agent/:nameを使った自動ルーティング- 例:
/agents/my-agent/user-123は MyAgent のインスタンス「user-123」にルーティングされます
- 例:
-
getAgentByName<Env, T>(env.AgentBinding, instanceName)- カスタムルーティング- メソッドの呼び出しやリクエストの受け渡しに使用するエージェントスタブを返します
- 例:
const agent = getAgentByName(env.MyAgent, 'user-${userId}')
複数エージェント間の通信:
export class AgentA extends Agent<Env> {
async processData(data: any) {
const agentB = getAgentByName<Env, AgentB>(this.env.AgentB, 'processor-1');
return await (await agentB).analyze(data);
}
}
セキュリティに関する重要事項:エージェントを作成またはアクセスする前に、必ず Worker で認証してください。エージェントは、呼び出し元が認可済みであることを前提としてください。
参照:https://developers.cloudflare.com/agents/api-reference/calling-agents/
クライアント API
ブラウザー/React との統合:
AgentClient(agents/clientから)- ブラウザー用 WebSocket クライアントagentFetch(agents/clientから)- エージェントへの HTTP リクエストuseAgent(agents/reactから)- WebSocket 接続と状態同期のための React フックuseAgentChat(agents/ai-reactから)- すぐに使えるチャット UI フック
すべてのクライアントライブラリが自動的に処理するもの:WebSocket 接続、状態の同期、再接続ロジック。
参照:https://developers.cloudflare.com/agents/api-reference/client-apis/
Model Context Protocol(MCP)
Agents SDK を使って MCP サーバーを構築します。
MCP サーバーのセットアップ
npm install @modelcontextprotocol/sdk agents
基本的な MCP サーバー
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
export class MyMCP extends McpAgent {
server = new McpServer({ name: "Demo", version: "1.0.0" });
async init() {
// Define a tool
this.server.tool(
"add",
"Add two numbers together",
{
a: z.number().describe("First number"),
b: z.number().describe("Second number")
},
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }]
})
);
}
}
ステートフル MCP サーバー
type State = { counter: number };
export class StatefulMCP extends McpAgent<Env, State> {
server = new McpServer({ name: "Counter", version: "1.0.0" });
initialState: State = { counter: 0 };
async init() {
// Resource
this.server.resource(
"counter",
"mcp://resource/counter",
(uri) => ({
contents: [{ uri: uri.href, text: String(this.state.counter) }]
})
);
// Tool
this.server.tool(
"increment",
"Increment the counter",
{ amount: z.number() },
async ({ amount }) => {
this.setState({
...this.state,
counter: this.state.counter + amount
});
return {
content: [{
type: "text",
text: `Counter is now ${this.state.counter}`
}]
};
}
);
}
}
MCP トランスポートの設定
import { Hono } from 'hono';
const app = new Hono();
// Modern streamable HTTP transport (recommended)
app.mount('/mcp', MyMCP.serve('/mcp').fetch, { replaceRequest: false });
// Legacy SSE transport (deprecated)
app.mount('/sse', MyMCP.serveSSE('/sse').fetch, { replaceRequest: false });
export default app;
トランスポートの比較:
- /mcp:ストリーミング可能な HTTP(最新の方式、推奨)
- /sse:Server-Sent Events(従来の方式、非推奨)
OAuth を使用する MCP
import { OAuthProvider } from '@cloudflare/workers-oauth-provider';
export default new OAuthProvider({
apiHandlers: {
'/sse': MyMCP.serveSSE('/sse'),
'/mcp': MyMCP.serve('/mcp')
},
// OAuth configuration
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
// ... other OAuth settings
});
MCP サーバーのテスト
# Run MCP inspector
npx @modelcontextprotocol/inspector@latest
# Connect to: http://localhost:8788/mcp
Cloudflare の MCP サーバー:本番環境での例については、リファレンスを参照してください。
重要なルール
必ず行うこと ✅
- Agent クラスをエクスポートする - バインディングを機能させるにはエクスポートが必要です
- v1 マイグレーションに new_sqlite_classes を含める - SQLite は後から追加できません
- バインディング名をクラス名と一致させる - 「binding not found」エラーを防ぎます
- 認証は Agent ではなく Worker で行う - セキュリティ上のベストプラクティスです
- SQL にはタグ付きテンプレートリテラルを使用する - SQL インジェクションを防ぎます
- WebSocket の切断に対処する - 状態は保持されますが、接続は保持されません
- スケジュール済みタスクのコールバックが存在することを確認する - メソッドがない場合はエラーがスローされます
- インスタンス名にはグローバルで一意な名前を使用する - 同じ名前はグローバルに同じエージェントを指します
- 状態のサイズ制限を確認する - エージェントごとの合計上限は 1GB です
- タスクのペイロードサイズを監視する - スケジュール済みタスクごとの上限は 2MB です
- ワークフローのバインディングを正しく使用する - wrangler.jsonc で設定する必要があります
- 挿入前に Vectorize インデックスを作成する - メタデータフィルタリングに必要です
- ブラウザーのインスタンスを閉じる - リソースリークを防ぎます
- 永続化には setState() を使用する - this.state を変更するだけでは不十分です
- まずローカルでマイグレーションをテストする - マイグレーションはアトミックで、ロールバックできません
絶対に行わないこと ❌
- デプロイ済みの既存クラスに SQLite を追加しない - 最初のマイグレーションに含める必要があります
- マイグレーションを段階的にデプロイしない - アトミックにのみ適用されます
- Worker での認証を省略しない - エージェントにアクセスする前に必ず認証します
- SQL 文字列を手動で構築しない - タグ付きテンプレートを使用します
- エージェントごとに 1GB の状態上限を超えない - 厳格な上限です
- 存在しないコールバックを指定してタスクをスケジュールしない - 実行時エラーになります
- 同じ名前なら別のエージェントだと思い込まない - 名前はグローバルで一意です
- MCP に SSE を使用しない - 非推奨です。/mcp トランスポートを使用してください
- ブラウザーのバインディングを忘れない - Web ブラウジングに必要です
- this.state を直接変更しない - 代わりに setState() を使用します
既知の問題の防止
このスキルは、ドキュメントに記載されている 16 件以上の問題を防ぎます:
問題 1:マイグレーションがアトミックではない
エラー: "Cannot gradually deploy migration"
出典: https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/
理由: マイグレーションはすべてのインスタンスに同時に適用されます
防止策: マイグレーションはコード変更とは別にデプロイし、npx wrangler versions deploy を使用します
問題 2:new_sqlite_classes がない
エラー: "Cannot enable SQLite on existing class"
出典: https://developers.cloudflare.com/agents/api-reference/configuration/
理由: SQLite は最初のマイグレーションで有効にする必要があります
防止策: タグ「v1」のマイグレーションに new_sqlite_classes を含めます
問題 3:Agent クラスがエクスポートされていない
エラー: "Binding not found" または "Cannot access undefined"
出典: https://developers.cloudflare.com/agents/api-reference/agents-api/
理由: Durable Objects ではクラスをエクスポートする必要があります
防止策: export class MyAgent extends Agent(export キーワードを付ける)
問題 4:バインディング名が一致しない
エラー: "Binding 'X' not found"
出典: https://developers.cloudflare.com/agents/api-reference/configuration/
理由: バインディング名はクラス名と完全に一致する必要があります
防止策: wrangler.jsonc 内で name と class_name が同一であることを確認します
問題 5:グローバルな一意性が理解されていない
エラー: エージェントのインスタンスで予期しない動作が発生する 出典: https://developers.cloudflare.com/agents/api-reference/agents-api/ 理由: 同じ名前を指定すると、常にグローバルで同じエージェントインスタンスが返されます 防止策: インスタンス名には一意な識別子(userId、sessionId)を使用します
問題 6:WebSocket の状態が永続化されない
エラー: 切断後に接続状態が失われる 出典: https://developers.cloudflare.com/agents/api-reference/websockets/ 理由: WebSocket 接続は保持されませんが、エージェントの状態は保持されます 防止策: 重要なデータは接続状態ではなく、setState() を使ってエージェントの状態に保存します
課題 7:スケジュールタスクのコールバックが存在しません
エラー:「Agent にメソッド X が存在しません」 参照元:https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ 理由:this.schedule() が定義されていないメソッドを呼び出しています 防止策:スケジュールを設定する前に、コールバックメソッドが存在することを確認してください
課題 8:状態のサイズ上限を超過しました
エラー:「データベースの最大サイズを超過しました」 参照元:https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/ 理由:Agent の状態とスケジュールタスクの合計が 1GB を超えています 防止策:状態のサイズを監視し、大容量データには外部ストレージ(D1、R2)を使用してください
課題 9:スケジュールタスクが大きすぎます
エラー:「タスクのペイロードが 2MB を超えています」 参照元:https://developers.cloudflare.com/agents/api-reference/schedule-tasks/ 理由:各タスクはデータベースの行に対応し、上限は 2MB です 防止策:タスクのペイロードは最小限にし、大容量データは Agent の状態または SQL に保存してください
課題 10:ワークフローのバインディングがありません
エラー:「undefined のプロパティ 'create' を読み取れません」 参照元:https://developers.cloudflare.com/agents/api-reference/run-workflows/ 理由:wrangler.jsonc でワークフローのバインディングが設定されていません 防止策:this.env.WORKFLOW を使用する前に、ワークフローのバインディングを追加してください
課題 11:ブラウザーのバインディングが必要です
エラー:「BROWSER バインディングが未定義です」
参照元:https://developers.cloudflare.com/agents/api-reference/browse-the-web/
理由:Browser Rendering には明示的なバインディングが必要です
防止策:wrangler.jsonc に "browser": { "binding": "BROWSER" } を追加してください
課題 12:Vectorize インデックスが見つかりません
エラー:「インデックスが存在しません」
参照元:https://developers.cloudflare.com/agents/api-reference/rag/
理由:Vectorize インデックスは使用前に作成する必要があります
防止策:Agent をデプロイする前に wrangler vectorize create を実行してください
課題 13:MCP トランスポートの混同
エラー:「SSE トランスポートは非推奨です」
参照元:https://developers.cloudflare.com/agents/model-context-protocol/transport/
理由:SSE トランスポートは旧式であり、ストリーミング可能な HTTP が推奨されています
防止策:/sse ではなく、MyMCP.serve('/mcp') を使用して /mcp エンドポイントを利用してください
課題 14:認証のバイパス
エラー:セキュリティの脆弱性 参照元:https://developers.cloudflare.com/agents/api-reference/calling-agents/ 理由:Worker ではなく Agent で認証を行っています 防止策:getAgentByName() を呼び出す前に、必ず Worker で認証してください
課題 15:インスタンス名のエラー
エラー:ユーザー間でのデータ漏えい
参照元:https://developers.cloudflare.com/agents/api-reference/calling-agents/
理由:不適切なインスタンス名により、誤った Agent へのアクセスが可能になります
防止策:user-${userId} のような名前空間付きの名前を使用し、所有者を検証してください
課題 16:Workers AI のストリーミングには手動解析が必要です
エラー:「undefined のプロパティ 'response' を読み取れません」、または AI の応答が空です
参照元:https://developers.cloudflare.com/workers-ai/platform/streaming/
理由:Workers AI はストリーミング応答を通常のオブジェクトではなく、Server-Sent Events(SSE)形式の Uint8Array として返します
防止策:TextDecoder と SSE 解析のパターンを使用してください(上記の「Workers AI(AI の代替手段)」セクションを参照)
問題 - ストリームのチャンクに直接アクセスしようとすると失敗します:
const response = await env.AI.run(model, { stream: true });
for await (const chunk of response) {
console.log(chunk.response); // ❌ undefined - chunk is Uint8Array, not object
}
解決策 - SSE 形式を手動で解析します:
const response = await env.AI.run(model, { stream: true });
for await (const chunk of response) {
const text = new TextDecoder().decode(chunk); // Step 1: Uint8Array → string
if (text.startsWith('data: ')) { // Step 2: Check SSE format
const jsonStr = text.slice(6).trim(); // Step 3: Extract JSON from "data: {...}"
if (jsonStr === '[DONE]') break; // Step 4: Handle termination
const data = JSON.parse(jsonStr); // Step 5: Parse JSON
if (data.response) { // Step 6: Extract .response field
fullResponse += data.response;
}
}
}
より良い代替手段:Vercel AI SDK を使用すると、自動的に処理されます:
import { streamText } from 'ai';
import { createCloudflare } from '@ai-sdk/cloudflare';
const cloudflare = createCloudflare();
const result = streamText({
model: cloudflare('@cf/meta/llama-3-8b-instruct', { binding: env.AI }),
messages
});
// No manual parsing needed ✅
手動解析を選ぶ場合:
- コストが重要な場合(Workers AI の方が安価です)
- 外部依存関係を許可できない場合
- SSE 解析コードを保守する意思がある場合
代わりに AI SDK を使用する場合:
- コンピューティングコストより開発者の作業時間を重視する場合
- ストリーミングを自動化したい場合
- 複数プロバイダーのサポートが必要な場合
依存関係
必須
- cloudflare-worker-base - 基盤(Hono、Vite、Workers のセットアップ)
オプション(機能別)
- cloudflare-workers-ai - Workers AI のモデル呼び出し用
- cloudflare-vectorize - Vectorize を使用した RAG 用
- cloudflare-d1 - エージェントの状態以外の永続ストレージ用
- cloudflare-r2 - ファイルストレージ用
- cloudflare-queues - メッセージキュー用
NPM パッケージ
agents- Agents SDK(必須)@modelcontextprotocol/sdk- MCP サーバーの構築用@cloudflare/puppeteer- ウェブブラウジング用ai- モデル呼び出し用の AI SDK@ai-sdk/openai- OpenAI モデル用@ai-sdk/anthropic- Anthropic モデル用
公式ドキュメント
- Agents SDK: https://developers.cloudflare.com/agents/
- API リファレンス: https://developers.cloudflare.com/agents/api-reference/
- Durable Objects: https://developers.cloudflare.com/durable-objects/
- Workflows: https://developers.cloudflare.com/workflows/
- Vectorize: https://developers.cloudflare.com/vectorize/
- Browser Rendering: https://developers.cloudflare.com/browser-rendering/
- Model Context Protocol: https://modelcontextprotocol.io/
- Cloudflare MCP Servers: https://github.com/cloudflare/mcp-server-cloudflare
同梱リソース
テンプレート(templates/)
wrangler-agents-config.jsonc- 完全な設定例basic-agent.ts- 最小構成の HTTP エージェントwebsocket-agent.ts- WebSocket ハンドラーstate-sync-agent.ts- 状態管理のパターンscheduled-agent.ts- タスクのスケジュール設定workflow-agent.ts- ワークフローの統合browser-agent.ts- ウェブブラウジングrag-agent.ts- RAG の実装chat-agent-streaming.ts- ストリーミングチャットcalling-agents-worker.ts- エージェントのルーティングreact-useagent-client.tsx- React クライアントmcp-server-basic.ts- MCP サーバーhitl-agent.ts- Human-in-the-loop
リファレンス(references/)
agent-class-api.md- Agent クラスの完全なリファレンスclient-api-reference.md- ブラウザークライアント APIstate-management-guide.md- 状態と SQL の詳細解説websockets-sse.md- WebSocket と SSE の比較scheduling-api.md- タスクのスケジュール設定の詳細workflows-integration.md- Workflows ガイドbrowser-rendering.md- ウェブブラウジングのパターンrag-patterns.md- RAG のベストプラクティスmcp-server-guide.md- MCP サーバー開発mcp-tools-reference.md- MCP ツール APIhitl-patterns.md- Human-in-the-loop ワークフローbest-practices.md- 本番環境向けのパターン
例(examples/)
chat-bot-complete.md- 完全なチャットエージェントmulti-agent-workflow.md- エージェントのオーケストレーションscheduled-reports.md- 定期タスクbrowser-scraper-agent.md- ウェブスクレイピングrag-knowledge-base.md- RAG システムmcp-remote-server.md- 本番環境向け MCP サーバー
最終確認日: 2025-10-21 パッケージバージョン: agents@latest 準拠状況: Cloudflare Agents SDK の公式ドキュメントに準拠