Skip to content

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

ツール

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

Think は、各ターンで組み込みのワークスペースファイルツールを提供します。加えて、カスタムツール、コード実行、動的拡張の連携ポイントがあります。

ツールのマージ順

各ターンで、Think は複数ソースのツールをマージします。名前が衝突した場合は、後のソースが先のソースを上書きします。

  1. ワークスペースツールreadwriteeditlistfindgrepdeletebash(組み込み)
  2. getTools() — 独自のサーバー側ツール
  3. 拡張ツール — 読み込んだ拡張のツール(拡張名でプレフィックス)
  4. セッションツールset_contextload_contextsearch_contextconfigureSession から)
  5. スキルツールactivate_skillread_skill_resourcerun_skill_scriptgetSkills() から。 Agent Skills を参照)
  6. MCP ツールincludeMcpToolstrue のとき、接続中の MCP サーバーから
  7. クライアントツール — ブラウザから(クライアントツール を参照)

ツールは、そのターンを実行しているエージェントに属します。親子のオーケストレーションでは、chat() に単発ツールを渡すのではなく Agents as tools を使います。

組み込みワークスペースツール

すべての Think エージェントは this.workspace を持ちます。Durable Object の SQLite を裏にした仮想ファイルシステムです。ワークスペースツールは設定なしで、モデルから自動で使えます。

ツール 説明
read 行番号付きでテキストを読みます。画像と PDF はマルチモーダルモデルへ渡せます
write ファイルへ内容を書き込みます(親ディレクトリを作成します)
edit 既存ファイルに検索置換の編集を適用します(ファジーマッチ対応)
list パス内のファイルとディレクトリを一覧します
find glob パターンに合うファイルを探します
grep 正規表現または固定文字列でファイル内容を検索します
delete ファイルまたはディレクトリを削除します
bash ワークスペースファイルに対して、サンドボックス内の Bash スクリプトを実行します

bash ツールはデフォルトで有効です。ワークスペースファイルを just-bash 仮想ファイルシステムにマウントし、ネットワークなしで実行し、作成・更新・削除したファイルと空ディレクトリをワークスペースへ書き戻します。複数のファイル操作を組み合わせるシェル風ワークフローに使います。単純な読み取り、書き込み、編集には、より狭いツールを使います。

ツール呼び出しを抑えるため、Bash ツールはデフォルトで最大 1,000 件のワークスペースファイルをスナップショットし、1 MB 超のファイルはスキップします。スキップしたファイルはツール結果に報告され、書き戻し時は保護扱いになります。マウントされていない内容をスクリプトが誤って上書き・削除しないようにするためです。maxWorkspaceFilesmaxWorkspaceFileBytesmaxOutputBytestimeoutnetworkworkspaceBash で調整できます。

保守的なデプロイでは、デフォルトの Bash ツールを無効にします。

export class MyAgent extends Think {
	workspaceBash = false;

	getModel() {
		/* ... */
	}
}
export class MyAgent extends Think<Env> {
	workspaceBash = false;

	getModel() {
		/* ... */
	}
}

R2 への退避

デフォルトでは、ワークスペースはすべてを SQLite に保存します。大きなファイルでは、workspace をオーバーライドして R2 への退避を追加します。

import { Think } from "@cloudflare/think";
import { Workspace } from "@cloudflare/shell";

export class MyAgent extends Think {
	workspace = new Workspace({
		sql: this.ctx.storage.sql,
		r2: this.env.R2,
		name: () => this.name,
	});

	getModel() {
		/* ... */
	}
}
import { Think } from "@cloudflare/think";
import { Workspace } from "@cloudflare/shell";

export class MyAgent extends Think<Env> {
	override workspace = new Workspace({
		sql: this.ctx.storage.sql,
		r2: this.env.R2,
		name: () => this.name,
	});

	getModel() {
		/* ... */
	}
}

これには R2 バケットバインディングが必要です。

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "r2_buckets": [
    {
      "binding": "R2",
      "bucket_name": "agent-files"
    }
  ]
}
[[r2_buckets]]
binding = "R2"
bucket_name = "agent-files"

カスタムツール

getTools() をオーバーライドして独自ツールを追加します。標準の AI SDK tool() 定義で、Zod や Valibot などのライブラリからスキーマを付けます。

import { Think } from "@cloudflare/think";
import { tool } from "ai";

