memory-os/setup/install.md

357 lines
12 KiB
Markdown

# Setup Guide
> **Prefer automated install?** Run `curl -sSL https://raw.githubusercontent.com/ClaudioDrews/memory-os/main/setup.sh | bash` — one command, 10 phases, fully idempotent. This manual guide is kept for reference and troubleshooting.
> Step-by-step installation of the Memory OS stack. Assumes Hermes Agent is already installed and configured.
## Prerequisites
- Hermes Agent 0.14.0+ (tested on 0.15.2)
- Python 3.11+
- Docker 24.0+
- OpenRouter API key **only if using OpenRouter as embedding backend** (Ollama/vLLM/llama.cpp local providers do not require a key — see [Layer 5: Qdrant](../layers/05-qdrant.md))
- 16 GB RAM recommended (8 GB minimum)
## Installation
### 1. Icarus Plugin (bundled)
```bash
# Copy the bundled Icarus fork into the Hermes plugins directory
cp -r icarus/ ~/.hermes/plugins/icarus/
```
### 2. Database Setup
Install the Python dependencies first:
```bash
pip install -r requirements.txt
```
Memory OS requires two SQLite databases with FTS5 full-text search indexes:
`state.db` (session history, lineage, reflection budget) and `memory_store.db`
(facts, entities, memory banks). The setup script creates both with idempotent
`CREATE TABLE IF NOT EXISTS` statements — safe to run multiple times.
```bash
python setup/setup_db.py
```
**What it creates:**
| Database | Tables |
|---|---|
| `state.db` | `sessions`, `messages`, `messages_fts` (FTS5), `messages_fts_trigram`, `lineage`, `reflection_budget`, `compression_locks`, `schema_version`, `state_meta` |
| `memory_store.db` | `entities`, `facts`, `facts_fts` (FTS5), `fact_entities`, `memory_banks` |
Options:
```bash
python setup/setup_db.py --dry-run # preview without executing
python setup/setup_db.py --state-db /custom/path/state.db
python setup/setup_db.py --memory-db /custom/path/memory_store.db
```
Environment variables override defaults:
```bash
export STATE_DB_PATH=/home/your-user/.hermes/state.db
export MEMORY_STORE_PATH=/home/your-user/.hermes/memory_store.db
```
### 3. Enable Icarus in Hermes Config
Icarus must be registered as an enabled plugin. Edit `~/.hermes/config.yaml`:
```yaml
enabled:
- hermes-achievements # optional
- icarus # required — activates fabric tools + context injection hooks
```
Then restart the gateway:
```bash
hermes gateway restart
```
Verify the plugin loaded:
```bash
hermes status
# → Should show: icarus v0.3.0 (16 tools, 4 hooks)
```
### 4. Docker Infrastructure
The compose file lives in the `docker/` directory of this repository and must be run **in-place** — the worker build context (`./worker`) is relative to the compose file location.
```bash
# Navigate to the docker directory inside your clone
cd /path/to/memory-os/docker
# Create .env with required variables
cat > .env << EOF
# Required only for OpenRouter embedding backend; safe to leave empty for local providers
OPENROUTER_API_KEY=sk-or-...
REDIS_PASSWORD=$(openssl rand -hex 16)
# Optional overrides (defaults shown)
EMBEDDING_DIMS=4096
COLLECTION_NAME=knowledge_base
LOG_LEVEL=INFO
EOF
# Optional — if you want the Docker stack to use your existing production
# directories instead of local test volumes, uncomment and set these:
# MEMORY_OS_WIKI_PATH=/home/your-user/vault/wiki
# MEMORY_OS_HERMES_HOME=/home/your-user/.hermes
# MEMORY_OS_FABRIC_DIR=/home/your-user/vault/fabric
# ⚠️ Do NOT set these to production paths unless you understand the risk.
# The worker mounts /fabric and /hermes as read-write.
# Start the stack
docker compose up -d
```
Verify all three services are running:
```bash
docker compose ps
# → Should show redis, qdrant, and worker all with Status: Up
curl -s http://localhost:6333/healthz # → {"title":"ok","version":"1.17.1"}
redis-cli -a "$REDIS_PASSWORD" ping # → PONG
```
### 5. Environment Variables
Add to your Hermes profile `.env` (e.g. `~/.hermes/.env`):
```bash
# Required
FABRIC_DIR=/home/your-user/vault/fabric
# Required only when using OpenRouter as embedding backend
OPENROUTER_API_KEY=sk-or-...
# Strongly recommended
ICARUS_EXTRACTION_MAX_TOKENS=4096
ICARUS_EXTRACTION_MODEL=deepseek/deepseek-v4-flash
EMBEDDING_DIMS=4096
# Optional — Embedding backend (defaults to OpenRouter)
# EMBEDDING_API_BASE=https://openrouter.ai/api/v1
# EMBEDDING_MODEL=qwen/qwen3-embedding-8b
# Optional — API key for non-OpenRouter authenticated embedding endpoints
# (vLLM with --api-key, custom hosted services). Not needed for OpenRouter
# or local unauthenticated providers.
# EMBEDDING_API_KEY=your-key-here
# Optional
ICARUS_OBSIDIAN=1
ICARUS_RESULT_MAX_CHARS=500
ICARUS_TASK_MAX_CHARS=300
```
**⚠️ Use absolute paths.** The Hermes gateway runs as a systemd service — `~` is not expanded. Always use `/home/your-user/...`.
### 6. Core File Modifications
Apply the additions documented in
[setup/rulebook.md](rulebook.md) and
[modifications/soul-rulebook.md](../modifications/soul-rulebook.md):
**`~/.hermes/rulebook.md`** — apply the three amendments from
`modifications/execution-agent-protocol.md` (see `setup/rulebook.md`
for a summary). Each amendment targets a specific section of the
Execution Agent protocol — insert it after the referenced section.
- Each amendment starts with `<!-- Memory OS amendment — do not duplicate -->`.
Before applying, check whether this marker already exists in your
rulebook — if it does, skip that amendment.
**`SOUL.md`** — add Ground Truth level 2 (injected memory) and context
injection convention as documented in `modifications/soul-rulebook.md`.
**`~/.hermes/.env`** — set `HERMES_AGENT_NAME=hermes` (or any unique name).
This distinguishes your agent in fabric entries and enables multi-agent
handoff. Without it, all entries use the fallback `agent: "agent"` and
cross-agent features are disabled.
These modifications ensure the agent treats injected memory as more
authoritative than training knowledge, and knows where to find
persisted information without re-discovering it.
### 7. Wiki + Vault Setup
Memory OS stores its knowledge pipeline inside an Obsidian vault. The vault
path is user-specific — set it as an environment variable first:
```bash
# Set this to your Obsidian vault path
export VAULT_PATH=/home/your-user/path/to/vault
```
Create the wiki directory structure:
```bash
mkdir -p $VAULT_PATH/wiki/{raw,concepts,entities,comparisons,_meta,_archive}
```
**What goes where:**
- `raw/` — source documents to be ingested and curated
- `concepts/`, `entities/`, `comparisons/` — auto-generated by vault-curator
- `_meta/` — pipeline metadata (SCHEMA.md, indexes)
- `_archive/` — aged-out content from decay scanner
The wiki starts empty. Add source documents to `raw/` and the wiki-continuous-ingest
cronjob (step 7) will begin extracting structured pages.
**Optional — Vault Curator:** For automatic enrichment, semantic linking, and
MOC generation, install [vault-curator](https://github.com/ClaudioDrews/vault-curator)
as a separate tool. It runs independently and is not required for Memory OS
core functionality.
### 8. Maintenance Scripts
The `scripts/` directory in this repository contains the maintenance tools
that keep the memory stack healthy. Copy them to a location of your choice
(e.g. `~/memory-os-scripts/`) and schedule them.
| Script | Schedule | Purpose |
|---|---|---|
| `wiki_continuous_ingest.py` | Hourly | Detects new/modified .md files and enqueues them to the ARQ worker |
| `decay_scanner.py` | Weekly (Sun 3am) | Archives low-importance chunks based on age and importance_score |
| `dlq_manager.py` | Every 6 hours | Reads, classifies, and reports dead letter queue failures |
| `semantic_dedup.py` | Monthly (1st Sun) | Scans for near-duplicate vectors (cosine > 0.92) |
| `backfill_decay_metadata.py` | One-shot / on-demand | Populates missing metadata (created_at, importance_score) for decay scanner |
| `pre_validator.py` | On-demand | Semantic linter — queries knowledge_base before I/O actions |
| `reflection_trigger.py` | Every 5 min | Triggers micro_reflection when ARQ worker is idle |
| `bulk_wiki_ingest.py` | One-shot | Initial bulk ingestion of existing wiki content |
| `holographic-memory-backup.py` | Weekly (Mon 4am) | Dump and compress `memory_store.db` to backup directory |
| `wiki-raw-ingest-monitor.py` | Twice/week (Mon/Thu 3am) | Detects new or drifted files in `raw/` vs FTS5 index |
| `maas-heartbeat.py` | Every 6 hours | Health-check ping against Qdrant, Redis, and ARQ queue depth |
**Using Hermes cron (recommended):**
```bash
hermes cron create \
--name "wiki-continuous-ingest" \
--schedule "0 * * * *" \
--script /path/to/scripts/wiki_continuous_ingest.py \
--no-agent \
--deliver local
hermes cron create \
--name "decay-scanner" \
--schedule "0 3 * * 0" \
--script /path/to/scripts/decay_scanner.py \
--no-agent \
--deliver local
hermes cron create \
--name "dlq-manager" \
--schedule "0 */6 * * *" \
--script /path/to/scripts/dlq_manager.py \
--no-agent \
--deliver local
hermes cron create \
--name "semantic-dedup" \
--schedule "0 3 1 * *" \
--script /path/to/scripts/semantic_dedup.py \
--no-agent \
--deliver local
hermes cron create \
--name "holographic-memory-backup" \
--schedule "0 4 * * 1" \
--script /path/to/scripts/holographic-memory-backup.py \
--no-agent \
--deliver local
hermes cron create \
--name "wiki-raw-ingest-monitor" \
--schedule "0 3 * * 1,4" \
--script /path/to/scripts/wiki-raw-ingest-monitor.py \
--no-agent \
--deliver local
hermes cron create \
--name "maas-heartbeat" \
--schedule "0 */6 * * *" \
--script /path/to/scripts/maas-heartbeat.py \
--no-agent \
--deliver local
```
**Before enabling decay scanner:** run `backfill_decay_metadata.py` once to
populate `created_at`, `last_accessed_at`, `importance_score`, and
`confidence_score` on existing Qdrant points. Without backfill, the decay
scanner will find zero eligible points.
**Exempting collections:** Set `DECAY_EXEMPT_PREFIXES` and
`DEDUP_EXEMPT_PREFIXES` env vars (comma-separated prefixes) to exclude
specific Qdrant collections from automated maintenance.
### 9. Gateway Restart
```bash
hermes gateway restart
```
Changes to `.env`, `SOUL.md`, `rulebook.md`, and Icarus plugin code only take effect after restart.
### 10. Verify
Inside Hermes chat:
```
/plugins
# → Should show: icarus v0.3.0 (16 tools, 4 hooks)
fabric_brief()
# → Should show recent fabric entries (initially empty)
qdrant_search("test query")
# → Should return results from knowledge_base (if wiki has content)
fact_store(action='probe', entity='test')
# → Should return empty (no facts stored yet)
```
## What to expect
**Day 1:** Infrastructure running. Fabric entries begin accumulating at session end. Qdrant indexing starts as wiki files are added.
**Week 1:** Context injection active. Agent references past decisions automatically. Wiki pipeline producing curated pages from raw documents.
**Month 1:** Decay scanner has aged content to evaluate. Structured facts accumulating with trust scores.
## Troubleshooting
### Qdrant collection shows 0 points
Check: `EMBEDDING_DIMS=4096` matches collection schema. Mismatch → vectors rejected silently.
### Fabric entries are truncated
Check: `ICARUS_EXTRACTION_MAX_TOKENS=4096` in `.env` AND gateway was restarted after setting it.
### Memory tool reports "Icarus write conflict"
Icarus is writing to MEMORY.md instead of CREATIVE.md. Verify Icarus fork is installed (not upstream esaradev version).
### Context injection not working
Check: OpenRouter API key is set, `context_enhancer.py` can import, gateway restarted after `hooks.py` edits.
### Decay scanner produces "0 archived" every week
Most likely: point payloads missing `last_accessed_at` or `importance_score` metadata. Run backfill before enabling decay.
### Multiple collections in Qdrant dashboard
The Memory OS uses the `knowledge_base` collection exclusively. Other
collections you may see (e.g., from other Hermes agent plugins or standalone
agents) are safe to coexist — Qdrant isolates each collection at the storage
and query level. Do NOT delete collections you did not create — they may
belong to other agents sharing the same Qdrant instance.