Skip to main content

Kairos — Graph-Based Persistent Memory for AI Agents

Your agents die every conversation. Kairos keeps them alive.

The persistent layer your LLMs run on top of. Memory formation, not retrieval. Background consolidation while they sleep. Conflict supersession when your mind changes. A knowledge-graph filesystem your agent walks instead of searches.


What this is

Most AI "memory" systems are retrieval wrappers.

They store chunks. Embed text. Run cosine similarity. Return vaguely related paragraphs.

Kairos is built around a different thesis:

Memory is not retrieval. Memory is formation, consolidation, synthesis, and evolving structure.

The engine continuously transforms raw conversations into a living cognitive graph, backed by Akar (pure-Rust embedded graph database, drop-in replacement for KuzuDB):

  • atomic facts,
  • semantic links,
  • supersession chains,
  • synthesized abstractions,
  • bridge memories,
  • latent preference structures,
  • temporal trajectories.

It does this locally. It works as a Hermes MemoryProvider adapter plugin (daemon-first). It survives across sessions.


Architecture — Daemon-First + Hermes Adapter

Kairos runs in daemon-first mode: a single akar_server process holds the exclusive graph DB lock on vela.db (directory format). All clients — Hermes plugin, MCP server, CLI, tests — connect via TCP loopback (JSON IPC) to this daemon. The graph backend is Akar (pure Rust, import kuzu aliased to import akar via kairos/kuzu.py).

┌─────────────────────────────────────────────────────────────────────┐
│                        HERMES AGENT PROCESS                          │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │ NeuralMemoryProvider (kairos/plugin.py)                      │   │
│  │   • MemoryProvider ABC: initialize / prefetch / sync_turn     │   │
│  │   • get_tool_schemas() → mcp_schemas.ALL_TOOL_SCHEMAS         │   │
│  │   • handle_tool_call() → _HANDLERS dict → engine methods      │   │
│  │   • 3 thread pools: _recall_pool(2) / _write_pool(1) /        │   │
│  │     _dream_pool(1) — prevent graph DB ContextVar contamination │   │
│  │   • DreamLeader (kairos/dream_leader.py): single cross-proc   │   │
│  │     leader via advisory lock on vela.db.dream.leader.lock     │   │
│  └──────────────────────────┬────────────────────────────────────┘   │
│                             │ TCP loopback :<random-port> (JSON IPC)   │
└─────────────────────────────┼────────────────────────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    KUZU_DAEMON PROCESS (1 per DB)                    │
│  • ThreadingTCPServer on 127.0.0.1:<random-port>                    │
│  • Owns single GraphStore + exclusive file lock (vela.db.daemon.lock)│
│  • Serialised writes (GraphStore._write_lock), concurrent reads     │
│  • Idle self-shutdown after KAIROS_KUZU_DAEMON_IDLE (default 86400s)  │
│  • Ops: execute / ping / flush / shutdown / stat / export           │
│  • Announces via sidecar: vela.db.daemon.json {port, token, pid}    │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
                       vela.db/ (Akar graph directory, ~46 MB)
                         ├── data.kz           (46,352 KB) — graph data
                         ├── .wal              (115 KB)    — write-ahead log
                         ├── catalog.kz        (13 KB)     — schema metadata
                         ├── metadata.kz       (22 KB)     — storage metadata
                         ├── n-*.hindex        (~20 KB ea) — vector indexes
                         ├── .lock                          — graph DB internal lock
                         └── .shadow                        — recovery shadow
                       vela.db.daemon.json     — sidecar (host, port, token, pid)
                       vela.db.daemon.lock     — OS-level exclusive lock (msvcrt.locking)
                       vela.db.daemon.log      — daemon stdout/stderr

Two Deployment Modes

Mode Who uses it DB lock holder Selected by
daemon (default for Hermes) Hermes plugin, MCP server, CLI Shared akar_server process KAIROS_KUZU_MODE=daemon (forced by plugin.py)
embedded (explicit opt-in) Standalone from kairos import Kairos The engine's own process KAIROS_KUZU_MODE=embedded (never automatic)

