BeamAgent.Memory (beam_agent_ex v0.1.0)

Copy Markdown View Source

Canonical long-term memory for BeamAgent.

Memories are durable cross-session facts and notes that can be scoped to sessions, threads, or runs, linked to artifacts and other typed references, and recalled later using lexical search. This is the Elixir facade over the Erlang :beam_agent_memory public module.

Summary

Types

Exact-match filter accepted by list/1, search/2, and expire/1.

Input accepted by remember/2,3.

Canonical memory record.

Scope passed to remember/2,3 and recall/2.

Typed source reference stored on a memory.

Store configuration for configure_persistence/1.

Map of mutable fields accepted by update/2.

Functions

Clear all memories.

Configure a persistence adapter for the memory domain.

Ensure the memory store exists.

Expire all currently expired, unpinned memories.

Expire currently expired, unpinned memories matching a filter.

Forget a memory by id.

Fetch a memory by id.

List all visible memories.

List memories with exact-match filters and visibility controls.

Pin a memory.

Recall memories for a scope using lexical search.

Remember content with embedded or explicit kind on a scope.

Remember content with an explicit kind on a scope.

Search memories across all scopes.

Search memories with a lexical query plus exact-match filters.

Unpin a memory.

Update mutable fields of an existing memory record.

Types

memory_filter()

@type memory_filter() :: %{
  optional(:memory_id) => binary(),
  optional(:kind) => atom() | binary(),
  optional(:session_id) => binary(),
  optional(:thread_id) => binary(),
  optional(:run_id) => binary(),
  optional(:pinned) => boolean(),
  optional(:source_ref_type) => atom() | binary(),
  optional(:source_ref_id) => binary(),
  optional(:limit) => pos_integer(),
  optional(:since) => integer(),
  optional(:include_expired) => boolean(),
  optional(:min_salience) => non_neg_integer(),
  optional(:before) => integer()
}

Exact-match filter accepted by list/1, search/2, and expire/1.

memory_input()

@type memory_input() ::
  binary()
  | %{
      optional(:memory_id) => binary(),
      optional(:kind) => atom() | binary(),
      optional(:content) => term(),
      optional(:attributes) => map(),
      optional(:source_refs) => [source_ref()],
      optional(:ttl) => non_neg_integer() | :infinity,
      optional(:pinned) => boolean(),
      optional(:salience) => non_neg_integer(),
      optional(:session_id) => binary(),
      optional(:thread_id) => binary(),
      optional(:run_id) => binary()
    }

Input accepted by remember/2,3.

memory_record()

@type memory_record() :: %{
  :memory_id => binary(),
  :kind => atom() | binary(),
  :content => term(),
  :attributes => map(),
  :source_refs => [source_ref()],
  :scope => map(),
  :pinned => boolean(),
  :salience => non_neg_integer(),
  :ttl => non_neg_integer() | :infinity,
  :created_at => integer(),
  :updated_at => integer(),
  optional(:expires_at) => integer()
}

Canonical memory record.

scope()

@type scope() ::
  binary()
  | %{
      optional(:session_id) => binary(),
      optional(:thread_id) => binary(),
      optional(:run_id) => binary()
    }

Scope passed to remember/2,3 and recall/2.

Use either a binary session id or a map containing any of :session_id, :thread_id, and :run_id.

source_ref()

@type source_ref() :: %{
  :type => atom() | binary(),
  :id => binary(),
  optional(:metadata) => map()
}

Typed source reference stored on a memory.

store_config()

@type store_config() :: %{:adapter => module(), optional(:options) => map()}

Store configuration for configure_persistence/1.

Keys:

  • :adapter — the adapter module (e.g. :beam_agent_store_dets)
  • :options — adapter-specific options map (optional)

update_input()

@type update_input() :: %{
  optional(:kind) => atom() | binary(),
  optional(:content) => term(),
  optional(:attributes) => map(),
  optional(:source_refs) => [source_ref()],
  optional(:ttl) => non_neg_integer() | :infinity,
  optional(:pinned) => boolean(),
  optional(:salience) => non_neg_integer()
}

Map of mutable fields accepted by update/2.

Mutable: :kind, :content, :attributes, :source_refs, :ttl, :pinned, :salience. Immutable fields (:memory_id, :scope, :created_at) are rejected with {:error, {:immutable_field, field}}.

Functions

clear()

@spec clear() :: :ok

Clear all memories.

configure_persistence(config)

@spec configure_persistence(store_config()) ::
  :ok | {:error, :invalid_options | {:invalid_adapter, atom()}}

Configure a persistence adapter for the memory domain.

By default memories live in ETS and vanish on VM restart. Call this to switch to a durable adapter such as :beam_agent_store_dets.

Example

BeamAgent.Memory.configure_persistence(%{
  adapter: :beam_agent_store_dets,
  options: %{data_dir: "/tmp/beam_agent"}
})

When using DETS, call :beam_agent_store_dets.close_table(:beam_agent_memory_records) during application shutdown to flush pending writes.

ensure_tables()

@spec ensure_tables() :: :ok

Ensure the memory store exists.

expire()

@spec expire() :: {:ok, non_neg_integer()}

Expire all currently expired, unpinned memories.

expire(filter)

@spec expire(memory_filter()) ::
  {:ok, non_neg_integer()}
  | {:error,
     {:invalid_filter,
      :before
      | :include_expired
      | :kind
      | :limit
      | :memory_id
      | :min_salience
      | :pinned
      | :run_id
      | :session_id
      | :since
      | :source_ref_id
      | :source_ref_type
      | :thread_id}
     | {:invalid_scope,
        :memory_id | :run_id | :session_id | :source_ref_id | :thread_id}}

Expire currently expired, unpinned memories matching a filter.

forget(memory_id)

@spec forget(binary()) :: :ok | {:error, :not_found}

Forget a memory by id.

get(memory_id)

@spec get(binary()) :: {:ok, memory_record()} | {:error, :not_found}

Fetch a memory by id.

list()

@spec list() :: {:ok, [memory_record()]}

List all visible memories.

list(filter)

@spec list(memory_filter()) :: {:ok, [memory_record()]} | {:error, term()}

List memories with exact-match filters and visibility controls.

pin(memory_id)

@spec pin(binary()) :: :ok | {:error, :not_found}

Pin a memory.

recall(scope, query)

@spec recall(scope(), binary()) :: {:ok, [memory_record()]} | {:error, term()}

Recall memories for a scope using lexical search.

remember(scope, memory_input)

@spec remember(scope(), memory_input()) :: {:ok, memory_record()} | {:error, term()}

Remember content with embedded or explicit kind on a scope.

remember(scope, kind, memory_input)

@spec remember(scope(), atom() | binary(), memory_input()) ::
  {:ok, memory_record()} | {:error, term()}

Remember content with an explicit kind on a scope.

search(query)

@spec search(binary()) :: {:ok, [memory_record()]}

Search memories across all scopes.

search(query, filter)

@spec search(binary(), memory_filter()) :: {:ok, [memory_record()]} | {:error, term()}

Search memories with a lexical query plus exact-match filters.

unpin(memory_id)

@spec unpin(binary()) :: :ok | {:error, :not_found}

Unpin a memory.

update(memory_id, changes)

@spec update(binary(), update_input()) ::
  {:ok, memory_record()}
  | {:error, :not_found | {:immutable_field, atom()} | term()}

Update mutable fields of an existing memory record.

When :ttl is updated, :expires_at is automatically recalculated from the current time. The :updated_at timestamp is always refreshed.