import { z } from "zod";

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}

	getTools() {
		return {
			getWeather: tool({
				description: "Get the current weather for a city",
				inputSchema: z.object({
					city: z.string().describe("City name"),
				}),
				execute: async ({ city }) => {
					const res = await fetch(
						`https://api.weather.com/v1/current?q=${city}&key=${this.env.WEATHER_KEY}`,
					);
					return res.json();
				},
			}),
		};
	}
}
import { Think } from "@cloudflare/think";
import { tool } from "ai";
import type { ToolSet } from "ai";
import { z } from "zod";

export class MyAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	getTools(): ToolSet {
		return {
			getWeather: tool({
				description: "Get the current weather for a city",
				inputSchema: z.object({
					city: z.string().describe("City name"),
				}),
				execute: async ({ city }) => {
					const res = await fetch(
						`https://api.weather.com/v1/current?q=${city}&key=${this.env.WEATHER_KEY}`,
					);
					return res.json();
				},
			}),
		};
	}
}

カスタムツールはワークスペースツールと自動でマージされます。カスタムツールとワークスペースツールが同名なら、カスタムツールが勝ちます。

ツール承認

needsApproval オプションで、実行前にユーザー承認を必須にできます。

getTools(): ToolSet {
	return {
		deleteFile: tool({
			description: "Delete a file from the system",
			inputSchema: z.object({ path: z.string() }),
			needsApproval: async ({ path }) => path.startsWith("/important/"),
			execute: async ({ path }) => {
				await this.workspace.rm(path);
				return { deleted: path };
			},
		}),
	};
}

needsApprovaltrue を返すと、ツール呼び出しは承認のためクライアントへ送られます。クライアントが CF_AGENT_TOOL_APPROVAL で応答するまで、会話は一時停止します。

ターン単位のツール上書き

beforeTurn フックは、特定のターン向けにツールを制限または追加できます。

beforeTurn(ctx: TurnContext) {
	return {
		activeTools: ["read", "write", "getWeather"],
		tools: { emergencyTool: this.createEmergencyTool() },
	};
}

activeTools は、モデルが呼べるツールを制限します。tools は、このターンだけ追加のツールを足します(既存ツールの上にマージされます)。

MCP ツール

Think は Agent 基底クラスから MCP クライアント対応を継承します。デフォルトでは、接続中の MCP サーバーのツールを AI SDK ツールへ変換し、各ターンに追加します。

推論の前に MCP サーバーがつながるよう、waitForMcpConnections を設定します。

export class MyAgent extends Think {
	waitForMcpConnections = true; // default 10s timeout
	// or: waitForMcpConnections = { timeout: 5000 };

	getModel() {
		/* ... */
	}
}
export class MyAgent extends Think<Env> {
	waitForMcpConnections = true; // default 10s timeout
	// or: waitForMcpConnections = { timeout: 5000 };

	getModel() {
		/* ... */
	}
}

Code Mode など、Think の自動ツールセット以外で MCP ツールを出す場合は、AI SDK への直接公開をオフにします。

export class MyAgent extends Think {
	includeMcpTools = false;
	waitForMcpConnections = true;

	getModel() {
		/* ... */
	}
}
export class MyAgent extends Think<Env> {
	includeMcpTools = false;
	waitForMcpConnections = true;

	getModel() {
		/* ... */
	}
}

includeMcpTools が制御するのは、自動のモデルツールマージだけです。MCP 接続の登録、復元、発見、待機は続きます。生のカタログアクセス、直接呼び出し、Code Mode コネクタ、明示的な this.mcp.getAITools() 呼び出しも動きます。

beforeTurnactiveTools で MCP ツール名を外す代わりに、このプロパティを使います。Think は beforeTurn を呼ぶ前に MCP スキーマを変換するため、activeTools ではその変換を避けられません。コネクタランタイムの設定は Code Mode で MCP ツールを使う を参照してください。

MCP サーバーはプログラムから、または @callable メソッド経由で追加します。

import { callable } from "agents";

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}

	@callable()
	async addServer(name, url) {
		return await this.addMcpServer(name, url);
	}

	@callable()
	async removeServer(serverId) {
		await this.removeMcpServer(serverId);
	}
}
import { callable } from "agents";

export class MyAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	@callable()
	async addServer(name: string, url: string) {
		return await this.addMcpServer(name, url);
	}

	@callable()
	async removeServer(serverId: string) {
		await this.removeMcpServer(serverId);
	}
}

コード実行ツール

LLM に、サンドボックス Worker 内で JavaScript を書いて実行させます。耐久的な Code Mode ランタイムに記録されます(abort-and-replay、人間の承認、監査証跡、再利用可能なスニペット)。@cloudflare/codemodeworker_loaders バインディングが必要です。

