Skip to Content

Workflow.until()

The .until() method repeats a step until a specified condition becomes true. This creates a loop that continues executing the specified step until the condition is satisfied.

Usage

workflow .step(incrementStep) .until(condition, incrementStep) .then(finalStep);

Parameters

condition:

Function | ReferenceCondition
A function or reference condition that determines when to stop looping

step:

Step
The step to repeat until the condition is met

Condition Types

Function Condition

You can use a function that returns a boolean:

workflow .step(incrementStep) .until(async ({ context }) => { const result = context.getStepResult<{ value: number }>('increment'); return (result?.value ?? 0) >= 10; // Stop when value reaches or exceeds 10 }, incrementStep) .then(finalStep);

Reference Condition

You can use a reference-based condition with comparison operators:

workflow .step(incrementStep) .until( { ref: { step: incrementStep, path: 'value' }, query: { $gte: 10 }, // Stop when value is greater than or equal to 10 }, incrementStep ) .then(finalStep);

Comparison Operators

When using reference-based conditions, you can use these comparison operators:

OperatorDescriptionExample
$eqEqual to{ $eq: 10 }
$neNot equal to{ $ne: 0 }
$gtGreater than{ $gt: 5 }
$gteGreater than or equal to{ $gte: 10 }
$ltLess than{ $lt: 20 }
$lteLess than or equal to{ $lte: 15 }

Returns

workflow:

Workflow
The workflow instance for chaining

Example

import { Workflow, Step } from '@mastra/core'; import { z } from 'zod'; // Create a step that increments a counter const incrementStep = new Step({ id: 'increment', description: 'Increments the counter by 1', outputSchema: z.object({ value: z.number(), }), execute: async ({ context }) => { // Get current value from previous execution or start at 0 const currentValue = context.getStepResult<{ value: number }>('increment')?.value || context.getStepResult<{ startValue: number }>('trigger')?.startValue || 0; // Increment the value const value = currentValue + 1; console.log(`Incrementing to ${value}`); return { value }; }, }); // Create a final step const finalStep = new Step({ id: 'final', description: 'Final step after loop completes', execute: async ({ context }) => { const finalValue = context.getStepResult<{ value: number }>('increment')?.value; console.log(`Loop completed with final value: ${finalValue}`); return { finalValue }; }, }); // Create the workflow const counterWorkflow = new Workflow({ name: 'counter-workflow', triggerSchema: z.object({ startValue: z.number(), targetValue: z.number(), }), }); // Configure the workflow with an until loop counterWorkflow .step(incrementStep) .until(async ({ context }) => { const targetValue = context.triggerData.targetValue; const currentValue = context.getStepResult<{ value: number }>('increment')?.value ?? 0; return currentValue >= targetValue; }, incrementStep) .then(finalStep) .commit(); // Execute the workflow const run = counterWorkflow.createRun(); const result = await run.start({ triggerData: { startValue: 0, targetValue: 5 } }); // Will increment from 0 to 5, then stop and execute finalStep