Skip to main content
Integrate Cloudflare Workflows with Agents for durable, multi-step background processing while Agents handle real-time communication.

Introduction

What are Cloudflare Workflows?

Cloudflare Workflows provide durable, multi-step execution that survives failures, retries automatically, and can pause to wait for external events. They’re ideal for:
  • Long-running background tasks (data processing, report generation)
  • Multi-step pipelines with retry logic
  • Human-in-the-loop approval flows
  • Tasks that shouldn’t block user requests

Why Integrate with Agents?

Agents excel at real-time communication and state management, while Workflows excel at durable execution. Together they provide:

When to Use What

Quick Start

1. Define Your Workflow

Create a Workflow that extends AgentWorkflow to get typed access to the originating Agent:

2. Start Workflow from Agent

Use runWorkflow() to start a workflow with automatic tracking:

3. Configure Wrangler

API Reference

AgentWorkflow

Base class for Workflows that integrate with Agents. Type Parameters:
  • AgentType - The Agent class type (for typed RPC)
  • Params - User params passed to the workflow (optional)
  • ProgressType - Type for progress reporting (defaults to DefaultProgress)
  • Env - Environment type (defaults to Cloudflare.Env)
Properties:
  • agent - Typed stub for calling Agent methods via RPC
  • instanceId - The workflow instance ID
  • workflowName - The workflow binding name
  • env - Environment bindings
Methods on this (non-durable, may repeat on retry): Methods on step (durable, idempotent, won’t repeat on retry): DefaultProgress Type:

Agent Workflow Methods

runWorkflow()

Start a workflow and track it in the Agent’s database.
Parameters:
  • workflowName - Workflow binding name from env
  • params - Params to pass to the workflow
  • options.id - Custom workflow ID (auto-generated if not provided)
  • options.metadata - Optional metadata stored for querying (not passed to workflow)
  • options.agentBinding - Agent binding name (auto-detected from class name if not provided)
Returns: Workflow instance ID

sendWorkflowEvent()

Send an event to a running workflow.

getWorkflowStatus()

Get the status of a workflow and update tracking record.

getWorkflow()

Get a tracked workflow by ID.

getWorkflows()

Query tracked workflows with cursor-based pagination. Returns a WorkflowPage with workflows, total count, and cursor for the next page.
The WorkflowPage type:

Workflow Control Methods

deleteWorkflow()

Delete a single workflow tracking record.

deleteWorkflows()

Delete workflow tracking records matching criteria. Useful for cleanup.

terminateWorkflow()

Terminate a running workflow immediately.
This stops the workflow and sets its status to "terminated". Throws if the workflow is not found in the tracking table. Cloudflare will throw if the workflow is already completed, errored, or terminated.
terminate() is not yet supported in local development with wrangler dev. It works when deployed to Cloudflare. Follow #823 for details and updates.

pauseWorkflow()

Pause a running workflow. The workflow can be resumed later with resumeWorkflow().
Throws if the workflow is not running. Cloudflare will throw if the workflow is already paused, completed, errored, or terminated.
pause() is not yet supported in local development with wrangler dev. It works when deployed to Cloudflare. Follow #823 for details and updates.

resumeWorkflow()

Resume a paused workflow.
Throws if the workflow is not paused. Cloudflare will throw if the workflow is already running, completed, errored, or terminated.
resume() is not yet supported in local development with wrangler dev. It works when deployed to Cloudflare. Follow #823 for details and updates.

restartWorkflow()

Restart a workflow instance from the beginning with the same ID.
This is useful for re-running failed workflows or retrying from scratch. The resetTracking option (default: true) controls whether to reset the created_at timestamp and clear error fields.
restart() is not yet supported in local development with wrangler dev. It works when deployed to Cloudflare. Follow #823 for details and updates.

Lifecycle Callbacks

Override these methods in your Agent to handle workflow events:

Approval Methods

Convenience methods for human-in-the-loop approval flows:

Workflow Tracking

Workflows started with runWorkflow() are automatically tracked in the Agent’s SQLite database.

cf_agents_workflows Table

Workflow params and output are not stored by default. Use metadata to store queryable information, and store large payloads in your own tables if needed.

Workflow Status Values

  • queued - Waiting to start
  • running - Currently executing
  • paused - Paused by user
  • waiting - Waiting for event
  • complete - Finished successfully
  • errored - Failed with error
  • terminated - Manually terminated

Patterns

Background Processing with Progress

Human-in-the-Loop Approval

Durable Task Queue with Retries

State Synchronization

Workflows can update the Agent’s state directly (durably via step), which automatically broadcasts to all connected clients:

Custom Progress Types

Define custom progress types for domain-specific reporting:

Bidirectional Communication

Workflow → Agent

Agent → Workflow

Best Practices

1

Keep workflows focused

One workflow per logical task
2

Use meaningful step names

Helps with debugging and observability
3

Report progress regularly

Keeps users informed
4

Handle errors gracefully

Use reportError() before throwing
5

Clean up completed workflows

The cf_agents_workflows table can grow unbounded, so implement a retention policy
6

Handle workflow binding renames carefully

If you rename a workflow binding in wrangler.jsonc, existing tracked workflows will reference the old name. Use migrateWorkflowBinding() to update them.
Cleanup example:
Handling binding renames:

Limitations

  • Workflows can have at most 1,024 steps
  • Maximum 10MB state per workflow
  • Events wait for at most 1 year
  • No direct WebSocket from workflows (use broadcastToClients())
  • Workflow execution time: up to 30 minutes per step