将 Cloudflare Workflows 与 Agent 集成,实现持久的多步骤后台处理,同时由 Agent 处理实时通信。
扩展 AgentWorkflow 以带类型地访问发起方 Agent:
import { AgentWorkflow } from "agents/workflows";
export class ProcessingWorkflow extends AgentWorkflow {
async run(event, step) {
const params = event.payload;
const result = await step.do("process-data", async () => {
return processData(params.data);
});
// Non-durable: progress reporting (may repeat on retry)
await this.reportProgress({
step: "process",
status: "complete",
percent: 0.5,
});
// Broadcast to connected WebSocket clients
this.broadcastToClients({ type: "update", taskId: params.taskId });
await step.do("save-results", async () => {
// Call Agent methods via RPC
await this.agent.saveResult(params.taskId, result);
});
// Durable: idempotent, won't repeat on retry
await step.reportComplete(result);
return result;
}
}import { AgentWorkflow } from "agents/workflows";
import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows";
import type { MyAgent } from "./agent";
type TaskParams = { taskId: string; data: string };
export class ProcessingWorkflow extends AgentWorkflow<MyAgent, TaskParams> {
async run(event: AgentWorkflowEvent<TaskParams>, step: AgentWorkflowStep) {
const params = event.payload;
const result = await step.do("process-data", async () => {
return processData(params.data);
});
// Non-durable: progress reporting (may repeat on retry)
await this.reportProgress({
step: "process",
status: "complete",
percent: 0.5,
});
// Broadcast to connected WebSocket clients
this.broadcastToClients({ type: "update", taskId: params.taskId });
await step.do("save-results", async () => {
// Call Agent methods via RPC
await this.agent.saveResult(params.taskId, result);
});
// Durable: idempotent, won't repeat on retry
await step.reportComplete(result);
return result;
}
}使用 runWorkflow() 启动并追踪 workflow:
import { Agent } from "agents";
export class MyAgent extends Agent {
async startTask(taskId, data) {
const instanceId = await this.runWorkflow("PROCESSING_WORKFLOW", {
taskId,
data,
});
return { instanceId };
}
async onWorkflowProgress(workflowName, instanceId, progress) {
this.broadcast(JSON.stringify({ type: "workflow-progress", progress }));
}
async onWorkflowComplete(workflowName, instanceId, result) {
console.log(`Workflow completed:`, result);
}
async saveResult(taskId, result) {
this
.sql`INSERT INTO results (task_id, data) VALUES (${taskId}, ${JSON.stringify(result)})`;
}
}import { Agent } from "agents";
export class MyAgent extends Agent {
async startTask(taskId: string, data: string) {
const instanceId = await this.runWorkflow("PROCESSING_WORKFLOW", {
taskId,
data,
});
return { instanceId };
}
async onWorkflowProgress(
workflowName: string,
instanceId: string,
progress: unknown,
) {
this.broadcast(JSON.stringify({ type: "workflow-progress", progress }));
}
async onWorkflowComplete(
workflowName: string,
instanceId: string,
result?: unknown,
) {
console.log(`Workflow completed:`, result);
}
async saveResult(taskId: string, result: unknown) {
this
.sql`INSERT INTO results (task_id, data) VALUES (${taskId}, ${JSON.stringify(result)})`;
}
}{
"name": "my-app",
"main": "src/index.ts",
// Set this to today's date
"compatibility_date": "2026-08-17",
"durable_objects": {
"bindings": [{ "name": "MY_AGENT", "class_name": "MyAgent" }],
},
"workflows": [
{
"name": "processing-workflow",
"binding": "PROCESSING_WORKFLOW",
"class_name": "ProcessingWorkflow",
},
],
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }],
}name = "my-app"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-17"
[[durable_objects.bindings]]
name = "MY_AGENT"
class_name = "MyAgent"
[[workflows]]
name = "processing-workflow"
binding = "PROCESSING_WORKFLOW"
class_name = "ProcessingWorkflow"
[[migrations]]
tag = "v1"
new_sqlite_classes = [ "MyAgent" ]与 Agents 集成的 Workflows 基类。
| 参数 | 描述 |
|---|---|
AgentType |
用于带类型 RPC 的 Agent 类类型 |
Params |
传给 Workflow 的参数 |
ProgressType |
进度报告类型(默认为 DefaultProgress) |
Env |
环境类型(默认为 Cloudflare.Env) |
| 属性 | 类型 | 描述 |
|---|---|---|
agent |
Stub | 用于调用 Agent 方法的带类型 stub。对于从子 Agent 启动的 Workflow,这是回到发起方面的仅 RPC stub;HTTP 或 WebSocket fetch() 流量请使用子 Agent 路由 |
instanceId |
string | Workflow 实例 ID |
workflowName |
string | Workflow 绑定名称 |
env |
Env | 环境绑定 |
这些方法可能在重试时重复执行。用于轻量、高频更新。
向 Agent 报告进度。触发 onWorkflowProgress 回调。
await this.reportProgress({
step: "processing",
status: "running",
percent: 0.5,
});await this.reportProgress({
step: "processing",
status: "running",
percent: 0.5,
});向连接到 Agent 的所有 WebSocket 客户端广播消息。
this.broadcastToClients({ type: "update", data: result });this.broadcastToClients({ type: "update", data: result });等待审批事件。若被拒绝则抛出 WorkflowRejectedError。
const approval = await this.waitForApproval(step, {
timeout: "7 days",
});const approval = await this.waitForApproval<{ approvedBy: string }>(step, {
timeout: "7 days",
});这些方法具有幂等性,重试时不会重复执行。用于必须持久化的状态变更。
| 方法 | 描述 |
|---|---|
step.reportComplete(result?) |
报告成功完成 |
step.reportError(error) |
报告错误 |
step.sendEvent(event) |
向 Agent 发送自定义事件 |
step.updateAgentState(state) |
替换 Agent 状态(广播到客户端) |
step.mergeAgentState(partial) |
合并到 Agent 状态(广播到客户端) |
step.resetAgentState() |
将 Agent 状态重置为 initialState |
type DefaultProgress = {
step?: string;
status?: "pending" | "running" | "complete" | "error";
message?: string;
percent?: number;
[key: string]: unknown;
};Agent 类上可用于 Workflow 管理的方法。
启动 workflow 实例并在 Agent 数据库中追踪。
参数:
| 参数 | 类型 | 描述 |
|---|---|---|
workflowName |
string | env 中的 Workflow 绑定名称 |
params |
object | 传给 Workflow 的参数 |
options.id |
string | 自定义 Workflow ID(未提供则自动生成) |
options.metadata |
object | 用于查询的元数据(不会传给 Workflow) |
options.agentBinding |
string | Agent 绑定名称(未提供则自动检测)。从子 Agent 调用时,这是根 Agent 绑定名称 |
返回值: Promise<string> — Workflow 实例 ID
const instanceId = await this.runWorkflow(
"MY_WORKFLOW",
{ taskId: "123" },
{
metadata: { userId: "user-456", priority: "high" },
},
);const instanceId = await this.runWorkflow(
"MY_WORKFLOW",
{ taskId: "123" },
{
metadata: { userId: "user-456", priority: "high" },
},
);子 Agent 可直接调用 this.runWorkflow()。Workflow 在发起方子 Agent 的 SQLite 数据库中跟踪,AgentWorkflow 内的 this.agent 将 RPC、回调、状态更新与广播路由回同一子 Agent。
父 Agent 不会自动列出或控制子 Agent 启动的 Workflow。SubAgentStub<T> 仅暴露用户定义的方法,而非继承的 Agent 方法(如 approveWorkflow() 或 getWorkflow())。要从父 Agent 控制子 Agent 启动的 Workflow,请在子 Agent 上定义小型包装方法,并通过子 Agent stub 调用这些包装。
export class ParentAgent extends Agent {
async startChildWorkflow(childName, task) {
const child = await this.subAgent(ChildAgent, childName);
return child.startWorkflow(task);
}
async approveChildWorkflow(childName, workflowId) {
const child = await this.subAgent(ChildAgent, childName);
return child.approveChildWorkflow(workflowId);
}
}
export class ChildAgent extends Agent {
async startWorkflow(task) {
return this.runWorkflow("CHILD_WORKFLOW", { task });
}
async approveChildWorkflow(workflowId) {
return this.approveWorkflow(workflowId);
}
async getChildWorkflow(workflowId) {
return this.getWorkflow(workflowId);
}
}export class ParentAgent extends Agent {
async startChildWorkflow(childName: string, task: string) {
const child = await this.subAgent(ChildAgent, childName);
return child.startWorkflow(task);
}
async approveChildWorkflow(childName: string, workflowId: string) {
const child = await this.subAgent(ChildAgent, childName);
return child.approveChildWorkflow(workflowId);
}
}
export class ChildAgent extends Agent {
async startWorkflow(task: string) {
return this.runWorkflow("CHILD_WORKFLOW", { task });
}
async approveChildWorkflow(workflowId: string) {
return this.approveWorkflow(workflowId);
}
async getChildWorkflow(workflowId: string) {
return this.getWorkflow(workflowId);
}
}对于子 Agent 来源,AgentWorkflow.agent 是仅 RPC 的 stub。用它调用 Agent 方法,但外部 HTTP 或 WebSocket 路由请使用 routeSubAgentRequest() 或 /agents/{parent}/{name}/sub/{child}/{name} URL 形状,而非 this.agent.fetch()。
由于发起方身份会持久化在 Workflow 参数中,并在每次回调时重放,以下约束适用于所有 Workflow(子 Agent 与顶层相同):
- 回调按名称解析 Agent。 运行时使用
getAgentByName(...)重新解析发起方 Agent。若用原始 Durable Object ID(idFromString/get(id))而非名称寻址 Agent,回调会落到不同实例。请从按名称寻址的 Agent 启动 Workflow。 - 类名须在打包后保留。 发起路径以
constructor.name为键。配置打包器保留类名(esbuildkeepNames: true),以便进度、完成与this.agentRPC 能路由回正确 facet。 agentBinding是根绑定。 从子 Agent 传入options.agentBinding时,使用 根 Agent 的 Durable Object 绑定名称,而非子绑定。
向运行中的 workflow 发送事件。
await this.sendWorkflowEvent("MY_WORKFLOW", instanceId, {
type: "custom-event",
payload: { action: "proceed" },
});await this.sendWorkflowEvent("MY_WORKFLOW", instanceId, {
type: "custom-event",
payload: { action: "proceed" },
});获取 workflow 状态并更新追踪记录。
const status = await this.getWorkflowStatus("MY_WORKFLOW", instanceId);
// { status: 'running', output: null, error: null }const status = await this.getWorkflowStatus("MY_WORKFLOW", instanceId);
// { status: 'running', output: null, error: null }按 ID 获取已追踪的 workflow。
const workflow = this.getWorkflow(instanceId);
// { instanceId, workflowName, status, metadata, error, createdAt, ... }const workflow = this.getWorkflow(instanceId);
// { instanceId, workflowName, status, metadata, error, createdAt, ... }使用基于 cursor 的分页查询已追踪 workflow。返回包含 workflow、总数与下一页 cursor 的 WorkflowPage。
// Get running workflows (default limit is 50, max is 100)
const { workflows, total } = this.getWorkflows({ status: "running" });
// Filter by metadata
const { workflows: userWorkflows } = this.getWorkflows({
metadata: { userId: "user-456" },
});
// Pagination with cursor
const page1 = this.getWorkflows({
status: ["complete", "errored"],
limit: 20,
orderBy: "desc",
});
console.log(`Showing ${page1.workflows.length} of ${page1.total} workflows`);
// Get next page using cursor
if (page1.nextCursor) {
const page2 = this.getWorkflows({
status: ["complete", "errored"],
limit: 20,
orderBy: "desc",
cursor: page1.nextCursor,
});
}// Get running workflows (default limit is 50, max is 100)
const { workflows, total } = this.getWorkflows({ status: "running" });
// Filter by metadata
const { workflows: userWorkflows } = this.getWorkflows({
metadata: { userId: "user-456" },
});
// Pagination with cursor
const page1 = this.getWorkflows({
status: ["complete", "errored"],
limit: 20,
orderBy: "desc",
});
console.log(`Showing ${page1.workflows.length} of ${page1.total} workflows`);
// Get next page using cursor
if (page1.nextCursor) {
const page2 = this.getWorkflows({
status: ["complete", "errored"],
limit: 20,
orderBy: "desc",
cursor: page1.nextCursor,
});
}WorkflowPage 类型:
type WorkflowPage = {
workflows: WorkflowInfo[];
total: number; // Total matching workflows
nextCursor: string | null; // null when no more pages
};删除单条 workflow 实例追踪记录。删除成功返回 true,未找到返回 false。
删除符合条件的 workflow 实例追踪记录。
// Delete completed workflow instances older than 7 days
this.deleteWorkflows({
status: "complete",
createdBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
});
// Delete all errored and terminated workflows
this.deleteWorkflows({
status: ["errored", "terminated"],
});// Delete completed workflow instances older than 7 days
this.deleteWorkflows({
status: "complete",
createdBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
});
// Delete all errored and terminated workflows
this.deleteWorkflows({
status: ["errored", "terminated"],
});立即终止运行中的 workflow。将 status 设为 "terminated"。
await this.terminateWorkflow(instanceId);await this.terminateWorkflow(instanceId);暂停运行中的 workflow。之后可用 resumeWorkflow() 恢复。
await this.pauseWorkflow(instanceId);await this.pauseWorkflow(instanceId);恢复已暂停的 workflow。
await this.resumeWorkflow(instanceId);await this.resumeWorkflow(instanceId);使用相同 ID 从头重启 workflow 实例。
// Reset tracking (default) - clears timestamps and error fields
await this.restartWorkflow(instanceId);
// Preserve original timestamps
await this.restartWorkflow(instanceId, { resetTracking: false });// Reset tracking (default) - clears timestamps and error fields
await this.restartWorkflow(instanceId);
// Preserve original timestamps
await this.restartWorkflow(instanceId, { resetTracking: false });批准等待中的 workflow。在 workflow 中与 waitForApproval() 配合使用。
await this.approveWorkflow(instanceId, {
reason: "Approved by admin",
metadata: { approvedBy: userId },
});await this.approveWorkflow(instanceId, {
reason: "Approved by admin",
metadata: { approvedBy: userId },
});拒绝等待中的 workflow。会导致 waitForApproval() 抛出 WorkflowRejectedError。
await this.rejectWorkflow(instanceId, { reason: "Request denied" });await this.rejectWorkflow(instanceId, { reason: "Request denied" });重命名 workflow binding 后迁移已追踪 workflow。
class MyAgent extends Agent {
async onStart() {
this.migrateWorkflowBinding("OLD_WORKFLOW", "NEW_WORKFLOW");
}
}class MyAgent extends Agent {
async onStart() {
this.migrateWorkflowBinding("OLD_WORKFLOW", "NEW_WORKFLOW");
}
}在 Agent 中 override 这些方法以处理 workflow 事件:
| 回调 | 参数 | 描述 |
|---|---|---|
onWorkflowProgress |
workflowName, instanceId, progress |
Workflow 报告进度时调用 |
onWorkflowComplete |
workflowName, instanceId, result? |
Workflow 完成时调用 |
onWorkflowError |
workflowName, instanceId, error |
Workflow 出错时调用 |
onWorkflowEvent |
workflowName, instanceId, event |
Workflow 发送事件时调用 |
onWorkflowCallback |
callback: WorkflowCallback |
所有回调类型时调用 |
class MyAgent extends Agent {
async onWorkflowProgress(workflowName, instanceId, progress) {
this.broadcast(
JSON.stringify({ type: "progress", workflowName, instanceId, progress }),
);
}
async onWorkflowComplete(workflowName, instanceId, result) {
console.log(`${workflowName}/${instanceId} completed`);
}
async onWorkflowError(workflowName, instanceId, error) {
console.error(`${workflowName}/${instanceId} failed:`, error);
}
}class MyAgent extends Agent {
async onWorkflowProgress(
workflowName: string,
instanceId: string,
progress: unknown,
) {
this.broadcast(
JSON.stringify({ type: "progress", workflowName, instanceId, progress }),
);
}
async onWorkflowComplete(
workflowName: string,
instanceId: string,
result?: unknown,
) {
console.log(`${workflowName}/${instanceId} completed`);
}
async onWorkflowError(
workflowName: string,
instanceId: string,
error: string,
) {
console.error(`${workflowName}/${instanceId} failed:`, error);
}
}使用 runWorkflow() 启动的 Workflow 会自动追踪在发起方 Agent 的内部数据库中。可使用上文方法(getWorkflow()、getWorkflows()、deleteWorkflow() 等)查询、筛选与管理 Workflow。
| 状态 | 描述 |
|---|---|
queued |
等待启动 |
running |
正在执行 |
paused |
用户暂停 |
waiting |
等待事件 |
complete |
成功完成 |
errored |
出错失败 |
terminated |
手动终止 |
在 runWorkflow() 中使用 metadata 选项存储可查询信息(如 user ID 或任务类型),以便之后用 getWorkflows() 筛选。
import { AgentWorkflow } from "agents/workflows";
export class ApprovalWorkflow extends AgentWorkflow {
async run(event, step) {
const request = await step.do("prepare", async () => {
return { ...event.payload, preparedAt: Date.now() };
});
await this.reportProgress({
step: "approval",
status: "pending",
message: "Awaiting approval",
});
// Throws WorkflowRejectedError if rejected
const approval = await this.waitForApproval(step, {
timeout: "7 days",
});
console.log("Approved by:", approval?.approvedBy);
const result = await step.do("execute", async () => {
return executeRequest(request);
});
await step.reportComplete(result);
return result;
}
}
class MyAgent extends Agent {
async handleApproval(instanceId, userId) {
await this.approveWorkflow(instanceId, {
reason: "Approved by admin",
metadata: { approvedBy: userId },
});
}
async handleRejection(instanceId, reason) {
await this.rejectWorkflow(instanceId, { reason });
}
}import { AgentWorkflow } from "agents/workflows";
import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows";
export class ApprovalWorkflow extends AgentWorkflow<MyAgent, RequestParams> {
async run(event: AgentWorkflowEvent<RequestParams>, step: AgentWorkflowStep) {
const request = await step.do("prepare", async () => {
return { ...event.payload, preparedAt: Date.now() };
});
await this.reportProgress({
step: "approval",
status: "pending",
message: "Awaiting approval",
});
// Throws WorkflowRejectedError if rejected
const approval = await this.waitForApproval<{ approvedBy: string }>(step, {
timeout: "7 days",
});
console.log("Approved by:", approval?.approvedBy);
const result = await step.do("execute", async () => {
return executeRequest(request);
});
await step.reportComplete(result);
return result;
}
}
class MyAgent extends Agent {
async handleApproval(instanceId: string, userId: string) {
await this.approveWorkflow(instanceId, {
reason: "Approved by admin",
metadata: { approvedBy: userId },
});
}
async handleRejection(instanceId: string, reason: string) {
await this.rejectWorkflow(instanceId, { reason });
}
}import { AgentWorkflow } from "agents/workflows";
export class ResilientWorkflow extends AgentWorkflow {
async run(event, step) {
const result = await step.do(
"call-api",
{
retries: { limit: 5, delay: "10 seconds", backoff: "exponential" },
timeout: "5 minutes",
},
async () => {
const response = await fetch("https://api.example.com/process", {
method: "POST",
body: JSON.stringify(event.payload),
});
if (!response.ok) throw new Error(`API error: ${response.status}`);
return response.json();
},
);
await step.reportComplete(result);
return result;
}
}import { AgentWorkflow } from "agents/workflows";
import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows";
export class ResilientWorkflow extends AgentWorkflow<MyAgent, TaskParams> {
async run(event: AgentWorkflowEvent<TaskParams>, step: AgentWorkflowStep) {
const result = await step.do(
"call-api",
{
retries: { limit: 5, delay: "10 seconds", backoff: "exponential" },
timeout: "5 minutes",
},
async () => {
const response = await fetch("https://api.example.com/process", {
method: "POST",
body: JSON.stringify(event.payload),
});
if (!response.ok) throw new Error(`API error: ${response.status}`);
return response.json();
},
);
await step.reportComplete(result);
return result;
}
}Workflow 可通过 step 持久更新 Agent 状态,并自动广播到所有已连接客户端:
import { AgentWorkflow } from "agents/workflows";
export class StatefulWorkflow extends AgentWorkflow {
async run(event, step) {
// Replace entire state (durable, broadcasts to clients)
await step.updateAgentState({
currentTask: {
id: event.payload.taskId,
status: "processing",
startedAt: Date.now(),
},
});
const result = await step.do("process", async () =>
processTask(event.payload),
);
// Merge partial state (durable, keeps existing fields)
await step.mergeAgentState({
currentTask: { status: "complete", result, completedAt: Date.now() },
});
await step.reportComplete(result);
return result;
}
}import { AgentWorkflow } from "agents/workflows";
import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows";
export class StatefulWorkflow extends AgentWorkflow<MyAgent, TaskParams> {
async run(event: AgentWorkflowEvent<TaskParams>, step: AgentWorkflowStep) {
// Replace entire state (durable, broadcasts to clients)
await step.updateAgentState({
currentTask: {
id: event.payload.taskId,
status: "processing",
startedAt: Date.now(),
},
});
const result = await step.do("process", async () =>
processTask(event.payload),
);
// Merge partial state (durable, keeps existing fields)
await step.mergeAgentState({
currentTask: { status: "complete", result, completedAt: Date.now() },
});
await step.reportComplete(result);
return result;
}
}为领域特定报告定义自定义进度类型:
import { AgentWorkflow } from "agents/workflows";
// Custom progress type for data pipeline
// Workflow with custom progress type (3rd type parameter)
export class ETLWorkflow extends AgentWorkflow {
async run(event, step) {
await this.reportProgress({
stage: "extract",
recordsProcessed: 0,
totalRecords: 1000,
currentTable: "users",
});
// ... processing
}
}
// Agent receives typed progress
class MyAgent extends Agent {
async onWorkflowProgress(workflowName, instanceId, progress) {
const p = progress;
console.log(`Stage: ${p.stage}, ${p.recordsProcessed}/${p.totalRecords}`);
}
}import { AgentWorkflow } from "agents/workflows";
import type { AgentWorkflowEvent, AgentWorkflowStep } from "agents/workflows";
// Custom progress type for data pipeline
type PipelineProgress = {
stage: "extract" | "transform" | "load";
recordsProcessed: number;
totalRecords: number;
currentTable?: string;
};
// Workflow with custom progress type (3rd type parameter)
export class ETLWorkflow extends AgentWorkflow<
MyAgent,
ETLParams,
PipelineProgress
> {
async run(event: AgentWorkflowEvent<ETLParams>, step: AgentWorkflowStep) {
await this.reportProgress({
stage: "extract",
recordsProcessed: 0,
totalRecords: 1000,
currentTable: "users",
});
// ... processing
}
}
// Agent receives typed progress
class MyAgent extends Agent {
async onWorkflowProgress(
workflowName: string,
instanceId: string,
progress: unknown,
) {
const p = progress as PipelineProgress;
console.log(`Stage: ${p.stage}, ${p.recordsProcessed}/${p.totalRecords}`);
}
}内部 cf_agents_workflows 表可能无限增长,因此应实现保留策略:
class MyAgent extends Agent {
// Option 1: Delete on completion
async onWorkflowComplete(workflowName, instanceId, result) {
// Process result first, then delete
this.deleteWorkflow(instanceId);
}
// Option 2: Scheduled cleanup (keep recent history)
async cleanupOldWorkflows() {
this.deleteWorkflows({
status: ["complete", "errored"],
createdBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
});
}
// Option 3: Keep all history for compliance/auditing
// Don't call deleteWorkflows() - query historical data as needed
}class MyAgent extends Agent {
// Option 1: Delete on completion
async onWorkflowComplete(
workflowName: string,
instanceId: string,
result?: unknown,
) {
// Process result first, then delete
this.deleteWorkflow(instanceId);
}
// Option 2: Scheduled cleanup (keep recent history)
async cleanupOldWorkflows() {
this.deleteWorkflows({
status: ["complete", "errored"],
createdBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
});
}
// Option 3: Keep all history for compliance/auditing
// Don't call deleteWorkflows() - query historical data as needed
}// Direct RPC call (typed)
await this.agent.updateTaskStatus(taskId, "processing");
const data = await this.agent.getData(taskId);
// Non-durable callbacks (may repeat on retry, use for frequent updates)
await this.reportProgress({ step: "process", percent: 0.5 });
this.broadcastToClients({ type: "update", data });
// Durable callbacks via step (idempotent, won't repeat on retry)
await step.reportComplete(result);
await step.reportError("Something went wrong");
await step.sendEvent({ type: "custom", data: {} });
// Durable state synchronization via step (broadcasts to clients)
await step.updateAgentState({ status: "processing" });
await step.mergeAgentState({ progress: 0.5 });// Direct RPC call (typed)
await this.agent.updateTaskStatus(taskId, "processing");
const data = await this.agent.getData(taskId);
// Non-durable callbacks (may repeat on retry, use for frequent updates)
await this.reportProgress({ step: "process", percent: 0.5 });
this.broadcastToClients({ type: "update", data });
// Durable callbacks via step (idempotent, won't repeat on retry)
await step.reportComplete(result);
await step.reportError("Something went wrong");
await step.sendEvent({ type: "custom", data: {} });
// Durable state synchronization via step (broadcasts to clients)
await step.updateAgentState({ status: "processing" });
await step.mergeAgentState({ progress: 0.5 });// Send event to waiting workflow
await this.sendWorkflowEvent("MY_WORKFLOW", instanceId, {
type: "custom-event",
payload: { action: "proceed" },
});
// Approve/reject workflows using convenience methods
await this.approveWorkflow(instanceId, {
reason: "Approved by admin",
metadata: { approvedBy: userId },
});
await this.rejectWorkflow(instanceId, { reason: "Request denied" });// Send event to waiting workflow
await this.sendWorkflowEvent("MY_WORKFLOW", instanceId, {
type: "custom-event",
payload: { action: "proceed" },
});
// Approve/reject workflows using convenience methods
await this.approveWorkflow(instanceId, {
reason: "Approved by admin",
metadata: { approvedBy: userId },
});
await this.rejectWorkflow(instanceId, { reason: "Request denied" });- 保持 workflow 聚焦 — 每个逻辑任务一个 workflow
- 使用有意义的 step 名称 — 有助于调试与可观测性
- 定期报告进度 — 让用户了解进展
- 优雅处理错误 — 抛出前使用
reportError() - 清理已完成 workflow — 为追踪表实现保留策略
- 处理 workflow binding 重命名 — 在
wrangler.jsonc中重命名 workflow binding 时使用migrateWorkflowBinding()
| 约束 | 限制 |
|---|---|
| 最大 step 数 | 每个 workflow 10,000(默认)/ 最高可配置 25,000 |
| State 大小 | 每个 workflow 10 MB |
| 事件等待时间 | 最长 1 年 |
| Step 执行时间 | 每个 step 30 分钟 |
Workflow 无法直接打开 WebSocket 连接。请通过 Agent 使用 broadcastToClients() 与已连接客户端通信。