跳转到内容
搜索文档

更新日志

Cloudflare 的最新更新与改进。

Pipeline 绑定(binding)配置字段重命名为 stream

您的 Wrangler 配置文件pipelines 绑定(binding)配置里的 pipeline 字段已重命名为 stream。旧字段已弃用但仍被接受。

请更新您的配置以使用 stream,从而避免弃用警告。

之前(已弃用):

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "pipelines": [
    {
      "binding": "MY_PIPELINE",
      "pipeline": "<STREAM_ID>"
    }
  ]
}
[[pipelines]]
binding = "MY_PIPELINE"
pipeline = "<STREAM_ID>"

之后:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "pipelines": [
    {
      "binding": "MY_PIPELINE",
      "stream": "<STREAM_ID>"
    }
  ]
}
[[pipelines]]
binding = "MY_PIPELINE"
stream = "<STREAM_ID>"

无需进行其他更改。绑定(binding)名称、TypeScript 类型和运行时 API (env.MY_PIPELINE.send(...)) 保持不变。

有关配置 pipeline 绑定(binding)的更多信息,请参阅写入流

新增 Workers 批量机密(secrets)API 端点

您现在可以使用 批量机密端点 在单个请求中为您的 Worker 创建、更新或删除多个机密(secrets)。

  • 包含具有值的机密以进行创建或更新。
  • 将机密设置为 null 以进行删除。
  • 请求中未包含的机密将保持不变。

以下示例创建 API_KEY,更新已存在的 DB_PASSWORD,并删除 OLD_SECRET

{
  "secrets": {
    "API_KEY": { "type": "secret_text", "name": "API_KEY", "text": "my-api-key" },
    "DB_PASSWORD": { "type": "secret_text", "name": "DB_PASSWORD", "text": "my-db-password" },
    "OLD_SECRET": null
  }
}

您可以使用 wrangler secret bulk 在命令行中执行相同的操作:

npx wrangler secret bulk < secrets.json

要删除某个键,请在 JSON 文件中将其值设置为 null.env 文件不支持删除操作。

每个请求最多支持 100 次总操作(包括创建、更新和删除的组合)

在您操作系统的钥匙串中存储 Wrangler 的 OAuth 凭证

Wrangler 现在可以将 wrangler login 返回的 OAuth 凭证存储在 AES-256-GCM 加密的文件中,加密密钥保存在您的操作系统钥匙串中。默认行为没有改变 —— 除非您选择启用,否则凭证仍保存在明文 TOML 文件中。

要选择启用,请运行:

npx wrangler login --use-keyring

该选择会在 Wrangler 调用之间持久保存。使用 npx wrangler login --no-use-keyring 可以取消选择,或者使用 CLOUDFLARE_AUTH_USE_KEYRING 环境变量覆盖单个命令的首选项。

wrangler whoami 现在会报告凭证的存储位置:

🔐 Credentials are stored in: Encrypted file (~/.config/.wrangler/config/default.enc) with key in macOS Keychain (service=wrangler, account=default)

各平台后端:

  • macOS 通过 /usr/bin/security 使用内置的 Keychain。
  • Linux 通过 libsecret-tools 包中的 secret-tool CLI 使用 libsecret
  • Windows 通过 @napi-rs/keyring 使用 凭据管理器 (Credential Manager),该包在您首次选择启用时按需安装。

有关完整详细信息,请参阅在操作系统钥匙串中存储 OAuth 凭证,包括启用/禁用时的迁移行为以及 CLOUDFLARE_AUTH_USE_KEYRING 环境变量。

直接从 Workflow 绑定调度 Workflow 实例

您现在可以在 wrangler.jsonc 中直接将 cron 计划附加到 Workflow 绑定(binding)。每次计划运行都会自动创建一个新的 Workflow 实例,因此您无需定义单独的带有 scheduled 处理程序的 Worker 来按间隔触发您的 Workflow。

例如,您可以在同一个 Workflow 上配置每小时、每 15 分钟或工作日计划:

{
	"workflows": [
		{
			"name": "my-scheduled-workflow",
			"binding": "MY_WORKFLOW",
			"class_name": "MyScheduledWorkflow",
			"schedules": ["0 * * * *", "*/15 * * * *", "0 9 * * MON-FRI"],
		},
	],
}

Cron 工作负载获得 Workflows 的所有相同优势,包括内置重试、多步骤持久执行以及 Workflows 的可配置超时。

import {
	WorkflowEntrypoint,
	WorkflowEvent,
	WorkflowStep,
} from "cloudflare:workers";

