BeamAgent.Capabilities (beam_agent_ex v0.1.0)

Copy Markdown View Source

Capability metadata for the BeamAgent SDK.

This module is the single source of truth for which features each backend supports and how. It answers questions like "can I use checkpointing with Gemini?" or "does OpenCode have a direct implementation of thread management?"

When to use directly vs through BeamAgent

Use this module in feature-detection code, capability-discovery UIs, documentation generators, or tests that verify backend parity. You do not need it for normal session usage.

Capability model

Every capability/backend pair is described across three orthogonal dimensions:

  • :support_level:missing | :partial | :baseline | :full

  • :implementation:direct_backend | :universal | :direct_backend_and_universal

  • :fidelity:exact | :validated_equivalent

All 23 capabilities are at :full support level across all 5 backends. The :implementation field records whether the route is a direct backend call, a BeamAgent universal path (OTP-layer shim), or a hybrid that exposes both.

The 23 capabilities

session_lifecycle       session_info            runtime_model_switch
interrupt               permission_mode         session_history
session_mutation        thread_management       metadata_accessors
in_process_mcp          mcp_management          hooks
checkpointing           thinking_budget         task_stop
command_execution       approval_callbacks      user_input_callbacks
realtime_review         config_management       provider_management
attachments             event_streaming

Quick example

# Is checkpointing supported for codex?
{:ok, true} = BeamAgent.Capabilities.supports(:checkpointing, :codex)

# What implementation does gemini use for permission_mode?
{:ok, %{implementation: :universal}} =
  BeamAgent.Capabilities.status(:permission_mode, :gemini)

# Full capability list for a live session:
{:ok, caps} = BeamAgent.Capabilities.for_session(session_pid)
[%{id: :session_lifecycle, support_level: :full} | _] = caps

Architecture deep dive

