跳转到内容
搜索文档

AI SDK 集成

最后更新 查看 MarkdownAgent 设置

@cloudflare/codemode/ai 入口将 AI SDK 工具转换为一个 Code Mode 工具。模型编写调用工具的 JavaScript,执行器在隔离沙箱中运行该代码。

在两种集成模式间选择:

模式 用例 审批行为
createCodeTool() 一个或多个工具提供商的简单无状态执行 排除使用 needsApproval 的工具
ToolSetConnector 或 toolSetConnector() 通过 Code Mode 运行时的持久执行 将 needsApproval 映射到持久运行时审批

创建无状态 Code Mode tool

createCodeTool() 接受 AI SDK ToolSet 或工具提供商数组。还需要执行器。返回标准 AI SDK 工具,供 streamText() 或 generateText() 使用。

  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-08-17",
      "compatibility_flags": [
        "nodejs_compat"
      ],
      "worker_loaders": [
        {
          "binding": "LOADER"
        }
      ]
    }
    # Set this to today's date
    compatibility_date = "2026-08-17"
    compatibility_flags = ["nodejs_compat"]
    
    [[worker_loaders]]
    binding = "LOADER"
  3. 定义可执行的 AI SDK tool。Code Mode 使用其 schema 生成类型并在调用 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"
        })
      })
    };

    每个沙箱可调用 tool 需要 execute 函数。Client-side 或 provider 执行的 tool 无法通过此 server-side executor 运行。

  4. 创建 Code Mode tool 并传给 AI SDK model 调用:

    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 tool 传给 streamText() 以流式传输。生成的 tool 描述包含 getWeather 的 TypeScript 定义。模型仍编写 JavaScript,例如:

async () => {
	const weather = await codemode.getWeather({ city: "Lisbon" });
	return weather.conditions;
};

默认命名空间为 codemode。createCodeTool() 也接受自定义 description。在 Code Mode 应插入生成定义处包含 {{types}}。

用 provider 组织 tool

Tool provider 将 tool 分组到一个沙箱命名空间下。每个 tool 属于 codemode.* 时直接传递 tool set。

与其他包的 provider 组合 AI SDK tool 时使用 aiTools()。以下可选 workspace 示例还需要 @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 tool 暴露为 codemode.*,workspace tool 为 state.*。

要分配自定义命名空间,改为传递 provider 对象:

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()。Provider 名称须唯一且为有效 JavaScript 标识符。

将 AI SDK 工具与持久运行时一起使用

当运行需要持久状态时使用 ToolSetConnector 或其 toolSetConnector() 便利函数。连接器将 AI SDK ToolSet 适配 createCodemodeRuntime()。辅助函数返回 new ToolSetConnector(ctx, options)。

在 Agent 或另一 Durable Object 内创建 connector:

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() 检查类型。

审批行为

两种集成模式对 AI SDK 审批处理不同。

createCodeTool() 审批

createCodeTool() 过滤 needsApproval 为 true 或函数的工具。过滤的工具不出现在生成类型中,无法从沙箱代码运行。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 按次审批流程。

这篇文档对您有帮助吗?