npm install @cloudflare/codemode

1 行で、エージェントからすべてを推論します。state.*this.workspace、executor は env.LOADER、ライブブラウザ(cdp.*)はバインドされていれば env.BROWSER です。

import { Think } from "@cloudflare/think";
import { createExecuteTool } from "@cloudflare/think/tools/execute";

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}

	getTools() {
		return {
			execute: createExecuteTool(this),
		};
	}
}
import { Think } from "@cloudflare/think";
import { createExecuteTool } from "@cloudflare/think/tools/execute";

export class MyAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	getTools() {
		return {
			execute: createExecuteTool(this),
		};
	}
}

セットアップのチェックリストです。

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "worker_loaders": [
    {
      "binding": "LOADER"
    }
  ],
  "browser": {
    "binding": "BROWSER"
  }
}
[[worker_loaders]]
binding = "LOADER"

[browser]
binding = "BROWSER" # optional — enables cdp.*
// worker entry — the runtime lives in a Durable Object facet, so the class
// must be exported (the @cloudflare/codemode/vite plugin does this
// automatically; the Think framework's generated entry already includes it)
export { CodemodeRuntime } from "@cloudflare/codemode";
// worker entry — the runtime lives in a Durable Object facet, so the class
// must be exported (the @cloudflare/codemode/vite plugin does this
// automatically; the Think framework's generated entry already includes it)
export { CodemodeRuntime } from "@cloudflare/codemode";

欠けている部品は、その手順名を含むエラーで失敗します。

サンドボックス内で、モデルは型付き名前空間とプラットフォーム SDK を見ます。

  • tools.* — 独自の AI SDK ツール(オブジェクト引数、スキーマで検証)。execute 関数があるツールだけ公開されます。クライアント側ツールはサンドボックスでは動きません。
  • state.* — ワークスペースファイルシステム(state.readFile({ path })state.glob({ pattern })state.planEdits(...) など)。
  • cdp.* — Browser Run バインディングがあるときのブラウザ。execute ツールのデフォルトは session: { mode: "dynamic" } です。セッションは実行単位です。モデルが cdp.startSession() で昇格した場合を除きます。
  • codemode.search / codemode.describe / codemode.step / codemode.run — 発見、副作用の境界、保存済みスニペット。

デフォルト以外はオーバーライドを渡します。たとえば、エージェント由来の状態と並べて独自の tools.* を足します。

execute: createExecuteTool(this, { tools: myDomainTools });
execute: createExecuteTool(this, { tools: myDomainTools });

または、エージェント推論なしの完全に明示的なオプションです。

import { createWorkspaceStateBackend } from "@cloudflare/shell";

createExecuteTool({
	ctx: this.ctx,
	tools: myDomainTools,
	state: createWorkspaceStateBackend(this.workspace),
	browser: this.env.BROWSER,
	loader: this.env.LOADER,
});
import { createWorkspaceStateBackend } from "@cloudflare/shell";

createExecuteTool({
	ctx: this.ctx,
	tools: myDomainTools,
	state: createWorkspaceStateBackend(this.workspace),
	browser: this.env.BROWSER,
	loader: this.env.LOADER,
});

承認(Human-in-the-loop)

needsApproval 付きの AI SDK ツールは、サンドボックス内ですぐには動きません。呼ぶと 実行を耐久的に一時停止します。一時停止は通常のツール出力({ status: "paused", executionId, pending })として返り、モデルがユーザーへ必要な内容を伝え、ターンが終わります。通常の getTools() ツールのクライアント側承認フローとは違います。サンドボックス内では、関数値の needsApproval を呼び出し引数に対して事前評価できないため、保守的に 常に 承認が必要です。Think は解決用の組み込み callable を同梱します。

  • approveExecution(executionId) — 止まった位置から実行を再開します。完了済みの作業は再生され、再実行されません。結果がトランスクリプトの一時停止出力を置き換え、チャットが自動継続します。
  • rejectExecution(executionId, reason?){ status: "rejected", reason } で実行を終え、モデルが対応できるようにします。
  • pendingExecutions() — 承認 UI 描画用の保留中アクション(引数つき)です。

動く承認カードは assistant の例 を参照してください。

ランタイムハンドル

ホストがツール以上の部品を必要とするとき、createExecuteRuntime が動く部分を返します。エージェントから作った場合、ハンドルは this.codemode にも割り当てられます。

import { createExecuteRuntime } from "@cloudflare/think/tools/execute";

