---
title: Workflows
description: Integrate Cloudflare Workflows with Agents for durable, multi-step background processing with automatic retries.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/agents/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Workflows

## What are Workflows?

[Cloudflare Workflows](https://developers.cloudflare.com/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:

| Capability              | Agents                                   | Workflows                      |
| ----------------------- | ---------------------------------------- | ------------------------------ |
| Execution model         | Long-lived identity that wakes on events | Run to completion              |
| Real-time communication | WebSockets, HTTP streaming               | Not supported                  |
| State persistence       | Built-in SQL database                    | Step-level persistence         |
| Failure handling        | Application-defined                      | Automatic retries and recovery |
| External events         | Direct handling                          | Pause and wait for events      |
| User interaction        | Direct (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 ](#tab-panel-4136)
* [  TypeScript ](#tab-panel-4137)

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)


```

TypeScript

```

// 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 ](#tab-panel-4138)
* [  TypeScript ](#tab-panel-4139)

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}`,

  });

}


```

TypeScript

```

// 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 ](#tab-panel-4140)
* [  TypeScript ](#tab-panel-4141)

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();

  },

);


```

TypeScript

```

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.

## Related resources

[ Run Workflows API ](https://developers.cloudflare.com/agents/api-reference/run-workflows/) Implementation details for agent workflows. 

[ Cloudflare Workflows ](https://developers.cloudflare.com/workflows/) Workflow fundamentals and documentation. 

[ Human-in-the-loop ](https://developers.cloudflare.com/agents/concepts/human-in-the-loop/) Approval flows and manual intervention. 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/agents/","name":"Agents"}},{"@type":"ListItem","position":3,"item":{"@id":"/agents/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/agents/concepts/workflows/","name":"Workflows"}}]}
```
