Jido.Tools.Workflow behaviour (Jido Action v2.3.0)

View Source

A specialized Action type that executes a sequence of workflow steps.

This Workflow is intentinoally simplistic - it is not meant to replace more mature Workflow libraries that exist in the Elixir ecosystem. It is included for basic use cases relevant to the Jido project.

This module extends Jido.Action with workflow capabilities, allowing you to define a sequence of steps to be executed in order. Each step follows the Elixir AST pattern of {:atom, metadata, params}.

Supported Step Types

  • {:step, metadata, [instruction]} - Execute a single instruction
  • {:branch, metadata, [condition_value, true_action, false_action]} - Conditional branching
  • {:converge, metadata, [instruction]} - Converge branch paths
  • {:parallel, metadata, [instructions]} - Execute instructions in parallel

Parallel Step Metadata

Parallel steps support the following metadata options:

  • :max_concurrency - Maximum number of parallel tasks (default: scheduler count)
  • :timeout_ms - Timeout per parallel task in milliseconds (default: :infinity, compatibility mode)
  • :fail_on_error - When true, any parallel error fails the workflow step. Defaults to false for backwards compatibility, in which case errors are returned as %{error: ...} entries in parallel_results.

Usage

defmodule MyWorkflow do
  use Jido.Tools.Workflow,
    name: "my_workflow",
    description: "A workflow that performs multiple steps",
    steps: [
      {:step, [name: "step_1"], [{LogAction, message: "Step 1"}]},
      {:branch, [name: "branch_1"], [
        true,  # This will typically be replaced at runtime with a dynamic value
        {:step, [name: "true_branch"], [{LogAction, message: "Greater than 10"}]},
        {:step, [name: "false_branch"], [{LogAction, message: "Less than or equal to 10"}]}
      ]},
      {:step, [name: "final_step"], [{LogAction, message: "Completed"}]}
    ]
end

Handling Dynamic Conditions

For branch conditions that need to be evaluated at runtime, override the execute_step/3 function in your module to handle the specific branch condition check:

# Override execute_step to handle a specific branch condition
def execute_step({:branch, [name: "my_condition"], [_placeholder, true_branch, false_branch]}, params, context) do
  # Determine condition dynamically using params
  condition_value = params.value > 10

  # Choose the branch based on the condition value
  if condition_value do
    execute_step(true_branch, params, context)
  else
    execute_step(false_branch, params, context)
  end
end

# Fall back to the default implementation for other steps
def execute_step(step, params, context) do
  super(step, params, context)
end

Summary

Callbacks

Callback for executing a single workflow step.

Functions

Macro for setting up a module as a Workflow with step execution capabilities.

Callbacks

execute_step(step, params, context)

(optional)
@callback execute_step(step :: tuple(), params :: map(), context :: map()) ::
  {:ok, map()} | {:error, any()}

Callback for executing a single workflow step.

Takes a step tuple, parameters, and context and returns the result.

Functions

__using__(opts)

(macro)
@spec __using__(keyword()) :: Macro.t()

Macro for setting up a module as a Workflow with step execution capabilities.