LLMAgent.Store (llm_agent v0.2.0)
View SourceManages state for LLM agent conversations.
This module extends AgentForge.Store to provide helpers specific to LLM agent state, including managing conversation history, thoughts, tool calls, and tasks. It leverages AgentForge's GenServer-based state management while adding LLM-specific abstractions.
Summary
Functions
Adds an error record to the state.
Adds a function result to the state, useful for tracking tool execution outcomes.
Adds a message to history.
Adds a task to the current tasks list.
Adds a thought to the current processing cycle.
Adds a tool call record to the state.
Deletes a key from the store.
Gets a value from the store by key.
Gets LLM history in the format expected by LLM providers.
Gets a specific user preference.
Gets all preferences from the state.
Gets all thoughts for the current processing cycle.
Creates or initializes a new store with default values.
Optimizes the state by trimming history and pruning thoughts.
Prunes the thoughts list to a maximum size to prevent memory bloat.
Puts a value into the store with the given key.
Sets user preferences in the state.
Starts the LLMAgent store process with an optional name.
Trims history to a maximum number of entries while preserving system messages.
Updates task state for a specific task.
Functions
Adds an error record to the state.
Parameters
state
- The current store stateerror
- The error record, typically in the form of a tuple with error type, message, and timestamp
Returns
An updated state with the new error record added.
Examples
iex> state = LLMAgent.Store.new()
iex> state = LLMAgent.Store.add_error(state, {:llm_error, "Service unavailable", DateTime.utc_now()})
iex> [error] = state.errors
iex> elem(error, 0) == :llm_error
true
Adds a function result to the state, useful for tracking tool execution outcomes.
Parameters
state
- The current store statefunction_name
- The name of the function/toolresult
- The result returned by the function
Returns
An updated state with the function result added to history in a format compatible with LLM context.
Examples
iex> state = LLMAgent.Store.new()
iex> state = LLMAgent.Store.add_function_result(state, "get_weather", %{temp: 72})
iex> Enum.any?(state.history, fn msg -> msg.role == "function" end)
true
Adds a message to history.
Parameters
store
- The store process name or pidrole
- The role of the message (e.g., "user", "assistant", "system")content
- The content of the message
Returns
:ok if the message was added successfully
Examples
iex> store = LLMAgent.Store.new()
iex> :ok = LLMAgent.Store.add_message(store, "user", "Hello")
iex> {:ok, history} = AgentForge.Store.get(store, :history)
iex> [%{role: "user", content: "Hello"}] = history
Adds a task to the current tasks list.
Parameters
store
- The store process name or pidtask
- The task to add
Returns
:ok if the task was added successfully
Examples
iex> store = LLMAgent.Store.new()
iex> task = %{id: "task_123", type: "analysis", status: "running"}
iex> :ok = LLMAgent.Store.add_task(store, task)
iex> {:ok, tasks} = AgentForge.Store.get(store, :current_tasks)
iex> [%{id: "task_123"}] = tasks
Adds a thought to the current processing cycle.
Parameters
store
- The store process name or pidthought
- The thought content
Returns
:ok if the thought was added successfully
Examples
iex> store = LLMAgent.Store.new()
iex> :ok = LLMAgent.Store.add_thought(store, "I should look up stock prices")
iex> {:ok, thoughts} = AgentForge.Store.get(store, :thoughts)
iex> ["I should look up stock prices"] = thoughts
Adds a tool call record to the state.
Parameters
store
- The store process name or pidname
- The name of the toolargs
- The arguments passed to the toolresult
- The result of the tool call
Returns
:ok if the tool call was added successfully
Examples
iex> store = LLMAgent.Store.new()
iex> :ok = LLMAgent.Store.add_tool_call(store, "get_weather", %{city: "New York"}, %{temp: 72})
iex> {:ok, tool_calls} = AgentForge.Store.get(store, :tool_calls)
iex> [%{name: "get_weather", args: %{city: "New York"}, result: %{temp: 72}}] = tool_calls
Deletes a key from the store.
Parameters
store_name
- The name of the storekey
- The key to delete
Returns
:ok
Examples
iex> LLMAgent.Store.delete(store, :test_key)
:ok
Gets a value from the store by key.
Parameters
store_name
- The name of the storekey
- The key to retrieve
Returns
if the key exists, {:error, :not_found} otherwise
Examples
iex> LLMAgent.Store.put(store, :test_key, "test_value")
:ok
iex> LLMAgent.Store.get(store, :test_key)
{:ok, "test_value"}
Gets LLM history in the format expected by LLM providers.
Parameters
store
- The store process name or pidmax_length
- The maximum number of history entries to return (default: 10)
Returns
A list of history entries, limited to the specified maximum length. Returns empty list if history can't be retrieved.
Examples
iex> store = LLMAgent.Store.new()
iex> :ok = LLMAgent.Store.add_message(store, "system", "You are a helpful assistant.")
iex> :ok = LLMAgent.Store.add_message(store, "user", "Hello")
iex> history = LLMAgent.Store.get_llm_history(store)
iex> length(history) == 2
true
Gets a specific user preference.
Parameters
state
- The current store statekey
- The preference key to getdefault
- The default value to return if the preference is not set
Returns
The preference value or the default value.
Examples
iex> state = LLMAgent.Store.new()
iex> state = LLMAgent.Store.set_preferences(state, %{language: "en"})
iex> LLMAgent.Store.get_preference(state, :language, "fr")
"en"
iex> LLMAgent.Store.get_preference(state, :theme, "dark")
"dark"
Gets all preferences from the state.
Parameters
state
- The current store state
Returns
A map of preferences.
Examples
iex> state = LLMAgent.Store.new(%{preferences: %{theme: "dark"}})
iex> LLMAgent.Store.get_preferences(state)
%{theme: "dark"}
Gets all thoughts for the current processing cycle.
Parameters
store
- The store process name or pid
Returns
A list of thoughts from the current processing cycle. Returns empty list if thoughts can't be retrieved.
Examples
iex> store = LLMAgent.Store.new()
iex> :ok = LLMAgent.Store.add_thought(store, "First thought")
iex> :ok = LLMAgent.Store.add_thought(store, "Second thought")
iex> thoughts = LLMAgent.Store.get_thoughts(store)
iex> length(thoughts) == 2
true
Creates or initializes a new store with default values.
If the store process doesn't exist, starts a new one. If it does exist, ensures it has the default keys initialized.
Parameters
attrs
- A map of attributes to merge with the default storeopts
- Options for the store, including the store name
Returns
The name of the initialized store.
Examples
iex> store = LLMAgent.Store.new()
iex> {:ok, history} = AgentForge.Store.get(store, :history)
iex> is_list(history)
true
iex> store = LLMAgent.Store.new(%{user_id: "123"})
iex> {:ok, "123"} = AgentForge.Store.get(store, :user_id)
Optimizes the state by trimming history and pruning thoughts.
This is a utility function that combines trim_history and prune_thoughts to optimize the entire state at once.
Parameters
state
- The current store stateoptions
- Options including :max_history and :max_thoughts
Returns
An optimized state.
Examples
iex> state = LLMAgent.Store.new()
iex> # Add lots of history and thoughts
iex> optimized_state = LLMAgent.Store.optimize(state, max_history: 30, max_thoughts: 10)
iex> is_map(optimized_state)
true
Prunes the thoughts list to a maximum size to prevent memory bloat.
Parameters
state
- The current store statemax_thoughts
- The maximum number of thoughts to keep (default: 20)
Returns
An updated state with pruned thoughts.
Examples
iex> state = LLMAgent.Store.new()
iex> state = Enum.reduce(1..30, state, fn n, acc -> LLMAgent.Store.add_thought(acc, "Thought " <> Integer.to_string(n)) end)
iex> pruned_state = LLMAgent.Store.prune_thoughts(state)
iex> length(pruned_state.thoughts) <= 20
true
Puts a value into the store with the given key.
Parameters
store_name
- The name of the storekey
- The key to setvalue
- The value to store
Returns
:ok
Examples
iex> LLMAgent.Store.put(store, :test_key, "test_value")
:ok
Sets user preferences in the state.
Parameters
state
- The current store statepreferences
- The preferences to set
Returns
An updated state with the preferences merged into the existing preferences.
Examples
iex> state = LLMAgent.Store.new()
iex> state = LLMAgent.Store.set_preferences(state, %{language: "en"})
iex> state.preferences.language
"en"
Starts the LLMAgent store process with an optional name.
Parameters
opts
- Options to pass to the store, including the store name
Returns
The result of GenServer.start_link/3 from AgentForge.Store
Examples
iex> {:ok, _pid} = LLMAgent.Store.start_link()
iex> {:ok, _pid} = LLMAgent.Store.start_link(name: :my_llm_store)
Trims history to a maximum number of entries while preserving system messages.
This function is useful for managing memory usage in long conversations. System messages are always preserved, and the most recent user/assistant messages are kept up to the specified limit.
Parameters
state
- The current store statemax_entries
- The maximum number of entries to keep (default: 50)
Returns
An updated state with trimmed history.
Examples
iex> state = LLMAgent.Store.new()
iex> state = LLMAgent.Store.add_message(state, "system", "You are an assistant")
iex> # Add many user/assistant message pairs to exceed the limit
iex> state = Enum.reduce(1..60, state, fn n, acc ->
...> acc = LLMAgent.Store.add_message(acc, "user", "Message " <> Integer.to_string(n))
...> LLMAgent.Store.add_message(acc, "assistant", "Response " <> Integer.to_string(n))
...> end)
iex> trimmed_state = LLMAgent.Store.trim_history(state)
iex> length(trimmed_state.history) <= 51 # 50 + 1 system message
true
iex> # Verify system message is preserved
iex> Enum.any?(trimmed_state.history, fn msg -> msg.role == "system" end)
true
Updates task state for a specific task.
Parameters
state
- The current store statetask_id
- The ID of the task to updatenew_state
- The new state for the task
Returns
An updated state with the task state updated.
Examples
iex> state = LLMAgent.Store.new()
iex> task = %{id: "task_123", status: "running"}
iex> state = LLMAgent.Store.add_task(state, task)
iex> state = LLMAgent.Store.update_task_state(state, "task_123", "completed")
iex> [%{id: "task_123", status: "completed"}] = state.current_tasks