@cloudflare/ai-chat

中文文档
0.12.2发布于 2026/10/20MITTypeScriptESM + CJS构建来源已验证近 30 天下载 261.7万

Cloudflare 代理 (x) AI SDK 聊天

中文使用文档
文档目录24 节
  1. 安装
  2. 快速启动
  3. 服务器
  4. 客户端
  5. 朗格勒配置
  6. 工具
  7. 服务器侧工具
  8. 客户端工具
  9. 工具审批(人-入-出)
  10. 代理工具
  11. 可还原流
  12. 持久聊天恢复
  13. 重叠信件
  14. 储存管理
  15. 限制已存储信件
  16. 控制 LLM 上下文
  17. 行大小保护
  18. 自定义请求数据
  19. API 参考
  20. AIChatAgent<Env, State, Props>
  21. useAgentChat(options)
  22. 出口
  23. 实例
  24. 许可证

@cloudflare/ai-chat (英语)

AI聊天代理,具有自动消息持续,可重复流出,以及工具支持等功能. 以 Cloudflare 持久物体和 AI SDK 软件。 。 。 .

安装

npm install @cloudflare/ai-chat agents ai workers-ai-provider

React 客户端也需要可选 React 的同位素 :

npm install @ai-sdk/react react

快速启动

服务器

import { AIChatAgent } from "@cloudflare/ai-chat";
import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages } from "ai";

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)
    });

    return result.toUIMessageStreamResponse();
  }
}

这给了你:在SQLite中自动消息持续,在断开/再连接上可重复流线,以及实时WebSocket向所有连接客户端发送.

客户端

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

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

  return (
    <div>
      {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;
          sendMessage({
            role: "user",
            parts: [{ type: "text", text: input.value }]
          });
          input.value = "";
        }}
      >
        <input name="input" placeholder="Type a message..." />
      </form>
    </div>
  );
}

朗格勒配置

// wrangler.jsonc
{
  "ai": { "binding": "AI" },
  "durable_objects": {
    "bindings": [{ "name": "ChatAgent", "class_name": "ChatAgent" }]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["ChatAgent"]
    }
  ]
}

工具

服务器侧工具

带有工具 execute 在服务器上自动运行的函数 :

import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, isStepCount, tool } 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 }) => {
            const data = await fetchWeather(city);
            return { temperature: data.temp, condition: data.condition };
          }
        })
      },
      stopWhen: isStepCount(5)
    });

    return result.toUIMessageStreamResponse();
  }
}

客户端工具

没有工具 execute 客户端通过 onToolCall。用于需要浏览器 API(地理、剪贴板、相机)的工具:

// Server: define tool without execute
getLocation: tool({
  description: "Get the user's location from their browser",
  inputSchema: z.object({})
  // No execute -- client handles it
});
// Client: handle via onToolCall
const { messages, sendMessage } = useAgentChat({
  agent,
  onToolCall: async ({ toolCall, addToolOutput }) => {
    if (toolCall.toolName === "getLocation") {
      const pos = await new Promise((resolve, reject) =>
        navigator.geolocation.getCurrentPosition(resolve, reject)
      );
      addToolOutput({
        toolCallId: toolCall.toolCallId,
        output: { lat: pos.coords.latitude, lng: pos.coords.longitude }
      });
    }
  }
});

工具审批(人-入-出)

使用 needsApproval 用于执行前需要用户确认的工具:

// Server
processPayment: tool({
  description: "Process a payment",
  inputSchema: z.object({ amount: z.number(), recipient: z.string() }),
  needsApproval: async ({ amount }) => amount > 100, // Only require approval for large amounts
  execute: async ({ amount, recipient }) => charge(amount, recipient)
});
// Client
const { messages, addToolApprovalResponse } = useAgentChat({ agent });

// When rendering tool parts with state === "approval-requested":
<button onClick={() => addToolApprovalResponse({ id: approvalId, approved: true })}>
  Approve
</button>
<button onClick={() => addToolApprovalResponse({ id: approvalId, approved: false })}>
  Reject
</button>

代理工具

AIChatAgent 子类可以用作保留、流出代理工具 父代理通过 runAgentTool() 或者说 agentTool()数字 :

