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 actionRegisterActionDirective
requires a valid module atomDeregisterActionDirective
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 anEnqueueDirective
is invalid:invalid_action_module
- The module specified in aRegister/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
@type directive_result() :: {:ok, Jido.Agent.t()} | {:error, term()}
Functions
@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.
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
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 directivefalse
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