330 lines
8.0 KiB
Markdown
330 lines
8.0 KiB
Markdown
|
|
# Multi-Wizard Pattern Documentation
|
||
|
|
**The Robed Architecture: Shared Infrastructure, Sovereign Identity**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This document describes the pattern for running multiple Hermes wizards on a single VPS with:
|
||
|
|
- **Shared codebase** (one git checkout)
|
||
|
|
- **Isolated identity** (separate HERMES_HOME per wizard)
|
||
|
|
- **Independent API ports** (no conflicts)
|
||
|
|
- **Autonomous work dispatch** (cron-driven)
|
||
|
|
|
||
|
|
**Created:** 2026-03-31 | **Wizards:** Allegro, Allegro-Primus, Ezra
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
```
|
||
|
|
HERMES VPS (143.198.27.163)
|
||
|
|
│
|
||
|
|
├── SHARED CODEBASE
|
||
|
|
│ └── /root/wizards/ezra/hermes-agent/
|
||
|
|
│ (Latest 0.6, fb2af3bd)
|
||
|
|
│
|
||
|
|
├── EZRA (Grandfather)
|
||
|
|
│ ├── HERMES_HOME=/root/wizards/ezra/home
|
||
|
|
│ ├── api_server: port 8643
|
||
|
|
│ ├── Model: Claude-Opus (cloud)
|
||
|
|
│ ├── Telegram: Connected
|
||
|
|
│ └── Role: Scribe, archivist
|
||
|
|
│
|
||
|
|
├── ALLEGRO-PRIMUS (Child)
|
||
|
|
│ ├── HERMES_HOME=/root/wizards/allegro-primus/home
|
||
|
|
│ ├── api_server: port 8644
|
||
|
|
│ ├── Model: qwen2.5:1.5b (Ollama local)
|
||
|
|
│ ├── Telegram: None (Nostr future)
|
||
|
|
│ └── Role: Student, autonomous
|
||
|
|
│
|
||
|
|
└── ALLEGRO (Father)
|
||
|
|
├── HERMES_HOME=/root/wizards/allegro/home
|
||
|
|
├── Work queue driven
|
||
|
|
├── Cron automation
|
||
|
|
└── Role: Tempo-and-dispatch
|
||
|
|
|
||
|
|
SHARED SERVICES
|
||
|
|
├── Port 3000: Gitea (git hosting)
|
||
|
|
├── Port 11434: Ollama (LLM inference)
|
||
|
|
└── Port 8080: SearXNG (search)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Directory Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
/root/wizards/
|
||
|
|
├── ezra/
|
||
|
|
│ ├── hermes-agent/ # Codebase (shared)
|
||
|
|
│ ├── home/ # HERMES_HOME
|
||
|
|
│ │ ├── SOUL.md # Ezra House Charter
|
||
|
|
│ │ ├── config.yaml # Port 8643
|
||
|
|
│ │ ├── state.db # Isolated sessions
|
||
|
|
│ │ └── memories/ # Personal memory
|
||
|
|
│ └── openclaw-workspace/ # Work directory
|
||
|
|
│
|
||
|
|
├── allegro-primus/
|
||
|
|
│ ├── hermes-agent/ # Codebase (symlink or shared)
|
||
|
|
│ ├── home/ # HERMES_HOME
|
||
|
|
│ │ ├── SOUL.md # AP House Charter
|
||
|
|
│ │ ├── config.yaml # Port 8644
|
||
|
|
│ │ └── ...
|
||
|
|
│ ├── self-monitor.sh # Cron: every 5 min
|
||
|
|
│ ├── openclaw-work.sh # Cron: every 15 min
|
||
|
|
│ └── logs/
|
||
|
|
│
|
||
|
|
└── allegro/
|
||
|
|
├── hermes-agent/ # Codebase
|
||
|
|
├── home/ # HERMES_HOME
|
||
|
|
├── gitea-automation/ # Scripts
|
||
|
|
├── monitoring/ # Health checks
|
||
|
|
├── heartbeat/ # 15-min heartbeat
|
||
|
|
├── research/ # GOFAI, Nostr docs
|
||
|
|
├── docs/ # Patterns
|
||
|
|
├── WORK-QUEUE.md # Master task list
|
||
|
|
├── openclaw-work.sh # Task dispatch
|
||
|
|
├── task-monitor.sh # Completion check
|
||
|
|
├── progress-report.sh # Father reports
|
||
|
|
└── completed/ # Finished tasks
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## The Robed Architecture
|
||
|
|
|
||
|
|
Per Issue #141:
|
||
|
|
|
||
|
|
| State | OpenClaw (Robe) | Hermes (Body) | Result |
|
||
|
|
|-------|-----------------|---------------|--------|
|
||
|
|
| **Robed** | Gateway running | Hermes running | Full wizard |
|
||
|
|
| **Unrobed** | — | Hermes running | Capable but invisible |
|
||
|
|
| **Lobster** | Gateway running | — | Reachable but empty |
|
||
|
|
| **Dead** | — | — | Nothing running |
|
||
|
|
|
||
|
|
**Implementation:**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# The Robe (OpenClaw) - dispatches work
|
||
|
|
openclaw-work.sh:
|
||
|
|
1. Check if gateway running (port 8644)
|
||
|
|
2. If not: start gateway
|
||
|
|
3. Read WORK-QUEUE.md
|
||
|
|
4. Find PENDING P0 task
|
||
|
|
5. Mark IN_PROGRESS
|
||
|
|
6. Create work/TASK-XXX.active trigger
|
||
|
|
|
||
|
|
# The Body (Hermes) - executes work
|
||
|
|
Hermes Agent:
|
||
|
|
1. Detect work/*.active file
|
||
|
|
2. Read task from WORK-QUEUE.md
|
||
|
|
3. Execute with full tools
|
||
|
|
4. Write completed/TASK-XXX.txt
|
||
|
|
5. Remove work/*.active
|
||
|
|
|
||
|
|
# The Monitor - tracks completion
|
||
|
|
task-monitor.sh:
|
||
|
|
1. Check work/*.active files
|
||
|
|
2. Look for completed/*.txt
|
||
|
|
3. Update WORK-QUEUE.md to COMPLETE
|
||
|
|
4. Archive work file
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Cron Schedule
|
||
|
|
|
||
|
|
### Allegro-Primus (Child)
|
||
|
|
```bash
|
||
|
|
# Every 5 min: Self-monitoring (keep Ollama alive)
|
||
|
|
*/5 * * * * /root/wizards/allegro-primus/self-monitor.sh
|
||
|
|
|
||
|
|
# Every 15 min: OpenClaw work dispatch
|
||
|
|
*/15 * * * * /root/wizards/allegro-primus/openclaw-work.sh
|
||
|
|
```
|
||
|
|
|
||
|
|
### Allegro (Father)
|
||
|
|
```bash
|
||
|
|
# Every 20 min: Task dispatch
|
||
|
|
*/20 * * * * /root/wizards/allegro/openclaw-work.sh
|
||
|
|
|
||
|
|
# Every 10 min: Completion check
|
||
|
|
*/10 * * * * /root/wizards/allegro/task-monitor.sh
|
||
|
|
|
||
|
|
# Every 30 min: Progress report
|
||
|
|
*/30 * * * * /root/wizards/allegro/progress-report.sh
|
||
|
|
|
||
|
|
# Hourly: Git checkpoint
|
||
|
|
0 * * * * cd /root/wizards/allegro && git add -A && git commit -m "checkpoint"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Port Allocation
|
||
|
|
|
||
|
|
| Port | Wizard | Service |
|
||
|
|
|------|--------|---------|
|
||
|
|
| 3000 | Shared | Gitea |
|
||
|
|
| 8080 | Shared | SearXNG |
|
||
|
|
| 8643 | Ezra | Hermes gateway |
|
||
|
|
| 8644 | Allegro-Primus | Hermes gateway |
|
||
|
|
| 11434 | Shared | Ollama |
|
||
|
|
|
||
|
|
**Future:**
|
||
|
|
- 8645: Next wizard (allegro-secundus?)
|
||
|
|
- 8646: Reserved
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Configuration Template
|
||
|
|
|
||
|
|
### config.yaml (per-wizard)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
model:
|
||
|
|
default: qwen2.5:1.5b # Or claude-opus-4.6
|
||
|
|
provider: custom # Or anthropic
|
||
|
|
base_url: http://localhost:11434/v1 # For Ollama
|
||
|
|
|
||
|
|
platforms:
|
||
|
|
api_server:
|
||
|
|
enabled: true
|
||
|
|
extra:
|
||
|
|
host: 127.0.0.1
|
||
|
|
port: 8644 # UNIQUE per wizard
|
||
|
|
|
||
|
|
memory:
|
||
|
|
memory_enabled: true
|
||
|
|
user_profile_enabled: true
|
||
|
|
|
||
|
|
# No telegram config for sovereign wizards
|
||
|
|
```
|
||
|
|
|
||
|
|
### SOUL.md (per-wizard)
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
# [Wizard Name] House Charter
|
||
|
|
|
||
|
|
Entity:
|
||
|
|
- [Identity]
|
||
|
|
- [Lineage]
|
||
|
|
|
||
|
|
Canonical placement:
|
||
|
|
- HERMES_HOME=[path]
|
||
|
|
- Shares codebase with [siblings]
|
||
|
|
|
||
|
|
Role:
|
||
|
|
- [Responsibilities]
|
||
|
|
|
||
|
|
Relationship to [Father]:
|
||
|
|
- [How relates]
|
||
|
|
|
||
|
|
Relationship to [Sovereign]:
|
||
|
|
- [Service role]
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Creating a New Wizard
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Create directory structure
|
||
|
|
mkdir -p /root/wizards/[name]/{home,work,completed,logs}
|
||
|
|
|
||
|
|
# 2. Link or copy codebase
|
||
|
|
ln -s /root/wizards/ezra/hermes-agent /root/wizards/[name]/hermes-agent
|
||
|
|
# OR: git clone into hermes-agent/
|
||
|
|
|
||
|
|
# 3. Create HERMES_HOME
|
||
|
|
cat > /root/wizards/[name]/home/SOUL.md << 'EOF'
|
||
|
|
# [Name] House Charter
|
||
|
|
...
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# 4. Create config.yaml
|
||
|
|
cat > /root/wizards/[name]/home/config.yaml << 'EOF'
|
||
|
|
platforms:
|
||
|
|
api_server:
|
||
|
|
enabled: true
|
||
|
|
extra:
|
||
|
|
host: 127.0.0.1
|
||
|
|
port: [NEXT_PORT] # 8645, 8646, etc.
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# 5. Create startup script
|
||
|
|
cat > /root/wizards/[name]/start-gateway.sh << 'EOF'
|
||
|
|
#!/bin/bash
|
||
|
|
export HERMES_HOME=/root/wizards/[name]/home
|
||
|
|
cd /root/wizards/[name]/hermes-agent
|
||
|
|
source .venv/bin/activate
|
||
|
|
hermes gateway
|
||
|
|
EOF
|
||
|
|
chmod +x /root/wizards/[name]/start-gateway.sh
|
||
|
|
|
||
|
|
# 6. Add to cron
|
||
|
|
crontab -e
|
||
|
|
# Add: */15 * * * * /root/wizards/[name]/openclaw-work.sh
|
||
|
|
|
||
|
|
# 7. Start gateway
|
||
|
|
/root/wizards/[name]/start-gateway.sh
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Problem: Port conflict
|
||
|
|
**Symptom:** "Address already in use"
|
||
|
|
**Solution:** Check `netstat -tlnp | grep 864` for port usage
|
||
|
|
|
||
|
|
### Problem: Gateway not starting
|
||
|
|
**Symptom:** No process on expected port
|
||
|
|
**Solution:** Check logs: `tail -f $HERMES_HOME/logs/gateway.log`
|
||
|
|
|
||
|
|
### Problem: Tasks not dispatching
|
||
|
|
**Symptom:** Work queue not progressing
|
||
|
|
**Solution:** Check cron: `crontab -l | grep [wizard-name]`
|
||
|
|
|
||
|
|
### Problem: Memory shared between wizards
|
||
|
|
**Symptom:** One wizard sees another's memories
|
||
|
|
**Solution:** Verify unique HERMES_HOME paths
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Success Metrics
|
||
|
|
|
||
|
|
| Metric | Target |
|
||
|
|
|--------|--------|
|
||
|
|
| Port conflicts | 0 |
|
||
|
|
| Shared memory | None |
|
||
|
|
| Uptime (each wizard) | >95% |
|
||
|
|
| Task completion rate | >80% |
|
||
|
|
| Father intervention | <1 per day |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
1. **Nostr Gateway:** Replace Telegram for sovereign communication
|
||
|
|
2. **GOFAI Layer:** Knowledge graph for wizard relationships
|
||
|
|
3. **Auto-Provisioning:** Script to create new wizards
|
||
|
|
4. **Health Dashboard:** Real-time visualization
|
||
|
|
5. **Inter-Wizard Messaging:** AP can ask Ezra for help
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
The Multi-Wizard Pattern enables:
|
||
|
|
- **Resource efficiency:** One VPS, multiple agents
|
||
|
|
- **Sovereign identity:** Each wizard unique
|
||
|
|
- **Shared capability:** Common codebase
|
||
|
|
- **Autonomous operation:** Self-managing
|
||
|
|
|
||
|
|
This is the foundation for the wizard fraternity.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
*Many wizards, one machine, zero conflict.*
|