跳转到内容
搜索文档

快速入门

最后更新 查看 MarkdownAgent 设置

分步构建带持久内存、内置文件工具与流式传输的聊天 Agent。

若你刚接触 Cloudflare Agents,请先浏览什么是 Agent?了解核心概念。否则可直接从这里从零开始。

本教程结束时你将拥有:

  • 向 React 聊天 UI 流式返回响应
  • 模型可读写的持久内存
  • 工作区文件工具(read、write、edit、find、grep、delete)
  • 自定义服务端工具支持

前提条件

  • Node.js 24+
  • 具有 Workers AI 访问权限的 Cloudflare 账户
  • 熟悉 TypeScript 与 Cloudflare Workers

1. 创建项目

mkdir my-think-agent && cd my-think-agent
npm init -y

安装依赖:

npm install @cloudflare/think @cloudflare/ai-chat agents ai @cloudflare/shell zod workers-ai-provider react react-dom
npm install -D wrangler @cloudflare/vite-plugin @cloudflare/workers-types @vitejs/plugin-react @tailwindcss/vite tailwindcss typescript vite

2. 配置 wrangler

创建 wrangler.jsonc

{
	"name": "my-think-agent",
	"compatibility_date": "2026-01-28",
	"compatibility_flags": ["nodejs_compat"],
	"ai": { "binding": "AI" },
	"assets": {
		"not_found_handling": "single-page-application",
		"run_worker_first": ["/agents/*"]
	},
	"durable_objects": {
		"bindings": [{ "class_name": "MyAgent", "name": "MyAgent" }]
	},
	"migrations": [{ "new_sqlite_classes": ["MyAgent"], "tag": "v1" }],
	"main": "src/server.ts"
}
name = "my-think-agent"
compatibility_date = "2026-01-28"
compatibility_flags = [ "nodejs_compat" ]
main = "src/server.ts"

[ai]
binding = "AI"

[assets]
not_found_handling = "single-page-application"
run_worker_first = [ "/agents/*" ]

[[durable_objects.bindings]]
class_name = "MyAgent"
name = "MyAgent"

[[migrations]]
new_sqlite_classes = [ "MyAgent" ]
tag = "v1"

创建 vite.config.ts

import { cloudflare } from "@cloudflare/vite-plugin";
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
	plugins: [react(), cloudflare(), tailwindcss()],
});
import { cloudflare } from "@cloudflare/vite-plugin";
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
	plugins: [react(), cloudflare(), tailwindcss()],
});

创建 tsconfig.json

{
	"extends": "agents/tsconfig"
}

3. 定义 Agent

创建 src/server.ts

import { Think } from "@cloudflare/think";
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";

export class MyAgent extends Think {
	getModel() {
		return createWorkersAI({ binding: this.env.AI })(
			"@cf/moonshotai/kimi-k2.6",
		);
	}

	getSystemPrompt() {
		return "You are a helpful assistant with access to a workspace filesystem.";
	}
}

export default {
	async fetch(request, env) {
		return (
			(await routeAgentRequest(request, env)) ||
			new Response("Not found", { status: 404 })
		);
	},
};
import { Think } from "@cloudflare/think";
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";

export class MyAgent extends Think<Env> {
	getModel() {
		return createWorkersAI({ binding: this.env.AI })(
			"@cf/moonshotai/kimi-k2.6",
		);
	}

	getSystemPrompt() {
		return "You are a helpful assistant with access to a workspace filesystem.";
	}
}

export default {
	async fetch(request: Request, env: Env) {
		return (
			(await routeAgentRequest(request, env)) ||
			new Response("Not found", { status: 404 })
		);
	},
} satisfies ExportedHandler<Env>;