import { AIChatAgent } from "@cloudflare/ai-chat";
import { agentTool } from "agents/agent-tools";
import { convertToModelMessages, streamText } from "ai";
import { z } from "zod";

export class Summarizer extends AIChatAgent<Env> {
  protected override formatAgentToolInput(input: { text: string }, request) {
    return {
      id: `agent-tool-${request.runId}-input`,
      role: "user",
      parts: [{ type: "text", text: `Summarize:\n\n${input.text}` }]
    };
  }

  async onChatMessage() {
    const result = streamText({
      model: this.env.MODEL,
      messages: await convertToModelMessages(this.messages)
    });

    return result.toUIMessageStreamResponse();
  }
}

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage() {
    const result = streamText({
      model: this.env.MODEL,
      messages: await convertToModelMessages(this.messages),
      tools: {
        summarize: agentTool(Summarizer, {
          description: "Summarize long text in a separate retained agent.",
          inputSchema: z.object({ text: z.string() })
        })
      }
    });

    return result.toUIMessageStreamResponse();
  }
}

特工工具转身无头. 服务器侧工具正常工作,但 浏览器提供的客户端工具不可用,除非您单独设计 服务器侧或由父机代理的交接。 覆盖 formatAgentToolInput(), (中文(简体) ), getAgentToolOutput(),以及 getAgentToolSummary() 当您需要结构化 投入或产出.

可还原流

断开/重新连接时自动恢复流 。 不需要配置 .

当客户端断开中流时,块会被缓冲到 SQLite. 在重新连接时,客户端接收所有缓冲块并持续接收活流.

这样可以处理浏览器断开、导航和反应清理,而持久对象则继续运行。 持久聊天恢复单独处理模式调用时被拆迁的持久对象本身.

持久聊天恢复

每个 AIChatAgent 转而使用可持久恢复的纤维,因此转而可以在工人部署、可持久物体驱逐或再生过程中幸存。 指定 a chatRecovery 对象仅在需要调和预算或终端行为时:

import type {
  ChatRecoveryContext,
  ChatRecoveryOptions
} from "@cloudflare/ai-chat";

export class ChatAgent extends AIChatAgent<Env> {
  override chatRecovery = {
    maxAttempts: 6,
    terminalMessage: "The assistant was interrupted. Please try again."
  };

  override async onChatRecovery(
    ctx: ChatRecoveryContext
  ): Promise<ChatRecoveryOptions> {
    console.log("Recovering", ctx.incidentId, ctx.recoveryKind);
    return {}; // persist partial output and continue/retry when possible
  }
}

chatRecovery = false 不再支持。 先前编译的仍然供应的 JavaScript false 接收默认持久配置。 如果自动续作不安全, 请返回 { continue: false } 从 onChatRecovery(); 使用持久状态进行取消或副作用警卫,并为成本控制配置回收预算.

见 docs/agents/chat-agents.md 用于移徙指导、针对提供者的恢复战略和可观察活动.

通用客户端流中止/清理默认只属于本地:服务器转会继续并可在稍后恢复. 明确 stop() 仍然取消服务器回合 :

const { messages, stop } = useAgentChat({ agent });

如果您的应用程序有意希望客户端生命周期拥有服务器生命周期, 请选择在客户端中止时取消 :

const { messages } = useAgentChat({
  agent,
  cancelOnClientAbort: true
});

用于请求寿命或节能符的流量 。 明确 stop() 总是 服务器端取消, 不论 cancelOnClientAbort。 。 。 .

禁用恢复为 resume: false数字 :

const { messages } = useAgentChat({ agent, resume: false });

重叠信件

当用户提交新消息,而另一个回合仍在运行时, AIChatAgent 可以队列、倒塌或丢弃重叠服务器侧:

export class ChatAgent extends AIChatAgent {
  messageConcurrency = "latest";

  async onChatMessage() {
    // ...
  }
}

现有战略:

  • "queue" (默认)——按顺序处理每次提交
  • "latest" ——只保留最新的重叠提交并跳过任何更旧的队列重叠回合
  • "merge" – 队列重叠提交, 然后将队列中的用户信件崩溃为一个合并的后继用户回合
  • "drop" - 忽略重叠提交
  • { strategy: "debounce", debounceMs: 750 } 等待一个安静的窗口, 然后运行只运行最新的提交

