Skip to main content

Run.resume()

The .resume() method resumes a suspended workflow run with new data, allowing you to continue execution from a specific step.

Usage example
Direct 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' },
})
}

Parameters
Direct link to Parameters

resumeData?:

z.infer<TResumeSchema>
Data for resuming the suspended step

step?:

Step<string, any, any, TResumeSchema, any, TEngineType> | [...Step<string, any, any, any, any, TEngineType>[], Step<string, any, any, TResumeSchema, any, TEngineType>] | string | string[]
The step(s) to resume execution from. Can be a Step instance, array of Steps, step ID string, or array of step ID strings

requestContext?:

RequestContext
Request Context data to use when resuming

retryCount?:

number
Optional retry count for nested workflow execution

forEachIndex?:

number
Target a specific iteration of a suspended .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?:

TracingContext
Tracing context for creating child spans and adding metadata. Automatically injected when using Mastra's tracing system.

currentSpan?:

Span
Current span for creating child spans and adding metadata. Use this to create custom child spans or update span attributes during execution.

tracingOptions?:

TracingOptions
Options for Tracing configuration.

metadata?:

Record<string, any>
Metadata to add to the root trace span. Useful for adding custom attributes like user IDs, session IDs, or feature flags.

requestContextKeys?:

string[]
Additional RequestContext keys to extract as metadata for this trace. Supports dot notation for nested values (e.g., 'user.id').

traceId?:

string
Trace ID to use for this execution (1-32 hexadecimal characters). If provided, this trace will be part of the specified trace.

parentSpanId?:

string
Parent span ID to use for this execution (1-16 hexadecimal characters). If provided, the root span will be created as a child of this span.

tags?:

string[]
Tags to apply to this trace. String labels for categorizing and filtering traces.

outputOptions?:

OutputOptions
Options for output configuration.

includeState?:

boolean
Whether to include the workflow run state in the result.

Returns
Direct link to Returns

result:

Promise<WorkflowResult<TState, TOutput, TSteps>>
A promise that resolves to the workflow execution result containing step outputs and status

traceId?:

string
The trace ID associated with this execution when Tracing is enabled. Use this to correlate logs and debug execution flow.

spanId?:

string
The root span ID associated with this execution when Tracing is enabled. Use this for span-level lookup and correlation.

Extended usage example
Direct link to Extended usage example

if (result.status === 'suspended') {
const resumedResults = await run.resume({
step: result.suspended[0],
resumeData: { value: 'resume data' },
})
}
note

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() iteration
Direct 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 calls
Direct 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.

note

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.