这是可工作的 Agent。Think 自动提供:

  • WebSocket 聊天协议(兼容 useAgentChat
  • SQLite 消息持久化
  • 可恢复流式传输(页面刷新重放缓冲 chunk)
  • 工作区文件工具(read、write、edit、list、find、grep、delete)
  • Abort/cancel 支持
  • 带部分消息持久化的错误处理

4. 连接 React 客户端

创建 src/client.tsx

import { createRoot } from "react-dom/client";
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";

function Chat() {
	const agent = useAgent({ agent: "MyAgent" });
	const { messages, sendMessage, status } = useAgentChat({ agent });

	return (
		<div>
			<h1>Think Agent</h1>
			{messages.map((msg) => (
				<div key={msg.id}>
					<strong>{msg.role}:</strong>
					{msg.parts.map((part, i) =>
						part.type === "text" ? <span key={i}>{part.text}</span> : null,
					)}
				</div>
			))}

			<form
				onSubmit={(e) => {
					e.preventDefault();
					const input = e.currentTarget.elements.namedItem("input");
					if (!input.value.trim()) return;
					sendMessage({ text: input.value });
					input.value = "";
				}}
			>
				<input name="input" placeholder="Send a message..." />
				<button type="submit">Send</button>
			</form>

			<p>Status: {status}</p>
		</div>
	);
}

const root = document.getElementById("root");
if (root) {
	createRoot(root).render(<Chat />);
}
import { createRoot } from "react-dom/client";
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";

function Chat() {
	const agent = useAgent({ agent: "MyAgent" });
	const { messages, sendMessage, status } = useAgentChat({ agent });

	return (
		<div>
			<h1>Think Agent</h1>
			{messages.map((msg) => (
				<div key={msg.id}>
					<strong>{msg.role}:</strong>
					{msg.parts.map((part, i) =>
						part.type === "text" ? <span key={i}>{part.text}</span> : null,
					)}
				</div>
			))}

			<form
				onSubmit={(e) => {
					e.preventDefault();
					const input = e.currentTarget.elements.namedItem(
						"input",
					) as HTMLInputElement;
					if (!input.value.trim()) return;
					sendMessage({ text: input.value });
					input.value = "";
				}}
			>
				<input name="input" placeholder="Send a message..." />
				<button type="submit">Send</button>
			</form>

			<p>Status: {status}</p>
		</div>
	);
}

const root = document.getElementById("root");
if (root) {
	createRoot(root).render(<Chat />);
}

创建 index.html

<!doctype html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Think Agent</title>
	</head>
	<body>
		<div id="root"></div>
		<script type="module" src="/src/client.tsx"></script>
	</body>
</html>

5. 运行

npx vite dev

打开浏览器并发送消息。Agent 以流式文本响应,工作区文件工具自动对模型可用。

6. 添加持久内存

重写 configureSession 为模型提供在重启后仍保留的可写内存:

export class MyAgent extends Think {
	getModel() {
		return createWorkersAI({ binding: this.env.AI })(
			"@cf/moonshotai/kimi-k2.6",
		);
	}

	configureSession(session) {
		return session
			.withContext("soul", {
				provider: {
					get: async () =>
						"You are a helpful assistant. Remember important facts about the user.",
				},
			})
			.withContext("memory", {
				description: "Important facts about the user and conversation.",
				maxTokens: 2000,
			})
			.withCachedPrompt();
	}
}
export class MyAgent extends Think<Env> {
	getModel(): LanguageModel {
		return createWorkersAI({ binding: this.env.AI })(
			"@cf/moonshotai/kimi-k2.6",
		);
	}

	configureSession(session: Session) {
		return session
			.withContext("soul", {
				provider: {
					get: async () =>
						"You are a helpful assistant. Remember important facts about the user.",
				},
			})
			.withContext("memory", {
				description: "Important facts about the user and conversation.",
				maxTokens: 2000,
			})
			.withCachedPrompt();
	}
}

模型在系统提示词中看到 MEMORY 部分并获得 set_context 工具更新它。写入内存的事实持久化在 SQLite,在 Durable Object 休眠与重启后仍然保留。

使用 configureSession 时,系统提示词由上下文块构建而非 getSystemPrompt()。上述 "soul" 块作为系统身份 — 只读且始终首先出现。"memory" 块可写,模型学到有用信息时主动更新。

上下文块、压缩、搜索、技能与多会话请参阅 会话文档

7. 添加自定义工具

重写 getTools() 在内置工作区工具旁添加自有工具:

import { tool } from "ai";
import { z } from "zod";

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}
	configureSession(session) {
		/* ... */
	}

	getTools() {
		return {
			getWeather: tool({
				description: "Get the current weather for a city",
				inputSchema: z.object({
					city: z.string().describe("City name"),
				}),
				execute: async ({ city }) => {
					const res = await fetch(
						`https://api.weatherapi.com/v1/current.json?key=${this.env.WEATHER_KEY}&q=${city}`,
					);
					return res.json();
				},
			}),
		};
	}
}
import { tool } from "ai";
import { z } from "zod";

export class MyAgent extends Think<Env> {
	getModel(): LanguageModel {
		/* ... */
	}
	configureSession(session: Session) {
		/* ... */
	}

	getTools(): ToolSet {
		return {
			getWeather: tool({
				description: "Get the current weather for a city",
				inputSchema: z.object({
					city: z.string().describe("City name"),
				}),
				execute: async ({ city }) => {
					const res = await fetch(
						`https://api.weatherapi.com/v1/current.json?key=${this.env.WEATHER_KEY}&q=${city}`,
					);
					return res.json();
				},
			}),
		};
	}
}

Think 自动合并多源工具。每轮模型可访问:

  1. 工作区工具 — read、write、edit、list、find、grep、delete、bash(内置)
  2. 你的工具 — 来自 getTools()
  3. 扩展工具 — 来自已加载扩展
  4. 会话工具 — set_context、load_context、search_context(来自 configureSession
  5. 技能工具 — activate_skill、read_skill_resource 与可选 run_skill_script(来自 getSkills()
  6. MCP 工具 — 来自已连接 MCP 服务器(如有)
  7. 客户端工具 — 来自浏览器(如有)

8. 添加生命周期钩子

Think 提供无论入口路径均在每轮触发的钩子:

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}

	beforeTurn(ctx) {
		console.log(
			`Turn starting: ${Object.keys(ctx.tools).length} tools available`,
		);
	}

	onChatResponse(result) {
		console.log(`Turn ${result.status}: ${result.message.parts.length} parts`);
	}
}
import type {
	TurnContext,
	TurnConfig,
	ChatResponseResult,
} from "@cloudflare/think";

export class MyAgent extends Think<Env> {
	getModel(): LanguageModel {
		/* ... */
	}

	beforeTurn(ctx: TurnContext): TurnConfig | void {
		console.log(
			`Turn starting: ${Object.keys(ctx.tools).length} tools available`,
		);
	}

	onChatResponse(result: ChatResponseResult) {
		console.log(`Turn ${result.status}: ${result.message.parts.length} parts`);
	}
}

完整参考请参阅生命周期钩子

下一步

这篇文档对您有帮助吗?