BeamAgent.Config (beam_agent_ex v0.1.0)

Copy Markdown View Source

Unified configuration management for the BeamAgent SDK.

This module provides both per-session configuration operations (reading, updating, writing individual values and batches, querying requirements, detecting/importing external agent configurations) and global SDK-wide settings (a shared key-value store that applies across all sessions).

Per-session operations work across all five agentic coder backends (Claude, Codex, Gemini, OpenCode, Copilot) via native-first routing with universal fallbacks. Global operations use an ETS-backed store.

When to use directly vs through BeamAgent

Most callers interact with configuration through BeamAgent. Use this module directly when you need focused access to configuration operations -- for example, in a settings UI, a configuration migration script, a tool that imports .cursorrules or CLAUDE.md files from other agentic tools, or during application startup to set SDK-wide defaults.

Quick example

# Read the full session config:
{:ok, config} = BeamAgent.Config.read(session)

# Update a setting:
{:ok, _} = BeamAgent.Config.update(session, %{model: "claude-sonnet-4-20250514"})

# Write a single value:
{:ok, _} = BeamAgent.Config.value_write(session, "permissions.mode", "full")

# Batch write:
{:ok, _} = BeamAgent.Config.batch_write(session, [
  %{key_path: "model", value: "claude-sonnet-4-20250514"},
  %{key_path: "permissions.mode", value: "full"}
])

# Detect external agent configs:
{:ok, configs} = BeamAgent.Config.external_agent_detect(session)

# Global SDK config:
:ok = BeamAgent.Config.global_set("max_retries", 3)
{:ok, 3} = BeamAgent.Config.global_get("max_retries")

Architecture deep dive

This module is a thin Elixir facade that defdelegates every call to the Erlang :beam_agent_config module. Zero business logic, zero state, zero processes live here -- the Erlang module owns the implementation. Session config uses native-first routing; global config uses an ETS-backed store.

See also: BeamAgent, BeamAgent.Provider, BeamAgent.Runtime.

Summary

Functions

Write multiple configuration values in a single batch.

Write multiple configuration values in a single batch with options.

Apply a batch of universal config writes.

Read the universal config/provider view for a live session pid or persisted session id.

Describe the universal config keys supported by the canonical fallback.

Apply universal config updates for backends without native config APIs.

Write a single universal config value at a dot-separated key path.

Create the global SDK config ETS table. Idempotent.

Detect universal config already materialized for a session.

Import universal config material from an already-decoded map.

Detect external agent configuration files in the project.

Detect external agent configuration files with options.

Import an external agent configuration into the session.

Remove all global SDK config entries.

Delete a global SDK config key. Idempotent.

Fetch a global SDK config value by key.

Fetch a global SDK config value by key, returning a default if not found.

List all global SDK config entries.

Set a global SDK config key-value pair.

Describe provider auth methods available through the universal fallback.

Start a universal provider auth flow when native OAuth is unavailable.

Complete a universal provider auth flow and persist the callback payload.

List the providers available in the session configuration.

Read the full configuration for a session.

Read the session configuration with additional options.

Read the configuration requirements for a session.

Update the session configuration with a partial patch.

Write a single configuration value at the given key path.

Write a single configuration value at the given key path with options.

Functions

batch_write(session, edits)

@spec batch_write(pid() | binary(), [map()]) :: {:ok, map()} | {:error, term()}

Write multiple configuration values in a single batch.

Convenience wrapper that calls batch_write/3 with empty options.

Parameters

  • session -- pid of a running session.
  • edits -- list of maps, each containing a :key_path and :value.

Returns

  • {:ok, result} or {:error, reason}.

batch_write(session, edits, opts)

@spec batch_write(pid() | binary(), [map()], map()) :: {:ok, map()} | {:error, term()}

Write multiple configuration values in a single batch with options.

All edits are applied atomically when the backend supports it.

Parameters

  • session -- pid of a running session.
  • edits -- list of maps, each containing a :key_path and :value.
  • opts -- backend-specific write options map.

Returns

  • {:ok, result} or {:error, reason} if any edit fails validation.

config_batch_write(session, edits, opts)

