Jido.Actions.Workflow behaviour (Jido v1.2.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

Usage

defmodule MyWorkflow do
  use Jido.Actions.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

execute_step(step, params, context)

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