// 根据 wrangler.jsonc 中为 MY_WORKFLOW 绑定定义的每个 cron 计划自动运行。
export class MyScheduledWorkflow extends WorkflowEntrypoint<Env> {
	async run(event: WorkflowEvent, step: WorkflowStep) {
		const data = await step.do("fetch source data", async () => {
			return await fetchSourceData();
		});

		// 如果此步骤失败,则仅使用以下自定义逻辑重试此步骤
		await step.do(
			"process and store results",
			{
				retries: { limit: 5, delay: "30 seconds", backoff: "exponential" },
				timeout: "10 minutes",
			},
			async () => {
				await processAndStore(data);
			},
		);
	}
}

这使得构建定期计划的作业(例如数据库备份、发票生成、报告聚合和清理任务)变得更加容易,而无需配置单独的 Cron Trigger 入口点。

有关更多信息,请参阅触发 Workflows

Agents SDK v0.14.0:Agent 技能、信使(messengers)、计划任务、Workflows 以及强化的聊天恢复

Agents SDK 的最新版本添加了四种使用 @cloudflare/think 进行构建的新方式:按需 Agent 技能(Agent Skills)、聊天信使(chat messengers,从 Telegram 开始)、声明式计划任务以及 Workflows 内部的持久推理步骤。此版本还显著强化了持久聊天恢复,因此轮次能够可靠地度过生产环境中的部署、驱逐和停滞的模型流。

Agent 技能(Agent Skills)(实验性)

给 agent 一个按需指令、资源和脚本的目录。技能源将目录添加到系统 Prompt 中,而模型仅在任务匹配时才激活技能 —— 因此庞大的功能库不会膨胀每个 Prompt。

import { Think, skills } from "@cloudflare/think";
import bundledSkills from "agents:skills";

export class SkillsAgent extends Think {
	getSkills() {
		return [
			bundledSkills,
			skills.r2(this.env.SKILLS_BUCKET, { prefix: "skills/" }),
		];
	}
}
import { Think, skills } from "@cloudflare/think";
import bundledSkills from "agents:skills";

export class SkillsAgent extends Think<Env> {
	getSkills() {
		return [
			bundledSkills,
			skills.r2(this.env.SKILLS_BUCKET, { prefix: "skills/" }),
		];
	}
}

agents:skills 导入通过 Agents Vite 插件打包本地的 ./skills 目录(每个技能一个目录,每个目录包含一个 SKILL.md)。技能也可以从 R2 或清单(manifest)中加载。当技能可用时,Think 会暴露 activate_skillread_skill_resource 和一个可选的 run_skill_script 工具。技能加载是弹性的:重复或失败的源将被跳过并发出警告,而不会损坏 agent。

Agent 技能处于实验性阶段,尤其是脚本执行还处于早期阶段。API 可能会在未来的版本中发生变化。我们非常期待您的反馈 —— 请在 Agents 仓库中告诉我们您正在构建什么以及缺少了什么。

信使(Messengers)

将 Think agent 直接连接到聊天平台。Think 拥有 Webhook 路由、会话路由、持久回复纤程(durable reply fiber)以及流式传送回提供商。Telegram 作为第一个提供商发布。

import { Think } from "@cloudflare/think";
import {
	defineMessengers,
	ThinkMessengerStateAgent,
} from "@cloudflare/think/messengers";
import telegramMessenger from "@cloudflare/think/messengers/telegram";

export { ThinkMessengerStateAgent };

export class SupportAgent extends Think {
	getMessengers() {
		return defineMessengers({
			telegram: telegramMessenger({
				token: this.env.TELEGRAM_BOT_TOKEN,
				userName: "support_bot",
				secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
			}),
		});
	}
}
import { Think } from "@cloudflare/think";
import {
	defineMessengers,
	ThinkMessengerStateAgent,
} from "@cloudflare/think/messengers";
import telegramMessenger from "@cloudflare/think/messengers/telegram";

export { ThinkMessengerStateAgent };

export class SupportAgent extends Think<Env> {
	getMessengers() {
		return defineMessengers({
			telegram: telegramMessenger({
				token: this.env.TELEGRAM_BOT_TOKEN,
				userName: "support_bot",
				secretToken: this.env.TELEGRAM_WEBHOOK_SECRET_TOKEN,
			}),
		});
	}
}

默认情况下,每个 Chat SDK 线程都映射到其自己的 Think 子 agent,因此群聊和直接消息不会共享内存。支持多个机器人、自定义会话路由和自定义提供商。

计划任务

