INTEGRITY Документация

Инструменты

На каждом ходу Think предоставляет встроенные инструменты для работы с файлами workspace, а также точки интеграции для собственных инструментов, выполнения кода и динамических расширений.

Порядок объединения инструментов

При каждом ходе Think объединяет инструменты из нескольких источников. Более поздние источники переопределяют более ранние, если имена совпадают:

  1. Инструменты рабочей области, read, write, edit, list, find, grep, delete, bash (встроенный)
  2. getTools() : ваши собственные инструменты на стороне сервера
  3. Инструменты расширений : инструменты из загруженных расширений (с префиксом по названию расширения)
  4. Инструменты Session, set_context, load_context, search_context (от configureSession)
  5. Инструменты skills, activate_skill, read_skill_resource, run_skill_script (от getSkills(), см. Agent Skills)
  6. MCP-инструменты : из подключённых MCP-серверов, когда includeMcpTools это true
  7. Клиентские инструменты : из браузера (см. Клиентские инструменты)

Инструменты принадлежат агенту, который выполняет ход. Для оркестрации родитель/потомок используйте Agents как инструменты вместо передачи одноразовых инструментов через chat().

Встроенные инструменты рабочего пространства

Каждый Think agent получает this.workspace : виртуальная файловая система на базе SQLite в Durable Object. Инструменты workspace автоматически доступны модели без какой-либо настройки.

Инструмент Описание
read Считывайте текст с номерами строк; передавайте изображения и PDF мультимодальным моделям
write Записать содержимое в файл (создаёт родительские каталоги)
edit Применить правку типа «найти и заменить» к существующему файлу (поддерживает нечёткое сопоставление)
list Выводит список файлов и каталогов по указанному пути
find Найдите файлы, соответствующие glob-шаблону
grep Поиск в содержимом файлов по регулярному выражению или фиксированной строке
delete Удалить файл или каталог
bash Запуск изолированного скрипта Bash для файлов рабочего пространства

bash инструмент включён по умолчанию. Он монтирует файлы рабочего пространства в just-bash виртуальную файловую систему, выполняется с отключённым доступом к сети и записывает созданные, изменённые и удалённые файлы, а также пустые каталоги обратно в рабочее пространство. Используйте его для рабочих процессов в стиле shell, которые объединяют несколько файловых операций; для простых операций чтения, записи и редактирования используйте более узкоспециализированные инструменты.

Чтобы ограничить объём вызовов инструмента, инструмент Bash по умолчанию делает снимок не более 1000 файлов рабочей области и пропускает файлы крупнее 1 МБ. Пропущенные файлы указываются в результате инструмента и считаются защищёнными при обратной записи, поэтому скрипт не может случайно перезаписать или удалить содержимое, которое не было смонтировано. Вы можете настроить maxWorkspaceFiles, maxWorkspaceFileBytes, maxOutputBytes, timeout, а также network через workspaceBash.

Для консервативных развёртываний отключите используемый по умолчанию инструмент 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 };
			},
		}),
	};
}

Когда needsApproval возвращает true, вызов инструмента отправляется клиенту на подтверждение. Разговор приостанавливается, пока клиент не ответит CF_AGENT_TOOL_APPROVAL.

Переопределения инструментов для отдельного хода

beforeTurn хук может ограничивать или добавлять инструменты для конкретного хода:

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

activeTools ограничивает, какие инструменты может вызывать модель. tools добавляет дополнительные инструменты только для этого хода (объединяются с уже существующими инструментами).

MCP-инструменты

Think наследует поддержку MCP-клиента от Agent базовый класс. По умолчанию 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() {
		/* ... */
	}
}

Если вы предоставляете инструменты MCP через Code Mode или другим способом за пределами автоматического набора инструментов Think, отключите прямое предоставление инструментов 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() вызовы продолжают работать.

Используйте это свойство вместо удаления имён инструментов MCP через activeTools в beforeTurn. Think преобразует схемы MCP перед вызовом beforeTurn, поэтому activeTools не может избежать этого преобразования. Чтобы настроить runtime коннектора, см. Используйте инструменты MCP с Code Mode.

Добавьте 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 писать и выполнять JavaScript в изолированном Worker, фиксируя всё в устойчивой среде выполнения Code Mode (прерывание с повтором, подтверждения человеком, журнал аудита, переиспользуемые сниппеты). Требует @cloudflare/codemode и worker_loaders привязку.

npm install @cloudflare/codemode

Однострочник выводит всё необходимое из агента: 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.* наряду с состоянием, производным от агента:

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)

Инструмент AI SDK с needsApproval не выполняется сразу внутри песочницы: вызов этого устойчиво приостанавливает запуск. Пауза возвращается как обычный результат инструмента ({ status: "paused", executionId, pending }), модель сообщает пользователю, что ей нужно, и ход завершается. Это отличается от клиентского процесса подтверждения для обычного getTools() инструменты: внутри sandbox функциональное значение needsApproval нельзя заранее вычислить относительно аргументов вызова, поэтому из осторожности всегда требует подтверждения. Think поставляется со встроенными callable-объектами для его разрешения:

Рабочий пример карточки подтверждения см. в assistant пример ↗.

Хендл runtime

createExecuteRuntime возвращает внутренние компоненты, когда host нуждается в большем, чем просто инструмент, а handle также присваивается 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

Инструменты браузера

Предоставьте своему агенту доступ к 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"

Это добавляет устойчивый CDP-инструмент, а также инструмент без сохранения состояния Quick Action инструменты, когда browser привязка присутствует:

Инструмент Описание
browser_execute Выполняйте JavaScript в живом браузере через CDP (снимки экрана, чтение DOM, выполнение JS).
browser_markdown Прочитайте страницу или необработанный HTML как Markdown.
browser_extract Извлекайте структурированные данные со страницы с помощью ИИ.
browser_links Выводит список ссылок на странице.
browser_scrape Извлекайте определённые элементы по CSS-селектору.

Передайте quickActions: false чтобы оставить только browser_execute, либо передайте quickActions: { actions, maxChars, options } чтобы настроить инструменты без сохранения состояния. Инструменты Quick Action используют общий browser привязку, не нуждаются в Worker Loader и разрешают ctx из текущего Agent автоматически. Чтобы использовать только инструменты без сохранения состояния, импортируйте createQuickActionTools от @cloudflare/think/tools/browser.

Инструмент работает на основе runtime Code Mode с cdp коннектор: модель пишет асинхронные arrow-функции, которые выполняются в изолированной среде Worker isolate, с 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,
});

Полное описание API CDP-коннектора см. в Просматривать веб.

Расширения

Расширения представляют собой динамически загружаемые sandbox Workers, которые добавляют инструменты во время выполнения. 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(),
		};
	}
}

Это даёт модели два инструмента:

Блоки контекста расширения

Расширения могут объявлять блоки контекста в своём манифесте. Они автоматически регистрируются в 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 (разделённые на пространства имён по названию расширения).

Пользовательские бэкенды рабочего пространства

Отдельные factory для инструментов экспортируются для использования с собственными backend хранения:

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