跳转到内容
搜索文档

工具

最后更新 查看 MarkdownAgent 设置

Think 在每轮次提供内置工作区文件工具,并提供自定义工具、代码执行与动态扩展的集成点。

工具合并顺序

每轮次 Think 从多个来源合并工具。若名称冲突,后出现的来源覆盖较早的:

  1. 工作区工具readwriteeditlistfindgrepdeletebash(内置)
  2. getTools() — 你的自定义服务端工具
  3. 扩展工具 — 已加载扩展的工具(以扩展名前缀)
  4. 会话工具set_contextload_contextsearch_context(来自 configureSession
  5. 技能工具activate_skillread_skill_resourcerun_skill_script(来自 getSkills(),请参阅 Agent Skills
  6. MCP 工具 — 当 includeMcpToolstrue 时,来自已连接 MCP 服务器
  7. 客户端工具 — 来自浏览器(请参阅 客户端工具

工具属于执行轮次的 agent。父子编排请使用 Agent 作为工具,而非通过 chat() 传递一次性工具。

内置工作区工具

每个 Think agent 拥有 this.workspace——由 Durable Object SQLite 支持的虚拟文件系统。工作区工具自动对模型可用,无需配置。

工具 描述
read 带行号读取文本;将图片与 PDF 传给多模态模型
write 将内容写入文件(创建父目录)
edit 对现有文件应用查找替换编辑(支持模糊匹配)
list 列出路径中的文件与目录
find 按 glob 模式查找文件
grep 按正则或固定字符串搜索文件内容
delete 删除文件或目录
bash 针对工作区文件运行沙箱化 Bash 脚本

bash 工具默认启用。它将工作区文件挂载到 just-bash 虚拟文件系统,禁用网络访问,并将创建、更新、删除的文件与空目录写回工作区。适用于组合多个文件操作的 shell 式工作流;简单读写编辑请用更窄的工具。

为限制工具调用范围,Bash 工具默认快照最多 1,000 个工作区文件,并跳过大于 1 MB 的文件。跳过的文件会在工具结果中报告,写回时视为受保护,脚本无法意外覆盖或删除未挂载的内容。可通过 workspaceBash 调整 maxWorkspaceFilesmaxWorkspaceFileBytesmaxOutputBytestimeoutnetwork

保守部署可禁用默认 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 存储桶绑定(binding):

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

自定义工具

覆盖 getTools() 以添加自定义工具。这些是带 Zod schema 的标准 AI SDK tool() 定义:

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 };
			},
		}),
	};
}

needsApproval 返回 true 时,工具调用会发送到客户端等待审批。对话暂停,直到客户端以 CF_AGENT_TOOL_APPROVAL 响应。

按轮次覆盖工具

beforeTurn 钩子可限制或添加特定轮次的工具:

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

activeTools 限制模型可调用的工具。tools 仅在本轮次添加额外工具(合并到现有工具之上)。

MCP 工具

Think 从 Agent 基类继承 MCP 客户端支持。默认 Think 将已连接 MCP 服务器的工具转换为 AI SDK 工具并添加到每轮次。

设置 waitForMcpConnections 以确保推理运行前 MCP 服务器已连接:

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() 调用仍可用。

请使用此属性,而非在 beforeTurn 中通过 activeTools 移除 MCP 工具名称。Think 在调用 beforeTurn 之前转换 MCP schema,因此 activeTools 无法避免该转换。配置连接器运行时请参阅将 MCP 工具与 Code Mode 配合使用

可通过编程或 @callable 方法添加 MCP 服务器:

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 运行时上(中止并重放、人工审批、审计追踪、可复用代码片段)。需要 @cloudflare/codemodeworker_loaders 绑定(binding)。

npm install @cloudflare/codemode

一行代码从 agent 推断一切——state.* 来自 this.workspace,执行器来自 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" # 可选 — 启用 cdp.*
// worker 入口 — runtime 位于 Durable Object facet,因此必须导出类
// (@cloudflare/codemode/vite 插件会自动处理;Think 框架生成的入口已包含)
export { CodemodeRuntime } from "@cloudflare/codemode";
// worker 入口 — runtime 位于 Durable Object facet,因此必须导出类
// (@cloudflare/codemode/vite 插件会自动处理;Think 框架生成的入口已包含)
export { CodemodeRuntime } from "@cloudflare/codemode";

缺少任一部分会以命名该步骤的错误失败。

沙箱内模型可见类型化命名空间及平台 SDK:

  • tools.* — 你的 AI SDK 工具(对象参数,按 schema 验证)。仅暴露带 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 — 发现、副作用边界与保存代码片段。

超出默认项可传入覆盖——例如 agent 派生状态旁添加自定义 tools.*

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

或完全显式选项(无 agent 推断):

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,
});

审批(人机协同)

needsApproval 的 AI SDK 工具在沙箱内不会立即运行——调用会持久化暂停运行。暂停以普通工具输出返回({ status: "paused", executionId, pending }),模型告知用户所需内容,轮次结束。这与普通 getTools() 工具的客户端审批流程不同:沙箱内函数型 needsApproval 无法提前针对调用参数求值,因此保守地始终需要审批。Think 提供内置可调用方法来解决:

  • approveExecution(executionId) — 从暂停处恢复运行。已完成工作重放,不重新执行。结果替换转录中的暂停输出,聊天自动继续。
  • rejectExecution(executionId, reason?) — 以 { status: "rejected", reason } 结束运行,供模型调整。
  • pendingExecutions() — 待处理操作(含完整参数),用于渲染审批 UI。

可工作的审批卡片请参阅 assistant 示例

运行时句柄

当宿主需要的不止工具时,createExecuteRuntime 返回活动部件——从 agent 创建时句柄也会赋给 this.codemode

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

const { runtime, connectors, tool } = createExecuteRuntime(this);
await runtime.executions(); // 审计追踪
await runtime.expirePaused(); // 回收从未审批的过期暂停(从定时任务调用)
await runtime.saveSnippet("name", { executionId }); // 提升脚本供复用
import { createExecuteRuntime } from "@cloudflare/think/tools/execute";

const { runtime, connectors, tool } = createExecuteRuntime(this);
await runtime.executions(); // 审计追踪
await runtime.expirePaused(); // 回收从未审批的过期暂停(从定时任务调用)
await runtime.saveSnippet("name", { executionId }); // 提升脚本供复用

浏览器工具

为 agent 提供 Chrome DevTools Protocol (CDP) 访问,用于网页检查、抓取、截图与调试。需要 @cloudflare/codemode 与 Browser Run 绑定(binding)。

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 选择器抓取特定元素。

传入 quickActions: false 仅保留 browser_execute,或传入 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())与调试日志辅助。执行被记录以支持中止并重放,浏览器会话可在审批暂停后继续存活。

默认每次执行获得全新浏览器会话(one-shot),运行结束时拆除。传入 session: { mode: "dynamic" } 让模型用 cdp.startSession() 提升会话,后续执行在同一浏览器中继续;或 session: { mode: "reuse", key } 使用命名长生命周期会话。过期会话由连接器的 sweep() 回收——从定时任务调用。

自定义 Chrome 端点可传入 cdpUrl 替代 browser

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 connector API 请参阅浏览 Web

扩展

扩展是运行时动态加载的沙箱化 Worker,可添加工具。LLM 可编写扩展源码、加载它,并在下一轮次使用新工具。

扩展需要 worker_loaders 绑定(binding):

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(),
		};
	}
}

这会向模型提供两个工具:

  • 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";

为存储后端实现操作接口:

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,
});

这篇文档对您有帮助吗?