Skip to content

Run

Turn a normal function into a durable function. Any function passed to step.run will be executed in a durable way, including retries and memoization.

Arguments

  • step_id (str): Step ID. Should be unique within the function.
  • handler (Callable): A callable that has no arguments and returns a JSON serializable value.
  • *handler_args: Positional arguments for the handler. This is type-safe since we infer the types from the handler using generics.

Examples

py
@inngest_client.create_function(
    fn_id="my_function",
    trigger=inngest.TriggerEvent(event="app/my_function"),
)
async def fn(ctx: inngest.Context) -> None:
    # Pass a function to step.run
    await ctx.step.run("my_fn", my_fn)

    # Args are passed after the function
    await ctx.step.run("my_fn_with_args", my_fn_with_args, 1, "a")

    # Kwargs require functools.partial
    await ctx.step.run(
        "my_fn_with_args_and_kwargs",
        functools.partial(my_fn_with_args_and_kwargs, 1, b="a"),
    )

    # Defining functions like this gives you easy access to scoped variables
    def use_scoped_variable() -> None:
        print(ctx.event.data["user_id"])

    await ctx.step.run("use_scoped_variable", use_scoped_variable)

async def my_fn() -> None:
    pass

async def my_fn_with_args(a: int, b: str) -> None:
    pass

async def my_fn_with_args_and_kwargs(a: int, *, b: str) -> None:
    pass

Retries

Each step.run() call has its own independent retry counter. When a step raises an exception, it will be retried according to your function's retry configuration. The retry configuration applies to each individual step, not as a shared pool across all steps in your function.

For example, if your function is configured with retries=4, each step.run() will be retried up to 4 times independently (5 total attempts including the initial attempt). If you have multiple steps in your function, each step gets its own full set of retries.

Learn more about configuring retries.