使用类型化的领域特定语言 (DSL) 声明循环的、具有时区感知的 Prompt 和处理器。Think 在启动时协调声明,并在每次运行后重新设定下一次发生,由持久幂等提交提供支持。

import { Think, defineScheduledTasks } from "@cloudflare/think";

export class DigestAgent extends Think {
	getScheduledTasks() {
		return defineScheduledTasks({
			weeklyCommitReport: {
				schedule: "every week on monday at 09:00",
				prompt:
					"Compile my GitHub commits for the last week and summarize them.",
			},
			workout: {
				schedule: "every day at 08:00 in Europe/London",
				prompt: "Start my workout.",
			},
		});
	}
}
import { Think, defineScheduledTasks } from "@cloudflare/think";

export class DigestAgent extends Think<Env> {
	getScheduledTasks() {
		return defineScheduledTasks({
			weeklyCommitReport: {
				schedule: "every week on monday at 09:00",
				prompt:
					"Compile my GitHub commits for the last week and summarize them.",
			},
			workout: {
				schedule: "every day at 08:00 in Europe/London",
				prompt: "Start my workout.",
			},
		});
	}
}

Think Workflows

使用 ThinkWorkflowstep.prompt() 在 Cloudflare Workflow 内部运行模型驱动的推理步骤,具有持久的类型化结构化输出、长时间等待和审批门槛。

import { z } from "zod";
import { ThinkWorkflow } from "@cloudflare/think/workflows";

const draftSchema = z.object({
	title: z.string(),
	summary: z.string(),
	labels: z.array(z.string()),
});

export class TriageWorkflow extends ThinkWorkflow {
	async run(event, step) {
		const draft = await step.prompt("triage-issue", {
			prompt: `Triage issue #${event.payload.issueNumber}`,
			output: draftSchema,
			timeout: "3 days",
		});

		await step.do("apply-labels", async () => {
			await this.agent.applyLabels(draft.labels);
		});
	}
}
import { z } from "zod";
import { ThinkWorkflow } from "@cloudflare/think/workflows";
import type { ThinkWorkflowStep } from "@cloudflare/think/workflows";
import type { AgentWorkflowEvent } from "agents/workflows";

const draftSchema = z.object({
	title: z.string(),
	summary: z.string(),
	labels: z.array(z.string()),
});

export class TriageWorkflow extends ThinkWorkflow<TriageAgent, Params> {
	async run(event: AgentWorkflowEvent<Params>, step: ThinkWorkflowStep) {
		const draft = await step.prompt("triage-issue", {
			prompt: `Triage issue #${event.payload.issueNumber}`,
			output: draftSchema,
			timeout: "3 days",
		});

		await step.do("apply-labels", async () => {
			await this.agent.applyLabels(draft.labels);
		});
	}
}

针对持久聊天恢复的生产硬化

持久聊天轮次一直被设计为在轮次途中部署或 Durable Object 驱逐后存活。此版本是针对该机制进行生产硬化的重大更新。

  • 在部署期间具有更好的恢复能力。 轮次现在可以度过持续部署和驱逐,而不会丢失已完成的工作,也不会重新运行已经运行过的工具。
  • 实时的 “recovering…” 信号。 useAgentChat 暴露了一个新的 isRecovering 标志,因此恢复中的轮次会显示进度,而不是看起来像冻结了一样。大多数 UI 将 isStreaming || isRecovering 渲染为“忙碌(busy)”。
  • 停滞的流恢复。 设置 chatStreamStallTimeoutMs 可以将挂起的提供商流路由到相同的恢复路径中,而不是留下一个无限旋转的加载指示器(spinner)。
  • 子 agent 重新挂载。 在父节点恢复时,正在运行的 agentTool() 子节点会重新挂载到其结果上,而不是被放弃并重新运行,因此长期运行的子节点在部署下不再丢失工作。

MCP 传输改进

  • 可恢复的流 — 基于服务器发送事件(SSE)的正在运行的工具调用可在连接中断时存活。客户端使用 Last-Event-ID 重新连接并回放它们遗漏的任何内容。
  • 可读的服务器 IDaddMcpServer 接受一个可选的 id,因此工具会呈现为可读的键(例如 tool_github_create_pull_request),而不是不透明的连接 ID。
  • 更好地处理并发请求 — 重叠的 JSON-RPC 请求现在可以跨 HTTP 和 RPC 传输正确关联到其响应。

