工作流 📋 7 个步骤 第 457 / 460 篇

用 Cloudflare Workflows 编排持久化多步 Agent 任务(agents/workflows SDK)

长任务最怕中途崩溃丢进度、重试逻辑写到吐。Cloudflare Workflows 把每一步都持久化到云端,进程挂了也能从断点续跑,还内置重试、超时与人工审批。本文用 agents/workflows SDK 搭一条「下载 → 处理 → 审批 → 通知」的多步 Agent 流水线,覆盖 step.do、waitForApproval 与从 Agent 类触发。

2026.09.20· 17 分钟阅读· 约 1161 字· ☁️ Cloudflare Workflows / 🤖 Cloudflare Agents SDK

你的 Agent 跑一个 20 分钟的长任务,跑到第 18 分钟进程崩了——进度全没,还得从零重来。更糟的是,付费、发邮件这种「副作用步骤」重复执行会出事故。Cloudflare Workflows 就是为这种场景生的:它把工作流每一步的状态都持久化在云端,任何一步失败都能从断点重试,且带 exactly-once 语义(同一步不会重复执行副作用)。

☁️ 本教程适合:要跑长任务 / 多步骤 Agent 的后端开发者、想给 Agent 加「可靠编排」的人。你需要一个 Cloudflare 账号,并装好 Node 与 Wrangler。

先搞懂:Workflows 解决什么?

和普通「写一个 async 函数顺序调 API」不同,Workflows 把每个 step.do() 当成一个可持久化、可恢复的检查点。一旦某步失败,引擎会从那一步(而不是开头)重启;引擎崩溃也无所谓,因为它不依赖内存里的状态。

裸 async 函数Cloudflare Workflows
崩了从零重跑,副作用重复从失败那步续跑,exactly-once
重试/超时要自己写step 内置 retries / timeout
人工审批要外接队列waitForApproval 原生支持

它不等于普通的「定时任务」。Workflows 面向有状态、多步骤、需要容错与人工介入的业务流;纯无状态短任务用 Workers Cron 更轻。

Step 1:建项目并装 agents/workflows

1 用官方模板起步
npm create cloudflare@latest -- my-agent-flow
# 选 "Hello World" Worker 模板
cd my-agent-flow
npm install agents
# agents 包内含 workflows 子模块
💡 确认你的 wrangler 已登录:wrangler login。Workflows 是 Cloudflare 托管能力,本地 dev 能跑,但完整持久化要在云端账号下生效。

Step 2:写第一个 Workflow(step.do 链)

2 把流程拆成可恢复的步骤

src/index.ts 里定义一个继承 WorkflowEntrypoint 的类,用 step.do() 包装每一步:

import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
import { Agent } from 'agents';

export class MyFlow extends WorkflowEntrypoint<Env, { url: string }> {
  async run(event: WorkflowEvent<{ url: string }>, step: WorkflowStep) {
    const url = event.payload.url;

    const raw = await step.do('download', async () => {
      const r = await fetch(url);
      return r.text();
    });

    const summary = await step.do('summarize', async () => {
      const agent = new Agent(...);
      return agent.run('总结这段内容:' + raw.slice(0, 4000));
    });

    return { summary };
  }
}

每个 step 的函数必须是「纯副作用 + 可重入」的:同样输入必须产出同样结果,因为失败时会重跑。不要把随机数、时间戳塞进 step 逻辑里还指望它不变。

Step 3:给步骤加重试与超时

3 别让一个慢接口拖垮整条流
const raw = await step.do('download', {
  retries: { limit: 3, delay: '5s', backoff: 'exponential' },
  timeout: '30s',
}, async () => {
  const r = await fetch(url);
  if (!r.ok) throw new Error('fetch failed: ' + r.status);
  return r.text();
});
💡 重试只在「抛错」时触发,且 step 本身具备 exactly-once——即便重试,已被标记为成功的下游不会重复。这正是它比手写重试安全的地方。

Step 4:人工审批 waitForApproval

4 敏感动作前先问人一句

发邮件、扣款、对外发布前,用 waitForApproval 暂停流程等人确认:

const approved = await step.waitForApproval({
  type: 'approval',
  timeout: '24h',
  // 可在 Dashboard 或 API 里 approve / reject
});
if (!approved) {
  return { status: 'rejected' };
}
await step.do('send-email', async () => { /* 真正发送 */ });

审批等待期间,工作流实例是「挂起」而非「空转」——不占计算、不计费空等,被人点通过后才从断点继续。这正是持久化的价值。

Step 5:从 Agent 类触发 + 共享状态

5 让 Agent 自己决定跑哪条流

agents 的 Agent 类里,用 runWorkflow() 触发,并用 updateAgentState / mergeAgentState 在多步间共享记忆:

class MyAgent extends Agent<Env, State> {
  async onRequest(req) {
    const instance = await this.runWorkflow('my-flow', {
      payload: { url: 'https://example.com/report' },
    });
    await this.setState({ lastRunId: instance.instanceId });
    return new Response('started ' + instance.instanceId);
  }
}
🚀 这样你的对话 Agent 就能「派发」长任务给 Workflow,自己不被长任务阻塞,任务状态还能跨消息保留。

Step 6 & 7:本地调试与云端部署

6 本地先跑通,再上云
wrangler dev
# 另开终端触发一次
curl -X POST localhost:8787/start -d '{"url":"https://example.com"}'

在本地能看到 step 的执行顺序与日志。确认无误后部署:

wrangler deploy
# 去 Cloudflare Dashboard → Workflows 看每次运行的甘特图与每步输入/输出
🎉 部署后,Dashboard 里每一步都可点开看「输入、输出、重试次数、耗时」,排错比看日志舒服太多。至此你已拥有一条崩了不丢进度、可人工把关的多步 Agent 流水线。

常见问题速查

现象大概率原因 & 解决
step 重跑后结果变了step 函数不纯(含随机/时间),把这类值提到 step 外或作为参数传入
本地能跑、云端卡住未 wrangler login 或 Workflows 功能未在该账号区域开启
审批一直 pending没人去 Dashboard / API 点 approve;检查 timeout 是否过期
想并行多步用 Promise.all 包多个 step.do,或拆成子工作流
← 返回教程中心