はじめに
Cloudflare は 2025 年後半から、Workers を AI エージェントの実行基盤として位置づける動きを加速させています。AIエージェントが簡単に構築できるAgents SDK は 50 万ダウンロードを突破し、Sandbox SDK や Dynamic Workers といったエージェント向け機能も次々とリリースされています。
この記事では、 Sandbox SDK とオープンベータになったばかりのDynamic Workers を整理しながら、実際にログ分析アプリを作ってみます。
Sandbox SDKとDynamic Workersの強みをそれぞれ体感しながら、Workers AIで使えるLLMとフロンティアモデルの機能差も最後に比較してみました。
Sandbox SDK とは
Sandbox SDK は、Cloudflare Workers から安全に「信頼できないコード」を実行するための SDK です。Cloudflare の Containers をベースにしており、Worker から隔離された Linux 環境を起動し、その中でコマンド実行・ファイル操作・バックグラウンドプロセスの起動・ポート公開まで扱えます。現在は Beta として提供されています (2026年4月時点)。
仕組み
Cloudflare のドキュメントでは、Sandbox SDK は 3 つの技術を組み合わせた仕組みとして説明されています。
| レイヤー | 役割 |
|---|---|
| Workers | アプリケーション本体 |
| Durable Objects | sandbox インスタンスの状態管理 |
| Containers | 実際にコードを動かす隔離環境 |
つまり、単にコードを実行するだけでなく、状態を持った安全な実行環境を Worker から扱えるのがポイントです。
AI エージェントとの相性
LLM が生成した Python や JavaScript をそのまま本番 Workers 上で動かすのは危険です。Sandbox SDK を使えば、隔離された環境の中だけで実行できます。さらに、生成したファイルを保存したり、バックグラウンドで処理を走らせたり、必要に応じてアプリを外部公開したりもできます。
Sandbox SDK は「Workers 上で AI を呼ぶ」ための機能ではなく、AI が必要に応じてコードを安全に実行するための基盤と捉えると分かりやすいです。
Dynamic Workers とは
Dynamic Workers は、実行時に任意のコードを Workers としてその場で読み込み、安全に実行できる仕組みです。2026 年 3 月 24 日に open beta となり、Paid Workers ユーザー向けに提供されています。
従来モデルとの違い
従来は「事前にデプロイしておいた Worker を呼ぶ」モデルでしたが、Dynamic Workers では アプリや AI エージェントが生成したコードをその場で Worker isolate として実行できます。
Cloudflare はこれをコンテナよりも軽量で高速な選択肢として位置づけており、ブログでは「traditional containers より 100x faster」と説明しています。
柔軟な権限制御
Dynamic Workers では、どのバインディングを渡すか、ネットワークアクセスを許可するかを呼び出し元が制御できます。バインディングも通常の KV や R2 に固定されるのではなく、Workers RPC を使って任意のインターフェースを渡せるのが特徴です。
代表的なユースケースとして、ブログでは以下を挙げてました。
- AI-generated app のプレビュー
- Code Mode 的なコード実行
- エージェントが作った一時的なアプリの起動
Sandbox SDK との対比
Dynamic Workers は「AI が生成したコードを、コンテナを立てるほど重くなく、通常の Worker より柔軟に、その場で安全に実行するための仕組み」と捉えると分かりやすいです。
Sandbox SDK が Linux 環境を含むリッチな実行環境であるのに対し、Dynamic Workers はその対極にある軽量・高速なコード実行基盤です。ブログでも "containers の lightweight alternative" と説明されています。
Cloudflare Log Investigator を作る
最近、自分の運営するサイトに対する攻撃アラートが増えてきたので、この 2 つの機能を活かせるログ分析アプリを作ってみることにしました。Agent に「サイトのセキュリティ分析をして」と投げるだけで答えが返ってくると便利ですね。
Workers のみの場合
ユーザー → Worker → Cloudflare GraphQL API → JSON
↓
Worker が整形して HTML を返す
この構成では、分析ロジックをすべて事前にコードとして書いておく必要があり、柔軟な分析はしづらくなります。
Sandbox SDK + Dynamic Workers の場合
ユーザー → Worker → AI がツールを選択
│
┌────────────┼────────────┐
▼ ▼ ▼
GraphQL API Sandbox SDK Dynamic Workers
(データ取得) (Python 実行) (プレビュー・公開)
この構成では、分析ロジックをすべて事前に書いておく必要がありません。ユーザーの質問に応じて AI がコードを生成し、Sandbox で実行し、その結果を Dynamic Workers で即座にプレビューしてから保存するか決めます。
動作イメージ
たとえば、「昨日の夜中に異常なリクエストがあったか調べて」と聞くと、以下の流れで動きます。
- Workers AI か Claude が時間範囲を判断 (番外編のWorkers AIとClaude LLM比較用に選択式)
-
fetch_logs: Cloudflare GraphQL から実データ取得 -
execute_code: Sandbox で Python 実行(z-score 異常検知 + matplotlib チャート) -
preview_report: Dynamic Workers(worker_loader)でレポートを即座にレンダリングし、UI にプレビュー表示 - ユーザーが確認 →「デプロイする」を選択
-
deploy_worker: Workers API で永続デプロイ - UI にチャート、異常一覧、レポート URL を表示
worker_loader は一時的な V8 isolate を生成するだけなので、ミリ秒で起動し、リクエスト終了後に自動で破棄されます。ユーザーがプレビューを確認して初めて、REST API による永続デプロイが走ります。
// Dynamic Workers によるプレビュー(一時的、ミリ秒で起動)
const worker = await env.LOADER.load({
compatibilityDate: '2026-01-01',
modules: { 'report.js': reportCode },
mainModule: 'report.js',
})
const entrypoint = worker.getEntrypoint()
const response = await entrypoint.fetch(new Request('https://preview/'))
const html = await response.text() // → UI にプレビュー表示
// ユーザーが承認後、REST API で永続デプロイ
await deployWorker({ name, code: reportCode }, env)
| Dynamic Workers(プレビュー) | REST API(永続デプロイ) | |
|---|---|---|
| 用途 | ユーザー確認用の一時レンダリング | 公開レポート |
| 起動時間 | ミリ秒 | 数秒 |
| 寿命 | リクエスト中のみ | 削除するまで永続 |
| URL | なし(親 Worker 内で実行) | *.workers.dev |
| ダッシュボード | 表示されない | 個別の Worker として管理可能 |
アーキテクチャ
Browser (Chat UI)
↓ SSE streaming
Cloudflare Worker (Hono)
↓ tool use loop
LLM (Kimi K2.5 or Claude Sonnet 4.6)
├── Tool: fetch_logs → Cloudflare Analytics GraphQL
├── Tool: execute_code → Sandbox SDK (Python)
├── Tool: preview_report → Dynamic Workers / worker_loader (プレビュー)
└── Tool: deploy_worker → Workers REST API (永続デプロイ)
技術スタック
| レイヤー | 技術 |
|---|---|
| フロントエンド | Vanilla JS(インライン HTML) |
| API サーバー | Hono on Workers |
| AI(デフォルト) | Kimi K2.5 (Workers AI) |
| AI(選択可能) | Claude Sonnet 4.6 (Anthropic API) |
| コード実行 | @cloudflare/sandbox |
| データ取得 | Cloudflare Analytics GraphQL |
| レポートプレビュー | Dynamic Workers (worker_loader) |
| レポート公開 | Workers REST API |
しばらくデモアプリを公開しておきます。
https://enterprise-log-investigator.soon-chang.workers.dev/
「過去24時間のトラフィックを分析して」と聞いてみた結果がこちら。
プレビュー
デプロイすると、URLが発行され共有しやすいです。ちなみに、これはDurable Objectの機能を使っても実装できるかもしれませんね。
https://log-report-2026-04-05.soon-chang.workers.dev
Githubでソースも公開しときます。
https://github.com/soonbig/enterprise-log-investigator
実装で工夫したポイント
① Sandbox のコールドスタート対策
Sandbox SDK はコンテナベースのため、初回起動に数秒かかります。ユーザーが質問してからコンテナが立ち上がるのを待つと体験が悪いので、2 つの対策を入れました。
-
Pre-warm: ページ読み込み時に
/api/warmupを呼び、バックグラウンドでコンテナを事前起動しておく -
リトライ:
Container is startingエラーが返った場合、バックオフしながら最大 5 回リトライする
app.get('/api/warmup', async (c) => {
const sandbox = await getSandbox(c.env.SANDBOX, 'warmup')
await sandbox.runCode('print("warm")', { language: 'python' })
})
Containers のコールドスタートは通常 2〜5秒のようですが、matplotlib のような重いライブラリの初回ロードを含めると 15〜30秒 かかることがあります。このアプリではページ読み込み時にウォームアップ API を呼び出し、ユーザーの Sandbox コンテナで matplotlib + pandas を事前ロードすることで、実際のコード実行は概ね 3〜10秒 に収まるようになりました。
② エージェントループの仕組み
このアプリの中核は、Claude API の tool use を使ったループです。Claude が「もう呼ぶツールはない」と判断する(stop_reason === 'end_turn')まで、「ツール呼び出し → 結果をメッセージに追加 → 再度 Claude に投げる」を繰り返します。
while (true) {
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
tools: TOOLS,
messages,
})
if (response.stop_reason === 'end_turn') break
// ツールを実行し、結果を messages に追加してループ継続
}
開発者が書くのはこのループ構造だけで、どのツールを、どの順番で、何回呼ぶかは Claude が自律的に判断します。
③ チャートデータの受け渡し
matplotlib で生成したチャート画像(base64 PNG)は数百 KB になることがあります。これをそのまま LLM のコンテキストに入れると、トークン数が膨らみ、応答も遅くなります。
そこで、チャート画像は SSE 経由で UI に直接送信し、LLM には「チャートは生成済みです」という軽量な情報だけを返すようにしました。
emit({ type: 'chart', base64: codeResult.chart })
result = {
success: true,
output: cleanOutput.substring(0, 2000),
chartGenerated: true,
}
この対策を入れる前は execute_code の結果が 340 KB になり、次のターンで 100 秒以上かかっていました。対策後はツール結果が数 KB に収まり、レスポンスも大幅に改善しました。
まとめ
Sandbox SDK と Dynamic Workers で、Workers アプリを「事前に書いたロジックを実行するもの」 から「実行時にロジックを生成・実行・公開できる」AIエージェントへと進化させることができました。
また、同じアプリでSandbox SDK と Dynamic Workersを併用してみるとDynamic Workersの方がコールドスタートがない分格段に早いことも体感できました。
Code Mode のように AI がコードを生成して実行する方式は、LLM が自力で全計算を行う場合と比べてトークン消費を大きく抑えられるという話がブログでも紹介されており、精度だけでなくコスト面でも合理的です。
Sandbox SDK と Dynamic Workers を活用することで、今後さらに多くのユースケースが生まれそうですね!
番外編: Kimi K2.5 と Claude Sonnet 4.6 を比べてみた
Cloudflare は最近、Kimi K2.5 という本格的なエージェント向けモデルへの対応を進めています。公式ブログでも、Kimi K2.5 の投入によって Workers AI が "big models game" に入ったと説明されています。
今回は検証も兼ねて、Kimi K2.5 と Claude Sonnet 4.6 の両方を選択できるようにし、結果の違いを比べてみました。
結果
| Claude Sonnet 4.6 | Kimi K2.5 | |
|---|---|---|
| 各ターン | 2〜4 秒 | 13〜100 秒 |
| 全体 | 約 11 秒 | 2〜4 分 |
| 安定性 | 安定 | 空レスポンス・タイムアウト(408)あり |
今回の分析アプリの用途において、Kimi K2.5 は単発の質問応答やシンプルな tool use はこなせるものの、「データを見て → 分析方針を決めて → コードを書いて → 結果を見て → レポートを作る」という複数ステップにわたる自律的な判断の連鎖は、まだ安定しませんでした。
高い自律性や安定したマルチステップ処理が求められるユースケースでは、現時点では Workers AI 単体というより、Workers AI とフロンティアモデルを併用する構成が現実的だと感じました。