其他改进

  • 压缩SessiontokenCounter 现在还驱动压缩边界决策(“压缩什么”),而不仅仅是触发/不触发。
  • @cloudflare/worker-bundler — 为 createWorker 添加了 virtualModules 选项,以便在打包(bundling)期间提供内存中模块源。
  • 客户端工具继续运行 — 并行工具结果现在合并为一个单一的继续,立即恢复请求会附加到挂起的继续上,并且服务器端 needsApproval 继续会在批准后可靠地恢复。

升级

要更新到最新版本:

npm i agents@latest @cloudflare/think@latest @cloudflare/ai-chat@latest

有关更多信息,请参阅 Agents API 参考聊天 Agent 文档

在 Wrangler 和 Vite 中通过 Cloudflare Tunnel 共享本地开发服务器

现在,当使用 WranglerCloudflare Vite 插件时,您可以通过 Cloudflare Tunnel 共享本地开发会话并获得一个公共 URL。当您需要共享预览、测试 Webhook 或从其他设备访问您的应用程序时,这非常有用。

Vite 本地开发隧道演示

这使您可以:

要启动隧道,请在开发服务器运行时在 Wrangler 中按 t 或在 Vite 中按 t + Enter。有关设置命名隧道的详细信息,请参阅共享本地开发服务器

Hyperdrive 开放数据库连接池大小指标

您现在可以查看 Hyperdrive 数据库连接池的大小,从而使您能够自诊断连接问题。使用 Cloudflare 仪表板或 GraphQL Analytics API 中的 hyperdrivePoolSizesAdaptiveGroups 数据集,您可以查看每个配置的 waitingClientscurrentPoolSizeavailablePoolSlotsmaxPoolSize

Cloudflare 仪表板中每个 Hyperdrive 配置的 **Metrics(指标)**选项卡中添加了一个新的 **Pool connections(连接池连接)**图表。您可以使用位置选择器,按机场代码钻取托管连接池的特定位置。

Hyperdrive 池大小指标图表

该图表显示:

  • Waiting clients(等待中的客户端):等待可用连接的客户端请求。
  • Open connections(打开的连接):到您数据库的活动连接。
  • Pool size maximum(最大连接池大小):您配置的源站连接限制。

连接争用表现为等待中的客户端激增,或者当打开的连接持续接近最大连接池大小时。如果您的打开连接经常接近此限制,请考虑联系 Cloudflare 以提高您的 Hyperdrive 连接限制

连接池大小指标

GraphQL Analytics API 中的 hyperdrivePoolSizesAdaptiveGroups 数据集为每个 Hyperdrive 配置公开了以下关键连接池指标:

avg 下:

  • currentPoolSize — 当前在池中打开的平均连接数。
  • availablePoolSlots — 可供检出的平均连接池连接数。
  • waitingClients — 等待池中连接的平均客户端数。

max 下:

  • maxPoolSize — 配置的连接池最大大小。
  • currentPoolSize — 池中打开的峰值连接数。
  • waitingClients — 等待池中连接的峰值客户端数。

有关更多信息,请参阅 Metrics and analyticsConnection pooling

Workers 仪表板中新增的域名(Domains)选项卡

在您的 Worker 仪表板中,现在有一个专用的 Domains(域名) 选项卡,您可以在其中通过 Cloudflare Registrar 购买新域名并使其自动连接,添加现有域名,并在一个地方管理所有 Worker 的路由。

Workers 仪表板中新增的域名(Domains)选项卡

您还可以启用或禁用您的 workers.dev 子域名预览 URL (Preview URLs),将它们置于 Cloudflare Access 保护之下以要求登录,并直接跳转到任何已连接域名的 分析 或域名概览。

要开始使用,请转到 Workers & Pages,选择一个 Worker,然后打开 Domains(域名) 选项卡。

Go to Workers & Pages ↗

Agents SDK v0.12.4:对话恢复、路由重试、持久化 Think 提交及 Voice 连接控制

Agents SDK 的最新版本带来了更可靠的对话恢复、修复了重连时的 Agent 状态同步、添加了 Think 的持久化提交、暴露了路由重试配置,并为 Voice agents 添加了连接控制。

对话恢复改进

@cloudflare/ai-chat 现在在浏览器或客户端流中断时保持服务端 turn 继续运行。这对于长时间运行的 AI 响应场景非常有用,例如用户刷新页面、关闭标签页或临时断线。调用 stop() 仍会取消服务端 turn。

如果浏览器或客户端中止也应取消服务端 turn,请设置 cancelOnClientAbort: true

const chat = useAgentChat({
	agent: "assistant",
	name: "user-123",
	cancelOnClientAbort: true,
});
const chat = useAgentChat({
	agent: "assistant",
	name: "user-123",
	cancelOnClientAbort: true,
});

