Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

AI SDK 連携

最終更新 Markdown で表示Agent セットアップ

@cloudflare/codemode/ai エントリポイントは、AI SDK ツールを 1 つの Code Mode ツールへ変換します。モデルはツールを呼ぶ JavaScript を書き、エグゼキューターがそのコードを隔離されたサンドボックスで実行します。

次の 2 つの連携パターンから選びます。

パターン 用途 承認の動作
createCodeTool() 1 つ以上のツールプロバイダーによる、単純でステートレスな実行 needsApproval を使うツールを除外します
ToolSetConnector または toolSetConnector() Code Mode ランタイム経由の耐久実行 needsApproval を耐久ランタイムの承認へ対応付けます

ステートレスな Code Mode ツールを作る

createCodeTool() は、AI SDK の ToolSet またはツールプロバイダーの配列を受け取ります。エグゼキューターも必須です。返す値は、streamText() または generateText() で使える標準の AI SDK ツールです。

  1. Code Mode、AI SDK、Zod をインストールします。

    npm i @cloudflare/codemode agents ai zod
  2. 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"
  3. 実行可能な 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 関数が必要です。クライアント側またはプロバイダー実行のツールは、このサーバー側エグゼキューターでは動きません。

  4. 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/shell
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 {
	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 識別子である必要があります。

耐久ランタイムで AI SDK ツールを使う

実行に耐久状態が必要なときは、ToolSetConnector または便利関数 toolSetConnector() を使います。コネクターは AI SDK の ToolSetcreateCodemodeRuntime() 向けに適応します。ヘルパーは new ToolSetConnector(ctx, options) を返します。

コネクターは Agent または別の Durable Object の内側で作成します。

src/server.jsjs
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();
	}
}
src/server.tsts
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() の承認

createCodeTool() は、needsApprovaltrue または関数であるツールを除外します。除外されたツールは生成型に現れず、サンドボックスコードから実行できません。needsApproval: false のツールは利用可能なままです。

このステートレス経路は、AI SDK の承認のために実行を一時停止しません。AI SDK の承認フローが必要なツールは、Code Mode の外で標準の AI SDK ツールとして使います。

ToolSetConnector の承認

ToolSetConnector は、AI SDK の needsApproval を耐久ランタイムの requiresApproval アノテーションへ対応付けます。そのツールを呼ぶと実行が一時停止します。アプリケーションは保留中のアクションを確認し、runtime.approve({ executionId }) で同じ実行を再開できます。

関数値の needsApproval は、サンドボックスが引数を渡す前に評価できません。そのためコネクターは、そのツールを常に承認必須として扱います。needsApproval: false は一時停止せず実行します。

この承認は、Code Mode ランタイムの耐久的な一時停止、承認、リプレイフローを使います。AI SDK の呼び出し単位の承認フローは使いません。

役に立ちましたか?