选择一项战略: 使用 "latest" 用于用户的焦点助理 能够修正自己在中游。 使用 "queue" 或者说 "merge" 用于通讯 每个消息都很重要的应用程序 。 使用 "drop" 防止双发. 使用 "debounce" 当用户发送短信息时.

用户看到的: 与 "queue",每个消息都有自己的反应. 与 "latest"中,所有信件都出现,但只有最后一个重叠的 反应。 与 "merge",重叠的信息会崩溃成一个。 与 "drop"中,重叠的信息会短暂出现,然后消失(倒转).

此设置只影响重叠 sendMessage() 提交。 重新创造, 工具的延续、核准和方案 saveMessages() 打电话保持 现有序列化行为。 何时 debounceMs 缺少或无效, AIChatAgent 返回到默认值 750 毫丝窗.

传递函数到 saveMessages() 以获取最新记录 转弯实际开始 —— 用于计时回调和 webhook 处理器 如果自电话发出以来消息可能有所改变:

await this.saveMessages((messages) => [
  ...messages,
  {
    id: crypto.randomUUID(),
    role: "user",
    parts: [{ type: "text", text: "Scheduled follow-up" }]
  }
]);

saveMessages() 返回时 { requestId, status }编辑 status 字段为 "completed" 当转弯时, "skipped" 中空飞行无效时 (例如,a) chat-clear),或 "aborted" 当外部 AbortSignal 已取消 这个 过 options.signal 取消外部程序转接, 不包含 了解内部生成的请求 id:

const controller = new AbortController();
const result = await this.saveMessages([userMsg], {
  signal: controller.signal
});
if (result.status === "aborted") {
  // ...
}

这是相同的形状 Think.saveMessages 使用——见 cloudflare/agents#1406 用于推动API的代理工具管弦模式。 运出 代理工具 API 在 docs/agents/agent-tools.md。 。 。 .

储存管理

限制已存储信件

控制保存在 SQLite 的信件数量 :

export class ChatAgent extends AIChatAgent {
  maxPersistedMessages = 200; // Keep last 200 messages

  async onChatMessage() {
    // ...
  }
}

当计数超过限制时,删除最旧的消息 。 这只控制存储——不影响发送给LLM的内容.

控制 LLM 上下文

使用 AI SDK 软件 pruneMessages() 以控制发送到模型中的内容,而不受存储内容的影响:

import { createWorkersAI } from "workers-ai-provider";
import { streamText, convertToModelMessages, pruneMessages } from "ai";

export class ChatAgent extends AIChatAgent {
  maxPersistedMessages = 200;

  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });

    const result = streamText({
      model: workersai("@cf/moonshotai/kimi-k2.7-code"),
      messages: pruneMessages({
        messages: await convertToModelMessages(this.messages),
        reasoning: "before-last-message",
        toolCalls: "before-last-2-messages"
      })
    });

    return result.toUIMessageStreamResponse();
  }
}

行大小保护

信件接近 SQLite 的 2MB 行限制会自动压缩 。 大型工具产出取而代之的是方便LLM的摘要,该摘要指示模型建议重新运行工具。 压缩信息包括 metadata.compactedToolOutputs 这样客户可以检测和显示这个优雅.

自定义请求数据

包含自定义数据,每个聊天请求使用 body 选项 :

const { messages, sendMessage } = useAgentChat({
  agent,
  body: {
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    userId: "abc"
  }
});

// Or use a function for dynamic values:
body: () => ({ token: getAuthToken(), timestamp: Date.now() });

通过 options.body数字 :

async onChatMessage(onFinish, options) {
  const { timezone, userId } = options?.body ?? {};
}

API 参考

AIChatAgent<Env, State, Props>

扩展 Agent 从 agents 软件包.