BeamAgent.Capabilities is the sole capability registry for the project and the normative source for the docs/architecture/*matrix*.md artifacts. All entries are compiled-in static data — there is no ETS or runtime state. This module is a thin Elixir facade that delegates to :beam_agent_capabilities.

Summary

Types

One of the five supported agent backends.

Capability atom identifier.

Full capability info map as returned by all/0.

Fidelity of the implementation relative to the canonical surface.

Implementation routing strategy for a capability/backend pair.

Support info map for a single capability/backend pair.

Support level for a capability/backend pair.

Functions

Return the full capability matrix as a list of capability_info() maps.

Assert that a capability is supported for a given backend.

Return the list of all supported backend atoms.

Return the full capability matrix as a list of capability info maps.

List capabilities for a specific session or backend.

Return the flat list of all 23 capability atom identifiers.

Return the projected capability list for a specific backend.

Return the projected capability list for the backend of a live session.

Return the full support_info() map for a specific capability/backend pair.

Check whether a capability is supported for a given backend.

Types

backend()

@type backend() :: :claude | :codex | :copilot | :gemini | :opencode

One of the five supported agent backends.

capability()

@type capability() :: atom()

Capability atom identifier.

One of: :session_lifecycle, :session_info, :runtime_model_switch, :interrupt, :permission_mode, :session_history, :session_mutation, :thread_management, :metadata_accessors, :in_process_mcp, :mcp_management, :hooks, :checkpointing, :thinking_budget, :task_stop, :command_execution, :approval_callbacks, :user_input_callbacks, :realtime_review, :config_management, :provider_management, :attachments, :event_streaming.

capability_info()

@type capability_info() :: %{
  id: capability(),
  title: binary(),
  support: %{
    required(:claude | :codex | :gemini | :opencode | :copilot) =>
      support_info()
  }
}

Full capability info map as returned by all/0.

Contains :id (capability atom), :title (binary), and :support (a map from backend atom to support_info()).

fidelity()

@type fidelity() :: :exact | :validated_equivalent

Fidelity of the implementation relative to the canonical surface.

implementation()

@type implementation() :: :direct_backend | :universal | :direct_backend_and_universal

Implementation routing strategy for a capability/backend pair.

support_info()

@type support_info() :: %{
  :support_level => support_level(),
  :implementation => implementation(),
  :fidelity => fidelity(),
  optional(:available_paths) => [implementation()],
  optional(:notes) => binary()
}

Support info map for a single capability/backend pair.

Always contains :support_level, :implementation, and :fidelity. May also include :available_paths (list of implementation atoms) and :notes (binary) for backend-specific detail.

support_level()

@type support_level() :: :missing | :partial | :baseline | :full

Support level for a capability/backend pair.

Functions

all()

@spec all() :: [capability_info()]

Return the full capability matrix as a list of capability_info() maps.

Each entry contains the capability :id, a human-readable :title, and a :support map keyed by backend atom. This is the master data source consulted by all other functions in this module.

Example

all = BeamAgent.Capabilities.all()
[%{id: :session_lifecycle, title: _, support: s} | _] = all

assert_capability(capability, backend)

@spec assert_capability(capability(), atom() | binary()) ::
  :ok
  | {:error,
     {:unsupported_capability, capability(), backend()}
     | {:unknown_capability, capability()}
     | {:unknown_backend, term()}}

Assert that a capability is supported for a given backend.

A pre-flight check wrapper around supports/2. Returns :ok when the capability is supported, or {:error, {:unsupported_capability, cap, backend}} when the capability is not available. Returns the underlying {:error, status_error()} tuple for unknown capability or backend atoms.

Use this before calling a feature to produce a clear error at the call site rather than a confusing failure inside the feature implementation.

Example

iex> BeamAgent.Capabilities.assert_capability(:checkpointing, :codex)
:ok

iex> BeamAgent.Capabilities.assert_capability(:bogus_feature, :claude)
{:error, {:unknown_capability, :bogus_feature}}

backends()

@spec backends() :: [:claude | :codex | :gemini | :opencode | :copilot, ...]

Return the list of all supported backend atoms.

The five backends are: :claude, :codex, :gemini, :opencode, :copilot.

Example

iex> BeamAgent.Capabilities.backends()
[:claude, :codex, :gemini, :opencode, :copilot]

capabilities()

@spec capabilities() :: [capability_info()]

Return the full capability matrix as a list of capability info maps.

Each entry describes one capability with its support level across all five backends. Equivalent to all/0 — this is the convenience name used by the top-level BeamAgent module.

Example

caps = BeamAgent.Capabilities.capabilities()
for cap <- caps, do: IO.puts(cap[:id])

capabilities(value)

@spec capabilities(pid() | atom() | binary()) ::
  {:ok, [map()]}
  | {:error,
     :backend_not_present
     | {:invalid_session_info, term()}
     | {:session_backend_lookup_failed, term()}
     | {:unknown_backend, term()}}

List capabilities for a specific session or backend.

When given a pid, queries the live session for its backend and returns that backend's capability set. When given a backend atom or binary, returns the static capability set for that backend without requiring a running session.

Parameters

  • value -- a session pid, backend atom (e.g., :claude), or binary.

Returns

  • {:ok, capabilities} -- list of capability maps.
  • {:error, reason} on failure.

Examples

{:ok, caps} = BeamAgent.Capabilities.capabilities(:claude)
{:ok, caps} = BeamAgent.Capabilities.capabilities(session)

capability_ids()

@spec capability_ids() :: [capability()]

Return the flat list of all 23 capability atom identifiers.

Useful for iterating over capabilities without loading the full matrix. The order matches the order of entries in all/0.

Example

ids = BeamAgent.Capabilities.capability_ids()
true = :checkpointing in ids

for_backend(backend)

@spec for_backend(atom() | binary()) ::
  {:ok, [map()]} | {:error, {:unknown_backend, term()}}

Return the projected capability list for a specific backend.

backend_like may be a backend atom (:claude), a binary ("codex"), or any value accepted by :beam_agent_backend.normalize/1.

Each entry in the returned list is a flat map with :id, :title, :backend, :support_level, :implementation, and :fidelity, plus optional :available_paths and :notes where present.

Returns {:error, {:unknown_backend, backend}} for unrecognised backend values.

Example

{:ok, caps} = BeamAgent.Capabilities.for_backend(:claude)
[%{id: :session_lifecycle, support_level: :full} | _] = caps

for_session(session)

@spec for_session(pid()) ::
  {:ok, [map()]}
  | {:error,
     :backend_not_present
     | {:unknown_backend, term()}
     | {:invalid_session_info, term()}
     | {:session_backend_lookup_failed, term()}}

Return the projected capability list for the backend of a live session.

Resolves the backend from the running session process and delegates to for_backend/1. This is the most convenient call during an active agent session when you do not know — or do not want to hard-code — the backend.

Returns {:error, :backend_not_present} if the session process is not registered, or {:error, {:session_backend_lookup_failed, reason}} for other lookup failures.

Example

{:ok, session} = BeamAgent.start_session(%{backend: :gemini})
{:ok, caps} = BeamAgent.Capabilities.for_session(session)

status(capability, backend)

@spec status(capability(), atom() | binary()) ::
  {:ok, support_info()}
  | {:error, {:unknown_backend, term()} | {:unknown_capability, term()}}

Return the full support_info() map for a specific capability/backend pair.

The returned map always contains :support_level, :implementation, and :fidelity. It may also include :available_paths and :notes where the capability has backend-specific detail.

Returns {:error, {:unknown_capability, cap}} for an unrecognised capability atom, or {:error, {:unknown_backend, backend}} for an unrecognised backend.

Example

{:ok, %{support_level: :full, implementation: :universal}} =
  BeamAgent.Capabilities.status(:permission_mode, :gemini)

supports(capability, backend)

@spec supports(capability(), atom() | binary()) ::
  {:ok, true}
  | {:error, {:unknown_capability, capability()} | {:unknown_backend, term()}}

Check whether a capability is supported for a given backend.

A convenience wrapper around status/2. Because all 23 capabilities are at :full support level for all 5 backends, this returns {:ok, true} for every valid capability/backend combination. It exists to make guard-style checks readable and to surface {:error, ...} for typos.

Returns {:error, {:unknown_capability, cap}} or {:error, {:unknown_backend, backend}} for invalid inputs.

Example

iex> BeamAgent.Capabilities.supports(:checkpointing, :codex)
{:ok, true}

iex> BeamAgent.Capabilities.supports(:in_process_mcp, "gemini")
{:ok, true}

iex> BeamAgent.Capabilities.supports(:bogus, :claude)
{:error, {:unknown_capability, :bogus}}