この例では、@cloudflare/codemode ↗ ライブラリと Agents SDK ↗ を使い、LLM がツールを 1 つずつ呼ぶのではなく、コードを書いてツール呼び出しをまとめて制御するエージェントを構築します。この手法は Code Mode ↗ と呼ばれ、消費トークンを最大 80% 削減し、より良い結果を返し、コンテキストウィンドウの肥大化を避けます。
この例で確認できる内容は次のとおりです。
- Zod スキーマ付きの通常の関数としてツールを定義する
createCodeToolを使い、ツール群を LLM へ「コードを書く」1 つのツールとして公開するDynamicWorkerExecutorを使い、LLM が生成したコードを安全に実行するAIChatAgentと組み合わせ、WebSocket 上のチャットを処理する
エージェントは、@cloudflare/codemode ↗ ライブラリと Agents SDK ↗ の 3 つのコンポーネントを使います。
AIChatAgent(@cloudflare/ai-chat) — エージェントのベースクラスです。WebSocket 上のチャットを処理し、メッセージを永続化し、LLM を呼び出します。createCodeTool(@cloudflare/codemode/ai) — ツール群を、{ code: string }を受け取る 1 つのcodemodeツールにまとめます。DynamicWorkerExecutor(@cloudflare/codemode) — LLM が生成したコードを、隔離された Dynamic Worker で実行します。
流れは次のとおりです。
- ユーザーが WebSocket でメッセージを送ります。
AIChatAgentは、利用可能なツールをcodemode1 つだけにして、そのメッセージを LLM へ渡します。- LLM は JavaScript を書きます。例:
const projects = await codemode.listProjects()。個別のツール呼び出しはしません。 DynamicWorkerExecutorが隔離された Worker を起動し、コードを実行します。サンドボックス内では、codemode.listProjects()が実際のlistProjects実装を呼びます。- 結果、コンソール出力、エラーが LLM へ返ります。
- LLM はその結果を使ってユーザーに応答するか、必要ならさらにコードを書きます。
DynamicWorkerExecutor は @cloudflare/codemode ライブラリの一部です。LLM がツールを組み合わせて動かすコードを書いたとき、そのコードは安全な場所で実行する必要があります。DynamicWorkerExecutor は、Worker Loader バインディングを使い、実行ごとに隔離された Dynamic Worker を起動します。サンドボックス内では次のように動きます。
codemodeプロキシオブジェクトが、codemode.createTask(...)のような呼び出しを Workers RPC 経由で実際のツール実装へルーティングしますglobalOutboundをnullにするとfetch()がブロックされ、コードはツール経由でしか外部へ到達できませんconsole.logの出力はキャプチャされ、結果と一緒に返されます- 実行ごとに Worker インスタンスが分かれ、タイムアウトは 30 秒です
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
const executor = new DynamicWorkerExecutor({
loader: env.LOADER, // WorkerLoader binding from wrangler.jsonc
timeout: 30000, // default: 30s
globalOutbound: null, // null = fetch blocked
});import { DynamicWorkerExecutor } from "@cloudflare/codemode";
const executor = new DynamicWorkerExecutor({
loader: env.LOADER, // WorkerLoader binding from wrangler.jsonc
timeout: 30000, // default: 30s
globalOutbound: null, // null = fetch blocked
});createCodeTool は @cloudflare/codemode の一部です。ツール群と executor を受け取り、1 つの AI SDK tool() を返します。次の処理を行います。
- ツールの Zod スキーマから TypeScript の型宣言を生成し、LLM が利用可能なものと引数の形を把握できるようにします。
- それらの型をツールの description に入れます。LLM から見えるのは、パラメーターが
{ code: string }の 1 つのツールと、型付き API 全体を含む description です。 - 実行時は、LLM のコードを正規化します(Markdown のフェンスを取り除き、裸の文を async 関数で包み、最後の式を自動で return します)。そのうえで
executorに渡します。
import { createCodeTool } from "@cloudflare/codemode/ai";
const codemode = createCodeTool({
tools: myTools, // Record<string, tool()> with Zod schemas
executor, // DynamicWorkerExecutor
});
// The LLM sees: one tool called "codemode" with input { code: string }
// The description includes TypeScript types for all your toolsimport { createCodeTool } from "@cloudflare/codemode/ai";
const codemode = createCodeTool({
tools: myTools, // Record<string, tool()> with Zod schemas
executor, // DynamicWorkerExecutor
});
// The LLM sees: one tool called "codemode" with input { code: string }
// The description includes TypeScript types for all your toolsLLM は async アロー関数を書きます。createCodeTool はそれを正規化し、executor に渡します。executor は codemode プロキシ付きの Worker モジュールを組み立ててコードを実行し、{ code, result, logs } を返します。