Skip to main content
The @talosjs/workflow component is a transition-based workflow engine. A workflow is an ordered list of transitions: small, focused steps that each decide whether they run, do their work, and know how to undo it. When you run a workflow, the active transitions execute in order. If any step throws, the engine rolls back the ones that already succeeded, in reverse, and raises a typed WorkflowException.

The transition model

A workflow breaks a process into small, focused steps rather than one monolithic function. Each transition’s isActive(data, context?) decides whether it runs for the current data, so the active set can vary from one run to the next. When a step fails, the transitions that already executed roll back in reverse order before the error propagates. You can react around every step with the onStart, onFinish, and onFail hooks. Workflows and transitions are registered with a decorator and resolved from @talosjs/container, and generic Data and Output types thread through the workflow and its transitions.

How it works

A workflow extends the abstract Workflow<Data, Output> class and implements getName, getDescription, and getTransitions. Each transition implements the ITransition<Data, Output> interface. Calling run(data, context?) does the following:
  1. Every transition’s isActive(data, context?) is evaluated to build the list of active transitions.
  2. Active transitions run in order. For each one: onStart fires, then handler(data, context?) produces an output, then onFinish fires with that output.
  3. The output of the last executed transition is returned.
  4. If a step throws, that transition’s onFail fires, the transitions executed so far are rolled back in reverse order, and a WorkflowException is thrown.
A transition implements these members: Every member may be synchronous or asynchronous. The optional context passed to run is forwarded to every member, so request-scoped values such as the current user or a request id reach each step. Rollback is precise. Only transitions whose handler completed are rolled back; the transition that threw is not, since its work never finished. The rollbacks are awaited before the WorkflowException is rethrown.

Decorator and usage

@decorator.transition()

Registers a transition class with the container. It accepts an optional scope (defaults to EContainerScope.Singleton).

@decorator.workflow()

Registers a workflow class with the container. It also accepts an optional scope (defaults to EContainerScope.Singleton). List the transition classes in getTransitions() in the order they should run, returning the class references only, never instances, since they are resolved from the container.
Resolve the workflow from the container and run it. The output is whatever the last executed transition returns:

Exceptions

A failed run throws a WorkflowException. It carries a machine-readable key, a human-readable message, an HTTP status, and a data object. The message reads Workflow "<name>" failed at transition "<name>"., the status is 500 (Internal Server Error), and data is { workflow, transition, error }, where error is the original message (non-Error throwables are stringified).

Composing workflows that recover

Keep each transition on a single, nameable action so it stays easy to test and roll back. Make rollback the true inverse of handler: whatever side effect a handler creates, whether a charge, a reservation, or a record, its rollback should undo it. Guard with isActive to skip steps that don’t apply to the current data instead of branching inside the handler. Order transitions deliberately. They run in the order getTransitions() returns and roll back in reverse, so put the reversible, cheap steps first where you can. List the transition classes in getTransitions(), never instances, since the container resolves them. Pass request-scoped values like the current user or a request id through the second run argument as context rather than threading them into Data. And catch WorkflowException at the boundary, reading its stable key and data to report the failing workflow and transition.

CLI command

Scaffold a workflow with workflow:create and each of its steps with workflow:transition:create. The generators write the class and a matching test under the target module and install @talosjs/workflow if it is missing.
workflow:create writes the class under modules/<module>/src/workflows/<Name>Workflow.ts as a Workflow subclass with an empty transition list, ready for you to fill in:
workflow:transition:create writes the class under modules/<module>/src/workflows/transitions/<Name>Transition.ts as an ITransition stub with every member ready to implement:
See workflow:create and workflow:transition:create for the full command references.

Use with Claude and Codex

The generators ship matching workflow:create and workflow:transition:create skills. They run the scaffold, then guide your AI agent through completing the workflow: defining the Data type, listing the transitions in order, and implementing each transition’s isActive, handler, and rollback. Initialize the skills once for your agent.
Then ask Claude in natural language. It maps the request to the generators, runs them, and fills in the implementation:
Prompt
For example, the prompt above maps to workflow:create --name=Order, then a workflow:transition:create for each step, wiring the transitions into getTransitions() in order.