@spec config_batch_write(pid() | binary(), [map()], map()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Apply a batch of universal config writes.

config_read(session)

@spec config_read(pid() | binary()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Read the universal config/provider view for a live session pid or persisted session id.

This is the universal (non-native) implementation exported so backend facades can delegate to it directly.

config_requirements_read(session)

@spec config_requirements_read(pid() | binary()) ::
  {:ok,
   %{
     config_sources: [:control | :runtime | :session, ...],
     control: %{max_thinking_tokens: :integer, permission_mode: [any(), ...]},
     providers: [map(), ...],
     runtime: %{
       agent: :binary,
       mode: :binary,
       model_id: :binary,
       provider: :map,
       provider_id: :binary,
       system: [any(), ...],
       tools: [any(), ...]
     },
     writable_key_paths: [<<_::64, _::_*8>>, ...]
   }}

Describe the universal config keys supported by the canonical fallback.

config_update(session, body)

@spec config_update(pid() | binary(), map()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Apply universal config updates for backends without native config APIs.

config_value_write(session, key_path, value, opts)

@spec config_value_write(pid() | binary(), binary(), term(), map()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Write a single universal config value at a dot-separated key path.

ensure_table()

@spec ensure_table() :: :ok

Create the global SDK config ETS table. Idempotent.

Call this during application startup or before first use of any global_* function.

external_agent_config_detect(session, opts)

@spec external_agent_config_detect(pid() | binary(), map()) ::
  {:ok,
   %{
     config: %{control: map(), runtime: map(), session: map()},
     detected: boolean(),
     source: :universal
   }}
  | {:error, term()}

Detect universal config already materialized for a session.

external_agent_config_import(session, opts)

@spec external_agent_config_import(pid() | binary(), map()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Import universal config material from an already-decoded map.

external_agent_detect(session)

@spec external_agent_detect(pid() | binary()) :: {:ok, map()} | {:error, term()}

Detect external agent configuration files in the project.

Scans the session's working directory for configuration files from other agentic tools (e.g., .cursorrules, CLAUDE.md, .github/copilot).

Parameters

  • session -- pid of a running session.

Returns

  • {:ok, configs} or {:error, reason}.

external_agent_detect(session, opts)

@spec external_agent_detect(pid() | binary(), map()) ::
  {:ok, map()} | {:error, term()}

Detect external agent configuration files with options.

opts may include filters such as a list of specific config formats to detect or directories to scan.

Parameters

  • session -- pid of a running session.
  • opts -- detection options map.

Returns

  • {:ok, configs} or {:error, reason}.

external_agent_import(session, opts)

@spec external_agent_import(pid() | binary(), map()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Import an external agent configuration into the session.

Takes a previously detected external config (from external_agent_detect/1) and merges its settings into the session configuration.

Parameters

  • session -- pid of a running session.
  • opts -- import options map (should include the path or identifier of the config to import).

Returns

  • {:ok, result} or {:error, reason}.

global_clear()

@spec global_clear() :: :ok

Remove all global SDK config entries.

global_delete(key)

@spec global_delete(:beam_agent_config.config_key()) :: :ok

Delete a global SDK config key. Idempotent.

global_get(key)

@spec global_get(:beam_agent_config.config_key()) ::
  {:ok, :beam_agent_config.config_value()} | {:error, :not_found}

Fetch a global SDK config value by key.

Returns

  • {:ok, value} if the key exists.
  • {:error, :not_found} if the key has not been set.

global_get(key, default)

Fetch a global SDK config value by key, returning a default if not found.

Parameters

  • key -- binary config key.
  • default -- value returned when the key does not exist.

global_list()

@spec global_list() :: [:beam_agent_config.config_entry()]

List all global SDK config entries.

Returns a list of {key, value} tuples.

global_set(key, value)

Set a global SDK config key-value pair.

Global config is shared across all sessions on the node. Mutations notify the reload bus so live sessions react without restart.

Parameters

  • key -- binary config key (e.g., "default_backend", "max_retries").
  • value -- any term to store.

provider_auth_methods(session)

@spec provider_auth_methods(pid() | binary()) :: {:ok, [map()]}

Describe provider auth methods available through the universal fallback.

provider_oauth_authorize(session, provider_id, body)

@spec provider_oauth_authorize(pid() | binary(), binary(), map()) ::
  {:ok,
   %{
     auth_method: <<_::112>>,
     authorize_url: any(),
     provider: %{
       auth_methods: [any(), ...],
       capabilities: [any(), ...],
       config_keys: [any()],
       id: binary(),
       label: binary(),
       source: :runtime | :universal_registry
     },
     provider_id: binary(),
     request_id: binary(),
     source: :universal,
     status: :pending
   }}

Start a universal provider auth flow when native OAuth is unavailable.

provider_oauth_callback(session, provider_id, body)

@spec provider_oauth_callback(pid() | binary(), binary(), map()) ::
  {:ok,
   %{
     auth_method: <<_::112>>,
     provider: %{
       oauth_callback: map(),
       provider_id: binary(),
       source: :universal
     },
     provider_id: binary(),
     source: :universal,
     status: :configured
   }}
  | {:error, :invalid_api_key | :invalid_provider_config}

Complete a universal provider auth flow and persist the callback payload.

providers(session)

@spec providers(pid() | binary()) :: {:ok, [map()]} | {:error, term()}

List the providers available in the session configuration.

A provider represents an LLM service endpoint (e.g., Anthropic, OpenAI, Google).

Parameters

  • session -- pid of a running session.

Returns

  • {:ok, providers} or {:error, reason}.

read(session)

@spec read(pid() | binary()) :: {:ok, map()} | {:error, term()}

Read the full configuration for a session.

Returns the merged configuration map that governs the session's behavior. This includes model settings, permission mode, system prompt, working directory, and any backend-specific keys.

Parameters

  • session -- pid of a running session.

Returns

  • {:ok, config_map} or {:error, reason}.

read(session, opts)

@spec read(pid() | binary(), map()) :: {:ok, map()} | {:error, term()}

Read the session configuration with additional options.

opts can filter or transform the returned configuration. The exact keys accepted depend on the backend.

Parameters

  • session -- pid of a running session.
  • opts -- filter/transform options map.

Returns

  • {:ok, config_map} or {:error, reason}.

requirements_read(session)

@spec requirements_read(pid() | binary()) :: {:ok, map()} | {:error, term()}

Read the configuration requirements for a session.

Returns the set of required configuration keys and their constraints (types, allowed values, defaults). Useful for building configuration UIs or validating user input before calling update/2.

Parameters

  • session -- pid of a running session.

Returns

  • {:ok, requirements} or {:error, reason}.

update(session, body)

@spec update(pid() | binary(), map()) ::
  {:ok, :beam_agent_config.config_view()} | {:error, term()}

Update the session configuration with a partial patch.

Merges body into the existing configuration. Only the keys present in body are changed; all other keys are preserved.

Parameters

  • session -- pid of a running session.
  • body -- map of configuration key-value pairs to update.

Returns

  • {:ok, updated_config} or {:error, reason}.

value_write(session, key_path, value)

@spec value_write(pid() | binary(), binary(), term()) ::
  {:ok, map()} | {:error, term()}

Write a single configuration value at the given key path.

Convenience wrapper that calls value_write/4 with empty options.

Parameters

  • session -- pid of a running session.
  • key_path -- dot-separated binary identifying the config key (e.g., "model", "permissions.mode").
  • value -- the new value to store.

Returns

  • {:ok, result} or {:error, reason}.

value_write(session, key_path, value, opts)

@spec value_write(pid() | binary(), binary(), term(), map()) ::
  {:ok, map()} | {:error, term()}

Write a single configuration value at the given key path with options.

key_path is a dot-separated binary identifying the configuration key. opts may include backend-specific write options such as scope or persistence level.

Parameters

  • session -- pid of a running session.
  • key_path -- dot-separated binary config key path.
  • value -- the new value to store.
  • opts -- backend-specific write options map.

Returns

  • {:ok, result} on success.
  • {:error, reason} if the key is read-only or the value is invalid.