跳到主要内容
非官方简体中文翻译,内容版权归 Mastra 所有,遵循 Apache-2.0 许可。

Run.timeTravel()

The .timeTravel() method re-executes a workflow starting from any specific step, using either stored snapshot data or custom context you provide. Use it to debug failed workflows and test individual steps with different inputs. It can also recover from errors without re-running the entire workflow.

Usage example
Usage example的直接链接

const run = await workflow.createRun()

const result = await run.timeTravel({
step: 'step2',
inputData: { value: 10 },
})

Parameters
Parameters的直接链接

step:

Step<string, any, TInputSchema, any, any, any, TEngineType> | [...Step<string, any, any, any, any, any, TEngineType>[], Step<string, any, TInputSchema, any, any, any, TEngineType>] | string | string[]
The target step to start execution from. It can be a Step instance, array of Steps (for nested workflows), step ID string, or array of step ID strings. Use dot notation or arrays for nested workflow steps (e.g., 'nestedWorkflow.step3' or ['nestedWorkflow', 'step3'])

inputData?:

z.infer<TInputSchema>
Input data for the target step. Must match the step's input schema. If not provided, uses data from the workflow snapshot

resumeData?:

any
Resume data to provide if the workflow was previously suspended

initialState?:

z.infer<TState>
Initial state to set for the workflow run. Used to set workflow-level state before execution

context?:

TimeTravelContext<any, any, any, any>
Execution context containing step results for steps before the target step. Each key is a step ID with a StepResult object containing status, payload, output, startedAt, endedAt, suspendPayload, and resumePayload

nestedStepsContext?:

Record<string, TimeTravelContext<any, any, any, any>>
Context for nested workflow steps. Keyed by nested workflow ID, each containing step results for that nested workflow

requestContext?:

RequestContext
Request Context data to use during time travel execution

outputWriter?:

(chunk: TOutput) => Promise<void>
Optional asynchronous function to handle output chunks as they are produced

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.

rootSpanName?:

string
Display name for the root span of this trace, replacing the default workflow run: '<id>' or agent run: '<id>' name. Use it to tell runs apart in trace lists.

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.

nestUnderParent?:

boolean
Set to true together with parentSpanId to attach this run as a child of that span inside the existing trace, for example an LLM judge under the run it scores. Exporters then keep the trace's own name, input, output, and tags. Leave unset when parentSpanId comes from your own tracing system. Ignored without a valid traceId and parentSpanId.

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.

includeResumeLabels?:

boolean
Whether to include resume labels in the result.

Returns
Returns的直接链接

result:

Promise<WorkflowResult<TState, TInput, 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 examples
Extended usage examples的直接链接

Time travel with custom context
Time travel with custom context的直接链接

const result = await run.timeTravel({
step: 'step2',
context: {
step1: {
status: 'success',
payload: { value: 0 },
output: { step1Result: 2 },
startedAt: Date.now(),
endedAt: Date.now(),
},
},
})

Time travel to nested workflow step
Time travel to nested workflow step的直接链接

// Using dot notation
const result = await run.timeTravel({
step: 'nestedWorkflow.step3',
inputData: { value: 10 },
})

// Using array of step IDs
const result = await run.timeTravel({
step: ['nestedWorkflow', 'step3'],
inputData: { value: 10 },
})

Time travel with initial state
Time travel with initial state的直接链接

const result = await run.timeTravel({
step: 'step2',
inputData: { value: 10 },
initialState: {
counter: 5,
metadata: { source: 'time-travel' },
},
})

Time travel with nested workflows context
Time travel with nested workflows context的直接链接

const result = await run.timeTravel({
step: 'nestedWorkflow.step3',
context: {
step1: {
status: 'success',
payload: { value: 0 },
output: { step1Result: 2 },
startedAt: Date.now(),
endedAt: Date.now(),
},
nestedWorkflow: {
status: 'running',
payload: { step1Result: 2 },
startedAt: Date.now(),
},
},
nestedStepsContext: {
nestedWorkflow: {
step2: {
status: 'success',
payload: { step1Result: 2 },
output: { step2Result: 3 },
startedAt: Date.now(),
endedAt: Date.now(),
},
},
},
})

Concurrent time travel calls
Concurrent time travel calls的直接链接

Only one timeTravel() call can run for a workflow run at a time. Before it runs anything, timeTravel() atomically claims the run by moving its stored status from the status it loaded (for example suspended or success) to running. If another caller already claimed it, this call throws WORKFLOW_TIME_TRAVEL_ALREADY_CLAIMED and executes no steps. A call that loads the run while it's already running throws WORKFLOW_TIME_TRAVEL_RUN_RUNNING.

This matters whenever time travel can be triggered more than once for the same run, such as a "retry from step" button pressed twice or a retried API request.

try {
await run.timeTravel({ step: 'step2' })
} catch (error) {
if (
error.id === 'WORKFLOW_TIME_TRAVEL_ALREADY_CLAIMED' ||
error.id === 'WORKFLOW_TIME_TRAVEL_RUN_RUNNING'
) {
// Another caller is already re-running this workflow. Re-read the run
// state instead of time travelling again.
}
}

Over HTTP, POST /api/workflows/:workflowId/time-travel-async returns 409 Conflict for a losing call. The time-travel and time-travel-stream endpoints respond before the time travel finishes, so a losing call doesn't change their status code.

Calling timeTravel() again after the previous call finished is still allowed and re-runs the target step.

备注

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. The Inngest workflow runner doesn't claim the run yet.

Notes
Notes的直接链接

  • Time travel requires storage to be configured since it relies on persisted workflow snapshots
  • When re-executing a workflow, the workflow loads the existing snapshot from storage (if available)
  • Step results before the target step are reconstructed from the snapshot or provided context
  • Execution begins from the specified step with the provided or reconstructed input data
  • If a step that precedes the target in the current workflow definition has no recorded entry in the snapshot (for example, the step was renamed since the run was recorded, or the run never reached it), timeTravel rejects with a descriptive error before anything executes and the stored snapshot is left unchanged
  • The workflow continues to completion from that point forward
  • Time travel can be used on workflows that haven't been run yet by providing custom context or input data for the step to start from.