View Source Jido.Agent.Directive (Jido v1.0.0)

Provides a type-safe way to modify agent state through discrete, validated directives.

## Overview

Directives are immutable instructions that can be applied to an agent to modify its state in predefined ways. Each directive type is implemented as a separate struct with its own validation rules, helping ensure type safety and consistent state transitions.

## Available Directives

  • EnqueueDirective - Adds a new instruction to the agent's pending queue

    • Requires an action atom
    • Supports optional params and context maps
    • Example: %EnqueueDirective{action: :move, params: %{location: :kitchen}}
  • RegisterActionDirective - Registers a new action module with the agent

    • Requires a valid module atom
    • Example: %RegisterActionDirective{action_module: MyApp.Actions.Move}
  • DeregisterActionDirective - Removes an action module from the agent

    • Requires a valid module atom
    • Example: %DeregisterActionDirective{action_module: MyApp.Actions.Move}

## Usage

Directives are typically created by action handlers and applied through the apply_directives/3 function. The function processes directives in order and ensures atomicity - if any directive fails, the entire operation is rolled back.

  # Single directive
  directive = %EnqueueDirective{action: :move, params: %{location: :kitchen}}
  result = %Result{directives: [directive]}
  {:ok, updated_agent} = Directive.apply_directives(agent, result)

  # Multiple directives
  directives = [
    %RegisterActionDirective{action_module: MyApp.Actions.Move},
    %EnqueueDirective{action: :move, params: %{location: :kitchen}}
  ]

  result = %Result{directives: directives}
  {:ok, updated_agent} = Directive.apply_directives(agent, result)

## Validation

Each directive type has its own validation rules:

  • EnqueueDirective requires a non-nil atom for the action
  • RegisterActionDirective requires a valid module atom
  • DeregisterActionDirective requires a valid module atom

Failed validation results in an error tuple being returned and processing being halted.

## Error Handling

The module uses tagged tuples for error handling:

  • {:ok, updated_agent} - Successful application of directives
  • {:error, reason} - Failed validation or application

Common error reasons include:

  • :invalid_action - The action specified in an EnqueueDirective is invalid
  • :invalid_action_module - The module specified in a Register/DeregisterDirective is invalid

Summary

Functions

Applies a single directive to an agent. Pattern matches on directive type to execute the appropriate transformation.

Applies a list of directives to an agent, maintaining ordering and atomicity. Returns either the updated agent or an error if any directive application fails.

Checks if a value is a valid directive struct or ok-tupled directive.

Types

Functions

apply_directive(agent, directive, opts)

@spec apply_directive(Jido.Agent.t(), t(), keyword()) :: directive_result()

Applies a single directive to an agent. Pattern matches on directive type to execute the appropriate transformation.

Parameters

  • agent: The agent struct to apply the directive to
  • directive: The directive struct to apply
  • opts: Optional keyword list of options (default: [])

Returns

  • {:ok, updated_agent} - Directive was successfully applied
  • {:error, reason} - Failed to apply directive with reason

Directive Types

EnqueueDirective

Adds a new instruction to the agent's pending queue.

RegisterActionDirective

Registers a new action module with the agent.

DeregisterActionDirective

Removes an action module from the agent.

apply_directives(agent, result, opts \\ [])

Applies a list of directives to an agent, maintaining ordering and atomicity. Returns either the updated agent or an error if any directive application fails.

Parameters

  • agent: The agent struct to apply directives to
  • result: A Result struct containing the list of directives to apply
  • opts: Optional keyword list of options (default: [])

Returns

  • {:ok, updated_agent} - All directives were successfully applied
  • {:error, reason} - A directive failed to apply, with reason for failure

Examples

result = %Result{directives: [
  %EnqueueDirective{action: :my_action, params: %{key: "value"}},
  %RegisterActionDirective{action_module: MyAction}
]}

{:ok, updated_agent} = Directive.apply_directives(agent, result)

Behavior

  • Applies directives in order, stopping on first error
  • Maintains atomicity - all directives succeed or none are applied
  • Logs debug info about directive application

dbug(_, _ \\ [], _ \\ [])

(macro)

error(_, _ \\ [], _ \\ [])

(macro)

is_directive?(directive)

@spec is_directive?(term()) :: boolean()

Checks if a value is a valid directive struct or ok-tupled directive.

A valid directive is either:

  • A struct of type EnqueueDirective, RegisterActionDirective, or DeregisterActionDirective
  • An ok-tuple containing one of the above directive structs

Parameters

  • value: Any value to check

Returns

  • true if the value is a valid directive
  • false otherwise

Examples

iex> is_directive?(%EnqueueDirective{action: :test})
true

iex> is_directive?({:ok, %RegisterActionDirective{action_module: MyModule}})
true

iex> is_directive?(:not_a_directive)
false