Decided direction: Daemon mode is the single operational path for multi-session Hermes. Embedded remains only as explicit opt-in for tests/CI/true single-process standalone. Automatic embedded/SQLite fallbacks have been removed for the daemon/kuzudb path — failures fail loud.

Thread Pools (in Hermes plugin process)

Pool Threads Used by
_recall_pool 2 recall, think, reasoning, graph, health, metadata, profile(get)
_write_pool 1 remember, protect, profile(set), backup, import, sync
_dream_pool 1 dream_control, dream_config, dream_nrem/rem/insight/afe/synthesis/dae

Total: 4 threads — one per pool.

Cache

diskcache-only (Redis removed per architectural decision):

Domain TTL Contents
recall 300s Recall result cache
dream 3600s Dream queue + status
session 3600s Session buffers

Quick Start

Via Hermes (Recommended)

# 1. Install Kairos package
pip install -e .

# 2. Deploy Hermes adapter plugin (one-time)
.\tools\deploy-kairos-provider.ps1

# 3. Configure Hermes
hermes memory setup kairos
# → prompts: db_path (default: ~/.kairos/engine/vela.db)
# → prompts: embedding_backend (auto/hash/tfidf/sentence-transformers)

# 4. Verify
hermes config get memory
# → provider: kairos
hermes kairos status
# → Backend: akar, Memories: 2895, Connections: 21, ...

Standalone (Single-Process)

# Explicit embedded mode (opt-in)
KAIROS_KUZU_MODE=embedded python -c "
from kairos import Kairos
mem = Kairos()
mem.remember('The user has a dog named Lou')
results = mem.recall('What pet does the user have?')
mem.think(results[0].id)
"

Features

🧠 Core Memory

Function Description
remember() Store a fact with embedding + auto-connection to related memories
recall() Multi-channel recall (semantic, graph, temporal, FTS)
think() Spreading activation — explore connected memories
graph() Connection graph summary

🌙 Dream Engine (Background Consolidation)

Runs in the leader session's _dream_pool; auto-triggers on idle/new-memory thresholds (idle=300s, memory_threshold=50 — source: dream_engine.py).

Phase What it does Notes / caveats
NREM Replay & strengthen active edges, prune weak (<0.05) Batch writes chunked (see §9.1)
Supersedes Directed "older→newer" edge for value-changed facts Only pairs with numeric tokens and differing tokens and cosine ≥ 0.85 (hardcoded, dream_engine.py:1310). Does not dedup exact duplicates.
REM Bridge discovery for isolated memories Up to max_isolated
Insight Louvain community detection → derived:cluster nodes
AFE Atomic Fact Extraction: Stage A/B = regex (afe.py), Stage C = LLM user-state (KAIROS_AFE_LLM_FALLBACK=1) Stage A/B have no LLM prompt; fragment quality governed by regex filters
Synthesis Stage S crystallization, grouped by source memory LLM mode via KAIROS_SYNTHESIS_LLM=1
DAE Graph-weighted second embedding recompute Every N NREM cycles; batch chunked

🔧 Tools (MemoryProvider)

Kairos registers 38+ tools via Hermes MemoryProvider: kairos_remember, kairos_recall, kairos_think, kairos_graph, kairos_reasoning, kairos_profile, kairos_dream_*, metadata catalog tools, and more.

📊 Metadata Catalog

Semantic search over database schemas, tables, columns, and business terms — imported from BigQuery, SQL databases, or YAML definitions.


Dream Engine Auto-Trigger

Dream daemon runs automatically as background thread in the leader session. Auto-trigger based on:

  • idle_threshold — seconds without activity before trigger (default: 300, from dream_engine.py)
  • memory_threshold — new memories before trigger (default: 50, from dream_engine.py)

Configure via kairos_dream_config():

kairos_dream_config(action="set", idle_threshold=7200, memory_threshold=10)

No cron job, no SSE server, no external process. Single daemon holds the lock; all sessions share it.


Storage Backends

Backend Type Status
Akar Embedded graph (pure Rust; import kuzuimport akar) The only backend — graph + vector index

SQLite and PostgreSQL/Supabase were removed (2026-08-21). In daemon mode, graph DB failure fails loud — no silent fallback to an empty store.


Project Structure

kairos/
├── kairos/                        # Python package utama
│   ├── plugin.py                  # NeuralMemoryProvider — Hermes adapter (daemon mode)
│   ├── __init__.py                # Re-export ringan (Kairos, Memory, NeuralMemoryProvider)
│   ├── engine.py                  # Kairos API — unified entry point
│   ├── cache.py                  # Cache via diskcache (Redis dihapus — diskcache only)
│   ├── disk_fallback.py           # DiskCacheDomain wrapper
│   ├── mcp_schemas.py             # Tool schemas — single source of truth
│   ├── kuzu_client.py             # KuzuClientStore + daemon IPC (daemon mode)
│   ├── kuzu_ipc.py                # JSON framing (u32-LE length prefix)
│   ├── kuzu.py                    # Shim: `import kuzu` → `import akar`
│   ├── akar_store.py              # GraphStore (Akar) embedded mode
│   ├── dream_engine.py            # 7-phase dream consolidation
│   ├── dream_akar_store.py        # Akar dream backend
│   ├── dream_leader.py            # Cross-process leader election (advisory lock)
│   ├── config.py                  # Config helpers
│   ├── afe.py                     # Atomic Fact Extraction
│   ├── dae.py                     # Dream-Augmented Embeddings
│   ├── synthesis.py               # LLM synthesis (reasoning)
│   ├── profile_extractor.py       # User profile management
│   ├── sync_store.py              # Cross-backend sync
│   ├── embed_provider.py          # Embedding backends
│   └── ...                        # Other support files
├── hermes-plugin/                 # Hermes skin plugin (TUI display) — NOT memory provider
│   ├── __init__.py                # import + register dari kairos.plugin
│   ├── plugin.yaml                # Plugin manifest (name: kairos)
│   └── neural_skin.yaml           # Hermes UI skin
├── docs/                          # Documentation
│   ├── ARCHITECTURE.md            # Canonical architecture (this is the source of truth)
│   └── references/                # Historical/reference notes
├── tools/
│   ├── deploy-kairos-provider.ps1 # One-command Hermes adapter deployment
│   └── kairos_doctor.py           # Read-only triage: sidecar, daemon, locks, backups
├── tests/
│   └── test_suite.py              # Test suite
└── pyproject.toml                 # Package metadata + dependencies

Hermes Adapter Plugin

The memory provider adapter lives at $HERMES_HOME/plugins/kairos/ (NOT under plugins/memory/):

$HERMES_HOME/plugins/kairos/
├── __init__.py          # Thin entry: from kairos.plugin import NeuralMemoryProvider; register()
├── plugin.yaml          # Metadata + pip_dependencies: [kairos-memory]
└── cli.py               # CLI: hermes kairos status|stats|dream

Deployment

# One-command deploy (installs package, creates adapter, cleans legacy)
.\tools\deploy-kairos-provider.ps1

CLI Commands

hermes kairos status          # Engine summary (backend, memories, connections, embedding, dream phase)
hermes kairos stats [--pretty|--no-pretty]  # Full JSON engine stats
hermes kairos dream status|pause|resume|force-nrem|force-rem  # Dream Engine control

All CLI commands use daemon RPC (via kuzu_ipc) — they never spawn an engine or touch the DB directly.

Desktop UI Config

Kairos appears in Hermes Desktop → Settings → Memory Provider with fields:

  • db_path (text, default: ~/.kairos/engine/vela.db)
  • embedding_backend (select: auto, hash, tfidf, sentence-transformers)

MCP Server (stdio)

Separate stdio MCP server at kairos_mcp_stdio.py — runs as independent process, also uses daemon mode:

# kairos_mcp_stdio.py initialize():
os.environ["KAIROS_KUZU_MODE"] = "daemon"
os.environ["KAIROS_NO_FALLBACK"] = "1"

