文章标题:Workflow SDK 5:为生产环境而构建
正文:

当我们首次推出 Workflow SDK 时,目标很简单:编写常规的异步 JavaScript,让 SDK 保证它在崩溃、部署和长时间等待中持续运行。
import { sleep } from "workflow";
export async function welcomeUser(email) { "use workflow";
const user = await createUser(email); await sendWelcomeEmail(user);
// Survives crashes and deployments // while it waits await sleep("3d"); await sendCheckInEmail(user);}
一个基础的持久化工作流
去年,我们交付的正是这样的产品,并配有 Vercel 一贯的世界级开发者体验。之后,我们观察了客户用它构建了什么。
在超过 40 亿个步骤和 7 亿次运行之后,两种清晰的模式浮现出来。
- 第一种是自动化:传统的工作流,用于移动数据、处理订单、协调后台任务、管理订阅,以及运行 ETL 和数据管道。
- 第二种是智能体与执行框架:智能体成本高昂且运行时间长,因此它们自然也需要持久性。
随着这些工作负载日趋成熟,Workflow 也随之成熟。我们的优先级始终是安全性、可靠性和性能。
以下是 Workflow SDK 5 如何在这三方面同时交付。
复制链接到标题更安全的工作流
Workflow 事件日志存储步骤参数和返回值,以便运行在崩溃或部署后能够恢复。这些数据可能包含敏感的客户信息、模型上下文、凭据和工具调用结果。持久化这些数据需要强有力的保护。
Workflow SDK 在数据离开你的代码之前,对每个负载进行端到端加密。Workflow 和步骤的输入输出、钩子负载以及流数据均使用 AES-256-GCM 加密,每次运行使用唯一密钥。启用加密后,任何 Workflow SDK 后端(包括 Vercel)只能看到并存储密文。明文在你的部署中或经授权的可观测性工具中解密。
你的部署:Workflow 和步骤代码
使用明文工作。SDK 对每次写入加密,对每次读取解密。
Workflow 后端:事件日志和流
仅存储密文。可见步骤名称、ID、时间戳和状态。
你的团队,按需访问:仪表盘或 CLI
在浏览器或终端中解密。需要访问项目的环境变量,并会被审计日志记录。
复制链接到标题在 Vercel 上零配置加密
在 Vercel 上,加密无需设置,也无需更改代码。每次运行的密钥派生自创建该运行的部署所作用域的密钥,因此一次运行只能解密自己的数据。你的工作流代码无需更改:
export async function onboardCustomer( customer: Customer,) { "use workflow";
// The customer record is stored // encrypted in the event log const account = await createAccount(customer); await sendWelcomeEmail(account.email); return account.id;}
async function createAccount( customer: Customer,) { "use step";
// ...and arrives here decrypted, // inside your deployment return db.accounts.create(customer);}
Workflow 和步骤负载在不更改应用逻辑的情况下被加密。
由于 Vercel 默认管理密钥,可观测性持续有效。名称、时间和状态始终可见,当你需要查看负载时,可以在仪表盘或 CLI 中解密。解密在你的浏览器或终端中进行,遵循与项目环境变量相同的权限,并且每个请求都会记录在你团队的审计日志中。
# Payloads show as 🔒 Encryptednpx workflow inspect run <run-id>
# Decrypts locally, if you have accessnpx workflow inspect run <run-id> --decrypt
检查加密负载,然后在获得授权的情况下本地解密。
复制链接到标题自托管 Worlds 上的加密
加密在 SDK 中实现,因此它也可以保护自托管 Worlds 上的负载,在它们到达存储、队列或流之前。
自定义 World 通过使用你的密钥管理实现 getEncryptionKeyForRun() 来启用加密。每次调用时为每个运行返回相同的 32 字节密钥,以便 SDK 可以加密新负载并在重放期间解密它们:
import type { World } from "@workflow/world";
type RunKeyProvider = World["getEncryptionKeyForRun"];
export const getEncryptionKeyForRun: RunKeyProvider = async (run) => { const runId = typeof run === "string" ? run : run.runId;
// Return the same 32 bytes for a run // every time, so replays can decrypt return keyStore.getRunKey(runId); };
为自定义 World 中的每次运行提供稳定的 32 字节加密密钥。
复制标题链接 v5 中的更多安全工作
跨运行写入也会被封存。当代码恢复另一个运行的 hook、在另一个部署中启动一次运行,或写入从另一个运行转发而来的流时,负载会使用目标运行的公钥加密。写入方可以为该运行加密,而无需读取其现有负载。
你也可以限制敏感数据的存储时长。将负载保留设置为 experimental_retention: 0 后,一次运行完成或失败时,输入、输出和流内容会被立即删除。运行的元数据仍可在可观测性中查看。
复制标题链接重新设计的追踪查看器
重新设计的追踪查看器让运行更易于导航,提供 span 搜索、缩放、小地图,以及开发期间的本地检查。
- enrichLeadenrichLeadenrichLead12s
- validateLeadvalidateLeadvalidateLead550ms
- fetchCompanyfetchCompanyfetchCompany2.45s
- findContactsfindContactsfindContacts3.35s
- scoreLeadscoreLeadscoreLead2.65s
- syncToCRMsyncToCRMsyncToCRM3.95s
- notifyTeamnotifyTeamnotifyTeam950ms
[
{
"leadId": "lead_1042",
"company": "Acme",
"domain": "acme.example"
}
]
{
"leadId": "lead_1042",
"recordId": "crm_1042",
"synced": true,
"score": 92,
"segment": "Enterprise",
"notified": true
}
运行属性是 v5 中的新功能。它们让你可以为一次运行附加可搜索的上下文,例如订单 ID,然后据此查找运行。属性是明文,因此不应包含机密信息。
复制标题链接各区域中的 Workflows
在 Workflow SDK 4 中,每次运行都位于 iad1。即使项目部署到多个区域,每次运行的事件日志、队列和流也只存储在一个区域,因此在其他任何地方运行的步骤都会发出跨区域请求来记录其进度。
对于 v5,我们将 Workflow 基础设施部署到了每个 Vercel Function 区域。每次运行都有自己的主区域:其状态、队列调度和流由它启动所在的区域提供,热路径上没有跨区域往返。
默认情况下,一次运行会在启动它的函数所在区域启动。部署到多个区域后,每次运行都会靠近触发它的用户,无需任何配置:
import { start } from "workflow/api";import { processOrder } from "@/workflows/process-order";
export async function POST(request: Request) { const order = await request.json();
// Runs in the
## 复制标题链接基础设施可靠性
区域隔离也提升了可靠性。一个区域发生故障,不必阻止健康区域中的新运行。对于配置了 Vercel Function 故障转移的项目,步骤可以在回退区域中执行,同时继续使用运行原始的主区域来保存状态。该状态仍固定在其主区域;在故障转移期间不会迁移。
借助匿名遥测数据以及与众多客户的紧密合作,我们发现并修复了 Workflow 运行时中数十个罕见的 bug 和竞态条件。Workflow SDK 还能自行从更多类型的间歇性网络错误中恢复。
因此,在使用 Workflow SDK 5 后,我们几乎看不到因平台或运行时 bug 导致的运行失败或停滞。
## 复制标题链接面向 Agent 的性能
在 Workflow SDK 4 中,每次步骤调用都涉及一次队列跳转来启动步骤,另一次队列跳转来继续工作流。这对于缓慢的后台自动化来说可以接受,但会给开发者如今正在构建的 AI 工作负载增加延迟。
Agent 循环和 harness 可能包含数千个顺序事件、高吞吐量的 token 流、工具链和动态子代理。在这种规模下,围绕每个步骤的网络和 CPU 工作成为了瓶颈。
在 Workflow SDK 5 中,我们重写了引擎的大部分内容,以尽量减少额外的队列跳转、不必要的网络和 CPU 工作。在测量的工作负载中,我们观察到测量延迟和开销有 1.6× 到 25× 的改进,同时保持相同的开发者体验,且没有引入重大破坏性变更。
以下基准测试在 Vercel 上比较 v5.2.0 与 v4.8.12。选择一个测量项来查看 v5 与 v4 的对比,然后播放或拖动解释器来确切了解每个基准测试测量的是什么。
## 首步时间(TTFS)
从你的应用调用 start() 到工作流第一个步骤的第一行代码运行所花费的时间。它涵盖创建和排队运行、运行工作流代码直到其第一个步骤,以及启动该步骤。
首步时间,快 2.4×
1// Your app2const t0 = Date.now() // clock starts3await start(myWorkflow, [input])4 5export async function myWorkflow(input) {6 "use workflow"7 await firstStep(input)8}9 10async function firstStep(input) {11 "use step"12 const t1 = Date.now() // clock stops13 await doWork()14}
Workflow SDK 5 包含数百项性能改进来实现这一点。以下是这些数字背后的一些主要变化:
更少的队列跳转
在 v4 中,每个步骤都通过队列交还执行权。在 v5 中,一次调用可以内联执行多个步骤,包括并行步骤,然后再让出以等待、等待钩子或接近超时。
运行时还避免了不必要的持久化往返,并将步骤创建合并到执行中。更少的队列和网络请求意味着更少的 CPU 工作和更低的运行时开销。在一个五步基准测试中,p75 步骤间开销从 618 ms 降至 109 ms。
增量重放
在一个 1,020 步的基准测试中,v4 的 p75 开销随事件日志增长:重放完整事件历史所需时间与其大小成正比。在最终采样范围内,开销达到 1,748 ms。在 v5.2.0 上,为 70 ms。完成全部 1,020 步的中位时间从 21.0 分钟降至 3.0 分钟。
步骤 101–120
步骤 1,001–1,020
WebSocket 流式传输
持久性不应使流式响应落后于其生产者。在 Vercel World 上,v5.2.0 默认通过 WebSocket 写入流。在一个重放 52.4 秒 agent 响应的基准测试中,中位交付时间从 226.1 秒降至 53.5 秒。
负载压缩减少了存储和传输的数据。AI token 流在压缩后平均缩小约 80%。
这些测量描述的是针对 Vercel World 的一个区域中的一个工作负载。它们是运行时开销的有用视图,而不是对每个应用的预测。
复制标题链接基准测试结果和方法
文章标题:Workflow SDK 5:为生产环境打造
正文: 测量于 2026 年 10 月 8 日,在 iad1 的 Vercel 生产环境,针对托管的 Vercel World 进行。每个版本使用同一应用的独立部署。步骤的输入和输出各为 1 KB 的 JSON。
部分结果 · v4.8.12 与 v5.2.0 对比
| 测量项 | v4.8.12 | v5.2.0 | 变化 |
|---|---|---|---|
| 首步,p75 | 418 ms | 172 ms | 快 2.4 倍 |
| 步骤之间,p75 | 618 ms | 109 ms | 快 5.7 倍 |
| 运行后期开销,p75 | 1,748 ms | 70 ms | 降低 25 倍 |
| 1,020 步,中位数 | 21.0 min | 3.0 min | 快 7 倍 |
| 恢复,p75 | 699 ms | 425 ms | 快 1.6 倍 |
| 流式传输,中位数 | 226.1 s | 53.5 s | 快 4.2 倍 |
| 分块传输时间,p75 | 172 ms | 102 ms | 快 1.7 倍 |
| 有分块延迟超过 1 s 的运行 | 6 / 10 | 0 / 10 | 减少 100% |
首步,p75
步骤之间,p75
运行后期开销,p75
1,020 步,中位数
流式传输,中位数
分块传输时间,p75
有分块延迟超过 1 s 的运行
包含尾部数据的完整结果见性能文档。
Copy link to headingWorlds:共享的持久化原语
Workflow SDK 的持久函数构建在 World 之上:这是用于存储进度、调度工作和交付流的接口。同一基础现在也支持 fx 和 durable-harness,后者为现有的 agent harness 增加持久化能力。
对共享存储、队列和流式传输基础设施的改进可以使 World 的任何使用者受益。Workflow 重放运行时的内部优化适用于 Workflow SDK;它们不会自动适用于每个 harness。
根据你想要的构建方式选择集成:
- Workflow SDK:使用 use workflow 和 use step 编写持久化应用逻辑。
- WorkflowAgent:使用 @ai-sdk/workflow 在工作流内运行 AI SDK agent 循环。
- fx:使用 libfx 嵌入并扩展原生编码 agent。
- durable-harness:保留现有的受支持 harness,并在其下方增加持久化能力。支持 Pi 和 OpenCode,并为 Vercel Sandbox 中的 Claude Code 和 Codex 提供实验性集成。
durable-harness:保留现有的受支持 harness,并在其下方增加持久化能力。
- 支持 Pi 和 OpenCode,并为 Vercel Sandbox 中的 Claude Code 和 Codex 提供实验性集成。
- eve:使用由 Workflow SDK 和 Worlds 原生驱动的持久会话构建 agent。
我们很快会在由 Worlds 提供持久化支持的 SDK 和框架目录中增加更多产品。
Copy link to heading使用 Workflow SDK 5 构建
除上述改进外,Workflow SDK 5 还新增了:
- 使用 AbortController 进行运行中取消
- 可搜索的运行属性
- 更多框架集成
v5 升级文档涵盖了变更内容。要开始构建新工作流,请安装 SDK:
pnpm add workflow@latest
安装最新的 Workflow SDK。
Workflow SDK 还有一个 Python SDK,现处于 beta 阶段,提供相同的持久工作流、步骤、sleep 和 hooks。