Skip to content

Step context

Every step.do callback receives a context object (WorkflowStepContext) as its first argument. The context gives your step code runtime information about the step itself, the current retry attempt, and the resolved configuration for that step.

WorkflowStepContext

TypeScript
type WorkflowStepContext = {
step: {
name: string;
count: number;
};
attempt: number;
config: WorkflowStepConfig;
};

Properties

PropertyTypeDescription
step.namestringThe name you passed to step.do.
step.countnumberHow many times step.do has been called with this name so far in the current Workflow run. Starts at 1 for the first call with a given name.
attemptnumberThe current attempt number (1-indexed). 1 on the first try, 2 on the first retry, and so on.
configWorkflowStepConfigThe resolved retry and timeout configuration for this step, including any defaults applied by the runtime.

Access the context

Pass a parameter to your step.do callback to receive the context object:

TypeScript
await step.do("my-step", async (ctx) => {
console.log(ctx.step.name); // "my-step"
console.log(ctx.step.count); // 1
console.log(ctx.attempt); // 1 on first try, 2 on first retry, etc.
console.log(ctx.config); // { retries: { limit: 5, ... }, timeout: "10 minutes" }
});

The context is also available when you pass a custom WorkflowStepConfig:

TypeScript
await step.do(
"call an API",
{
retries: {
limit: 10,
delay: "10 seconds",
backoff: "exponential",
},
timeout: "30 minutes",
},
async (ctx) => {
console.log(ctx.config.retries.limit); // 10
console.log(ctx.config.timeout); // "30 minutes"
},
);

Examples

Adjust behavior based on retry attempt

Use ctx.attempt to change how your step behaves on retries. For example, you might use a fallback endpoint after a certain number of retries:

TypeScript
await step.do(
"fetch data",
{ retries: { limit: 5, delay: "5 seconds", backoff: "linear" } },
async (ctx) => {
const url =
ctx.attempt <= 3
? "https://api.example.com/primary"
: "https://api.example.com/fallback";
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return await response.json();
},
);

Log step metadata for observability

Use ctx.step to add structured metadata to your logs:

TypeScript
await step.do("process-order", async (ctx) => {
console.log(
JSON.stringify({
step: ctx.step.name,
stepCount: ctx.step.count,
attempt: ctx.attempt,
retryLimit: ctx.config.retries?.limit,
}),
);
// Your step logic here
});