Skip to content

CL_EX: The Self-Architecting Distributed Agent System #1

@nshkrdotcom

Description

@nshkrdotcom

CL_EX Ecosystem Mapping

Component-by-Component Mapping to BEAM/Elixir + CL_EX Ecosystem Equivalents

Document 03 of the CL_EX Design Series
Date: 2026-02-02


Table of Contents

  1. Component Mapping Table
  2. Detailed Component Mappings
  3. Dependency Graph
  4. Heterogeneous Stack Diagrams
  5. What's Missing
  6. Generic Agentic Stack

1. Component Mapping Table

# OpenClaw Component Role CL_EX Equivalent Status Hex Package
1 pi-agent-core Agent execution, AgentTool, AgentMessage, streaming cl_ex_agent (Jido.Agent-based runtime, OTP GenServer) NEW {:jido, "~> 1.0"}
2 pi-coding-agent (SessionManager, tools) Session lifecycle, filesystem tools, skills cl_ex_agent (sessions) + cl_ex_tools (Jido.Action-based tools) NEW --
3 pi-ai (Model API, streaming) Model abstraction, API clients, completions cl_ex_agent LLM layer via altar_ai + provider SDKs (claude_agent_sdk, codex_sdk, gemini_ex, ollixir) ADAPT {:altar_ai, "~> 0.1"}
4 pi-tui (Terminal UI) Terminal UI components owl + ratatouille + custom cl_ex_tui ADAPT {:owl, "~> 0.1"}, {:ratatouille, "~> 0.5"}
5 grammy (Telegram) Telegram Bot API nadia / telegex / ex_gram ADAPT {:ex_gram, "~> 0.52"}
6 @buape/carbon (Discord) Discord framework nostrum ADAPT {:nostrum, "~> 0.10"}
7 @slack/bolt (Slack) Slack integration slack_elixir / custom ADAPT {:slack_elixir, "~> 1.0"}
8 @whiskeysockets/baileys (WhatsApp) WhatsApp Web protocol None -- must wrap or port NEW --
9 playwright-core (Browser) Browser automation wallaby + playwright_elixir ADAPT {:wallaby, "~> 0.30"}
10 sqlite-vec (Vector search) Vector search, embeddings cl_ex_memory via Bedrock (primary), portfolio_core/portfolio_index for RAG, pgvector + ecto (fallback) ADAPT {:bedrock, "~> 0.1"}, {:pgvector, "~> 0.3"}
11 commander (CLI) CLI argument parsing Built-in OptionParser + owl EXISTS (stdlib)
12 hono (HTTP server) HTTP server, webhooks bandit + plug / phoenix EXISTS {:bandit, "~> 1.0"}, {:plug, "~> 1.16"}
13 croner (Cron) Cron scheduling quantum EXISTS {:quantum, "~> 3.5"}
14 dotenv (Env) Environment variable loading dotenvy EXISTS {:dotenvy, "~> 0.8"}
15 JSONL session files Session transcript persistence Bedrock (primary state store) with ETS cache; session management in cl_ex_agent NEW {:bedrock, "~> 0.1"}
16 Docker sandbox Sandboxed code execution cl_ex_sandbox (Docker via :erlexec + NIF, or Firecracker) NEW --
17 Plugin loader (jiti) Dynamic plugin loading Native BEAM code loading + cl_ex_plugins EXISTS (OTP native)
18 Config (JSON5 + Zod) Configuration + validation NimbleOptions + Application config (part of cl_ex core) EXISTS {:nimble_options, "~> 1.1"}

2. Detailed Component Mappings

2.1 pi-agent-core --> cl_ex_agent

OpenClaw Role: Core agent execution runtime. Defines AgentTool, AgentMessage, StreamFn, and event primitives. Manages the run/attempt lifecycle, streaming token delivery, and tool-call dispatch loop.

CL_EX Equivalent: cl_ex_agent -- a NEW OTP application built on Jido.Agent + Jido.AgentServer (GenServer-based agent runtime). See Doc 01 Section 3.4 and Doc 02 Section 3 for the canonical agent architecture.

Status: NEW

Integration Notes:

  • Each agent instance is a Jido.AgentServer process (GenServer) wrapping a Jido.Agent struct. Agent state transitions (idle, thinking, tool_calling, streaming, error) are managed via Jido's directive-based effect model rather than explicit state machine states.
  • Agent processes are registered in a Registry namespaced by {agent_id, session_key}. Session keys follow the canonical format: session:{identity_id}:{channel}:{session_id}.
  • The run/attempt loop uses Jido's cmd/2 pipeline: each tool call is a Jido.Action dispatched via directives, each LLM response updates agent state immutably.
  • AgentTool maps to Jido.Action with @callback run(params, context) :: {:ok, result} | {:error, %ClEx.Error{}}. Higher-level tool compositions use Jido.Skill.
  • AgentMessage maps to a typed struct: %ClEx.Signal{role: :user | :assistant | :tool, content: term(), metadata: map()} -- the canonical internal envelope (see Doc 01).
  • Streaming is handled via Process.send/2 -- the BEAM's message passing IS the streaming primitive. No need for StreamFn callbacks; subscribers simply receive messages.
  • Event bus: Phoenix.PubSub (or :pg for pure OTP) for lifecycle events. Synapse workflow integration provides step-level retry and signal registry.
  • Supervision tree: one DynamicSupervisor per node manages all agent processes. Crash recovery is automatic via OTP. State is persisted to Bedrock and restored on restart.

Key Elixir Advantage: The BEAM makes every agent a lightweight process (~2KB), enabling thousands of concurrent agents per node with preemptive scheduling. See Doc 04 for detailed comparison with OpenClaw's concurrency model.

defmodule MyApp.Agent do
  use Jido.Agent,
    name: "my_agent",
    description: "A CL_EX agent",
    actions: [ClEx.Tools.Read, ClEx.Tools.Write, ClEx.Tools.Search],
    schema: [
      model: [type: :string, default: "claude-sonnet-4-20250514"],
      workspace: [type: :string]
    ]

  # Jido agents are pure functional -- state transitions return
  # directives (effects) rather than performing side effects directly.
  # The AgentServer (GenServer) executes directives on behalf of the agent.
end

# Starting an agent (managed by cl_ex_agent supervisor):
{:ok, pid} = ClEx.Agent.Runtime.start_agent(%{
  id: "helper",
  module: MyApp.Agent,
  model: "claude-sonnet-4-20250514"
})

2.2 pi-coding-agent --> cl_ex_agent (sessions) + cl_ex_tools

OpenClaw Role: SessionManager handles JSONL transcript persistence, session keying, reset policies. Coding tools provide read, write, edit filesystem operations with policy enforcement.

CL_EX Equivalent:

  • cl_ex_agent -- Session lifecycle management is embedded within the agent component (as ClEx.Agent.Session / ClEx.Agent.Session.Store). See Doc 02 Section 3.
  • cl_ex_tools -- Tool behaviour and standard tool library, using Jido.Action as the tool primitive (NEW)

Status: NEW

