Cloudflare Agents 从入门到精通
附录

§06 工具调用:把能力拆成工具

06.1 聊天 Agent 的工具三态

AIChatAgent 上,工具分三种:服务端工具(有 execute)、客户端工具(无 execute)、审批工具(服务端 + needsApproval)。

import { AIChatAgent } from "@cloudflare/ai-chat";
import { streamText, tool, convertToModelMessages, stepCountIs } from "ai";
import { z } from "zod";

export class ChatAgent extends AIChatAgent {
  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });
    const result = streamText({
      model: workersai("@cf/moonshotai/kimi-k2.7-code"),
      messages: await convertToModelMessages(this.messages),
      tools: {
        getWeather: tool({
          description: "Get weather for a city",
          inputSchema: z.object({ city: z.string() }),
          execute: async ({ city }) => fetchWeather(city), // 服务端执行
        }),
      },
      stopWhen: stepCountIs(5), // 最多 5 步,防止死循环
    });
    return result.toUIMessageStreamResponse();
  }
}

06.2 客户端工具:让浏览器动手

有些事只能在浏览器做,比如拿定位。服务端只声明 schema,不写 execute

// 服务端:只描述,不实现
tools: {
  getLocation: tool({
    description: "Get the user's location from the browser",
    inputSchema: z.object({}),
    // 没有 execute —— 客户端处理
  });
}
// 客户端:用 onToolCall 补上实现
const { messages, sendMessage } = useAgentChat({
  agent,
  onToolCall: async ({ toolCall, addToolOutput }) => {
    if (toolCall.toolName === "getLocation") {
      const pos = await new Promise((r) => navigator.geolocation.getCurrentPosition(r));
      addToolOutput({ toolCallId: toolCall.toolCallId, output: { lat: pos.coords.latitude } });
    }
  },
});
类型 在哪执行 典型用途 标叔的结论
服务端工具 Worker 查库、调 API 主力
客户端工具 浏览器 定位、DOM 善用浏览器能力
审批工具 服务端 付款、删号 危险操作必加

06.3 消息历史自动持久化

AIChatAgent 把聊天记录存进 SQLite,maxPersistedMessages 只限制存多少条,不影响发给模型的消息数。

export class ChatAgent extends AIChatAgent {
  maxPersistedMessages = 200; // 仅限存储,不裁剪发给 LLM 的
}
注意
想控制发给模型的 token,用 AI SDK 的 pruneMessages(),不是这个字段。这俩经常被人搞混。

工具讲完一半。MCP 这种"工具的标准化形态",我们放到 §17 专章讲。下一章先讲怎么看清 Agent 在干什么。