Run.resume()
The .resume() method resumes a suspended workflow run with new data, allowing you to continue execution from a specific step.
Usage exampleDirect link to Usage example
const run = await workflow.createRun()
const result = await run.start({ inputData: { value: 'initial data' } })
if (result.status === 'suspended') {
const resumedResults = await run.resume({
resumeData: { value: 'resume data' },
})
}
ParametersDirect link to Parameters
resumeData?:
step?:
requestContext?:
retryCount?:
forEachIndex?:
.foreach() step. Pass the zero-based index of the iteration you want to resume; other iterations remain suspended. Omit this field to resume all suspended iterations of the step with the same resumeData.tracingContext?:
currentSpan?:
tracingOptions?:
metadata?:
requestContextKeys?:
traceId?:
parentSpanId?:
tags?:
outputOptions?:
includeState?:
ReturnsDirect link to Returns
result:
traceId?:
spanId?:
Extended usage exampleDirect link to Extended usage example
if (result.status === 'suspended') {
const resumedResults = await run.resume({
step: result.suspended[0],
resumeData: { value: 'resume data' },
})
}
When exactly one step is suspended, you can omit the step parameter and the workflow will automatically resume that step. For workflows with multiple suspended steps, you must explicitly specify which step to resume.
Resuming a single .foreach() iterationDirect link to resuming-a-single-foreach-iteration
When a .foreach() step suspends across multiple iterations, use forEachIndex (zero-based) to resume one iteration at a time with different resumeData. Iterations not targeted by forEachIndex remain suspended until resumed.
// Resume only the second iteration (index 1) with its own data
await run.resume({
step: 'approve',
resumeData: { ok: true },
forEachIndex: 1,
})
// Later, resume the first iteration with different data
await run.resume({
step: 'approve',
resumeData: { ok: false },
forEachIndex: 0,
})
If forEachIndex is omitted, every suspended iteration of the step is resumed with the same resumeData.
Concurrent resume callsDirect link to Concurrent resume calls
Only one resume() call can continue a suspension. Before it runs anything, resume() atomically claims the run by moving its stored status from suspended to running. If another caller already claimed it, this call throws WORKFLOW_RESUME_ALREADY_CLAIMED and executes no steps, so downstream steps and their side effects run once per suspension.
This matters whenever a resume can be triggered more than once, such as an approval button pressed twice or a retried webhook. It also applies when several server instances react to the same event.
try {
await run.resume({ step: 'approval', resumeData: { approved: true } })
} catch (error) {
if (error.id === 'WORKFLOW_RESUME_ALREADY_CLAIMED') {
// Another caller is already continuing this run. Re-read the run state
// instead of resuming again.
}
}
Over HTTP, a losing resume returns 409 Conflict.
The claim is enforced atomically by storage adapters that report supportsConcurrentUpdates(). Adapters without atomic read-modify-write support (such as ClickHouse, Cloudflare D1, Cloudflare KV, Cloudflare Durable Objects, LanceDB, and Redis) can't enforce it, and the claim is also skipped when shouldPersistSnapshot excludes the running status.