Integration Notes:

  • Session storage: Bedrock is the primary state store for all session data. Sessions are keyed by session:{identity_id}:{channel}:{session_id} (matching Doc 01's canonical key format). ETS serves as a hot cache with Bedrock as the durable backend.
  • For single-node/embedded deployments without Bedrock: ETS + DETS provides a graceful degradation path.
  • Reset policies: Implemented as configurable strategies via NimbleOptions: :manual, :age_based, :token_count, :message_count.
  • Coding tools: Implemented as Jido.Action modules (e.g., ClEx.Tools.Read, ClEx.Tools.Write, ClEx.Tools.Edit). Elixir's File module provides all filesystem ops. The edit tool can use :binary.match/2 for fast string replacement. Sandbox policies enforced via cl_ex_security (GUARDRAIL) by checking paths against allowed directories before any operation.
  • Session compaction: Transcript summarization via LLM call when token count exceeds threshold -- same pattern as OpenClaw but triggered by a GenServer timer. FlowStone can orchestrate the compaction pipeline with lineage tracking.
defmodule ClEx.Agent.Session.Store do
  @moduledoc "Bedrock-backed session store with ETS cache"

  def append(session_key, message) do
    # Write-through: ETS cache + Bedrock persistence
    :ets.insert(:cl_ex_sessions, {session_key, message})
    Bedrock.put("session:#{session_key}", message)
  end

  def load(session_key) do
    case :ets.lookup(:cl_ex_sessions, session_key) do
      [] -> Bedrock.get("session:#{session_key}")
      [{_, messages}] -> {:ok, messages}
    end
  end
end

2.3 pi-ai --> cl_ex_agent LLM layer (ADAPT ecosystem SDKs)

OpenClaw Role: Model abstraction layer. Provides unified API across OpenAI, Anthropic, Google, Bedrock, Ollama. Handles streaming completions, tool-call formatting, token counting, and fallback chains.

CL_EX Equivalent: The LLM abstraction lives within cl_ex_agent as ClEx.Agent.LLM (see Doc 02 Section 3). It is built on the ecosystem's own provider SDKs:

  • altar_ai -- Multi-provider LLM abstraction with unified API
  • claude_agent_sdk -- Anthropic Claude provider adapter
  • codex_sdk -- OpenAI / Codex provider adapter
  • gemini_ex -- Google Gemini provider adapter
  • ollixir -- Ollama / local model provider adapter
  • langchain (Elixir) -- Optional fallback for providers not yet covered by ecosystem SDKs

Status: ADAPT

Integration Notes:

  • altar_ai provides the unified LLM interface with streaming, tool calls, and structured output. Provider-specific adapters (ClEx.Agent.LLM.Anthropic, ClEx.Agent.LLM.OpenAI, ClEx.Agent.LLM.Gemini, ClEx.Agent.LLM.Ollama) wrap the ecosystem SDKs.
  • ClEx.LLM.Router handles ensemble routing via crucible_* modules for model selection, fallback chains, and load balancing across providers.
  • Structured output validation uses Exdantic schemas (replacing Zod-based output parsing in OpenClaw).
  • Rate limiting via Foundation's rate limiter. Token counting via provider SDK utilities.
  • Telemetry integration via :telemetry for cost tracking; AITrace for LLM call observability.
  • Streaming: Provider SDKs emit BEAM messages natively -- the subscribing agent process receives tokens directly. No callback adapter layer needed.
  • langchain can be retained as an optional dependency for providers not yet supported by the ecosystem SDKs, but it is not the primary abstraction.
defmodule ClEx.Agent.LLM do
  @moduledoc "Unified LLM interface with provider routing and fallback chains"

  def chat(messages, opts \\ []) do
    chain = Keyword.get(opts, :fallback_chain, [opts[:model] || default_model()])

    Enum.reduce_while(chain, {:error, %ClEx.Error{type: :llm, reason: :all_models_failed}}, fn model, _acc ->
      adapter = adapter_for(model)
      case adapter.chat(messages, opts) do
        {:ok, response} -> {:halt, {:ok, response}}
        {:error, _reason} -> {:cont, {:error, %ClEx.Error{type: :llm, reason: :all_models_failed}}}
      end
    end)
  end

  defp adapter_for("claude-" <> _), do: ClEx.Agent.LLM.Anthropic
  defp adapter_for("gpt-" <> _), do: ClEx.Agent.LLM.OpenAI
  defp adapter_for("gemini-" <> _), do: ClEx.Agent.LLM.Gemini
  defp adapter_for(_), do: ClEx.Agent.LLM.Ollama
end

Hex Dependencies:

{:altar_ai, "~> 0.1"},            # Multi-provider LLM abstraction
{:claude_agent_sdk, "~> 0.1"},    # Anthropic provider
{:codex_sdk, "~> 0.1"},           # OpenAI provider
{:gemini_ex, "~> 0.1"},           # Google Gemini provider
{:ollixir, "~> 0.1"},             # Ollama / local models
{:langchain, "~> 0.3", optional: true},  # Optional fallback

2.4 pi-tui --> cl_ex_tui (ADAPT)

OpenClaw Role: Terminal UI for interactive agent sessions. Renders streaming output, tool call progress, thinking indicators, and markdown-formatted responses.

CL_EX Equivalent:

  • ratatouille -- Termbox-based terminal UI framework for Elixir
  • owl -- Terminal UI component library (progress bars, spinners, tables)
  • cl_ex_tui -- NEW composition layer

Status: ADAPT

Integration Notes:

  • ratatouille provides the Elm-architecture terminal UI framework (model-update-view). It handles raw terminal rendering, keyboard input, and layout.
  • owl provides higher-level components: spinners, progress bars, tables, and live-updating output. Good for CLI-mode rendering.
  • cl_ex_tui composes these into agent-specific views:
    • Streaming text panel (assistant output arriving token-by-token)
    • Tool call sidebar (shows active tool executions)
    • Session info bar (model, token count, session key)
    • Input area with history
  • Alternative: ExTermbox for lower-level control, or simply use IO.ANSI + owl for a lighter approach.
  • The BEAM's process model means the TUI is a separate process receiving messages from the agent -- no callback spaghetti.

2.5 grammy --> ExGram / Telegex (ADAPT)

OpenClaw Role: Telegram Bot API client. Handles long polling, webhook mode, inline keyboards, message formatting, media upload/download, and bot commands.

CL_EX Equivalent: ex_gram -- Telegram Bot API framework for Elixir.

Status: ADAPT

Integration Notes:

  • ex_gram provides a full Telegram Bot API implementation with both long-polling and webhook modes.
  • It includes middleware, command handling, and inline keyboard support.
  • Adaptation needed: Wrap ex_gram in a ClEx.Transport.Telegram adapter that implements the ClEx.Transport.Channel behaviour (see Doc 02 Section 2):
    • Normalize inbound messages to %ClEx.Signal{}
    • Translate outbound %ClEx.Signal{} to Telegram API calls
    • Map Telegram threading (reply_to_message_id) to CL_EX session threading
    • Handle media attachments (photos, documents, voice)
  • Alternative: telegex is another option with a more modern API but smaller community.
  • nadia exists but is older and less maintained.
defmodule ClEx.Transport.Telegram do
  @behaviour ClEx.Transport.Channel

  @impl true
  def normalize(%ExGram.Model.Message{} = msg) do
    %ClEx.Signal{
      channel: :telegram,
      sender_id: "tg:#{msg.from.id}",
      group_id: if(msg.chat.type != "private", do: "tg:#{msg.chat.id}"),
      text: msg.text,
      thread_id: msg.message_thread_id,
      metadata: %{chat_type: msg.chat.type}
    }
  end

  @impl true
  def deliver(signal, opts) do
    ExGram.send_message(signal.metadata.chat_id, signal.content, opts)
  end
end

2.6 @buape/carbon --> Nostrum (ADAPT)

OpenClaw Role: Discord bot framework. Handles gateway connection, slash commands, message events, embeds, reactions, threads, and voice channel awareness.

CL_EX Equivalent: nostrum -- Discord API library for Elixir.

Status: ADAPT

Integration Notes:

  • nostrum is the mature Discord library in Elixir. It provides:
    • Gateway WebSocket connection with automatic reconnection
    • Full REST API coverage
    • Built-in caching (ETS-backed) for guilds, channels, users
    • Consumer-based event handling
  • Adaptation needed: Same pattern as Telegram -- wrap in ClEx.Transport.Discord:
    • Normalize Discord events to %ClEx.Signal{}
    • Handle Discord-specific features: embeds, slash commands, components (buttons, selects)
    • Map Discord threads to CL_EX sessions
    • Handle rate limiting (Nostrum does this internally)
  • nostrum uses its own supervision tree and process structure -- fits naturally into the BEAM.

2.7 @slack/bolt --> Slack Elixir (ADAPT)

OpenClaw Role: Slack integration. Handles Events API, slash commands, interactive messages, modal dialogs, threading, and workspace management.

CL_EX Equivalent: slack_elixir or custom Plug-based integration.

Status: ADAPT

Integration Notes:

  • The Elixir Slack ecosystem is less mature than Telegram/Discord. Options:
    • slack_elixir -- Basic Slack Web API + Events API
    • slack_web -- Auto-generated API client from Slack's OpenAPI spec
    • Custom: Use Plug to receive Events API webhooks + Req/Finch for API calls
  • Recommendation: Build ClEx.Transport.Slack with Req for API calls and a Plug.Router for incoming webhooks. This gives full control and avoids dependency on under-maintained wrappers.
  • Socket Mode support may need to be built (WebSocket connection to Slack instead of HTTP webhooks).

2.8 @whiskeysockets/baileys --> cl_ex_whatsapp (NEW)

OpenClaw Role: WhatsApp Web multi-device protocol implementation. Handles QR code authentication, message encryption (Signal protocol), media upload/download, group management, and presence updates.

CL_EX Equivalent: cl_ex_whatsapp -- Must be built or wrapped.

Status: NEW

Integration Notes:

  • This is the biggest gap. Baileys is a complex reverse-engineered protocol implementation (~20k lines of TypeScript). There is no Elixir equivalent.
  • Options:
    1. NIF/Port wrapper: Run a minimal Node.js Baileys instance as a Port or use Rustler to wrap a Rust WhatsApp library (e.g., whatsmeow in Go can be called via Port).
    2. Go port: whatsmeow is a mature Go implementation. Call it via Erlang ports or use go_erlang for tighter integration.
    3. Direct port: Long-term, port the Signal protocol implementation and WhatsApp Web protocol to Elixir. Massive effort.
    4. Cloud API: Use WhatsApp Business Cloud API (official REST API) instead of Web protocol. Much simpler but requires Business account and has message template restrictions.
  • Recommendation for v1: Use WhatsApp Business Cloud API via Req HTTP client. For full feature parity with OpenClaw, wrap whatsmeow (Go) as an Erlang port.

2.9 playwright-core --> Wallaby / Playwright Elixir (ADAPT)

OpenClaw Role: Browser automation for web scraping, screenshot capture, and interactive browsing by agents.

CL_EX Equivalent:

  • wallaby -- Browser automation testing framework (wraps ChromeDriver/Selenium)
  • playwright_elixir -- Elixir bindings for Playwright (if available)
  • Custom: Use Req + Floki for HTML scraping without a browser

Status: ADAPT

Integration Notes:

  • wallaby is mature but oriented toward testing. Needs adaptation for agent-driven browsing.
  • For headless browsing: Use Chrome DevTools Protocol (CDP) directly via WebSocket. Libraries like chrome_remote_interface exist.
  • For simple scraping: Req + Floki (HTML parser) handles most cases without browser overhead.
  • Recommendation: Layer approach:
    1. Light scraping: Req + Floki (no browser needed)
    2. JavaScript-rendered pages: CDP via WebSocket
    3. Full interaction: Playwright via Node.js port (same pattern as WhatsApp)

2.10 sqlite-vec --> cl_ex_memory (Bedrock + portfolio_core) (ADAPT)

OpenClaw Role: SQLite with vector search extension for semantic memory. Stores embeddings, enables cosine similarity search, and provides the memory/RAG backend.

CL_EX Equivalent:

  • Bedrock -- Primary distributed state store for all memory data (see Doc 01)
  • portfolio_core / portfolio_index -- RAG pipeline: chunking, indexing, and retrieval
  • embed_ex -- Embedding generation (local or API-based)
  • pgvector + ecto -- PostgreSQL vector extension (fallback for deployments without Bedrock)
  • exqlite -- SQLite3 NIF bindings (single-node/embedded fallback)

Status: ADAPT

Integration Notes:

  • Primary path (Bedrock): Bedrock provides the distributed KV store for memory entries with consistent reads across the cluster. Vector indices are managed via portfolio_index, which provides chunking, embedding, and semantic search over Bedrock-stored documents.
  • RAG pipeline: portfolio_core handles the end-to-end RAG flow: document ingestion, chunking strategies, embedding via embed_ex, storage in Bedrock, and retrieval with reranking. This replaces the need to manually wire pgvector + Ecto for RAG.
  • Fallback Option A (PostgreSQL): Use pgvector with Ecto. Better for teams with existing Postgres infrastructure who do not want the Bedrock dependency.
  • Fallback Option B (SQLite): Use exqlite and load the sqlite-vec extension at runtime. Maintains parity with OpenClaw's approach for single-node embedded deployments.
  • Embedding generation: Use embed_ex which wraps Bumblebee + EXLA for local embedding models, or calls OpenAI/Voyage embeddings API via Req.
  • Recommendation: Default to Bedrock + portfolio_core for production. Fall back to pgvector + Ecto when Bedrock is unavailable. Use exqlite + sqlite-vec only for single-node/embedded deployments. Abstract behind ClEx.Memory.VectorStore behaviour.
defmodule ClEx.Memory.VectorStore do
  @callback store(collection :: String.t(), text :: String.t(), embedding :: [float()], metadata :: map()) :: :ok
  @callback search(collection :: String.t(), query_embedding :: [float()], opts :: keyword()) :: [result()]
  @callback delete(collection :: String.t(), id :: String.t()) :: :ok
end

2.11 commander --> OptionParser (EXISTS)

OpenClaw Role: CLI argument parsing, subcommand routing, help generation.

CL_EX Equivalent: Elixir's built-in OptionParser + Mix tasks + Owl for rich output.

Status: EXISTS

Integration Notes:

  • Elixir's OptionParser handles flag/option parsing natively. No external dependency needed.
  • For subcommand routing: Use Mix tasks (mix cl_ex.start, mix cl_ex.status) during development. For production CLI, use escript or Burrito for self-contained binaries.
  • Owl provides rich terminal output (tables, trees, spinners) for CLI responses.
  • For interactive prompts: IO.gets/1 + custom wrapper, or ex_prompt.

2.12 hono --> Bandit + Plug / Phoenix (EXISTS)

OpenClaw Role: Lightweight HTTP server for webhook endpoints, gateway API, and health checks.

CL_EX Equivalent: Bandit (HTTP server) + Plug (middleware) or full Phoenix framework.

Status: EXISTS

Integration Notes:

  • Bandit is a modern, pure-Elixir HTTP/1.1 and HTTP/2 server. Drop-in replacement for Cowboy.
  • Plug provides composable middleware (routing, parsing, CORS, etc.).
  • For WebSocket support: Phoenix.Channel or WebSockAdapter with Bandit.
  • Decision: Use Plug + Bandit for the lightweight gateway. If users want to embed CL_EX into a Phoenix app, it plugs directly into the Phoenix router.
  • Phoenix is NOT required -- Plug + Bandit gives a full HTTP stack in ~50 lines of config.
defmodule ClEx.Gateway.Router do
  use Plug.Router

  plug :match
  plug Plug.Parsers, parsers: [:json], json_decoder: Jason
  plug :dispatch

  post "/webhook/:channel" do
    ClEx.Transport.dispatch(channel, conn.body_params)
    send_resp(conn, 200, "ok")
  end

  get "/health" do
    send_resp(conn, 200, Jason.encode!(%{status: "ok", agents: ClEx.Agent.count()}))
  end
end

2.13 croner --> Quantum (EXISTS)

OpenClaw Role: Cron-style job scheduling for periodic agent tasks, health checks, and automation.

CL_EX Equivalent: Quantum -- Cron-like job scheduler for Elixir.

Status: EXISTS

Integration Notes:

  • Quantum supports cron expressions, runtime job management, and clustered execution (only one node runs each job).
  • Direct replacement -- no adaptation needed.
  • Alternative: Oban for persistent job queues with retry/backoff (heavier but more robust for critical tasks).

2.14 dotenv --> Dotenvy (EXISTS)

OpenClaw Role: Load environment variables from .env files.

CL_EX Equivalent: Dotenvy -- Dotenv file loading for Elixir.

Status: EXISTS

Integration Notes:

  • Dotenvy loads .env files and integrates with Elixir's Config system.
  • Elixir's config/runtime.exs already provides environment-based configuration.
  • No adaptation needed. Use Dotenvy for development convenience; rely on system env vars or Config.Provider for production.

2.15 JSONL Session Files --> Bedrock (primary) + ETS cache (NEW)

OpenClaw Role: Persist session transcripts as JSONL (one JSON object per line) files on the filesystem. Each session has a file; messages are appended.

CL_EX Equivalent: Session data is managed within cl_ex_agent (as ClEx.Agent.Session.Store). Bedrock is the primary durable store; ETS serves as a hot cache.

Status: NEW

Integration Notes:

  • Bedrock is the primary state store for session transcripts. Session keys follow the canonical format session:{identity_id}:{channel}:{session_id} (see Doc 01 Section 3.3.2). Bedrock provides distributed durability with Raft consensus, so sessions survive node failures without Mnesia.
  • ETS serves as the hot cache for active sessions -- O(1) lookup, ordered_set for message ordering, ~microsecond access. Write-through to Bedrock on every append.
  • Graceful degradation: When Bedrock is unavailable (e.g., single-node dev mode), ETS + DETS provides a local-only fallback (see Doc 02 Section 3).
  • JSONL format can be maintained for export/import compatibility, but internal representation should be native Erlang terms for performance.
  • Session compaction and memory consolidation can be orchestrated via FlowStone with lineage tracking.

2.16 Docker Sandbox --> cl_ex_sandbox (NEW)

OpenClaw Role: Run agent-generated code in a Docker container for isolation. Mounts workspace directory, sets resource limits, captures stdout/stderr.

CL_EX Equivalent: cl_ex_sandbox -- NEW module for sandboxed execution.

Status: NEW

Integration Notes:

  • Option A (Docker): Use Erlang :os.cmd/1 or System.cmd/2 to invoke docker run. Wrap in a GenServer for lifecycle management.
  • Option B (erlexec): Use erlexec for advanced OS process management with resource limits, signal handling, and stdout/stderr capture. Can run Docker or direct processes.
  • Option C (Firecracker): MicroVMs for stronger isolation. More complex but better security properties.
  • Option D (BEAM sandbox): For Elixir code execution, use Code.eval_string/3 in a restricted environment with a separate node (Node.spawn_link/2) and resource limits via cgroups.
  • Recommendation: Start with Docker via System.cmd/2 wrapped in a GenServer. Add Firecracker support later for enterprise deployments.
defmodule ClEx.Sandbox do
  use GenServer

  def execute(code, opts \\ []) do
    timeout = Keyword.get(opts, :timeout, 30_000)
    workspace = Keyword.get(opts, :workspace, "/tmp/cl_ex_sandbox")

    GenServer.call(__MODULE__, {:execute, code, workspace, timeout}, timeout + 5_000)
  end
end

2.17 Plugin Loader (jiti) --> OTP Code Loading (EXISTS)

OpenClaw Role: Dynamic plugin loading at runtime. jiti transpiles and loads TypeScript/JavaScript modules on-the-fly.

CL_EX Equivalent: Native BEAM code loading, managed by cl_ex_plugins (see Doc 02 Section 10).

Status: EXISTS

Integration Notes:

  • The BEAM has first-class hot code loading. Plugins can be:
    1. Compiled .beam files: Loaded via :code.load_file/1 or :code.load_binary/3
    2. Mix dependencies: Standard Hex packages added to mix.exs
    3. Script plugins: .exs files evaluated via Code.eval_file/1 (similar to jiti's dynamic loading)
    4. OTP releases with plugins: Use :release_handler for hot upgrades
  • Plugin discovery: Scan a plugins/ directory for .beam files or .exs scripts.
  • Plugin contract: Elixir behaviours enforce the interface at compile time. Runtime plugin installation is gated by allow_runtime_install: false by default (security consideration -- see Doc 02).
  • This is a massive BEAM advantage. No transpilation, no module resolution hacks, no bundler. Plugins are just modules that implement a behaviour.
defmodule ClEx.Plugins.Plugin do
  @callback init(config :: map()) :: {:ok, state :: term()} | {:error, %ClEx.Error{}}
  @callback handle_event(event :: ClEx.Signal.t(), state :: term()) :: {:ok, state :: term()}
  @callback tools() :: [Jido.Action.t()]
  @optional_callbacks [tools: 0]
end

2.18 Config (JSON5 + Zod) --> NimbleOptions + Application Config (EXISTS)

OpenClaw Role: Configuration loading (JSON5 format) with runtime validation (Zod schemas). Supports nested config, defaults, and type coercion.

CL_EX Equivalent: NimbleOptions + Elixir's Config system.

Status: EXISTS

Integration Notes:

  • NimbleOptions provides declarative option schemas with types, defaults, validation, and documentation generation. It is the Zod equivalent for Elixir.
  • Elixir's Config system (config/config.exs, config/runtime.exs) replaces JSON5 files.
  • For user-facing config files: Support TOML via toml hex package (more user-friendly than Elixir syntax for non-developers).
  • Config validation happens at application startup -- fail fast with clear error messages.
defmodule ClEx.Config do
  @schema [
    agents: [
      type: {:list, :keyword_list},
      default: [],
      doc: "List of agent configurations",
      keys: [
        id: [type: :string, required: true],
        model: [type: :string, default: "claude-sonnet-4-20250514"],
        workspace: [type: :string],
        tools: [type: {:list, :atom}, default: [:read, :write, :edit, :search]]
      ]
    ],
    channels: [
      type: :keyword_list,
      default: [],
      doc: "Channel configurations"
    ]
  ]

  def validate!(opts), do: NimbleOptions.validate!(opts, @schema)
end

3. Dependency Graph

                         ┌─────────────────────────────────────────────────┐
                         │                  cl_ex (core)                   │
                         │       Top-level application + public API        │
                         └──────────────────────┬──────────────────────────┘
                                                │
          ┌─────────────────┬───────────────────┼───────────────────┬─────────────────┐
          │                 │                   │                   │                 │
          ▼                 ▼                   ▼                   ▼                 ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐ ┌──────────────┐
│  cl_ex_transport │ │   cl_ex_agent    │ │   cl_ex_tools    │ │ cl_ex_memory │ │ cl_ex_observe│
│  (Transport)     │ │  (Agent Runtime) │ │  (Tool Framework)│ │ (Memory/RAG) │ │ (Telemetry)  │
│                  │ │                  │ │                  │ │              │ │              │
│ Channel behaviour│ │ Jido.AgentServer │ │ Jido.Action-based│ │ Bedrock store│ │ AITrace      │
│ Bandit + Plug    │ │ Session mgmt     │ │ Coding tools     │ │ portfolio_*  │ │ OpenTelemetry│
│ Webhook ingress  │ │ LLM adapter layer│ │ Policy enforce   │ │ embed_ex     │ │ Metrics      │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ └──────────────┘ └──────────────┘
         │                    │                     │
         ▼                    │                     ▼
  ┌──────────────┐            │            ┌──────────────────┐
  │ Adapters:    │            │            │  cl_ex_sandbox   │
  │ Telegram     │            │            │ (Sandboxed Exec) │
  │ Discord      │            │            │                  │
  │ Slack        │            │            │ Docker/Firecracker│
  │ WhatsApp     │            │            │ Resource limits   │
  │ Signal       │            │            └──────────────────┘
  │ HTTP/WS      │            │
  └──────────────┘            │
                              │
          ┌───────────────────┼───────────────────┐
          │                   │                   │
          ▼                   ▼                   ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│  cl_ex_security  │ │   cl_ex_mesh     │ │  cl_ex_plugins   │
│  (Security)      │ │  (Distribution)  │ │  (Plugin System) │
│                  │ │                  │ │                  │
│ GUARDRAIL engine │ │ libcluster       │ │ Behaviour-based  │
│ Shield zero-trust│ │ Bedrock distrib. │ │ Hot code loading │
│ Capability tokens│ │ :pg process grps │ │ Plugin discovery │
└──────────────────┘ └──────────────────┘ └──────────────────┘

    ════════════════════════════════════════════════════════════════════════════
                     ECOSYSTEM + EXTERNAL HEX DEPENDENCIES
    ════════════════════════════════════════════════════════════════════════════

    Ecosystem (custom)      LLM/AI SDKs         Channels            Infrastructure
    ──────────────────      ───────────          ────────            ──────────────
    jido                    altar_ai             ex_gram             bandit
    bedrock                 claude_agent_sdk     nostrum             plug
    foundation              codex_sdk            req                 phoenix_pubsub
    synapse                 gemini_ex            floki               quantum
    flowstone               ollixir              wallaby             oban
    guardrail               langchain (optional)                     libcluster
    shield                  bumblebee                                telemetry
    portfolio_core          exla
    portfolio_index
    embed_ex                Storage              Utilities
    exdantic                ───────              ─────────
    aitrace                 ecto                 jason
                            pgvector             nimble_options
                            exqlite (fallback)   dotenvy
                                                 owl
                                                 ratatouille

4. Heterogeneous Stack Diagrams

4.1 Minimal: Single BEAM Node, Embedded in Phoenix App

For developers who want to add AI agent capability to an existing Phoenix application.

┌─────────────────────────────────────────────────────────────────┐
│                    Single BEAM Node (fly.io / VPS)              │
│                                                                 │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   Phoenix Application                      │  │
│  │                                                           │  │
│  │  ┌─────────────┐  ┌──────────────┐  ┌────────────────┐  │  │
│  │  │ Phoenix      │  │ Phoenix      │  │ Your existing  │  │  │
│  │  │ Router       │  │ LiveView     │  │ business logic │  │  │
│  │  │              │  │              │  │                │  │  │
│  │  │ /webhook/*   │  │ /agent/chat  │  │                │  │  │
│  │  └──────┬───────┘  └──────┬───────┘  └────────────────┘  │  │
│  │         │                  │                               │  │
│  │  ┌──────▼──────────────────▼──────────────────────────┐   │  │
│  │  │              ClEx (embedded)                         │   │  │
│  │  │                                                     │   │  │
│  │  │  ┌──────────┐  ┌──────────┐  ┌──────────────────┐ │   │  │
│  │  │  │ 1 Agent  │  │ Session  │  │ LLM (altar_ai)   │ │   │  │
│  │  │  │ (Jido)   │  │ (ETS+BD) │  │ Anthropic/OpenAI │ │   │  │
│  │  │  └──────────┘  └──────────┘  └──────────────────┘ │   │  │
│  │  │  ┌──────────┐  ┌──────────┐                       │   │  │
│  │  │  │ Telegram  │  │ Memory   │                       │   │  │
│  │  │  │ Channel   │  │ (SQLite) │                       │   │  │
│  │  │  └──────────┘  └──────────┘                       │   │  │
│  │  └─────────────────────────────────────────────────────┘   │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  Resources: 1 CPU, 512MB RAM, 1GB disk                         │
│  Agents: 1-10 concurrent                                       │
│  Channels: 1-2                                                  │
└─────────────────────────────────────────────────────────────────┘

mix.exs:

defp deps do
  [
    {:phoenix, "~> 1.7"},
    {:cl_ex, "~> 0.1"},          # <-- Just add this
    # ... your existing deps
  ]
end

application.ex:

children = [
  # ... your existing children
  {ClEx, config: Application.get_env(:my_app, :cl_ex)}
]

4.2 Standard: Multi-Node BEAM Cluster

For teams running multiple agents across channels with high availability.

                        ┌──────────────────────┐
                        │    Load Balancer      │
                        │  (Fly.io / AWS ALB)   │
                        └──────────┬───────────┘
                                   │
              ┌────────────────────┼────────────────────┐
              │                    │                     │
              ▼                    ▼                     ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│  BEAM Node A     │ │  BEAM Node B     │ │  BEAM Node C     │
│  (us-east-1)     │ │  (eu-west-1)     │ │  (ap-southeast-1)│
│                  │ │                  │ │                  │
│ ┌──────────────┐ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │  ClEx Core   │ │ │ │  ClEx Core   │ │ │ │  ClEx Core   │ │
│ │              │ │ │ │              │ │ │ │              │ │
│ │ Agents: 500  │ │ │ │ Agents: 500  │ │ │ │ Agents: 500  │ │
│ │ Telegram ch. │ │ │ │ Discord ch.  │ │ │ │ Slack ch.    │ │
│ │ Slack ch.    │ │ │ │ WhatsApp ch. │ │ │ │ Web ch.      │ │
│ └──────────────┘ │ │ └──────────────┘ │ │ └──────────────┘ │
│                  │ │                  │ │                  │
│ ┌──────────────┐ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │  Gateway     │ │ │ │  Gateway     │ │ │ │  Gateway     │ │
│ │  (Bandit)    │ │ │ │  (Bandit)    │ │ │ │  (Bandit)    │ │
│ └──────────────┘ │ │ └──────────────┘ │ │ └──────────────┘ │
│                  │ │                  │ │                  │
│ ┌──────────────┐ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Bedrock      │◄├─┤►│ Bedrock      │◄├─┤►│ Bedrock      │ │
│ │ (Distributed │ │ │ │ (Distributed │ │ │ │ (Distributed │ │
│ │  State/Raft) │ │ │ │  State/Raft) │ │ │ │  State/Raft) │ │
│ └──────────────┘ │ │ └──────────────┘ │ │ └──────────────┘ │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
         │                     │                     │
         │    ┌────────────────┤                     │
         │    │    libcluster  │  (Gossip / DNS)     │
         │    │    auto-discovery                    │
         └────┴─────────────┬──┴─────────────────────┘
                            │
                   ┌────────▼────────┐
                   │   PostgreSQL    │
                   │   + pgvector    │
                   │   (fallback DB) │
                   │                 │
                   │ Vectors/search  │
                   │ Analytics       │
                   └─────────────────┘

  Total capacity: ~1500 concurrent agents
  Channels: All supported
  State: Bedrock (Raft consensus) for sessions, config, and distributed KV
  Failover: Automatic (Bedrock replicates state; OTP restarts agents on surviving nodes)
  Session affinity: Not needed (Bedrock provides consistent reads from any node)

4.3 Full: BEAM Cluster + Sprites + Cloud VPS Auto-Provisioning

For power users and organizations running autonomous agents that need compute resources.

┌─────────────────────────────────────────────────────────────────────────────┐
│                         CONTROL PLANE (BEAM Cluster)                        │
│                                                                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │  Node A       │  │  Node B       │  │  Node C       │  │  Node D       │  │
│  │  Agent Mesh   │  │  Agent Mesh   │  │  Channel Hub  │  │  Scheduler   │  │
│  │  100 agents   │  │  100 agents   │  │  All channels │  │  Quantum     │  │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  │
│         │    libcluster    │                  │                  │          │
│         └──────────────────┴──────────────────┴──────────────────┘          │
└────────────────────────────────┬────────────────────────────────────────────┘
                                 │
                    ┌────────────┴────────────┐
                    │   Sprite Orchestrator   │
                    │   (cl_ex_sprites)       │
                    │                         │
                    │   Provisions, monitors, │
                    │   and reclaims compute  │
                    └────┬──────────┬─────────┘
                         │          │
            ┌────────────┘          └────────────┐
            ▼                                     ▼
┌───────────────────────┐            ┌───────────────────────┐
│  Sprite Pool A        │            │  Sprite Pool B        │
│  (Hetzner ARM VPS)    │            │  (AWS Spot Instances) │
│                       │            │                       │
│  ┌─────────────────┐  │            │  ┌─────────────────┐  │
│  │ Sprite 1        │  │            │  │ Sprite 5        │  │
│  │ Docker sandbox  │  │            │  │ GPU instance    │  │
│  │ Agent workspace │  │            │  │ Bumblebee       │  │
│  │ 2 CPU / 4GB     │  │            │  │ Local embeddings│  │
│  ├─────────────────┤  │            │  │ Local LLM       │  │
│  │ Sprite 2        │  │            │  │ 8 CPU / 32GB    │  │
│  │ Docker sandbox  │  │            │  ├─────────────────┤  │
│  │ Agent workspace │  │            │  │ Sprite 6        │  │
│  │ 2 CPU / 4GB     │  │            │  │ Browser farm    │  │
│  ├─────────────────┤  │            │  │ Playwright      │  │
│  │ Sprite 3        │  │            │  │ 4 CPU / 8GB     │  │
│  │ Docker sandbox  │  │            │  └─────────────────┘  │
│  │ 2 CPU / 4GB     │  │            │                       │
│  ├─────────────────┤  │            └───────────────────────┘
│  │ Sprite 4        │  │
│  │ Docker sandbox  │  │
│  │ 2 CPU / 4GB     │  │
│  └─────────────────┘  │
└───────────────────────┘

  Sprite lifecycle:
    1. Agent needs compute → Orchestrator provisions VPS via cloud API
    2. Sprite boots → Connects back to BEAM cluster as hidden node
    3. Agent dispatches work → Sprite executes in Docker sandbox
    4. Work complete → Sprite idles → Auto-reclaimed after timeout
    5. Crash → Orchestrator detects via BEAM monitor → Reprovisions

  Cloud providers supported:
    - Hetzner (ARM, cheapest)
    - AWS (Spot instances, GPU)
    - GCP, Azure, DigitalOcean, Vultr, Linode
    - Fly.io (BEAM-native, fastest provision)

4.4 Enterprise: Full + ASKA Security + Shield Zero-Trust

For regulated industries, government, and high-security deployments.

┌─────────────────────────────────────────────────────────────────────────────────┐
│                            ASKA SECURITY PERIMETER                              │
│                     (Adaptive Security Kernel Architecture)                      │
│                                                                                 │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │                         Shield Zero-Trust Layer                           │  │
│  │                                                                           │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌────────────────┐  │  │
│  │  │ Identity    │  │ Policy      │  │ Audit       │  │ Secrets        │  │  │
│  │  │ Provider    │  │ Engine      │  │ Logger      │  │ Manager        │  │  │
│  │  │             │  │             │  │             │  │                │  │  │
│  │  │ mTLS certs  │  │ OPA/Rego   │  │ Immutable   │  │ Vault / SOPS  │  │  │
│  │  │ SPIFFE IDs  │  │ ABAC rules │  │ append-only │  │ Rotate on use │  │  │
│  │  │ JWT + RBAC  │  │ Per-agent   │  │ Signed log  │  │ Env isolation │  │  │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └───────┬────────┘  │  │
│  │         └────────────────┴────────────────┴──────────────────┘            │  │
│  └──────────────────────────────┬────────────────────────────────────────────┘  │
│                                  │                                               │
│  ┌──────────────────────────────▼────────────────────────────────────────────┐  │
│  │                      BEAM CLUSTER (Encrypted Mesh)                        │  │
│  │                   All inter-node traffic: TLS 1.3                         │  │
│  │                   Cookie: Derived from HSM / TPM                          │  │
│  │                                                                           │  │
│  │   ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                   │  │
│  │   │  Agent Node  │  │  Agent Node  │  │  Gateway     │                   │  │
│  │   │  (Enclave A) │  │  (Enclave B) │  │  (DMZ Node)  │                   │  │
│  │   │              │  │              │  │              │                   │  │
│  │   │ Agents run   │  │ Agents run   │  │ TLS termn.  │                   │  │
│  │   │ in isolated  │  │ in isolated  │  │ WAF rules   │                   │  │
│  │   │ schedulers   │  │ schedulers   │  │ Rate limit  │                   │  │
│  │   │              │  │              │  │ DDoS prot.  │                   │  │
│  │   │ Memory:      │  │ Memory:      │  │              │                   │  │
│  │   │  encrypted   │  │  encrypted   │  │ Channels:   │                   │  │
│  │   │  at rest     │  │  at rest     │  │  All, with  │                   │  │
│  │   │              │  │              │  │  E2E proxy  │                   │  │
│  │   └──────────────┘  └──────────────┘  └──────────────┘                   │  │
│  │                                                                           │  │
│  │   ┌──────────────────────────────────────────────────────────────────┐   │  │
│  │   │  Tool Execution: Sandboxed Sprites (Firecracker microVMs)       │   │  │
│  │   │                                                                  │   │  │
│  │   │  - Each agent gets dedicated microVM                             │   │  │
│  │   │  - Network: Isolated VPC, egress whitelist only                  │   │  │
│  │   │  - Filesystem: Encrypted, ephemeral, no persistence by default   │   │  │
│  │   │  - Resource: Hard cgroup limits (CPU, RAM, I/O, network)         │   │  │
│  │   │  - Lifetime: Max 1 hour, then force-terminated and shredded      │   │  │
│  │   └──────────────────────────────────────────────────────────────────┘   │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │                         Data Layer (Encrypted)                            │  │
│  │                                                                           │  │
│  │  ┌──────────────────┐  ┌──────────────────┐  ┌────────────────────────┐  │  │
│  │  │ PostgreSQL       │  │ Object Storage   │  │ Audit Store            │  │  │
│  │  │ (TDE enabled)    │  │ (S3 + SSE-KMS)   │  │ (Immutable, signed)    │  │  │
│  │  │                  │  │                  │  │                        │  │  │
│  │  │ Sessions         │  │ Agent artifacts  │  │ Every agent action     │  │  │
│  │  │ Vectors          │  │ Media files      │  │ Every tool invocation  │  │  │
│  │  │ Config           │  │ Exports          │  │ Every LLM call         │  │  │
│  │  │ (Row-level       │  │                  │  │ Tamper-evident chain   │  │  │
│  │  │  encryption)     │  │                  │  │                        │  │  │
│  │  └──────────────────┘  └──────────────────┘  └────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│  Compliance: SOC2 Type II, HIPAA, FedRAMP (with appropriate CSP)               │
│  Key management: AWS KMS / GCP KMS / HashiCorp Vault                           │
│  Network: Private VPC, no public IPs on agent/data nodes                       │
│  Observability: OpenTelemetry → encrypted Grafana stack                        │
└─────────────────────────────────────────────────────────────────────────────────┘

5. What's Missing

5.1 Critical Gaps (Must Build for v0.1)

Gap Severity Description Estimated Effort
Agent Runtime (cl_ex_agent) CRITICAL Jido provides the core agent model (Jido.Agent, Jido.AgentServer), so the work is integration rather than greenfield. Must build: LLM adapter layer (over altar_ai + provider SDKs), session management (ClEx.Agent.Session), and the ClEx.Agent.Runtime orchestration wrapper. 3-4 weeks
Transport Layer (cl_ex_transport) CRITICAL No unified channel behaviour exists. Each platform library (ExGram, Nostrum, etc.) has its own API. Need a ClEx.Transport.Channel behaviour, normalization pipeline (to ClEx.Signal), and per-platform adapters. 2-3 weeks
Session Management (within cl_ex_agent) HIGH Session lifecycle is part of cl_ex_agent (not a separate package). Must integrate with Bedrock for persistence, implement compaction and reset policies. Effort is lower since Bedrock provides the state backend. 1-2 weeks
WhatsApp Adapter HIGH No Elixir WhatsApp library exists. Must wrap Go's whatsmeow via Port or use Business Cloud API. 3-4 weeks (Port) or 1 week (Cloud API)
Tool Framework (cl_ex_tools) HIGH Jido provides Jido.Action as the tool primitive, so the behaviour contract exists. Must build: standard tool library (read, write, edit, search, bash), policy enforcement via cl_ex_security (GUARDRAIL), and sandboxing hooks. 2-3 weeks
Sandbox Execution (cl_ex_sandbox) MEDIUM No existing package provides agent-oriented sandboxed code execution. Must build Docker/Firecracker integration. 2-3 weeks

5.2 Channel Adapter Libraries -- Detailed Gap Analysis

Channel        Elixir Library    Quality    Gap / Work Needed
─────────────  ────────────────  ─────────  ──────────────────────────────────
Telegram       ex_gram           Good       Wrap in ClEx.Transport.Channel behaviour.
                                            Needs: media handling adapter,
                                            inline keyboard → CL_EX action map.
                                            Effort: 3-5 days.

Discord        nostrum           Excellent  Wrap in ClEx.Transport.Channel behaviour.
                                            Needs: slash command registration,
                                            embed builder, component mapping.
                                            Effort: 3-5 days.

Slack          slack_elixir      Fair       Thin wrapper, may need custom
                                            Events API webhook handler.
                                            Socket Mode: must build.
                                            Effort: 1-2 weeks.

WhatsApp       NONE              N/A        Biggest gap. Options:
                                            A) Cloud API (Req) - 1 week
                                            B) whatsmeow Port - 3-4 weeks
                                            C) Baileys Port - 2-3 weeks
                                            Effort: 1-4 weeks.

Signal         NONE              N/A        signal-cli exists (Java). Wrap as
                                            Port or use Signal REST API.
                                            Effort: 2-3 weeks.

iMessage       NONE              N/A        macOS-only. Requires AppleScript
                                            or BlueBubbles server integration.
                                            Effort: 2-3 weeks.

LINE           NONE              N/A        REST API is straightforward.
                                            Build from scratch with Req.
                                            Effort: 1 week.

Google Chat    NONE              N/A        REST API + PubSub. Build with
                                            Req + goth (Google auth).
                                            Effort: 1 week.

Matrix         NONE partial      Poor       matrix_sdk_ex exists but
                                            unmaintained. Likely rebuild.
                                            Effort: 2 weeks.

MS Teams       NONE              N/A        Bot Framework REST API.
                                            Build with Req.
                                            Effort: 1-2 weeks.

5.3 CLI Framework Gap

Elixir has no single "commander.js equivalent" that provides:

  • Subcommand trees with help generation
  • Interactive prompts
  • Rich terminal output (tables, colors, spinners)
  • Shell completions

Solution: Compose from existing pieces:

  • OptionParser (stdlib) -- argument parsing
  • Owl -- rich output, tables, spinners, progress bars
  • IO.ANSI (stdlib) -- colors
  • Custom subcommand router (~100 lines)
  • Burrito -- package as standalone binary (replaces npm global install)

This is a minor gap -- the pieces exist, they just need composition.

5.4 Other Gaps

Gap Description Solution
Sprite Orchestrator Cloud VPS provisioning and management. No existing package. Build within cl_ex_mesh using cloud provider APIs via Req. 4-6 weeks.
Security Layer Zero-trust security kernel. Build cl_ex_security. Integrate GUARDRAIL (policy engine) and Shield (zero-trust auth). Leverage OTP distribution security (TLS), add SPIFFE/mTLS. 6-8 weeks.
Skill System Reusable prompt fragments with discovery. Leverage Jido.Skill for higher-level compositions of Jido.Action tools. Build skill registry and filesystem discovery. 1-2 weeks.
Memory/RAG Pipeline End-to-end: chunk, embed, store, search, inject. Build cl_ex_memory. Integrate portfolio_core/portfolio_index for RAG, embed_ex for embeddings, Bedrock for storage. 2-3 weeks.
Config File Format User-friendly config for non-Elixir developers. Support TOML via toml package + NimbleOptions validation. 3-5 days.
Hot Code Upgrade Seamless agent updates without dropping sessions. Leverage OTP releases + :release_handler. Built-in but needs orchestration. 1-2 weeks.

6. Generic Agentic Stack

The Vision: One Dependency, Full Agent Infrastructure

Any Elixir developer adds one line to their mix.exs and gets a complete, production-grade AI agent platform:

# mix.exs
defp deps do
  [
    {:cl_ex, "~> 0.1"}
  ]
end

This single dependency brings the entire stack. Here is what activates and how.

6.1 What You Get

┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│   {:cl_ex, "~> 0.1"}                                                       │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐   │
│   │  AUTO-DISCOVERED BEAM CLUSTERING                                    │   │
│   │                                                                     │   │
│   │  ClEx starts libcluster automatically.                              │   │
│   │  Strategy auto-detected:                                            │   │
│   │    - Fly.io  → Fly.io DNS strategy (zero config)                    │   │
│   │    - K8s     → Kubernetes DNS strategy (zero config)                │   │
│   │    - Local   → Epmd strategy (zero config)                          │   │
│   │    - Custom  → Configure in application env                         │   │
│   │                                                                     │   │
│   │  Result: Add more nodes → agents auto-distribute.                   │   │
│   └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐   │
│   │  SELF-HEALING AGENT MESH                                            │   │
│   │                                                                     │   │
│   │  Every agent is a supervised Jido.AgentServer (GenServer) process.  │   │
│   │  Bedrock + cl_ex_mesh distribute agents across cluster.             │   │
│   │                                                                     │   │
│   │  Node dies → cl_ex_mesh restarts agents on surviving nodes.          │   │
│   │  Agent crashes → DynamicSupervisor restarts it.                     │   │
│   │  Session restored from persistent storage automatically.            │   │
│   │                                                                     │   │
│   │  You write:                                                         │   │
│   │    ClEx.chat("my-agent", "Hello!", model: "claude-sonnet-4-20250514")│   │
│   │  That's it. Crash recovery, distribution, and monitoring are free.  │   │
│   └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐   │
│   │  ZERO-CONFIG CHANNEL CONNECTIVITY                                   │   │
│   │                                                                     │   │
│   │  Set environment variables. Channels auto-activate:                 │   │
│   │                                                                     │   │
│   │    CLEX_TELEGRAM_BOT_TOKEN=xxx  → Telegram channel starts            │   │
│   │    CLEX_DISCORD_BOT_TOKEN=xxx  → Discord channel starts             │   │
│   │    CLEX_SLACK_BOT_TOKEN=xxx    → Slack channel starts               │   │
│   │    CLEX_WHATSAPP_API_TOKEN=xxx → WhatsApp channel starts            │   │
│   │                                                                     │   │
│   │  No channel configured? HTTP webhook gateway starts by default.     │   │
│   │  All channels normalize to %ClEx.Signal{} automatically.             │   │
│   └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐   │
│   │  EMBEDDED AI AGENT WITH TOOLS                                       │   │
│   │                                                                     │   │
│   │  Built-in tools (opt-in via config):                                │   │
│   │    :read, :write, :edit       → Filesystem operations               │   │
│   │    :search                    → Code/text search                    │   │
│   │    :bash                      → Shell execution (sandboxed)         │   │
│   │    :web_search, :web_fetch    → Internet access                     │   │
│   │    :message                   → Cross-channel messaging             │   │
│   │    :memory_search             → Semantic memory recall              │   │
│   │    :browser                   → Headless browser automation         │   │
│   │                                                                     │   │
│   │  Custom tools in 5 lines:                                           │   │
│   │    defmodule MyTool do                                              │   │
│   │      use Jido.Action,                                               │   │
│   │        name: "my_tool",                                             │   │
│   │        description: "Does something useful",                        │   │
│   │        schema: [input: [type: :string, required: true]]             │   │
│   │      def run(%{input: val}, _ctx), do: {:ok, process(val)}          │   │
│   │    end                                                              │   │
│   └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
│   ┌─────────────────────────────────────────────────────────────────────┐   │
│   │  MEMORY / RAG CAPABILITY                                            │   │
│   │                                                                     │   │
│   │  Three memory tiers, all automatic:                                 │   │
│   │                                                                     │   │
│   │  1. Session Memory (Bedrock + ETS cache)                             │   │
│   │     - Current conversation transcript                               │   │
│   │     - Auto-compaction when token limit approached                   │   │
│   │     - Distributed across cluster via Bedrock (Raft consensus)       │   │
│   │                                                                     │   │
│   │  2. Semantic Memory (portfolio_core + portfolio_index)               │   │
│   │     - Long-term knowledge base with RAG pipeline                    │   │
│   │     - Auto-embedded via embed_ex (local Bumblebee or API)           │   │
│   │     - Searched automatically when agent needs context               │   │
│   │     - Backend: Bedrock (primary) or pgvector/SQLite (fallback)      │   │
│   │                                                                     │   │
│   │  3. Episodic Memory (Event Log)                                     │   │
│   │     - What happened, when, across which channels                    │   │
│   │     - Queryable timeline of agent actions                           │   │
│   │     - Powers "what did I do yesterday?" queries                     │   │
│   │                                                                     │   │
│   │  Config:                                                            │   │
│   │    config :cl_ex_memory,                                            │   │
│   │      backend: :bedrock,      # or :pgvector, :sqlite, :in_memory   │   │
│   │      embedding: :local,      # or :openai, :voyage (via embed_ex)  │   │
│   │      auto_embed: true                                               │   │
│   └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

6.2 Progressive Disclosure: From Simple to Full

LEVEL 0: Library Mode (10 seconds)
══════════════════════════════════

    ClEx.chat("What is 2+2?")
    #=> "2 + 2 equals 4."

    No config. No processes. Just a function call.
    Uses default model, no tools, no memory.


LEVEL 1: Agent Mode (1 minute)
══════════════════════════════

    # In your application.ex:
    children = [{ClEx, agents: [%{id: "helper", model: "claude-sonnet-4-20250514"}]}]

    # Anywhere in your code:
    ClEx.chat("helper", "Summarize this document", context: doc_text)
    #=> "The document discusses..."

    One supervised agent. Tools optional. Memory optional.


LEVEL 2: Channel Mode (5 minutes)
═════════════════════════════════

    # config/runtime.exs:
    config :cl_ex,
      agents: [%{id: "bot", model: "claude-sonnet-4-20250514", tools: [:search, :memory_search]}],
      channels: [
        telegram: [token: System.get_env("CLEX_TELEGRAM_BOT_TOKEN")],
        discord: [token: System.get_env("CLEX_DISCORD_BOT_TOKEN")]
      ]

    # That's it. Bot is now live on Telegram and Discord.
    # Messages auto-route to the "bot" agent.
    # Sessions auto-managed per user per channel.


LEVEL 3: Multi-Agent Mode (15 minutes)
══════════════════════════════════════

    config :cl_ex,
      agents: [
        %{id: "triage",   model: "claude-haiku", tools: [:message],
          system: "Route questions to the right specialist agent."},
        %{id: "coder",    model: "claude-sonnet-4-20250514", tools: [:read, :write, :edit, :bash],
          workspace: "/app/code"},
        %{id: "research", model: "claude-sonnet-4-20250514", tools: [:web_search, :web_fetch, :memory_search]},
        %{id: "ops",      model: "claude-haiku", tools: [:bash, :message],
          system: "You manage infrastructure."}
      ],
      channels: [
        telegram: [token: "..."],
        slack: [token: "...", channel_routing: %{"#dev" => "coder", "#research" => "research"}]
      ]

    # Triage agent receives all unrouted messages.
    # It uses the :message tool to hand off to specialists.
    # Each specialist has its own session, tools, and workspace.


LEVEL 4: Distributed + Sprites (30 minutes)
═══════════════════════════════════════════

    config :cl_ex,
      cluster: [strategy: :fly_io],           # Auto-discover peers
      sprites: [
        provider: :hetzner,                    # Auto-provision VPS
        pool_size: {2, 10},                    # Min 2, max 10 sprites
        instance_type: "cax11"                 # ARM, 2 CPU, 4GB
      ],
      # ... agents and channels as before

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions