@cloudflare/codemode/ai エントリポイントは、AI SDK ツールを 1 つの Code Mode ツールへ変換します。モデルはツールを呼ぶ JavaScript を書き、エグゼキューターがそのコードを隔離されたサンドボックスで実行します。
次の 2 つの連携パターンから選びます。
| パターン | 用途 | 承認の動作 |
|---|---|---|
createCodeTool() |
1 つ以上のツールプロバイダーによる、単純でステートレスな実行 | needsApproval を使うツールを除外します |
ToolSetConnector または toolSetConnector() |
Code Mode ランタイム経由の耐久実行 | needsApproval を耐久ランタイムの承認へ対応付けます |
createCodeTool() は、AI SDK の ToolSet またはツールプロバイダーの配列を受け取ります。エグゼキューターも必須です。返す値は、streamText() または generateText() で使える標準の AI SDK ツールです。
-
Code Mode、AI SDK、Zod をインストールします。
npm i @cloudflare/codemode agents ai zodyarn add @cloudflare/codemode agents ai zodpnpm add @cloudflare/codemode agents ai zodbun add @cloudflare/codemode agents ai zod -
DynamicWorkerExecutor用の Worker Loader バインディングを追加します。{ "$schema": "./node_modules/wrangler/config-schema.json", // Set this to today's date "compatibility_date": "2026-09-20", "compatibility_flags": [ "nodejs_compat" ], "worker_loaders": [ { "binding": "LOADER" } ] }# Set this to today's date compatibility_date = "2026-09-20" compatibility_flags = ["nodejs_compat"] [[worker_loaders]] binding = "LOADER" -
実行可能な AI SDK ツールを定義します。Code Mode はスキーマから型を生成し、
executeを呼ぶ前に引数を検証します。src/tools.jsjs import { tool } from "ai"; import { z } from "zod"; export const weatherTools = { getWeather: tool({ description: "Get the weather for a city", inputSchema: z.object({ city: z.string().describe("City name"), }), outputSchema: z.object({ city: z.string(), conditions: z.string(), }), execute: async ({ city }) => ({ city, conditions: "sunny", }), }), };src/tools.tsts import { tool } from "ai"; import { z } from "zod"; export const weatherTools = { getWeather: tool({ description: "Get the weather for a city", inputSchema: z.object({ city: z.string().describe("City name") }), outputSchema: z.object({ city: z.string(), conditions: z.string() }), execute: async ({ city }) => ({ city, conditions: "sunny" }) }) };サンドボックスから呼べる各ツールには
execute関数が必要です。クライアント側またはプロバイダー実行のツールは、このサーバー側エグゼキューターでは動きません。 -
Code Mode ツールを作り、AI SDK のモデル呼び出しへ渡します。
src/index.jsjs import { DynamicWorkerExecutor } from "@cloudflare/codemode"; import { createCodeTool } from "@cloudflare/codemode/ai"; import { generateText, stepCountIs } from "ai"; import { model } from "./model"; import { weatherTools } from "./tools"; export default { async fetch(request, env) { const executor = new DynamicWorkerExecutor({ loader: env.LOADER }); const codemode = createCodeTool({ tools: weatherTools, executor }); const response = await generateText({ model, prompt: await request.text(), tools: { codemode }, stopWhen: stepCountIs(5), }); return new Response(response.text); }, };src/index.tsts import { DynamicWorkerExecutor } from "@cloudflare/codemode"; import { createCodeTool } from "@cloudflare/codemode/ai"; import { generateText, stepCountIs } from "ai"; import { model } from "./model"; import { weatherTools } from "./tools"; export default { async fetch(request, env): Promise<Response> { const executor = new DynamicWorkerExecutor({ loader: env.LOADER }); const codemode = createCodeTool({ tools: weatherTools, executor }); const response = await generateText({ model, prompt: await request.text(), tools: { codemode }, stopWhen: stepCountIs(5), }); return new Response(response.text); }, } satisfies ExportedHandler<Env>;
この例は完了した応答のために generateText() を使っています。同じ codemode ツールを streamText() に渡せばストリーミングできます。生成されるツールの説明には、getWeather の TypeScript 定義が含まれます。モデルが書くのは、次のような JavaScript です。
async () => {
const weather = await codemode.getWeather({ city: "Lisbon" });
return weather.conditions;
};デフォルトの名前空間は codemode です。createCodeTool() はカスタムの description も受け取ります。Code Mode が生成した定義を差し込む位置に {{types}} を入れてください。
ツールプロバイダーは、サンドボックスの 1 つの名前空間の下にツールをまとめます。すべてのツールを codemode.* の下に置くときは、ツールセットを直接渡します。
AI SDK ツールを他パッケージのプロバイダーと組み合わせるときは aiTools() を使います。次の任意のワークスペース例では @cloudflare/shell も必要です。
npm i @cloudflare/shellyarn add @cloudflare/shellpnpm add @cloudflare/shellbun add @cloudflare/shellimport { AIChatAgent } from "@cloudflare/ai-chat";
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
import { aiTools, createCodeTool } from "@cloudflare/codemode/ai";
import { Workspace } from "@cloudflare/shell";
import { stateTools } from "@cloudflare/shell/workers";
import { weatherTools } from "./tools";
export class Chat extends AIChatAgent {
workspace = new Workspace({ sql: this.ctx.storage.sql });
codemodeTool() {
return createCodeTool({
tools: [aiTools(weatherTools), stateTools(this.workspace)],
executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }),
});
}
}import { AIChatAgent } from "@cloudflare/ai-chat";
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
import { aiTools, createCodeTool } from "@cloudflare/codemode/ai";
import { Workspace } from "@cloudflare/shell";
import { stateTools } from "@cloudflare/shell/workers";
import { weatherTools } from "./tools";
export class Chat extends AIChatAgent<Env> {
workspace = new Workspace({ sql: this.ctx.storage.sql });
codemodeTool() {
return createCodeTool({
tools: [aiTools(weatherTools), stateTools(this.workspace)],
executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }),
});
}
}この例では、AI SDK ツールを codemode.*、ワークスペースツールを state.* として公開します。
カスタム名前空間を付けるときは、代わりにプロバイダーオブジェクトを渡します。
const executor = new DynamicWorkerExecutor({ loader: env.LOADER });
const codemode = createCodeTool({
tools: [
{ name: "weather", tools: weatherTools },
{ name: "notifications", tools: notificationTools },
],
executor,
});const executor = new DynamicWorkerExecutor({ loader: env.LOADER });
const codemode = createCodeTool({
tools: [
{ name: "weather", tools: weatherTools },
{ name: "notifications", tools: notificationTools },
],
executor,
});生成されたコードは weather.getWeather() と notifications.send() を呼べます。プロバイダー名は一意で、有効な JavaScript 識別子である必要があります。
実行に耐久状態が必要なときは、ToolSetConnector または便利関数 toolSetConnector() を使います。コネクターは AI SDK の ToolSet を createCodemodeRuntime() 向けに適応します。ヘルパーは new ToolSetConnector(ctx, options) を返します。
コネクターは Agent または別の Durable Object の内側で作成します。
import { AIChatAgent } from "@cloudflare/ai-chat";
import {
createCodemodeRuntime,
DynamicWorkerExecutor,
} from "@cloudflare/codemode";
import { toolSetConnector } from "@cloudflare/codemode/ai";
import { convertToModelMessages, streamText } from "ai";
import { model } from "./model";
import { operationTools } from "./tools";
// Export this manually when the @cloudflare/codemode/vite plugin is not configured.
export { CodemodeRuntime } from "@cloudflare/codemode";
export class OperationsAgent extends AIChatAgent {
async onChatMessage() {
const operations = toolSetConnector(this.ctx, {
name: "operations",
instructions: "Use these tools to manage customer requests.",
tools: operationTools,
});
const runtime = createCodemodeRuntime({
ctx: this.ctx,
executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }),
connectors: [operations],
});
const result = streamText({
model,
messages: await convertToModelMessages(this.messages),
tools: { codemode: runtime.tool() },
});
return result.toUIMessageStreamResponse();
}
}import { AIChatAgent } from "@cloudflare/ai-chat";
import {
createCodemodeRuntime,
DynamicWorkerExecutor,
} from "@cloudflare/codemode";
import { toolSetConnector } from "@cloudflare/codemode/ai";
import { convertToModelMessages, streamText } from "ai";
import { model } from "./model";
import { operationTools } from "./tools";
// Export this manually when the @cloudflare/codemode/vite plugin is not configured.
export { CodemodeRuntime } from "@cloudflare/codemode";
export class OperationsAgent extends AIChatAgent<Env> {
async onChatMessage() {
const operations = toolSetConnector(this.ctx, {
name: "operations",
instructions: "Use these tools to manage customer requests.",
tools: operationTools,
});
const runtime = createCodemodeRuntime({
ctx: this.ctx,
executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }),
connectors: [operations],
});
const result = streamText({
model,
messages: await convertToModelMessages(this.messages),
tools: { codemode: runtime.tool() },
});
return result.toUIMessageStreamResponse();
}
}この例では CodemodeRuntime を手でエクスポートしています。耐久 Code Mode ランタイムを作る のとおりに Code Mode の Vite プラグインを設定している場合は、プラグインが追加するため、この手動エクスポートを削除します。
name を省略すると、コネクターはデフォルトで tools 名前空間を使います。execute 関数のないツールは、生成型とサンドボックスバインディングの両方から除外されます。
耐久ランタイムは実行ログ、一時停止と再開、オンデマンドのコネクター発見を追加します。モデルは codemode.search() でメソッドを探し、codemode.describe() で型を確認できます。
2 つの連携パターンは、AI SDK の承認を別の方法で扱います。
createCodeTool() は、needsApproval が true または関数であるツールを除外します。除外されたツールは生成型に現れず、サンドボックスコードから実行できません。needsApproval: false のツールは利用可能なままです。
このステートレス経路は、AI SDK の承認のために実行を一時停止しません。AI SDK の承認フローが必要なツールは、Code Mode の外で標準の AI SDK ツールとして使います。
ToolSetConnector は、AI SDK の needsApproval を耐久ランタイムの requiresApproval アノテーションへ対応付けます。そのツールを呼ぶと実行が一時停止します。アプリケーションは保留中のアクションを確認し、runtime.approve({ executionId }) で同じ実行を再開できます。
関数値の needsApproval は、サンドボックスが引数を渡す前に評価できません。そのためコネクターは、そのツールを常に承認必須として扱います。needsApproval: false は一時停止せず実行します。
この承認は、Code Mode ランタイムの耐久的な一時停止、承認、リプレイフローを使います。AI SDK の呼び出し単位の承認フローは使いません。