Skip to content
Cloudflare Docs

Workflows

What are Workflows?

Cloudflare Workflows provide durable, multi-step execution for tasks that need to survive failures, retry automatically, and wait for external events. When integrated with Agents, Workflows handle long-running background processing while Agents manage real-time communication.

Agents vs. Workflows

Agents and Workflows have complementary strengths:

CapabilityAgentsWorkflows
Execution modelCan run indefinitelyRun to completion
Real-time communicationWebSockets, HTTP streamingNot supported
State persistenceBuilt-in SQL databaseStep-level persistence
Failure handlingApplication-definedAutomatic retries and recovery
External eventsDirect handlingPause and wait for events
User interactionDirect (chat, UI)Through Agent callbacks

Agents can loop, branch, and interact directly with users. Workflows execute steps sequentially with guaranteed delivery and can pause for days waiting for approvals or external data.

When to use each

Use Agents alone for:

  • Chat and messaging applications
  • Quick API calls and responses
  • Real-time collaborative features
  • Tasks under 30 seconds

Use Agents with Workflows for:

  • Data processing pipelines
  • Report generation
  • Human-in-the-loop approval flows
  • Tasks requiring guaranteed delivery
  • Multi-step operations with retry requirements

Use Workflows alone for:

  • Background jobs with or without user approval
  • Scheduled data synchronization
  • Event-driven processing pipelines

How Agents and Workflows communicate

The AgentWorkflow class (imported from agents/workflows) provides bidirectional communication between Workflows and their originating Agent.

Workflow to Agent

Workflows can communicate with Agents through several mechanisms:

  • RPC calls: Directly call Agent methods with full type safety via this.agent
  • Progress reporting: Send progress updates via this.reportProgress() that trigger Agent callbacks
  • State updates: Modify Agent state via step.updateAgentState() or step.mergeAgentState(), which broadcasts to connected clients
  • Client broadcasts: Send messages to all WebSocket clients via this.broadcastToClients()
JavaScript
// Inside a workflow's run() method
await this.agent.updateTaskStatus(taskId, "processing"); // RPC call
await this.reportProgress({ step: "process", percent: 0.5 }); // Progress (non-durable)
this.broadcastToClients({ type: "update", taskId }); // Broadcast (non-durable)
await step.mergeAgentState({ taskProgress: 0.5 }); // State update (durable)

Agent to Workflow

Agents can interact with running Workflows by:

  • Starting workflows: Launch new workflow instances with runWorkflow()
  • Sending events: Dispatch events with sendWorkflowEvent()
  • Approval/rejection: Respond to approval requests with approveWorkflow() / rejectWorkflow()
  • Workflow control: Pause, resume, terminate, or restart workflows
  • Status queries: Check workflow progress with getWorkflow() / getWorkflows()

Durable vs. non-durable operations

Understanding durability is key to using workflows effectively:

Non-durable (may repeat on retry)

These operations are lightweight and suitable for frequent updates, but may execute multiple times if the workflow retries:

  • this.reportProgress() — Progress reporting
  • this.broadcastToClients() — WebSocket broadcasts
  • Direct RPC calls to this.agent

Durable (idempotent, won't repeat)

These operations use the step parameter and are guaranteed to execute exactly once:

  • step.do() — Execute durable steps
  • step.reportComplete() / step.reportError() — Completion reporting
  • step.sendEvent() — Custom events
  • step.updateAgentState() / step.mergeAgentState() — State synchronization

Durability guarantees

Workflows provide durability through step-based execution:

  1. Step completion is permanent — Once a step completes, it will not re-execute even if the workflow restarts
  2. Automatic retries — Failed steps retry with configurable backoff
  3. Event persistence — Workflows can wait for events for up to one year
  4. State recovery — Workflow state survives infrastructure failures

This durability model means workflows are well-suited for tasks where partial completion must be preserved, such as multi-stage data processing or transactions spanning multiple systems.

Workflow tracking

When an Agent starts a workflow using runWorkflow(), the workflow is automatically tracked in the Agent's internal database. This enables:

  • Querying workflow status by ID, name, or metadata with cursor-based pagination
  • Monitoring progress through lifecycle callbacks (onWorkflowProgress, onWorkflowComplete, onWorkflowError)
  • Workflow control: pause, resume, terminate, restart
  • Cleaning up completed workflow records with deleteWorkflow() / deleteWorkflows()
  • Correlating workflows with users or sessions through metadata

Common patterns

Background processing with progress

An Agent receives a request, starts a Workflow for heavy processing, and broadcasts progress updates to connected clients as the Workflow executes each step.

JavaScript
// Workflow reports progress after each item
for (let i = 0; i < items.length; i++) {
await step.do(`process-${i}`, async () => processItem(items[i]));
await this.reportProgress({
step: `process-${i}`,
percent: (i + 1) / items.length,
message: `Processed ${i + 1}/${items.length}`,
});
}

Human-in-the-loop approval

A Workflow prepares a request, pauses to wait for approval using waitForApproval(), and the Agent provides UI for users to approve or reject via approveWorkflow() / rejectWorkflow(). The Workflow resumes or throws WorkflowRejectedError based on the decision.

Resilient external API calls

A Workflow wraps external API calls in durable steps with retry logic. If the API fails or the workflow restarts, completed calls are not repeated and failed calls retry automatically.

JavaScript
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");
if (!response.ok) throw new Error(`API error: ${response.status}`);
return response.json();
},
);

State synchronization

A Workflow updates Agent state at key milestones using step.updateAgentState() or step.mergeAgentState(). These state changes broadcast to all connected clients, keeping UIs synchronized without polling.