const { runtime, connectors, tool } = createExecuteRuntime(this);
await runtime.executions(); // audit trail
await runtime.expirePaused(); // reclaim stale never-approved pauses (call from a scheduled task)
await runtime.saveSnippet("name", { executionId }); // promote a script for reuse
import { createExecuteRuntime } from "@cloudflare/think/tools/execute";

const { runtime, connectors, tool } = createExecuteRuntime(this);
await runtime.executions(); // audit trail
await runtime.expirePaused(); // reclaim stale never-approved pauses (call from a scheduled task)
await runtime.saveSnippet("name", { executionId }); // promote a script for reuse

ブラウザツール

Web ページの検査、スクレイピング、スクリーンショット、デバッグのため、エージェントに Chrome DevTools Protocol(CDP)へのアクセスを渡します。@cloudflare/codemode と Browser Run バインディングが必要です。

import { Think } from "@cloudflare/think";
import { createBrowserTools } from "@cloudflare/think/tools/browser";

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}

	getTools() {
		return {
			...createBrowserTools({
				ctx: this.ctx,
				browser: this.env.BROWSER,
				loader: this.env.LOADER,
			}),
		};
	}
}
import { Think } from "@cloudflare/think";
import { createBrowserTools } from "@cloudflare/think/tools/browser";

export class MyAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	getTools() {
		return {
			...createBrowserTools({
				ctx: this.ctx,
				browser: this.env.BROWSER,
				loader: this.env.LOADER,
			}),
		};
	}
}
{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "browser": {
    "binding": "BROWSER"
  },
  "worker_loaders": [
    {
      "binding": "LOADER"
    }
  ]
}
[browser]
binding = "BROWSER"

[[worker_loaders]]
binding = "LOADER"

browser バインディングがあるとき、耐久的な CDP ツールに加え、ステートレスな Quick Action ツールが追加されます。

ツール 説明
browser_execute CDP 経由でライブブラウザに対して JavaScript を実行します(スクリーンショット、DOM 読み取り、JS 評価)。
browser_markdown ページまたは生 HTML を Markdown として読みます。
browser_extract AI でページから構造化データを抽出します。
browser_links ページ上のリンクを一覧します。
browser_scrape CSS セレクタで特定の要素をスクレイピングします。

browser_execute だけ残す場合は quickActions: false を渡します。ステートレスツールを設定する場合は quickActions: { actions, maxChars, options } を渡します。Quick Action ツールは browser バインディングを共有し、Worker Loader は不要で、現在の Agent から ctx を自動解決します。ステートレスツールだけ使う場合は、@cloudflare/think/tools/browser から createQuickActionTools をインポートします。

このツールは cdp コネクタ付きの Code Mode ランタイムが裏にあります。モデルは、サンドボックス Worker isolate で動く async アロー関数を書き、cdp.send()cdp.attachToTarget()cdp.spec()(ライブで正規化したプロトコル記述)、セッションヘルパー(cdp.startSession()cdp.sessionInfo()cdp.closeSession())、デバッグログヘルパーを使います。実行は abort-and-replay 用に記録されるので、ブラウザセッションは承認の一時停止を越えて残ります。

デフォルトでは、各実行が新しいブラウザセッション(one-shot)を受け、実行終了時に破棄されます。後続の実行を同じブラウザで続ける場合は session: { mode: "dynamic" } を渡し、モデルが cdp.startSession() でセッションを昇格できるようにします。名前付きの長寿命セッションには session: { mode: "reuse", key } を使います。古いセッションはコネクタの sweep() が回収します。スケジュールタスクから呼んでください。

独自の Chrome エンドポイントでは、browser の代わりに cdpUrl を渡します。

createBrowserTools({
	ctx: this.ctx,
	cdpUrl: "http://localhost:9222",
	loader: this.env.LOADER,
});
createBrowserTools({
	ctx: this.ctx,
	cdpUrl: "http://localhost:9222",
	loader: this.env.LOADER,
});

CDP コネクタ API の全体は Web を閲覧する を参照してください。

拡張

拡張は、実行時にツールを足す、動的読み込みのサンドボックス Worker です。LLM は拡張のソースコードを書き、読み込み、次のターンで新しいツールを使えます。

拡張には worker_loaders バインディングが必要です。

import { Think } from "@cloudflare/think";

export class MyAgent extends Think {
	extensionLoader = this.env.LOADER;

	getModel() {
		/* ... */
	}
}
import { Think } from "@cloudflare/think";

export class MyAgent extends Think<Env> {
	extensionLoader = this.env.LOADER;

