An open-source multi-platform AI assistant ecosystem with a modular architecture. The brain service (Emerald) connects to platform adapters (Discord, Matrix) and an LLM gateway (Sapphire) backed by llama.cpp (Krystal).
graph TD
Discord["Discord"] --> Jade["Jade<br/>(Discord adapter)"]
Matrix["Matrix"] --> Pixieglow["Pixieglow<br/>(Matrix adapter)"]
Jade -- "WebSocket :3126" --> Emerald["Emerald<br/>(Brain)"]
Pixieglow -- "WebSocket :3126" --> Emerald
Emerald -- "HTTP :3123" --> Sapphire["Sapphire<br/>(LLM gateway)"]
Sapphire -- "HTTP :3124" --> Krystal["Krystal<br/>(llama.cpp)"]
| Service | Role | Port | Language |
|---|---|---|---|
| Emerald | Brain & behavior engine | 3126 | TypeScript |
| Sapphire | LLM gateway (sessions, classification, prompting) | 3123 | Python |
| Krystal | LLM inference (llama.cpp) | 3124 | C++ |
| Jade | Discord adapter | — | TypeScript |
| Pixieglow | Matrix adapter | — | TypeScript |
- User sends a message on Discord or Matrix
- The adapter (Jade/Pixieglow) forwards it to Emerald via WebSocket
- Emerald evaluates behavior rules (burst, typo, sleep, mannerisms)
- Emerald calls Sapphire's HTTP API with the message and behavior context
- Sapphire classifies the message (emotion valence/arousal, category), manages conversation sessions, injects few-shot examples, and constructs the prompt
- Sapphire calls Krystal with emotion-aware sampling parameters (temperature by arousal, repeat penalty by valence)
- Sapphire checks for degenerate responses and retries if needed
- Sapphire returns the response text (and optionally debug stats)
- Emerald applies typo/swap behavior and sends a
RespondCommandback to the adapter - The adapter posts the response to the platform
Any adapter can pass debug: true on message events. This flows through the entire stack:
- Emerald passes
"debug": trueto Sapphire - Sapphire returns token counts, timing, emotion state, and classification confidence
- Emerald maps snake_case → camelCase and includes
DebugStatsin the respond command - The adapter appends
-#formatted stat lines to the Discord/Matrix response
- Multi-platform — Discord (Jade) and Matrix (Pixieglow) with the same brain backend
- Behavior system — Configurable burst, sleep schedule, typo/swap, mannerisms
- Emotion-aware LLM — Valence/arousal classification adjusts sampling parameters
- Few-shot learning — Category-matched example injection from YAML files
- Session management — Per-channel conversation history
- Debug mode — End-to-end token counting and timing across all layers
- Single small model — Luna Protocol 1.5B Q4_K_M fits in ~3 GB RAM
- All services run on a single VPS managed by PM2
- WebSocket :3126 (Emerald ↔ bots)
- HTTP :3123 (Emerald ↔ Sapphire)
- HTTP :3124 (Sapphire ↔ Krystal)
- Cloudflared tunnel
matrixhandlesmatrix.fox3000foxy.com → palpo (8008)andluna.fox3000foxy.com → tuwunel (8009) - GitHub Pages serves
protocol-luna.github.iofrom.github/workflows/static.yml