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 在干什么。