Tools exposed: kairos_remember, kairos_recall, kairos_think, kairos_graph, kairos_reasoning, kairos_profile, kairos_dream_*, metadata catalog tools.

Backup: Supabase/Postgres sync removed (2026-08-21). For version-safe backup use kairos_backup_local (daemon EXPORT DATABASE op) — see docs/ARCHITECTURE.md §8.


Observability & Troubleshooting

Health Check

# Via tool (plugin)
kairos_health
# → {status, backend, memories, connections, embedding_dim, storage: {daemon_pid, sidecar_age, ...}}

# Via CLI (daemon RPC)
hermes kairos stats

Daemon Status

# Cek proses daemon
Get-CimInstance Win32_Process -Filter "Name LIKE 'akar_server%'"

# Cek sidecar
Get-Content "$env:USERPROFILE\.kairos\engine\vela.db.daemon.json" | ConvertFrom-Json

# Cek log daemon
Get-Content "$env:USERPROFILE\.kairos\engine\vela.db.daemon.log" -Tail 50

Doctor Script (Comprehensive Triage)

python tools/kairos_doctor.py
# → healthy  OR  "1 issue(s) found: UNREACHABLE/STALE/LOCK_HELD"

Checks: sidecar liveness, daemon reachability, spawn/leader locks, backup freshness.

Common Issues

Symptom Cause Fix
memories: 0 but DB 40MB graph DB version mismatch Use logical export/import; check kairos_doctor.py
Could not set lock on file Stale lock / zombie daemon Remove-Item vela.db.daemon.lock -Force; kill zombie python; restart
hermes kairos status → 0 memories DB path not configured correctly Check ~/.hermes/config.yamlmemory.kairos.db_path
Dream not running Leader election stuck Check vela.db.dream.leader.lock; kairos_dream_control resume

License

Business Source License 1.1View License

  • Non-commercial use: free
  • Commercial use: requires a paid license
  • After 2030-01-01: automatically converts to Apache 2.0

Forks & Attribution

Kairos was forked from Mazemaker and evolved independently with:

  • Akar (pure Rust) as the primary backend (embedded, no Docker)
  • Complete Dream Backend for all store types
  • Daemon-first architecture — single akar_server holds exclusive lock
  • Hermes MemoryProvider adapter plugin (thin, imports from package)
  • Auto-trigger dream daemon (no cron job)
  • Storage hardening: bounded retries, no silent fallbacks, backup-as-daemon-op, WAL crash fix, observability (stat op, kairos_health storage section, kairos_doctor)
  • Cleaned architecture, no license gates

Built with ❤️ for the Indonesian AI ecosystem.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kairos_memory-1.0.2.tar.gz (310.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kairos_memory-1.0.2-py3-none-any.whl (320.7 kB view details)

Uploaded Python 3

File details

Details for the file kairos_memory-1.0.2.tar.gz.

File metadata

  • Download URL: kairos_memory-1.0.2.tar.gz
  • Upload date:
  • Size: 310.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for kairos_memory-1.0.2.tar.gz
Algorithm Hash digest
SHA256 333d5f5e6d7bed2328d1527a1403771a903445a3ff0b5728b06940af0a50bd27
MD5 e9a5e0365403222f2ba3f242496aba40
BLAKE2b-256 f1b9469ca3c2b0ed5f84bd259297e21db300a4632ef46311fe1e1cbbd80b81b3

See more details on using hashes here.

File details

Details for the file kairos_memory-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: kairos_memory-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 320.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for kairos_memory-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 54f19c8cb561e03d1da4ea05c3fabef9677213b58795b5e55e48392265a798cf
MD5 4c821c675c08a74595f5598ca756ff59
BLAKE2b-256 98deca691bc8b8070a655d0d77e2e8ece0db40395ab2211c09c30811667dca8c

See more details on using hashes here.

Release history Release notifications | RSS feed

1.0.3

2 files

This release

1.0.2 This release

2 files

1.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page