	getModel() {
		/* ... */
	}
}

静的拡張

起動時に読み込む拡張を定義します。

export class MyAgent extends Think {
	extensionLoader = this.env.LOADER;

	getModel() {
		/* ... */
	}

	getExtensions() {
		return [
			{
				manifest: {
					name: "math",
					version: "1.0.0",
					permissions: { network: false },
				},
				source: `({
					tools: {
						add: {
							description: "Add two numbers",
							parameters: { a: { type: "number" }, b: { type: "number" } },
							execute: async ({ a, b }) => ({ result: a + b })
						}
					}
				})`,
			},
		];
	}
}
export class MyAgent extends Think<Env> {
	extensionLoader = this.env.LOADER;

	getModel() {
		/* ... */
	}

	getExtensions() {
		return [
			{
				manifest: {
					name: "math",
					version: "1.0.0",
					permissions: { network: false },
				},
				source: `({
					tools: {
						add: {
							description: "Add two numbers",
							parameters: { a: { type: "number" }, b: { type: "number" } },
							execute: async ({ a, b }) => ({ result: a + b })
						}
					}
				})`,
			},
		];
	}
}

拡張ツールは名前空間化されます。math 拡張の add ツールは、モデルのツールセットでは math_add になります。

LLM 駆動の拡張

モデルに createExtensionTools を渡し、拡張を動的に読み込めるようにします。

import { createExtensionTools } from "@cloudflare/think/tools/extensions";

export class MyAgent extends Think {
	extensionLoader = this.env.LOADER;

	getModel() {
		/* ... */
	}

	getTools() {
		return {
			...createExtensionTools({ manager: this.extensionManager }),
			...this.extensionManager.getTools(),
		};
	}
}
import { createExtensionTools } from "@cloudflare/think/tools/extensions";

export class MyAgent extends Think<Env> {
	extensionLoader = this.env.LOADER;

	getModel() {
		/* ... */
	}

	getTools() {
		return {
			...createExtensionTools({ manager: this.extensionManager! }),
			...this.extensionManager!.getTools(),
		};
	}
}

これでモデルは次の 2 つのツールを得ます。

  • load_extension — JavaScript ソースから新しい拡張を読み込みます
  • list_extensions — 現在読み込まれている拡張を一覧します

拡張のコンテキストブロック

拡張はマニフェストでコンテキストブロックを宣言できます。これらは Session に自動登録されます。

getExtensions() {
	return [{
		manifest: {
			name: "notes",
			version: "1.0.0",
			permissions: { network: false },
			context: [
				{ label: "scratchpad", description: "Extension scratch space", maxTokens: 500 },
			],
		},
		source: `({ tools: { /* ... */ } })`,
	}];
}

コンテキストブロックは notes_scratchpad として登録されます(拡張名で名前空間化されます)。

カスタムワークスペースバックエンド

個別のツールファクトリは、カスタムストレージバックエンド向けにエクスポートされています。

import {
	createReadTool,
	createWriteTool,
	createEditTool,
	createListTool,
	createFindTool,
	createGrepTool,
	createDeleteTool,
	createWorkspaceTools,
} from "@cloudflare/think/tools/workspace";
import {
	createReadTool,
	createWriteTool,
	createEditTool,
	createListTool,
	createFindTool,
	createGrepTool,
	createDeleteTool,
	createWorkspaceTools,
} from "@cloudflare/think/tools/workspace";

ストレージバックエンド向けに operations インターフェイスを実装します。

const myReadOps = {
	readFile: async (path) => fetchFromMyStorage(path),
	stat: async (path) => getFileInfo(path),
};

const readTool = createReadTool({ ops: myReadOps });
import type { ReadOperations } from "@cloudflare/think/tools/workspace";

const myReadOps: ReadOperations = {
	readFile: async (path) => fetchFromMyStorage(path),
	stat: async (path) => getFileInfo(path),
};

const readTool = createReadTool({ ops: myReadOps });

または Workspace から一式を作ります。Bash ツールは任意で無効にできます。

import { createWorkspaceTools } from "@cloudflare/think/tools/workspace";

const tools = createWorkspaceTools(myCustomWorkspace);
const toolsWithoutBash = createWorkspaceTools(myCustomWorkspace, {
	bash: false,
});
import { createWorkspaceTools } from "@cloudflare/think/tools/workspace";

const tools = createWorkspaceTools(myCustomWorkspace);
const toolsWithoutBash = createWorkspaceTools(myCustomWorkspace, {
	bash: false,
});

役に立ちましたか?