← Создание агентов на Cloudflare / agents / tools / codemode
Интеграция AI SDK
@cloudflare/codemode/ai точка входа преобразует инструменты AI SDK в один инструмент Code Mode. Модель пишет код JavaScript, который вызывает ваши инструменты, а исполнитель выполняет этот код в изолированной песочнице.
Выберите один из двух паттернов интеграции:
| Шаблон | Сценарий использования | Поведение подтверждения |
|---|---|---|
createCodeTool() |
Простое выполнение без сохранения состояния с одним или несколькими поставщиками инструментов | Исключает инструменты, использующие needsApproval |
ToolSetConnector или toolSetConnector() |
Устойчивое выполнение через рантайм Code Mode | Сопоставляет needsApproval к одобрению в устойчивом runtime |
Создайте инструмент Code Mode без сохранения состояния
createCodeTool() принимает AI SDK ToolSet или массив провайдеров инструментов. Также требуется executor. Возвращает стандартный инструмент AI SDK для использования с streamText() или generateText().
-
Установите Code Mode, AI SDK и Zod:
npm i @cloudflare/codemode agents ai zod -
Добавьте привязку Worker Loader для
DynamicWorkerExecutor:{ "$schema": "./node_modules/wrangler/config-schema.json", // Set this to today's date "compatibility_date": "2026-08-28", "compatibility_flags": [ "nodejs_compat" ], "worker_loaders": [ { "binding": "LOADER" } ] }# Set this to today's date compatibility_date = "2026-08-28" compatibility_flags = ["nodejs_compat"] [[worker_loaders]] binding = "LOADER" -
Определите исполняемые инструменты AI SDK. Code Mode использует их схемы, чтобы сгенерировать типы и проверить аргументы перед вызовом
execute.src/tools.jsimport { 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.tsimport { 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.jsimport { 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.tsimport { 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() для потоковой передачи. Сгенерированное описание инструмента включает определения TypeScript для getWeather. Модель по-прежнему пишет JavaScript, например:
async () => {
const weather = await codemode.getWeather({ city: "Lisbon" });
return weather.conditions;
};Пространство имён по умолчанию: codemode. createCodeTool() также принимает пользовательский description. Включите {{types}} в этом описании, куда Code Mode должен вставить сгенерированные определения.
Организуйте инструменты с помощью провайдеров
Tool provider группирует инструменты под одним sandbox-пространством имён. Передавайте набор инструментов напрямую, если каждый инструмент относится к codemode.*.
Используйте aiTools() при объединении инструментов AI SDK с провайдерами из других пакетов. Следующий необязательный пример с рабочей областью также требует @cloudflare/shell:
npm i @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.
Используйте инструменты AI SDK с устойчивым runtime
Используйте 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 Vite, как описано в Создайте устойчивый рантайм Code Mode, удалите этот ручной экспорт, потому что плагин добавляет его сам.
Коннектор по умолчанию использует tools пространство имён, когда name не задан. Из результата исключаются инструменты без execute функцию как из сгенерированных типов, так и из привязок песочницы.
Устойчивый runtime добавляет журнал выполнения, поведение приостановки и возобновления, а также обнаружение коннекторов по запросу. Модель может находить методы с помощью codemode.search() и проверьте их типы с помощью codemode.describe().
Поведение подтверждения
Два паттерна интеграции по-разному обрабатывают подтверждения AI SDK.
createCodeTool() подтверждения
createCodeTool() отфильтровывает инструменты, у которых needsApproval это true или функцию. Отфильтрованные инструменты не появляются в сгенерированных типах и не могут быть вызваны из кода в sandbox. Инструмент с needsApproval: false остаётся доступным.
Этот путь без сохранения состояния не приостанавливает выполнение для подтверждения AI SDK. Если инструменту нужен процесс подтверждения AI SDK, используйте обычный инструмент AI SDK вне Code Mode.
ToolSetConnector подтверждения
ToolSetConnector сопоставляет AI SDK needsApproval к устойчивому runtime requiresApproval аннотацию. Вызов этого инструмента приостанавливает выполнение. Ваше приложение может проверить ожидающие действия и возобновить то же выполнение с помощью runtime.approve({ executionId }).
Функциональное needsApproval нельзя вычислить до того, как песочница предоставит аргументы. Поэтому коннектор считает, что этот инструмент всегда требует подтверждения. needsApproval: false выполняется без приостановки.
Это подтверждение использует устойчивый механизм паузы, подтверждения и повторного воспроизведения рантайма Code Mode. Оно не использует механизм подтверждения AI SDK для отдельных вызовов.