主要 bug 修复:

  • 对话流恢复协商不再在 replay 与关闭的 WebSocket 连接竞争时抛出异常。
  • 恢复的对话续传不再在原始 socket 在终端响应前断开时,导致 useAgentChat 卡在流式传输状态。
  • 审批自动续传保留推理部分,并在最终消息中持久化续传推理。
  • 当恢复的流从备用观察路径切换到传输拥有的流时,isServerStreaming 现在能正确重置。

Agent 状态和路由修复

[email protected] 防止在 WebSocket 连接设置期间出现重复的初始状态帧。这避免了过时的初始状态消息覆盖客户端已发送的状态更新。

当工具调用跨越 Durable Object 重启时,Agent 恢复也更加可靠。恢复现在会将用户完成钩子推迟到 agent 启动后,并隔离钩子失败,因此一个失败的钩子不会阻止其他恢复的运行完成。

getAgentByName() 现在支持 routingRetry,用于处理瞬态 Durable Object 路由失败:

import { getAgentByName } from "agents";

const agent = await getAgentByName(env.AssistantAgent, "user-123", {
	routingRetry: {
		maxAttempts: 3,
	},
});
import { getAgentByName } from "agents";

const agent = await getAgentByName(env.AssistantAgent, "user-123", {
	routingRetry: {
		maxAttempts: 3,
	},
});

持久化 Think 提交

@cloudflare/think 现在支持持久化的程序化提交。submitMessages() 提供持久化接受、幂等重试、状态检查、取消和清理功能,适用于应在调用方返回后继续运行的服务器驱动 turn。

Think.chat() RPC turn 现在在对话恢复 fiber 内运行并持久化其流式数据块。中断的子 agent turn 可以恢复部分输出,而不必从头开始。

ChatOptions.tools 已从 TypeScript API 中移除。请在子 agent 上定义持久化工具,或使用 agent 工具进行编排。遗留调用者传入的运行时 options.tools 值将被忽略并产生警告。

Think 消息裁剪行为变更

@cloudflare/think 默认不再对模型上下文应用 pruneMessages({ toolCalls: "before-last-2-messages" })。以前的默认行为可能会从较长的多轮流程中剥离客户端工具结果。

truncateOlderMessages 仍照常运行,因此上下文成本保持有界。依赖旧的激进裁剪行为的子类可以从 beforeTurn 重新启用:

import { Think } from "@cloudflare/think";
import { pruneMessages } from "ai";

export class MyAgent extends Think {
	beforeTurn(ctx) {
		return {
			messages: pruneMessages({
				messages: ctx.messages,
				toolCalls: "before-last-2-messages",
			}),
		};
	}
}
import { Think } from "@cloudflare/think";
import { pruneMessages } from "ai";

export class MyAgent extends Think<Env> {
	beforeTurn(ctx) {
		return {
			messages: pruneMessages({
				messages: ctx.messages,
				toolCalls: "before-last-2-messages",
			}),
		};
	}
}

Voice agent 连接控制

@cloudflare/voiceuseVoiceAgent 添加了 enabled 选项。React 应用现在可以延迟创建和连接 VoiceClient,直到所需条件(如能力令牌)就绪。

const voice = useVoiceAgent({
	agent: "MyVoiceAgent",
	enabled: Boolean(token),
});
const voice = useVoiceAgent({
	agent: "MyVoiceAgent",
	enabled: Boolean(token),
});

此版本还修复了 Workers AI 语音转文字会话的边界情况,以及 AI SDK textStream 响应中 withVoice 文本流的问题。

其他改进

  • Streamable HTTP 路由 — 当没有独立 SSE 流可用时,服务器到客户端的请求现在通过原始 POST 流路由。
  • 结构化工具输出 — 裁剪旧消息或超大持久化行时会保留工具输出的形状。
  • 非对话 Think 工具步骤 — Think agent 工具子项可在不发出助手文本的情况下完成,并可通过 getAgentToolOutput 返回结构化输出。
  • 子 agent 调度 — 当拥有 facet 注册条目不再存在时,过时的子 agent 调度行会被清理。
  • @cloudflare/codemode — 添加了带有 iframe sandbox 执行器的浏览器安全导出,并在 sandbox 内解析 OpenAPI 规范以避免 Worker Loader RPC 大小限制。

升级

升级到最新版本:

npm i agents@latest @cloudflare/ai-chat@latest @cloudflare/think@latest @cloudflare/voice@latest

更多信息请参阅 Agents API 参考对话 agents 文档