财产/方法类型说明
messagesChatMessage[]当前对话消息( 从 SQLite 上载)
chatRecoveryChatRecoveryConfig总是在持久恢复配置。 指定一个对象来调和预算和终端行为
maxPersistedMessagesnumber | undefined要保存在 SQLite 中的最大消息 。 默认:无限
messageConcurrencyMessageConcurrency货币战略 sendMessage() 提交。 默认 : "queue"
onChatMessage(onFinish?, options?)覆盖处理收到的聊天信息 。 还原 a Response。 。 。 . onFinish 是可选的.
onChatRecovery(ctx)覆盖聊天回合中断后自定义恢复
onChatResponse(result)覆盖聊天回合完成后调用. result 已经 message, (中文(简体) ), requestId, (中文(简体) ), status, (中文(简体) ), continuation
persistMessages(messages)Promise<void>手动粘接信件( 通常是自动)
saveMessages(messages, options?)Promise<SaveMessagesResult>持久性信息和触发 onChatMessage。接受数组或函数. options.signal 取消外部转弯.
waitUntilStable()Promise<boolean>受保护的助手等待谈话完全稳定
resetTurnState()void保护帮助中止活动回合并取消队列的续作
hasPendingInteraction()boolean保护助手以检测待决工具输入或核准助理信件

useAgentChat(options)

聊天互动的反应钩. 包装 AI SDK 的 useChat 与WebSocket运输.

选项 :

选项类型说明
agentReturnType<typeof useAgent>代理连接( 需要)
onToolCall({ toolCall, addToolOutput }) => void处理客户端工具执行
autoContinueAfterToolResultboolean在客户端工具结果后自动继续. 默认 : true
resumeboolean启用流恢复 。 默认 : true
cancelOnClientAbortboolean当发生通用客户端流中止/清理时取消服务器回合 。 明确 stop() 总是取消。 默认 : false
bodyobject | () => object按每次请求发送的自定义数据(见下文)
prepareSendMessagesRequest(options) => { body?, headers? }按要求预先定制
getInitialMessages(options) => Promise<ChatMessage[]>自定义初始信件加载器

回返情况:

财产类型说明
messagesChatMessage[]聊天消息
sendMessage(message) => void发送消息
clearHistory() => void清除对话
addToolOutput({ toolCallId, output }) => void提供工具输出
addToolApprovalResponse({ id, approved }) => void批准/拒绝一个工具
setMessages(messages | updater) => void设置信件( 同步到服务器)
statusstring"idle" | "submitted" | "streaming" | "error"

出口

导入路径它提供的东西
@cloudflare/ai-chatAIChatAgent, (中文(简体) ), ChatMessage, (中文(简体) ), createToolsFromClientSchemas, (中文(简体) ), ChatRecoveryContext, (中文(简体) ), ChatRecoveryConfig
@cloudflare/ai-chat/reactuseAgentChat
@cloudflare/ai-chat/typesMessageType, (中文(简体) ), OutgoingMessage, (中文(简体) ), IncomingMessage

实例

许可证

麻省理工学院

版本与发布记录

@cloudflare/ai-chat 共发布 63 个版本,首次发布于 2025/12/30;过去 12 个月发布了 63 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.12.2latest2026/10/2020 天前
0.12.12026/10/021 个月前
0.12.02026/09/111 个月前
0.11.02026/08/272 个月前
0.10.22026/08/182 个月前
0.10.12026/07/293 个月前

关于 @cloudflare/ai-chat 的常见问题

@cloudflare/ai-chat 是什么?

Cloudflare 代理 (x) AI SDK 聊天

如何安装 @cloudflare/ai-chat?

在项目目录运行 npm install @cloudflare/ai-chat,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:ai(^6.0.0 || ^7.0.0)、agents(>=0.25.0 <1.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@cloudflare/ai-chat 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cloudflare/ai-chat 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@cloudflare/ai-chat 可以商用吗?

@cloudflare/ai-chat 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cloudflare/ai-chat 的下载量有多少?

根据 npm 官方下载统计,@cloudflare/ai-chat 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,617,373 次,日均约 87,246 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cloudflare/ai-chat 还在维护吗?

最新版本 0.12.2 发布于 2026/10/20(20 天前);至今共发布 63 个版本,其中过去 12 个月发布了 63 个;首次发布于 2025/12/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。