Packages
AI agent framework for Elixir built on OTP. TEA-based agents with crash isolation, inter-agent messaging, team supervision, and real SSE streaming to Anthropic, OpenAI, Ollama, and more.
Current section
Files
Jump to
Current section
Files
lib/raxol/agent/context_store.ex
defmodule Raxol.Agent.ContextStore do
@moduledoc """
ETS-backed persistent context that survives agent restarts.
Stores agent state snapshots keyed by agent_id. When an agent crashes
and restarts, it can restore its context from here rather than starting
from scratch.
Table: `:raxol_agent_contexts`, named_table, public, set, read_concurrency.
"""
@table :raxol_agent_contexts
@doc """
Initializes the ETS table. Safe to call multiple times.
"""
@spec init() :: :ok
def init do
case :ets.whereis(@table) do
:undefined ->
_ =
:ets.new(@table, [:named_table, :public, :set, read_concurrency: true])
:ok
_ref ->
:ok
end
end
@doc """
Saves a context snapshot for an agent.
"""
@spec save(atom(), map()) :: :ok
def save(agent_id, context) when is_atom(agent_id) and is_map(context) do
ensure_table()
:ets.insert(@table, {agent_id, context, DateTime.utc_now()})
:ok
end
@doc """
Loads the most recent context snapshot for an agent.
"""
@spec load(atom()) :: {:ok, map()} | {:error, :not_found}
def load(agent_id) when is_atom(agent_id) do
ensure_table()
case :ets.lookup(@table, agent_id) do
[{^agent_id, context, _saved_at}] -> {:ok, context}
[] -> {:error, :not_found}
end
end
@doc """
Updates an agent's context by applying a transformation function.
"""
@spec update(atom(), (map() -> map())) :: {:ok, map()} | {:error, :not_found}
def update(agent_id, fun) when is_atom(agent_id) and is_function(fun, 1) do
case load(agent_id) do
{:ok, context} ->
new_context = fun.(context)
save(agent_id, new_context)
{:ok, new_context}
error ->
error
end
end
@doc """
Deletes an agent's context.
"""
@spec delete(atom()) :: :ok
def delete(agent_id) when is_atom(agent_id) do
ensure_table()
:ets.delete(@table, agent_id)
:ok
end
@doc """
Lists all agent ids that have stored contexts.
"""
@spec list() :: [atom()]
def list do
ensure_table()
:ets.select(@table, [{{:"$1", :_, :_}, [], [:"$1"]}])
end
defp ensure_table do
if :ets.whereis(@table) == :undefined do
init()
end
end
end