Lopen is a production-ready, local-first autonomous assistant framework that runs entirely on your Mac. It uses an intent-driven, plugin-extensible architecture to handle any open-ended user request — routing it semantically to the best available tool, without hardcoded mappings or pre-defined task lists.
Designed for a 2017 Intel MacBook Pro (8 GB RAM, target ≤4 GB runtime) — no cloud, no subscriptions, all private.
git clone https://github.com/agarw48550/Lopen && cd Lopen
bash install.sh
The installer will:
.venv/llama-cpp-python for local LLM (cmake installed via pip)# Activate environment and start all services
source .venv/bin/activate
bash scripts/start.sh
# Open the web dashboard
open http://localhost:8080
# Launch the interactive CLI
python cli.py
_
| | ___ _ __ ___ _ __
| | / _ \| '_ \ / _ \ '_ \
| |__| (_) | |_) | __/ | | |
|_____\___/| .__/ \___|_| |_|
|_|
Your local-first autonomous assistant. No cloud required. 🖥️
Systems nominal. Type 'help' for commands.
Host: http://localhost:8000 | Session: cli-1711234567
lopen › chat write a Python hello-world function
lopen › status
lopen › plugins
lopen › debug on
lopen › benchmark
lopen › joke
lopen › quit
CLI commands:
| Command | Description |
|---|---|
chat <message> | Send a message to the agent |
status | Service health, RAM usage, uptime |
system | Detailed RAM/CPU/disk report with memory guard |
plugins | List loaded plugins |
tools | List all tools with descriptions |
history | Show recent conversation turns |
summary | Summarise the current conversation |
clear | Clear conversation history |
config | Print active configuration |
model [name] | Show or switch the active LLM |
memory | RAM usage and memory guard thresholds |
fetch <url> | Fetch a URL and summarise its content |
ingest <file> | Ingest a local file into agent memory |
logs [N] | Tail the last N lines from the agent log |
restart | Restart the orchestrator service |
debug on|off | Toggle verbose debug output |
benchmark | Run inference speed test |
help | Show all commands |
Fun extras: joke, haiku, sing, quote, about, fortune, matrix, coffee
# Start CLI with debug output
python cli.py --debug
# Connect to a remote instance
python cli.py --host my-macbook.local --port 8000
# Full self-diagnostics (OS, Python, RAM, models, services)
bash scripts/diagnose.sh
# Check running service status
bash scripts/status.sh
# Start with verbose debug logging (LOPEN_DEBUG=1)
bash scripts/start.sh --debug
# Tail logs
tail -f logs/lopen.log
tail -f logs/lopen_error.log
tail -f logs/lopen_debug.log # created in debug mode
Debug mode activates via:
bash scripts/start.sh --debugLOPEN_DEBUG=1 bash scripts/start.shpython cli.py --debugLOPEN_LOG_LEVEL=DEBUG python cli.pyStructured logs in logs/:
lopen.log — standard operation log (50 MB rotating, 5 backups)lopen_error.log — errors only (10 MB rotating, 3 backups)lopen_debug.log — verbose debug trace (20 MB rotating, 3 backups)# Run inference speed test
bash scripts/benchmark.sh
# Verbose mode (shows responses)
bash scripts/benchmark.sh --verbose
Target performance on a 2017 Intel MacBook Pro with Qwen3.5-0.8B-Instruct Q4_K_M (April 2026 default):
Previous default (Phi-3-mini Q4_K_M): 3–8s average. Replaced by Qwen3.5-0.8B for 3× faster responses and 4× smaller model footprint. Set
llm.active: phi3-mini-q4to revert.
The web gateway provides multiplatform control from any browser — laptop, phone, or tablet — on your local network:
Access from your MacBook Air: http://[your-mac-ip]:8080
User Query (any interface)
│
┌──────────▼──────────┐
│ SafetyEngine │ ← NemoClaw-inspired guardrails
│ check_input() │ pattern + topic blocklist, PII redaction
└──────────┬──────────┘
│ (if safe)
┌──────────▼──────────┐
│ IntentEngine │ ← TF-IDF cosine similarity
│ (semantic match) │ no model downloads, <1 MB RAM
└──────────┬──────────┘
│ scores every registered tool
┌──────────▼──────────┐
│ ToolSelector │ ← ranks + safety tool check
└──────────┬──────────┘
│
┌─────────────▼─────────────────┐
│ AgentDispatcher (OMLX) │ ← multi-agent reasoning
│ planner → executor → reflector│ LRU memory eviction
└──────────────┬────────────────┘
│
┌──────────────▼────────────────┐
│ AirLLMEngine │ ← AirLLM / llama-cpp-python
│ (layer-split or GGUF backend) │ mock fallback for CI
└──────────────┬────────────────┘
│
┌───────────▼──────────┐
│ SafetyEngine │ ← output PII redaction
│ check_output() │
└───────────┬──────────┘
│
Final Response
┌─────────────────────────────────────────────────────────────────────────────┐
│ Lopen Orchestrator (port 8000) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │IntentEngine │→ │ToolSelector │→ │Tool Registry │ │ Task Queue │ │
│ │ (TF-IDF) │ │+ ToolFilter │ │+ PluginLoader│ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ AirLLMEngine (airllm → llama_cpp → mock, auto-select) │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ AgentDispatcher: planner | executor | reflector | summarizer │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ SafetyEngine: input guardrails | tool filter | output redaction │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Conversation Memory ←→ SQLite Storage + Analytics │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│ │ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌─────▼──────┐ ┌────▼───────────┐
│ Voice Loop │ │ WhatsApp │ │ Web │ │ System Health │
│ Mic→Wake→ │ │ Bridge │ │ Dashboard │ │ RAM/Disk/Hb/ │
│ ASR→LLM→TTS│ │ (Playwright)│ │ (port 8080)│ │ Log Rotation │
└─────────────┘ └─────────────┘ └────────────┘ └────────────────┘
Tools: HomeworkTutor │ Researcher │ CoderAssist │ DesktopOrganizer │ FileOps │ BrowserAutomation
+ any .py file dropped in tools/third_party/ — auto-discovered
Unlike assistants with hardcoded intent→tool mappings, Lopen uses semantic routing:
tools/third_party/ and it
is automatically discovered, indexed, and becomes available for routing.llm/airllm_engine.py)Efficient large-model inference inspired by lyogavin/airllm.
Conditional activation (new in this session):
llama-cpp-python (estimated as 1.2× the GGUF file size).llama-cpp-python is used directly as the fastest possible path (no layer-split overhead).Auto-selection logic:
model RAM estimate ≤ 4 GB → llama_cpp (fastest path, always preferred)
model RAM estimate > 4 GB → airllm (layer-split, stays within budget)
no backend / no model → mock (CI / offline development)
Force a specific backend via config/settings.yaml:
llm:
engine: auto # auto | airllm | llama_cpp | mock
agent_core/multi_agent.py)OMLX-inspired parallel agent orchestration (jundot/omlx).
OMLX Intel Mac compatibility (new in this session):
omlx package is installed and compatible on your platform.asyncio.gather for concurrency.AgentDispatcher API is used regardless.Startup log messages:
# When OMLX is available:
INFO OMLX is available and compatible — using OMLX-accelerated parallel agent routing.
# When OMLX is absent (Intel Mac, most setups):
INFO OMLX not available/compatible (common on Intel Mac x86_64).
Using built-in asyncio agent pool — provides identical OpenClaw-style pipeline.
config/agents.yamlagent_core/safety.py)NemoClaw-inspired guardrails (NVIDIA/NeMo-Guardrails).
config/settings.yamlSee docs/AI_ARCHITECTURE.md for the complete guide.
# 1. One-command install (recommended)
bash install.sh
# OR manually:
bash scripts/bootstrap.sh # Install system dependencies
bash scripts/setup_venv.sh # Create Python venv + install packages
bash scripts/download_models.sh # Download AI models (~2.3 GB)
cp .env.example .env # Copy config
# 2. Start all services
bash scripts/start.sh
# 3. Open the dashboard
open http://localhost:8080
# 4. Launch the interactive CLI
python cli.py
# 5. Verify (run tests)
python -m pytest tests/ -q
# → 275 passed
| Model stack | File size | RAM usage | LLM speed | Notes |
|---|---|---|---|---|
| Default (Qwen3.5-0.8B Q4_K_M) | 550 MB | ~1.05 GB total | <1s 🚀 | Ultra-fast, multi-agent |
| Quality (Qwen3.5-1.5B Q4_K_M) | 1.0 GB | ~1.5 GB total | ~2s ✅ | Better reasoning |
| Legacy (Phi-3-mini Q4_K_M) | 2.2 GB | ~2.7 GB total | ~3–5s | Previous default |
| Smart (Mistral-7B Q4_K_M, AirLLM auto) | 4.1 GB | ~4.0 GB total | ~8s | AirLLM auto-activated (>4 GB RAM estimate); disable reflection agent |
# Default stack (Qwen3.5-0.8B — ultra-fast, recommended)
bash scripts/download_models.sh
# Quality upgrade (Qwen3.5-1.5B)
bash scripts/download_models.sh --quality
# Legacy (Phi-3-mini)
bash scripts/download_models.sh --phi3
# Smart stack (Mistral-7B, for AirLLM engine)
bash scripts/download_models.sh --mistral
Why Qwen3.5-0.8B over Phi-3-mini?
- 4× smaller (550 MB vs 2.2 GB) → cold starts in seconds
- 3× faster inference (8–12 tok/s vs 2–4 tok/s on Intel Mac)
- First response reliably < 1 second (vs 3–5s)
- Leaves 3+ GB free for voice pipeline, multi-agent, and browser tools
- Instruction-tuned quality matches Phi-3-mini on everyday tasks
| Component | Typical RAM | Notes |
|---|---|---|
| Orchestrator + Engine | ~100 MB | FastAPI + TF-IDF index (pure Python, ~1 MB) |
| Safety Engine | ~1 MB | Pure Python, no model |
| Multi-Agent Dispatcher | ~5 MB | Agent pool (models loaded on demand) |
| LLM (Qwen3.5-0.8B Q4, active) | ~0.55 GB | Loaded on-demand, unloaded after use |
| Web Dashboard | ~80 MB | FastAPI + Jinja2 |
| Voice Service | ~150 MB | includes whisper.cpp model |
| ~200 MB | Playwright Chromium (headless) | |
| Total (default) | ~900 MB | 3.1 GB free — well within 4 GB target ✓ |
| Method | Path | Description |
|---|---|---|
| GET | /health | Health check + uptime |
| GET | /status | Extended status (LLM, safety, agents, tasks) |
| POST | /chat | Query with safety checks + multi-agent routing |
| GET | /memory | Get conversation history |
| DELETE | /memory | Clear conversation history |
| GET | /plugins | List all registered plugins with metadata |
| POST | /plugins/reload | Rescan tools/ dirs, register new plugins |
| GET | /analytics | Usage statistics (tool counts, success rates) |
| POST | /feedback | Submit helpfulness signal for RL tracking |
| GET | /safety | Safety engine status and configuration |
| GET | /agents | Multi-agent dispatcher pool status |
Both query and message field names are accepted by /chat for compatibility.
tools/third_party/my_plugin.py:from tools.base_tool import BaseTool
class MyPlugin(BaseTool):
name = "my_plugin"
description = (
"Handles my specific use case with detailed natural language description "
"so the intent engine can match queries accurately."
)
tags = ["my", "custom", "keywords"]
def run(self, query: str, **kwargs) -> str:
return f"MyPlugin result for: {query}"
POST /plugins/reload.POST /chat with {"query": "do my specific thing"}.See PLUGINS.md for the full plugin development guide.
bash install.sh # full install with model download prompt
bash install.sh --no-models # skip model downloads (install later)
bash install.sh --yes --no-models # fully non-interactive quick install
bash install.sh --yes --with-llama # non-interactive + llama-cpp-python
bash install.sh --debug # verbose output
xcode-select --installSee docs/INSTALL_NO_HOMEBREW.md for the full Homebrew-free install guide with step-by-step instructions for every dependency.
# Install system dependencies (Homebrew-free)
bash scripts/bootstrap.sh
# Set up Python virtual environment
bash scripts/setup_venv.sh
# Download AI models (Qwen3.5-0.8B + whisper-tiny + piper)
bash scripts/download_models.sh
# Start all services
bash scripts/start.sh
# Start with debug logging
bash scripts/start.sh --debug
# Stop all services
bash scripts/stop.sh
# Check status
bash scripts/status.sh
# Full self-diagnostics
bash scripts/diagnose.sh
# Inference benchmark
bash scripts/benchmark.sh
# Health check
bash scripts/health_check.sh
# Individual services
bash scripts/start_orchestrator.sh # port 8000
bash scripts/start_dashboard.sh # port 8080
bash scripts/start_voice.sh
bash scripts/start_whatsapp.sh
Voice is enabled by default in config/settings.yaml. The service will:
say command)whatsapp.enabled: true in config/settings.yamlbash scripts/start_whatsapp.shAccess at http://localhost:8080. Features:
config/settings.yaml| Key | Default | Description |
|---|---|---|
llm.model_path | models/llm/model.gguf | Path to GGUF model |
llm.memory_conservative | true | Unload model between calls to save RAM |
intent_engine.confidence_threshold | 0.2 | Below this, fall back to keyword planner |
plugin_loader.auto_discover | true | Scan tool dirs on startup |
plugin_loader.tool_dirs | [tools, tools/third_party] | Directories to scan |
sandbox.confidence_threshold | 0.3 | Require confirmation below this |
sandbox.auto_approve_known_tools | true | Skip confirmation after enough uses |
analytics.enabled | true | Log usage to local SQLite |
config/tools.yamlEnable/disable individual tools and configure permissions.
bash scripts/diagnose.sh
This checks OS, Python, RAM, disk, models, services, and config — and tells you what to fix.
Download a GGUF model:
bash scripts/download_models.sh
# or manually (Qwen3.5-0.8B default):
mkdir -p models/llm
curl -L -o models/llm/qwen3.5-0.8b-instruct-q4_k_m.gguf \
"https://huggingface.co/Qwen/Qwen3.5-0.8B-Instruct-GGUF/resolve/main/qwen3.5-0.8b-instruct-q4_k_m.gguf"
Then install llama-cpp-python (cmake is installed via pip — no Homebrew needed):
pip install cmake
CMAKE_ARGS="-DGGML_METAL=OFF" pip install "llama-cpp-python>=0.3.0"
Build whisper.cpp:
git clone https://github.com/ggerganov/whisper.cpp
cd whisper.cpp && make
cp main /usr/local/bin/whisper
Or install a pre-built binary from the releases page.
bash scripts/status.sh # see what's running
bash scripts/stop.sh # stop all services
# Or kill specific PID:
lsof -ti:8000 | xargs kill -9
llm.memory_conservative: true in config/settings.yamlbash scripts/health_check.sh for RAM reportllm.context_window to 1024multi_agent.enabled: falsebash scripts/diagnose.sh# Check orchestrator is running
bash scripts/status.sh
# Start if not running
bash scripts/start.sh
# Try debug mode
python cli.py --debug
# Check the error log
cat logs/lopen_error.log
# Run with debug mode
bash scripts/start.sh --debug
cat logs/lopen_debug.log
source .venv/bin/activate
# Full test suite
pytest tests/ -v --tb=short
# → 275 passed
# CLI tests only
pytest tests/test_cli.py -v
# Safety engine tests
pytest tests/test_safety.py -v
# Smoke tests (requires running services)
pytest tests/smoke/ -v
Orchestrator API: ~100 MB
IntentEngine: <1 MB (pure Python TF-IDF, no extra dependencies)
LLM Qwen3.5-0.8B Q4: ~0.55 GB (load on demand, unloaded after use)
whisper-tiny ASR: ~80 MB
piper TTS: ~70 MB
WhatsApp (Chrome): ~200 MB
TOTAL (default stack): ~1.05 GB (target: ≤ 4 GB) ← 2.9 GB headroom ✓
Memory guard thresholds:
Warning at: 3.2 GB used
Critical at: 3.6 GB used → watchdog triggers model unload + service restart
Previously, AirLLMEngine always preferred the AirLLM layer-split backend
whenever the airllm package was installed, even for tiny models. This added
unnecessary overhead (layer-split I/O) for small models like Qwen3.5-0.8B that
fit comfortably in RAM.
As of this session, AirLLM is only activated when a model's estimated RAM usage (1.2× the GGUF file size) exceeds the 4 GB budget:
≤ 4 GB estimate → llama_cpp (fastest path, no layer-split overhead)> 4 GB estimate → airllm (layer-by-layer loading, keeps peak RAM ≤ ~2 GB)llm.engine: airllm|llama_cpp|mock in config/settings.yamlThis change delivers faster inference for all default models and only incurs the AirLLM overhead when strictly necessary.
OMLX (pip install omlx) provides native parallel multi-LLM routing but is not
always compatible with Intel Mac (x86_64 darwin).
As of this session, Lopen auto-detects OMLX compatibility at startup:
planner → executor → reflector pipeline with zero extra
dependencies.In both cases the AgentDispatcher API is identical. Check the startup log
for which path was selected:
INFO OMLX not available/compatible (common on Intel Mac x86_64).
Using built-in asyncio agent pool…
22 commits
2 commits
Python
88.2%
Shell
8.6%
HTML
3.2%
Lopen is a production-ready, local-first autonomous assistant framework that runs entirely on your Mac. It uses an intent-driven, plugin-extensible architecture to handle any open-ended user request — routing it semantically to the best available tool, without hardcoded mappings or pre-defined task lists.
Designed for a 2017 Intel MacBook Pro (8 GB RAM, target ≤4 GB runtime) — no cloud, no subscriptions, all private.
git clone https://github.com/agarw48550/Lopen && cd Lopen
bash install.sh
The installer will:
.venv/llama-cpp-python for local LLM (cmake installed via pip)# Activate environment and start all services
source .venv/bin/activate
bash scripts/start.sh
# Open the web dashboard
open http://localhost:8080
# Launch the interactive CLI
python cli.py
_
| | ___ _ __ ___ _ __
| | / _ \| '_ \ / _ \ '_ \
| |__| (_) | |_) | __/ | | |
|_____\___/| .__/ \___|_| |_|
|_|
Your local-first autonomous assistant. No cloud required. 🖥️
Systems nominal. Type 'help' for commands.
Host: http://localhost:8000 | Session: cli-1711234567
lopen › chat write a Python hello-world function
lopen › status
lopen › plugins
lopen › debug on
lopen › benchmark
lopen › joke
lopen › quit
CLI commands:
| Command | Description |
|---|---|
chat <message> | Send a message to the agent |
status | Service health, RAM usage, uptime |
system | Detailed RAM/CPU/disk report with memory guard |
plugins | List loaded plugins |
tools | List all tools with descriptions |
history | Show recent conversation turns |
summary | Summarise the current conversation |
clear | Clear conversation history |
config | Print active configuration |
model [name] | Show or switch the active LLM |
memory | RAM usage and memory guard thresholds |
fetch <url> | Fetch a URL and summarise its content |
ingest <file> | Ingest a local file into agent memory |
logs [N] | Tail the last N lines from the agent log |
restart | Restart the orchestrator service |
debug on|off | Toggle verbose debug output |
benchmark | Run inference speed test |
help | Show all commands |
Fun extras: joke, haiku, sing, quote, about, fortune, matrix, coffee
# Start CLI with debug output
python cli.py --debug
# Connect to a remote instance
python cli.py --host my-macbook.local --port 8000
# Full self-diagnostics (OS, Python, RAM, models, services)
bash scripts/diagnose.sh
# Check running service status
bash scripts/status.sh
# Start with verbose debug logging (LOPEN_DEBUG=1)
bash scripts/start.sh --debug
# Tail logs
tail -f logs/lopen.log
tail -f logs/lopen_error.log
tail -f logs/lopen_debug.log # created in debug mode
Debug mode activates via:
bash scripts/start.sh --debugLOPEN_DEBUG=1 bash scripts/start.shpython cli.py --debugLOPEN_LOG_LEVEL=DEBUG python cli.pyStructured logs in logs/:
lopen.log — standard operation log (50 MB rotating, 5 backups)lopen_error.log — errors only (10 MB rotating, 3 backups)lopen_debug.log — verbose debug trace (20 MB rotating, 3 backups)# Run inference speed test
bash scripts/benchmark.sh
# Verbose mode (shows responses)
bash scripts/benchmark.sh --verbose
Target performance on a 2017 Intel MacBook Pro with Qwen3.5-0.8B-Instruct Q4_K_M (April 2026 default):
Previous default (Phi-3-mini Q4_K_M): 3–8s average. Replaced by Qwen3.5-0.8B for 3× faster responses and 4× smaller model footprint. Set
llm.active: phi3-mini-q4to revert.
The web gateway provides multiplatform control from any browser — laptop, phone, or tablet — on your local network:
Access from your MacBook Air: http://[your-mac-ip]:8080
User Query (any interface)
│
┌──────────▼──────────┐
│ SafetyEngine │ ← NemoClaw-inspired guardrails
│ check_input() │ pattern + topic blocklist, PII redaction
└──────────┬──────────┘
│ (if safe)
┌──────────▼──────────┐
│ IntentEngine │ ← TF-IDF cosine similarity
│ (semantic match) │ no model downloads, <1 MB RAM
└──────────┬──────────┘
│ scores every registered tool
┌──────────▼──────────┐
│ ToolSelector │ ← ranks + safety tool check
└──────────┬──────────┘
│
┌─────────────▼─────────────────┐
│ AgentDispatcher (OMLX) │ ← multi-agent reasoning
│ planner → executor → reflector│ LRU memory eviction
└──────────────┬────────────────┘
│
┌──────────────▼────────────────┐
│ AirLLMEngine │ ← AirLLM / llama-cpp-python
│ (layer-split or GGUF backend) │ mock fallback for CI
└──────────────┬────────────────┘
│
┌───────────▼──────────┐
│ SafetyEngine │ ← output PII redaction
│ check_output() │
└───────────┬──────────┘
│
Final Response
┌─────────────────────────────────────────────────────────────────────────────┐
│ Lopen Orchestrator (port 8000) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │IntentEngine │→ │ToolSelector │→ │Tool Registry │ │ Task Queue │ │
│ │ (TF-IDF) │ │+ ToolFilter │ │+ PluginLoader│ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ AirLLMEngine (airllm → llama_cpp → mock, auto-select) │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ AgentDispatcher: planner | executor | reflector | summarizer │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ SafetyEngine: input guardrails | tool filter | output redaction │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Conversation Memory ←→ SQLite Storage + Analytics │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│ │ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌─────▼──────┐ ┌────▼───────────┐
│ Voice Loop │ │ WhatsApp │ │ Web │ │ System Health │
│ Mic→Wake→ │ │ Bridge │ │ Dashboard │ │ RAM/Disk/Hb/ │
│ ASR→LLM→TTS│ │ (Playwright)│ │ (port 8080)│ │ Log Rotation │
└─────────────┘ └─────────────┘ └────────────┘ └────────────────┘
Tools: HomeworkTutor │ Researcher │ CoderAssist │ DesktopOrganizer │ FileOps │ BrowserAutomation
+ any .py file dropped in tools/third_party/ — auto-discovered
Unlike assistants with hardcoded intent→tool mappings, Lopen uses semantic routing:
tools/third_party/ and it
is automatically discovered, indexed, and becomes available for routing.llm/airllm_engine.py)Efficient large-model inference inspired by lyogavin/airllm.
Conditional activation (new in this session):
llama-cpp-python (estimated as 1.2× the GGUF file size).llama-cpp-python is used directly as the fastest possible path (no layer-split overhead).Auto-selection logic:
model RAM estimate ≤ 4 GB → llama_cpp (fastest path, always preferred)
model RAM estimate > 4 GB → airllm (layer-split, stays within budget)
no backend / no model → mock (CI / offline development)
Force a specific backend via config/settings.yaml:
llm:
engine: auto # auto | airllm | llama_cpp | mock
agent_core/multi_agent.py)OMLX-inspired parallel agent orchestration (jundot/omlx).
OMLX Intel Mac compatibility (new in this session):
omlx package is installed and compatible on your platform.asyncio.gather for concurrency.AgentDispatcher API is used regardless.Startup log messages:
# When OMLX is available:
INFO OMLX is available and compatible — using OMLX-accelerated parallel agent routing.
# When OMLX is absent (Intel Mac, most setups):
INFO OMLX not available/compatible (common on Intel Mac x86_64).
Using built-in asyncio agent pool — provides identical OpenClaw-style pipeline.
config/agents.yamlagent_core/safety.py)NemoClaw-inspired guardrails (NVIDIA/NeMo-Guardrails).
config/settings.yamlSee docs/AI_ARCHITECTURE.md for the complete guide.
# 1. One-command install (recommended)
bash install.sh
# OR manually:
bash scripts/bootstrap.sh # Install system dependencies
bash scripts/setup_venv.sh # Create Python venv + install packages
bash scripts/download_models.sh # Download AI models (~2.3 GB)
cp .env.example .env # Copy config
# 2. Start all services
bash scripts/start.sh
# 3. Open the dashboard
open http://localhost:8080
# 4. Launch the interactive CLI
python cli.py
# 5. Verify (run tests)
python -m pytest tests/ -q
# → 275 passed
| Model stack | File size | RAM usage | LLM speed | Notes |
|---|---|---|---|---|
| Default (Qwen3.5-0.8B Q4_K_M) | 550 MB | ~1.05 GB total | <1s 🚀 | Ultra-fast, multi-agent |
| Quality (Qwen3.5-1.5B Q4_K_M) | 1.0 GB | ~1.5 GB total | ~2s ✅ | Better reasoning |
| Legacy (Phi-3-mini Q4_K_M) | 2.2 GB | ~2.7 GB total | ~3–5s | Previous default |
| Smart (Mistral-7B Q4_K_M, AirLLM auto) | 4.1 GB | ~4.0 GB total | ~8s | AirLLM auto-activated (>4 GB RAM estimate); disable reflection agent |
# Default stack (Qwen3.5-0.8B — ultra-fast, recommended)
bash scripts/download_models.sh
# Quality upgrade (Qwen3.5-1.5B)
bash scripts/download_models.sh --quality
# Legacy (Phi-3-mini)
bash scripts/download_models.sh --phi3
# Smart stack (Mistral-7B, for AirLLM engine)
bash scripts/download_models.sh --mistral
Why Qwen3.5-0.8B over Phi-3-mini?
- 4× smaller (550 MB vs 2.2 GB) → cold starts in seconds
- 3× faster inference (8–12 tok/s vs 2–4 tok/s on Intel Mac)
- First response reliably < 1 second (vs 3–5s)
- Leaves 3+ GB free for voice pipeline, multi-agent, and browser tools
- Instruction-tuned quality matches Phi-3-mini on everyday tasks
| Component | Typical RAM | Notes |
|---|---|---|
| Orchestrator + Engine | ~100 MB | FastAPI + TF-IDF index (pure Python, ~1 MB) |
| Safety Engine | ~1 MB | Pure Python, no model |
| Multi-Agent Dispatcher | ~5 MB | Agent pool (models loaded on demand) |
| LLM (Qwen3.5-0.8B Q4, active) | ~0.55 GB | Loaded on-demand, unloaded after use |
| Web Dashboard | ~80 MB | FastAPI + Jinja2 |
| Voice Service | ~150 MB | includes whisper.cpp model |
| ~200 MB | Playwright Chromium (headless) | |
| Total (default) | ~900 MB | 3.1 GB free — well within 4 GB target ✓ |
| Method | Path | Description |
|---|---|---|
| GET | /health | Health check + uptime |
| GET | /status | Extended status (LLM, safety, agents, tasks) |
| POST | /chat | Query with safety checks + multi-agent routing |
| GET | /memory | Get conversation history |
| DELETE | /memory | Clear conversation history |
| GET | /plugins | List all registered plugins with metadata |
| POST | /plugins/reload | Rescan tools/ dirs, register new plugins |
| GET | /analytics | Usage statistics (tool counts, success rates) |
| POST | /feedback | Submit helpfulness signal for RL tracking |
| GET | /safety | Safety engine status and configuration |
| GET | /agents | Multi-agent dispatcher pool status |
Both query and message field names are accepted by /chat for compatibility.
tools/third_party/my_plugin.py:from tools.base_tool import BaseTool
class MyPlugin(BaseTool):
name = "my_plugin"
description = (
"Handles my specific use case with detailed natural language description "
"so the intent engine can match queries accurately."
)
tags = ["my", "custom", "keywords"]
def run(self, query: str, **kwargs) -> str:
return f"MyPlugin result for: {query}"
POST /plugins/reload.POST /chat with {"query": "do my specific thing"}.See PLUGINS.md for the full plugin development guide.
bash install.sh # full install with model download prompt
bash install.sh --no-models # skip model downloads (install later)
bash install.sh --yes --no-models # fully non-interactive quick install
bash install.sh --yes --with-llama # non-interactive + llama-cpp-python
bash install.sh --debug # verbose output
xcode-select --installSee docs/INSTALL_NO_HOMEBREW.md for the full Homebrew-free install guide with step-by-step instructions for every dependency.
# Install system dependencies (Homebrew-free)
bash scripts/bootstrap.sh
# Set up Python virtual environment
bash scripts/setup_venv.sh
# Download AI models (Qwen3.5-0.8B + whisper-tiny + piper)
bash scripts/download_models.sh
# Start all services
bash scripts/start.sh
# Start with debug logging
bash scripts/start.sh --debug
# Stop all services
bash scripts/stop.sh
# Check status
bash scripts/status.sh
# Full self-diagnostics
bash scripts/diagnose.sh
# Inference benchmark
bash scripts/benchmark.sh
# Health check
bash scripts/health_check.sh
# Individual services
bash scripts/start_orchestrator.sh # port 8000
bash scripts/start_dashboard.sh # port 8080
bash scripts/start_voice.sh
bash scripts/start_whatsapp.sh
Voice is enabled by default in config/settings.yaml. The service will:
say command)whatsapp.enabled: true in config/settings.yamlbash scripts/start_whatsapp.shAccess at http://localhost:8080. Features:
config/settings.yaml| Key | Default | Description |
|---|---|---|
llm.model_path | models/llm/model.gguf | Path to GGUF model |
llm.memory_conservative | true | Unload model between calls to save RAM |
intent_engine.confidence_threshold | 0.2 | Below this, fall back to keyword planner |
plugin_loader.auto_discover | true | Scan tool dirs on startup |
plugin_loader.tool_dirs | [tools, tools/third_party] | Directories to scan |
sandbox.confidence_threshold | 0.3 | Require confirmation below this |
sandbox.auto_approve_known_tools | true | Skip confirmation after enough uses |
analytics.enabled | true | Log usage to local SQLite |
config/tools.yamlEnable/disable individual tools and configure permissions.
bash scripts/diagnose.sh
This checks OS, Python, RAM, disk, models, services, and config — and tells you what to fix.
Download a GGUF model:
bash scripts/download_models.sh
# or manually (Qwen3.5-0.8B default):
mkdir -p models/llm
curl -L -o models/llm/qwen3.5-0.8b-instruct-q4_k_m.gguf \
"https://huggingface.co/Qwen/Qwen3.5-0.8B-Instruct-GGUF/resolve/main/qwen3.5-0.8b-instruct-q4_k_m.gguf"
Then install llama-cpp-python (cmake is installed via pip — no Homebrew needed):
pip install cmake
CMAKE_ARGS="-DGGML_METAL=OFF" pip install "llama-cpp-python>=0.3.0"
Build whisper.cpp:
git clone https://github.com/ggerganov/whisper.cpp
cd whisper.cpp && make
cp main /usr/local/bin/whisper
Or install a pre-built binary from the releases page.
bash scripts/status.sh # see what's running
bash scripts/stop.sh # stop all services
# Or kill specific PID:
lsof -ti:8000 | xargs kill -9
llm.memory_conservative: true in config/settings.yamlbash scripts/health_check.sh for RAM reportllm.context_window to 1024multi_agent.enabled: falsebash scripts/diagnose.sh# Check orchestrator is running
bash scripts/status.sh
# Start if not running
bash scripts/start.sh
# Try debug mode
python cli.py --debug
# Check the error log
cat logs/lopen_error.log
# Run with debug mode
bash scripts/start.sh --debug
cat logs/lopen_debug.log
source .venv/bin/activate
# Full test suite
pytest tests/ -v --tb=short
# → 275 passed
# CLI tests only
pytest tests/test_cli.py -v
# Safety engine tests
pytest tests/test_safety.py -v
# Smoke tests (requires running services)
pytest tests/smoke/ -v
Orchestrator API: ~100 MB
IntentEngine: <1 MB (pure Python TF-IDF, no extra dependencies)
LLM Qwen3.5-0.8B Q4: ~0.55 GB (load on demand, unloaded after use)
whisper-tiny ASR: ~80 MB
piper TTS: ~70 MB
WhatsApp (Chrome): ~200 MB
TOTAL (default stack): ~1.05 GB (target: ≤ 4 GB) ← 2.9 GB headroom ✓
Memory guard thresholds:
Warning at: 3.2 GB used
Critical at: 3.6 GB used → watchdog triggers model unload + service restart
Previously, AirLLMEngine always preferred the AirLLM layer-split backend
whenever the airllm package was installed, even for tiny models. This added
unnecessary overhead (layer-split I/O) for small models like Qwen3.5-0.8B that
fit comfortably in RAM.
As of this session, AirLLM is only activated when a model's estimated RAM usage (1.2× the GGUF file size) exceeds the 4 GB budget:
≤ 4 GB estimate → llama_cpp (fastest path, no layer-split overhead)> 4 GB estimate → airllm (layer-by-layer loading, keeps peak RAM ≤ ~2 GB)llm.engine: airllm|llama_cpp|mock in config/settings.yamlThis change delivers faster inference for all default models and only incurs the AirLLM overhead when strictly necessary.
OMLX (pip install omlx) provides native parallel multi-LLM routing but is not
always compatible with Intel Mac (x86_64 darwin).
As of this session, Lopen auto-detects OMLX compatibility at startup:
planner → executor → reflector pipeline with zero extra
dependencies.In both cases the AgentDispatcher API is identical. Check the startup log
for which path was selected:
INFO OMLX not available/compatible (common on Intel Mac x86_64).
Using built-in asyncio agent pool…
22 commits
2 commits
Python
88.2%
Shell
8.6%
HTML
3.2%