Jido.AI.Reasoning.Helpers (Jido AI v2.1.0)

View Source

Helper functions for creating StateOps in Jido.AI strategies.

This module provides convenient helpers for common state operation patterns used across strategies. It wraps Jido.Agent.StateOp constructors with strategy-specific semantics.

StateOp Types

  • SetState - Deep merge attributes into state
  • SetPath - Set value at nested path
  • DeleteKeys - Remove top-level keys
  • DeletePath - Delete value at nested path

Usage

state_ops = [
  Helpers.set_strategy_status(:running),
  Helpers.increment_iteration(),
  Helpers.append_to_conversation(message)
]

Summary

Functions

Builds normalized context for plugin-routed action execution.

Creates a StateOp to add a pending tool call.

Creates a StateOp to append a message to the conversation.

Creates a StateOp to append to the streaming text.

Applies state operations to a state map.

Creates a StateOp to clear the current LLM call ID.

Creates a StateOp to clear pending tool calls.

Composes multiple state operations into a single list.

Creates a StateOp to delete specific keys from strategy state.

Creates a StateOp to delete temporary keys from strategy state.

Executes a non-strategy Jido.Action instruction using direct strategy semantics.

Executes an instruction if its action is a module implementing run/2.

Creates a StateOp to prepend a message to the conversation.

Creates a StateOp to remove a specific pending tool by ID.

Creates a StateOp to reset the strategy state to initial values.

Creates a StateOp to set the current LLM call ID.

Creates a StateOp to set a specific config field.

Creates a StateOp to set the entire conversation.

Creates a StateOp to set the final answer.

Creates a StateOp to increment the iteration counter.

Creates a StateOp to set the iteration status.

Creates a StateOp to set pending tool calls.

Creates a StateOp to set a specific field in the strategy state.

Creates a StateOp to set the streaming text.

Creates a StateOp to set the termination reason.

Creates a StateOp to set the usage metadata.

Creates a StateOp to update the config field in strategy state.

Creates StateOps to update multiple config fields at once.

Creates a StateOp to update the strategy state.

Creates StateOps to update tools, actions_by_name, and reqllm_tools together.

Types

state_op()

strategy_ctx()

@type strategy_ctx() :: map()

Functions

action_context(agent, ctx \\ %{})

@spec action_context(Jido.Agent.t(), strategy_ctx()) :: map()

Builds normalized context for plugin-routed action execution.

Guarantees the state, agent, and plugin_state keys are present.

add_pending_tool(tool)

@spec add_pending_tool(map()) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to add a pending tool call.

Examples

iex> tool = %{id: "call_1", name: "search", arguments: %{query: "test"}}
iex> Helpers.add_pending_tool(tool)
%Jido.Agent.StateOp.SetState{attrs: %{pending_tool_calls: [%{id: "call_1", name: "search", arguments: %{query: "test"}}]}}

append_conversation(messages)

@spec append_conversation([map()]) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to append a message to the conversation.

Examples

iex> message = %{role: :user, content: "Hello"}
iex> Helpers.append_conversation([message])
%Jido.Agent.StateOp.SetState{attrs: %{conversation: [%{role: :user, content: "Hello"}]}}

append_streaming_text(text)

@spec append_streaming_text(String.t()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to append to the streaming text.

Examples

iex> Helpers.append_streaming_text(" world")
%Jido.Agent.StateOp.SetPath{path: [:streaming_text], value: " world"}

apply_to_state(state, ops)

@spec apply_to_state(map(), [state_op()]) :: map()

Applies state operations to a state map.

This is useful for strategies to apply state operations internally before setting the strategy state on the agent.

Examples

iex> ops = [Jido.Agent.StateOp.set_path([:status], :running)]
iex> Helpers.apply_to_state(%{iteration: 1}, ops)
%{iteration: 1, status: :running}

clear_call_id()

@spec clear_call_id() :: Jido.Agent.StateOp.DeletePath.t()

Creates a StateOp to clear the current LLM call ID.

Examples

iex> Helpers.clear_call_id()
%Jido.Agent.StateOp.DeletePath{path: [:current_llm_call_id]}

clear_pending_tools()

@spec clear_pending_tools() :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to clear pending tool calls.

Examples

iex> Helpers.clear_pending_tools()
%Jido.Agent.StateOp.SetState{attrs: %{pending_tool_calls: []}}

compose(ops)

@spec compose([state_op()]) :: [state_op()]

Composes multiple state operations into a single list.

This is a convenience function for building state operation lists.

Examples

iex> Helpers.compose([
...>   Helpers.set_iteration_status(:running),
...>   Helpers.set_iteration(1)
...> ])
[%Jido.Agent.StateOp.SetPath{path: [:status], value: :running}, %Jido.Agent.StateOp.SetPath{path: [:iteration], value: 1}]

delete_keys(keys)

@spec delete_keys([atom()]) :: Jido.Agent.StateOp.DeleteKeys.t()

Creates a StateOp to delete specific keys from strategy state.

Examples

iex> Helpers.delete_keys([:temp1, :temp2])
%Jido.Agent.StateOp.DeleteKeys{keys: [:temp1, :temp2]}

delete_temp_keys()

@spec delete_temp_keys() :: Jido.Agent.StateOp.DeleteKeys.t()

Creates a StateOp to delete temporary keys from strategy state.

Examples

iex> Helpers.delete_temp_keys()
%Jido.Agent.StateOp.DeleteKeys{keys: [:temp, :cache, :ephemeral]}

execute_action_instruction(agent, instruction, ctx \\ %{})

@spec execute_action_instruction(Jido.Agent.t(), Jido.Instruction.t(), strategy_ctx()) ::
  {Jido.Agent.t(), [struct()]}

Executes a non-strategy Jido.Action instruction using direct strategy semantics.

This is used as a fallback path in strategy adapters so plugin-routed action modules can run even when the strategy does not have a dedicated command atom.

maybe_execute_action_instruction(agent, instruction, ctx \\ %{})

@spec maybe_execute_action_instruction(
  Jido.Agent.t(),
  Jido.Instruction.t(),
  strategy_ctx()
) ::
  {Jido.Agent.t(), [struct()]} | :noop

Executes an instruction if its action is a module implementing run/2.

Returns :noop when the action is not an executable module.

prepend_conversation(message, existing_conversation \\ [])

@spec prepend_conversation(map(), [map()]) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to prepend a message to the conversation.

Examples

iex> message = %{role: :user, content: "Hello"}
iex> current_conversation = [%{role: :assistant, content: "Hi"}]
iex> Helpers.prepend_conversation(message, current_conversation)
%Jido.Agent.StateOp.SetState{attrs: %{conversation: [%{role: :user, content: "Hello"}, %{role: :assistant, content: "Hi"}]}}

remove_pending_tool(tool_id)

@spec remove_pending_tool(String.t()) :: Jido.Agent.StateOp.DeletePath.t()

Creates a StateOp to remove a specific pending tool by ID.

Examples

iex> Helpers.remove_pending_tool("call_1")
%Jido.Agent.StateOp.DeletePath{path: [:pending_tool_calls, "call_1"]}

Note: This operation is meant for map-based pending_tool_calls. For list-based pending_tool_calls, use filter_pending_tools/1 instead.

reset_strategy_state()

@spec reset_strategy_state() :: Jido.Agent.StateOp.ReplaceState.t()

Creates a StateOp to reset the strategy state to initial values.

Examples

iex> result = Helpers.reset_strategy_state()
iex> result.state.status == :idle and result.state.iteration == 0
true

set_call_id(call_id)

@spec set_call_id(String.t()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set the current LLM call ID.

Examples

iex> Helpers.set_call_id("call_123")
%Jido.Agent.StateOp.SetPath{path: [:current_llm_call_id], value: "call_123"}

set_config_field(key, value)

@spec set_config_field(atom(), term()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set a specific config field.

Examples

iex> Helpers.set_config_field(:tools, [MyAction])
%Jido.Agent.StateOp.SetPath{path: [:config, :tools], value: [MyAction]}

set_conversation(messages)

@spec set_conversation([map()]) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to set the entire conversation.

Examples

iex> messages = [%{role: :user, content: "Hello"}, %{role: :assistant, content: "Hi"}]
iex> Helpers.set_conversation(messages)
%Jido.Agent.StateOp.SetState{attrs: %{conversation: messages}}

set_final_answer(answer)

@spec set_final_answer(String.t()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set the final answer.

Examples

iex> Helpers.set_final_answer("42")
%Jido.Agent.StateOp.SetPath{path: [:final_answer], value: "42"}

set_iteration(iteration)

@spec set_iteration(non_neg_integer()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to increment the iteration counter.

Note: This cannot directly read the current value, so it should be used with the current iteration value known from context.

Examples

iex> Helpers.set_iteration(5)
%Jido.Agent.StateOp.SetPath{path: [:iteration], value: 5}

set_iteration_status(status)

@spec set_iteration_status(atom()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set the iteration status.

Examples

iex> Helpers.set_iteration_status(:awaiting_llm)
%Jido.Agent.StateOp.SetPath{path: [:status], value: :awaiting_llm}

set_pending_tools(tools)

@spec set_pending_tools([map()]) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to set pending tool calls.

Examples

iex> tools = [%{id: "call_1", name: "search", arguments: %{query: "test"}}]
iex> Helpers.set_pending_tools(tools)
%Jido.Agent.StateOp.SetState{attrs: %{pending_tool_calls: tools}}

set_strategy_field(key, value)

@spec set_strategy_field(atom(), term()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set a specific field in the strategy state.

Examples

iex> Helpers.set_strategy_field(:status, :running)
%Jido.Agent.StateOp.SetPath{path: [:status], value: :running}

set_streaming_text(text)

@spec set_streaming_text(String.t()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set the streaming text.

Examples

iex> Helpers.set_streaming_text("Hello")
%Jido.Agent.StateOp.SetPath{path: [:streaming_text], value: "Hello"}

set_termination_reason(reason)

@spec set_termination_reason(atom()) :: Jido.Agent.StateOp.SetPath.t()

Creates a StateOp to set the termination reason.

Examples

iex> Helpers.set_termination_reason(:final_answer)
%Jido.Agent.StateOp.SetPath{path: [:termination_reason], value: :final_answer}

set_usage(usage)

@spec set_usage(map()) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to set the usage metadata.

Examples

iex> usage = %{input_tokens: 10, output_tokens: 20}
iex> Helpers.set_usage(usage)
%Jido.Agent.StateOp.SetState{attrs: %{usage: usage}}

update_config(config)

@spec update_config(map()) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to update the config field in strategy state.

Examples

iex> config = %{tools: [], model: "test"}
iex> Helpers.update_config(config)
%Jido.Agent.StateOp.SetState{attrs: %{config: config}}

update_config_fields(fields)

@spec update_config_fields(map()) :: [Jido.Agent.StateOp.SetPath.t()]

Creates StateOps to update multiple config fields at once.

Examples

iex> ops = Helpers.update_config_fields(%{tools: [], model: "test"})
iex> length(ops)
2
iex> hd(ops).path
[:config, :tools]

update_strategy_state(attrs)

@spec update_strategy_state(map()) :: Jido.Agent.StateOp.SetState.t()

Creates a StateOp to update the strategy state.

Performs a deep merge of the given attributes into the strategy state.

Examples

iex> Helpers.update_strategy_state(%{status: :running, iteration: 1})
%Jido.Agent.StateOp.SetState{attrs: %{status: :running, iteration: 1}}

update_tools_config(tools, actions_by_name, reqllm_tools)

@spec update_tools_config([module()], %{required(String.t()) => module()}, [map()]) ::
  [
    Jido.Agent.StateOp.SetPath.t()
  ]

Creates StateOps to update tools, actions_by_name, and reqllm_tools together.

This is a common pattern when registering/unregistering tools.

Examples

iex> tools = [SomeAction]
iex> actions_by_name = %{"action" => SomeAction}
iex> reqllm_tools = [%{name: "action"}]
iex> ops = Helpers.update_tools_config(tools, actions_by_name, reqllm_tools)
iex> length(ops)
3
iex> hd(ops).path
[:config, :tools]