从模板到真实项目,把能力串起来。
08.1 我们要做什么
做一个能聊天、有记忆、会调天气工具、危险操作要你确认的 Agent。这就是 Starter 模板里 ChatAgent 的真身。
08.2 服务端骨架
import { AIChatAgent } from "@cloudflare/ai-chat";
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, tool, 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),
}),
processPayment: tool({
description: "Process a payment",
inputSchema: z.object({ amount: z.number(), recipient: z.string() }),
needsApproval: async ({ amount }) => amount > 100, // 超 100 要批
execute: async ({ amount, recipient }) => charge(amount, recipient),
}),
},
stopWhen: stepCountIs(5),
});
return result.toUIMessageStreamResponse();
}
}
08.3 wrangler 配置
{
"ai": { "binding": "AI" },
"durable_objects": {
"bindings": [{ "name": "ChatAgent", "class_name": "ChatAgent" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["ChatAgent"] }]
}
注意
AIChatAgent用 SQLite 存消息和流式缓冲,new_sqlite_classes是必选项。漏了,对话历史不落盘。
08.4 客户端连上
import { useAgentChat } from "@cloudflare/ai-chat/react";
const { messages, sendMessage, addToolApprovalResponse } = useAgentChat({ agent: "ChatAgent" });
useAgentChat 返回 messages、sendMessage、clearHistory、addToolOutput、addToolApprovalResponse 等。一个 hook 管全了。
标叔的经验
我第一次把 needsApproval 加上去,看到前端弹出"是否批准付款"的按钮,才真正觉得这是生产级。安全不是事后补,是内建的。
聊天 Agent 拆完了。下一章讲怎么把它配好、部署到全球。