Time Travel
Time Travel 让你可以从任意指定步骤开始重新执行 Workflow,既可以使用已存储的 Snapshot 数据,也可以使用你提供的自定义上下文。
这适合调试失败的 Workflow、使用不同输入测试单个步骤,或在不重新运行整个 Workflow 的情况下从错误中恢复。你也可以对尚未运行的 Workflow 使用 Time Travel,从任意指定步骤开始执行。
Time Travel 的工作原理Time Travel 的工作原理的直接链接
在 Workflow Run 上调用 timeTravel() 时:
- Workflow 从 Storage 加载现有 Snapshot(如果存在)
- 根据 Snapshot 或所提供的上下文重建目标步骤之前的步骤结果
- 使用提供或重建的输入数据从指定步骤开始执行
- Workflow 从该位置继续运行直至完成
Time Travel 依赖持久化的 Workflow Snapshot,因此必须配置 Storage。
基本用法基本用法的直接链接
使用 run.timeTravel() 从特定步骤重新执行 Workflow:
import { mastra } from './mastra'
const workflow = mastra.getWorkflow('myWorkflow')
const run = await workflow.createRun()
const result = await run.timeTravel({
step: 'step2',
inputData: { previousStepResult: 'custom value' },
})
指定目标步骤指定目标步骤的直接链接
可以使用步骤引用或步骤 ID 指定目标步骤:
使用步骤引用使用步骤引用的直接链接
const result = await run.timeTravel({
step: step2,
inputData: { value: 10 },
})
使用步骤 ID使用步骤 ID的直接链接
const result = await run.timeTravel({
step: 'step2',
inputData: { value: 10 },
})
嵌套 Workflow 步骤嵌套 Workflow 步骤的直接链接
对于嵌套 Workflow 内的步骤,请使用点号表示法、步骤 ID 数组或步骤引用数组:
// 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 },
})
// Using array of step references
const result = await run.timeTravel({
step: [nestedWorkflow, step3],
inputData: { value: 10 },
})
提供执行上下文提供执行上下文的直接链接
进行 Time Travel 时,可以提供上下文来指定先前步骤的状态:
const result = await run.timeTravel({
step: 'step2',
context: {
step1: {
status: 'success',
payload: { value: 0 },
output: { step1Result: 2 },
startedAt: Date.now(),
endedAt: Date.now(),
},
},
})
上下文对象以步骤 ID 为键,包含步骤结果。每个步骤结果包括:
status:步骤执行状态(success、failed、suspended)payload:传给步骤的输入数据output:步骤输出数据(成功步骤)startedAt:步骤开始时间戳endedAt:步骤结束时间戳(已完成步骤)suspendPayload:传给suspend()的数据(已挂起步骤)resumePayload:传给resume()的数据(已恢复步骤)
重新运行失败的 Workflow重新运行失败的 Workflow的直接链接
Time Travel 特别适合调试失败的 Workflow 执行并从中恢复:
const workflow = mastra.getWorkflow('myWorkflow')
const run = await workflow.createRun()
// Initial run fails at step2
const failedResult = await run.start({
inputData: { value: 1 },
})
if (failedResult.status === 'failed') {
// Re-run from step2 with corrected input
const recoveredResult = await run.timeTravel({
step: 'step2',
inputData: { step1Result: 5 }, // Provide corrected input
})
}
对已挂起 Workflow 使用 Time Travel对已挂起 Workflow 使用 Time Travel的直接链接
可以通过 Time Travel 从较早的步骤恢复已挂起 Workflow:
const run = await workflow.createRun()
// Start workflow - suspends at promptAgent step
const initialResult = await run.start({
inputData: { input: 'test' },
})
if (initialResult.status === 'suspended') {
// Time travel back to an earlier step with resume data
const result = await run.timeTravel({
step: 'getUserInput',
resumeData: {
userInput: 'corrected input',
},
})
}
以 Stream 形式获取 Time Travel 结果以 Stream 形式获取 Time Travel 结果的直接链接
使用 timeTravelStream() 接收 Time Travel 执行期间的 Stream 事件:
const run = await workflow.createRun()
const stream = run.timeTravelStream({
step: 'step2',
inputData: { value: 10 },
})
for await (const event of stream.fullStream) {
console.log(event.type, event.payload)
}
const result = await stream.result
if (result.status === 'success') {
console.log(result.result)
}
使用初始状态进行 Time Travel使用初始状态进行 Time Travel的直接链接
进行 Time Travel 时,可以提供初始状态来设置 Workflow 级状态:
const result = await run.timeTravel({
step: 'step2',
inputData: { value: 10 },
initialState: {
counter: 5,
metadata: { source: 'time-travel' },
},
})
错误处理错误处理的直接链接
Time Travel 会在特定情况下抛出错误:
Workflow 正在运行Workflow 正在运行的直接链接
不能对当前正在运行的 Workflow 进行 Time Travel:
try {
await run.timeTravel({ step: 'step2' })
} catch (error) {
// "This workflow run is still running, cannot time travel"
}
无效步骤 ID无效步骤 ID的直接链接
如果目标步骤不存在于 Workflow 中,Time Travel 会抛出错误:
try {
await run.timeTravel({ step: 'nonExistentStep' })
} catch (error) {
// "Time travel target step not found in execution graph: 'nonExistentStep'. Verify the step id/path."
}
无效输入数据无效输入数据的直接链接
启用 validateInputs 时,Time Travel 会根据步骤 Schema 验证输入数据:
try {
await run.timeTravel({
step: 'step2',
inputData: { invalidField: 'value' },
})
} catch (error) {
// "Invalid inputData: \n- step1Result: Required"
}
嵌套 Workflow 上下文嵌套 Workflow 上下文的直接链接
通过 Time Travel 进入嵌套 Workflow 时,可以同时为父 Workflow 和嵌套 Workflow 步骤提供上下文:
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(),
},
},
},
})
使用场景使用场景的直接链接
调试失败步骤调试失败步骤的直接链接
使用相同或修改后的输入重新运行失败步骤,以诊断问题:
const result = await run.timeTravel({
step: failedStepId,
context: originalContext, // Use context from the failed run
})
在新 Workflow Run 中测试步骤逻辑在新 Workflow Run 中测试步骤逻辑的直接链接
在新的 Workflow Run 中使用特定输入测试单个步骤,这适合在不从头开始执行 Workflow 的情况下测试步骤逻辑。
const result = await run.timeTravel({
step: 'processData',
inputData: { testData: 'specific test case' },
})
从临时故障中恢复从临时故障中恢复的直接链接
重新运行因临时问题(网络错误、速率限制)而失败的步骤:
// After fixing the external service issue
const result = await run.timeTravel({
step: 'callExternalApi',
inputData: savedInputData,
})