<div align="center">

# 🐑 evaOS (Electric Sheep)

**AI memory that remembers who you are.**

[![PyPI version](https://img.shields.io/pypi/v/evaos.svg)](https://pypi.org/project/evaos/)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://python.org)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Tests](https://img.shields.io/github/actions/workflow/status/100yenadmin/electric-sheep/ci.yml?label=tests)](https://github.com/100yenadmin/electric-sheep/actions)

*Identity-preserving memory engine for AI agents.  
Your agent wakes up tomorrow and still knows who it is.*

</div>

---

## What's New in v1.2

🚀 **v1.2** is the cognitive pipeline release — a complete memory lifecycle from wake to sleep, with intelligent retrieval, context compilation, and production observability.

- **Session Boot Loader** — Deterministic boot sequence loads continuity context (handoff, identity, commitments, preferences) at session start
- **Task-Mode Classification** — Zero-LLM query classification into 8 task modes (debug, plan, write, recall, etc.) for intelligent retrieval routing
- **Retrieval Policy Engine** — Task-mode-driven channel selection: which retrieval channels to query, with what budget weights
- **Context Compiler** — Assembles retrieval results into injection-ready bundles with strict token budgeting and priority-based compression
- **Injection Slot Manager** — Deterministic assignment of compiled bundles to prompt positions (system prefix → post-system → pre-user → appendix)
- **Mid-Turn Re-Retrieval** — Detects topic shifts and new entities mid-conversation, triggering supplemental memory retrieval
- **Working Memory Cache** — Fast in-memory session store with LRU eviction and TTL, checked before DB queries
- **Token Budget Overhaul** — Context-window-fraction budgeting, slot-priority allocation, and multi-level compression (evidence → compact → pointer)
- **Promotion Scoring** — Six-factor weighted scoring for session → long-term memory promotion during sleep
- **Model Routing** — Three-tier model routing (fast/main/reasoning) with operation-to-tier mapping and fallback chains
- **Metrics & Quality Gates** — Pipeline observability with counters, histograms, gauges, and threshold-based quality gates
- **Feature Flags** — Deterministic hash-based feature gating for gradual rollout control
- **Circuit Breaker** — Per-provider circuit breaker for quota/rate-limit resilience (reads continue when writes are blocked)

See the [CHANGELOG](CHANGELOG.md) for the full list of changes, and the [v1.2 documentation](docs/v1.2/) for architecture deep-dives.

---

## Why evaOS?

Most AI memory systems are glorified vector stores. They dump embeddings into a database and call it "memory." The result: **progressive identity drift** (your agent slowly forgets who it is), **junk accumulation** (10,000 useless coding-session memories), and **no lifecycle** (no consolidation, no forgetting, no sleep).

evaOS is a cognitive memory engine grounded in memory research. It extracts claims, resolves entities, protects core identity, and runs dream cycles to consolidate and prune — just like biological memory.

---

## Install

```bash
pip install evaos
```

With vector search (recommended):
```bash
pip install "evaos[vec]"
```

All extras (LLM providers, HTTP API, MCP server):
```bash
pip install "evaos[all]"
```

---

## 30-Second Quickstart

**CLI:**

```bash
# Initialize a new memory store
evaos init

# Teach it something
evaos remember "Andrew is the founder of 100Yen Org. He lives in Bangkok."

# Ask it later
evaos recall "Where does Andrew live?"
# → Andrew lives in Bangkok. He is the founder of 100Yen Org.

# Ask your memory (Dialectic Engine — new in v1.1)
evaos ask "What do I know about Andrew's work?"
# → Multi-step reasoning across your memory graph
```

**Python SDK:**

```python
import asyncio
from evaos import Cortex

async def main():
    cortex = Cortex(db_path="my_memory.db", profile="companion")
    await cortex.initialize()

    # Start a session
    await cortex.wake(session_id="session_001")

    # Store information — claim extraction happens automatically
    await cortex.remember("Andrew is the founder of 100Yen Org. He lives in Bangkok.")

    # Retrieve relevant memories for an LLM prompt
    context = await cortex.retrieve("Where does Andrew live?")
    print(context.context_block)
    # → "Andrew lives in Bangkok. He is the founder of 100Yen Org."

    # End the session
    await cortex.sleep(session_id="session_001")

asyncio.run(main())
```

That's it. Memories persist in a local SQLite database, searchable via hybrid BM25 + vector retrieval.

---

## Features

### 🧠 5-Layer Memory Model

| Layer | What It Does |
|-------|-------------|
| **Extraction** | LLM-powered claim extraction with noise filtering (skips "changed line 47 of auth.py") |
| **Entity Resolution** | Fuzzy deduplication — "Andrew", "andrew", "@andrew" → same person |
| **Reconciliation** | Smart conflict resolution: ADD / UPDATE / SUPERSEDE / NOOP |
| **Cornerstones** | Immutable identity anchors that resist drift and accidental deletion |
| **Token Budget** | Assembles memory context within configurable token ceilings |

### 🌙 Dream Cycles & Staged Sleep Pipeline

Circadian engine with sleep/wake/dream phases. The **staged sleep pipeline** (S1→S2→S3→S4) consolidates session memories, promotes important claims, builds handoff packets for session continuity, and carries forward open loops. During dream cycles, evaOS runs Ebbinghaus decay, calculates identity drift, and generates curiosity seeds.

### 📋 Commitments & Open Loops *(v1.2)*

First-class tracking of agent commitments and unresolved threads. Commitments track promises with due dates. Open loops track dangling threads across sessions. Stale loops auto-resolve after 5 cycles. Both inject into session boot context for continuity.

### ⚡ Activation Routing *(v1.2)*

Wake pipeline (W1–W4) enriches memories with activation metadata — intrinsic type, stability, explicitness — and writes structured activation policies. Zero LLM cost. Enables intelligent memory surfacing based on context, not just similarity.

### 💬 Dialectic Engine *(v1.1)*

Ask your memory natural-language questions. Fast path for simple lookups, agentic multi-step QueryPlanner for complex reasoning across your memory graph.

### 👥 Peer Modeling *(v1.1)*

Track relationships between entities. Auto-creates peer records from entity resolution, builds relationship representations, and integrates with dream cycles for periodic peer refresh.

### 🕸️ Brain Graph

File-watcher + auto-registration document memory graph. Index your docs, specs, and decisions — query them alongside conversational memory.

### 📊 Graph Visualization *(v1.1)*

Force-directed graph data endpoints for visualizing memory relationships: nodes, edges, paths, and neighbors.

### 🖥️ Dashboard *(v1.1)*

8-page web UI for exploring your memory engine: memories, entities, cornerstones, peers, brain graph, events, configuration, and health status.

### 🔔 Webhooks *(v1.1)*

Subscribe to 16 event types with reliable webhook delivery, automatic retry, and event filtering.

### 🔍 Hybrid Retrieval

BM25 full-text search + vector similarity with Reciprocal Rank Fusion. Optional agentic re-ranking for high-stakes queries.

### 🛡️ Resilience *(v1.1)*

- LLM retry with exponential backoff and provider cascade
- Embedding model switch protection (prevents silent vector corruption)
- API key redaction in all log output
- SQLite integrity checks on startup
- 40 write locks, NaN validation, OOM protection

### 🔌 Five Interfaces

| Interface | Use Case |
|-----------|----------|
| **CLI** | `evaos remember`, `evaos recall`, `evaos ask`, `evaos dream` |
| **HTTP API** | FastAPI REST server — `evaos serve` |
| **MCP Server** | Model Context Protocol for agent frameworks — `evaos mcp` |
| **TypeScript SDK** | `@evaos/client` — typed client for Node.js applications |
| **OpenClaw Plugin** | `eva-memory` — drop-in memory plugin for OpenClaw agents |

---

## Python SDK Reference

The `Cortex` class is the recommended way to embed evaOS memory into Python applications.

```python
from evaos import Cortex

# Default — uses OpenAI, stores in cortex.db
cortex = Cortex()

# Customised
cortex = Cortex(
    db_path="~/my_app/memory.db",
    profile="companion",       # companion | developer | local | minimal
    llm_provider="openai",     # openai | anthropic | ollama
    extract_model="gpt-4.1-nano-2025-04-14",
    embed_model="text-embedding-3-small",
)

# From a config file
cortex = Cortex.from_config("~/.config/cortex.toml")
```

### Core methods

| Method | Description |
|--------|-------------|
| `await cortex.initialize()` | Initialize storage + apply migrations |
| `await cortex.wake(session_id)` | Start a session, load cornerstones |
| `await cortex.remember(content)` | Store text/conversation; extraction is automatic |
| `await cortex.retrieve(query)` | Hybrid BM25 + vector search, returns context block |
| `await cortex.ask(query)` | Dialectic engine — ask your memory questions |
| `await cortex.sleep(session_id)` | End session, trigger consolidation |
| `await cortex.dream()` | Run overnight reconsolidation cycle manually |
| `await cortex.seal_cornerstone(label, content)` | Pin an identity anchor |
| `await cortex.check_drift()` | Drift scores for all cornerstones |
| `await cortex.feedback(claim_id, "helpful")` | Rate a retrieved memory |
| `await cortex.health()` | System health dict |
| `await cortex.stats()` | Memory counts (claims, entities, cornerstones, sessions) |
| `await cortex.export(format="json")` | Export all active memories |

---

## TypeScript SDK

```bash
npm install @evaos/client
```

```typescript
import { CortexClient } from '@evaos/client';

const client = new CortexClient({
  baseUrl: 'http://localhost:8420',
  apiKey: 'your-api-key',
});

// Store a memory
await client.remember('Andrew is the founder of 100Yen Org.');

// Retrieve memories
const results = await client.recall('Who is Andrew?');
console.log(results.context_block);
```

See [`sdks/typescript/`](sdks/typescript/) for full documentation.

---

## OpenClaw Plugin

evaOS ships an [OpenClaw](https://openclaw.com) plugin (`eva-memory`) that bridges your agent's memory to a running Cortex instance. Drop it into your OpenClaw setup for automatic memory recall and capture.

```jsonc
// openclaw.plugin.json (included in openclaw-plugin/)
{
  "id": "eva-memory",
  "kind": "memory"
  // configSchema: cortexUrl, apiKey, ownerId, autoRecall, autoCapture, ...
}
```

**What it does:**
- **before_agent_start** — retrieves relevant memories and injects them into context
- **agent_end** — captures conversation content as new memories (fire-and-forget)
- **session_start / session_end** — calls wake/sleep for session lifecycle
- **Tools exposed:** `cortex_search`, `cortex_remember`, `cortex_forget`

See [`openclaw-plugin/`](openclaw-plugin/) for the full source and configuration schema.

---

## Architecture

### Full Pipeline: Wake → Boot → Retrieve → Compile → Inject → Re-Retrieve → Sleep

```
 ┌──────────────────── SESSION LIFECYCLE ────────────────────┐
 │                                                           │
 │  WAKE                    MID-TURN                  SLEEP  │
 │  ════                    ════════                  ═════  │
 │                                                           │
 │  ┌─────────┐  ┌──────────────┐  ┌────────────────────┐   │
 │  │  Wake   │  │   Retrieve   │  │   Sleep Pipeline   │   │
 │  │ Pipeline│  │   Pipeline   │  │  S1 Consolidation  │   │
 │  │ W1→W4   │  │  BM25+Vector │  │  S2 Promotion      │   │
 │  └────┬────┘  │  +RRF+Rerank │  │  S3 Handoff        │   │
 │       │       └───────┬──────┘  │  S4 Carry-Forward   │   │
 │       ▼               │         └────────────────────┘   │
 │  ┌─────────┐          │                ▲                  │
 │  │  Boot   │          ▼                │                  │
 │  │ Loader  │  ┌───────────────┐  ┌─────┴──────┐          │
 │  │ (hand-  │  │Task-Mode      │  │ Circadian  │          │
 │  │  off,   │  │Classifier     │  │ Engine     │          │
 │  │  identity│ └───────┬───────┘  │ (dream,    │          │
 │  │  prefs) │          │          │  decay)     │          │
 │  └────┬────┘          ▼          └────────────┘          │
 │       │       ┌───────────────┐                           │
 │       │       │Retrieval      │                           │
 │       │       │Policy Engine  │                           │
 │       │       └───────┬───────┘                           │
 │       │               │                                   │
 │       │               ▼                                   │
 │       │       ┌───────────────┐  ┌───────────────┐       │
 │       │       │   Context     │  │ Re-Retrieval  │       │
 │       │       │   Compiler    │◄─│ (topic shift,  │       │
 │       │       │ (bundle +     │  │  new entities) │       │
 │       │       │  compress)    │  └───────────────┘       │
 │       │       └───────┬───────┘                           │
 │       │               │                                   │
 │       │               ▼                                   │
 │       │       ┌───────────────┐                           │
 │       └──────►│  Injection    │                           │
 │               │  Slot Manager │                           │
 │               │ (prompt       │                           │
 │               │  assembly)    │                           │
 │               └───────────────┘                           │
 └───────────────────────────────────────────────────────────┘

 ┌──────────────── CROSS-CUTTING SERVICES ──────────────────┐
 │                                                           │
 │  Working Memory Cache    Token Budget Manager             │
 │  Model Router (3-tier)   Promotion Scorer (6-factor)      │
 │  Metrics Collector       Quality Gates                    │
 │  Feature Flags           Circuit Breaker                  │
 │  Feedback System         Contradiction Tracker            │
 │                                                           │
 └───────────────────────────────────────────────────────────┘

 ┌──────────────────── INFRASTRUCTURE ──────────────────────┐
 │                                                           │
 │  ┌──────────┬──────────┬──────────┬────────────────┐     │
 │  │   CLI    │ HTTP API │   MCP    │  TypeScript SDK │     │
 │  └──────────┴──────────┴──────────┴────────────────┘     │
 │  ┌──────────────────────────────────────────────────┐     │
 │  │  Extraction │ Entity Res. │ Reconciliation       │     │
 │  ├──────────────────────────────────────────────────┤     │
 │  │  Cornerstones │ Drift Calc │ Dialectic Engine    │     │
 │  ├──────────────────────────────────────────────────┤     │
 │  │  Peer Modeling │ Brain Graph │ Webhooks/Events   │     │
 │  ├──────────────────────────────────────────────────┤     │
 │  │  Commitments │ Open Loops │ Activation Router    │     │
 │  ├──────────────────────────────────────────────────┤     │
 │  │          SQLite + FTS5 + sqlite-vec              │     │
 │  └──────────────────────────────────────────────────┘     │
 └───────────────────────────────────────────────────────────┘
```

---

## Configuration

evaOS uses a `cortex.toml` config file:

```toml
[cortex]
storage_backend = "sqlite"

[cortex.storage]
db_path = "evaos.db"

[cortex.extraction]
model = "gpt-4.1-nano"
coding_noise_filter = true

[cortex.cornerstones]
max_count = 7
drift_threshold = 0.05

[cortex.circadian]
dream_cycle_enabled = true
dream_cycle_hour_utc = 8
auto_sleep_after_minutes = 30

[cortex.deprecation]
forgetting_curve = "ebbinghaus"
```

See [`docs/`](docs/) for full configuration reference and architecture deep-dives.

### v1.2 Documentation

| Document | Description |
|----------|-------------|
| [Architecture Overview](docs/v1.2/architecture-overview.md) | Full v1.2 pipeline walkthrough |
| [Config Reference](docs/v1.2/config-reference.md) | All new TOML fields with defaults and validation rules |
| [Integration Guide](docs/v1.2/integration-guide.md) | Developer guide for configuring and extending v1.2 subsystems |
| [Working Memory API](docs/v1.2/working-memory-api.md) | Working memory cache API reference |
| [Token Budget API](docs/v1.2/token-budget-api.md) | Token budget manager API reference |
| [Promotion Scoring API](docs/v1.2/promotion-scoring-api.md) | Multi-factor promotion scoring API reference |
| [Model Routing API](docs/v1.2/model-routing-api.md) | Three-tier model routing API reference |
| [Changelog](docs/v1.2/changelog-v1.2.md) | Sprint-by-sprint changelog for v1.2 |

---

## CLI Reference

```bash
evaos init [--profile companion|coding|enterprise]
evaos remember "text"
evaos recall "query"
evaos ask "question"                    # Dialectic engine (v1.1)
evaos ask "question" --agentic          # Multi-step reasoning
evaos cornerstones list
evaos cornerstones seal --label "name" --content "text"
evaos dream
evaos stats
evaos health
evaos export [--format json|sql]
evaos serve [--port 8000]
evaos mcp
evaos backup [--output path]
```

---

## Dashboard

evaOS includes a built-in web dashboard for exploring and managing your memory engine.

```bash
evaos serve
# Dashboard available at http://localhost:8420/dashboard
```

**Pages:** Memories · Entities · Cornerstones · Peers · Brain Graph · Events · Config · Health

---

## Project Structure

```
cortex/                 # 148 Python modules | ~52K lines
├── core/               # Extraction, entity resolution, reconciliation, retrieval, contradictions,
│                       #   working memory, token budget, promotion, task-mode, retrieval policy,
│                       #   context compiler, injection slots, boot loader, re-retrieval,
│                       #   metrics, quality gates, feature flags
├── storage/            # SQLite adapter with FTS5 + vector support, 11 query mixins, v3-v9 migrations
├── brain_graph/        # Document memory graph with file watching
├── circadian/          # Sleep/wake/dream cycle engine (CircadianEngine + CuriosityEngine)
├── sleep/              # Staged sleep pipeline: S1 consolidation → S2 promotion → S3 handoff → S4 carry-forward
├── capture/            # Wake pipeline: W1-W4 activation routing, episode adapter
├── commitments/        # Commitment/open loop tracking + carry-forward
├── deprecation/        # Ebbinghaus decay pipeline
├── identity/           # Cornerstone guardian + drift calculator
├── config/             # TOML config loading + profiles
├── api/                # FastAPI HTTP server (85 endpoints), 18 route modules
├── integrations/       # MCP server (15 tools) + plugin interface
├── dialectic/          # Dialectic engine (ask your memory)
├── peers/              # Peer modeling (relationship tracking)
├── events/             # Event emitter + webhook dispatcher
├── llm/                # Multi-provider LLM abstraction with fallback
├── cli.py              # Click-based CLI (1,360 lines)
├── sdk.py              # High-level Cortex class for external consumers
└── types.py            # Shared dataclasses and types

dashboard/              # 8-page web UI (SPA)
sdks/typescript/        # @evaos/client TypeScript SDK
openclaw-plugin/        # eva-memory OpenClaw plugin (TypeScript)
```

---

## Benchmarks

evaOS ships a benchmark suite that measures core operation latency and throughput.
All benchmarks use **mocked LLM/embedding providers** — we measure evaOS code performance, not API latency.

### Run benchmarks

```bash
# Full suite (retrieval at 10K scale takes ~2-3 min)
python -m benchmarks.run_benchmarks

# Skip slow 10K retrieval during development
python -m benchmarks.run_benchmarks --skip-retrieval

# Individual suites
python -m benchmarks.bench_retrieval
python -m benchmarks.bench_remember
python -m benchmarks.bench_consolidation
```

Results are saved to `benchmarks/results/latest.json`.

### What's measured

| Suite | What | Scales |
|---|---|---|
| `bench_retrieval` | vector search, FTS (BM25), hybrid RRF | 100 / 1k / 10k claims |
| `bench_remember` | extract + embed + store pipeline | single / batch 10 / batch 50 |
| `bench_consolidation` | `sleep()` consolidation pass | 100 / 500 / 1k claims |

Metrics: **p50 / p95 / p99 latency in ms**, 50 runs per measurement (10 for consolidation).
Vectors: 1024-dim, deterministic seed=42.

---

## Docker

Run evaOS as a container — no Python setup required.

### Quick start

```bash
# Clone the repo (or just grab the docker-compose.yml)
git clone https://github.com/100yenadmin/electric-sheep.git
cd electric-sheep

# Set your API keys
export OPENAI_API_KEY=sk-...
export VOYAGE_API_KEY=pa-...

# Start the server
docker compose up -d
```

The HTTP API is now available at `http://localhost:8420`.

### Build the image manually

```bash
docker build -t evaos .
docker run -d \
  -p 8420:8420 \
  -v evaos-data:/data \
  -e OPENAI_API_KEY=$OPENAI_API_KEY \
  -e VOYAGE_API_KEY=$VOYAGE_API_KEY \
  evaos
```

### Environment variables

| Variable | Default | Description |
|---|---|---|
| `CORTEX_DB_PATH` | `/data/cortex.db` | Path to the SQLite database |
| `CORTEX_API_KEY` | _(none)_ | API key to protect the HTTP server |
| `OPENAI_API_KEY` | _(none)_ | OpenAI API key for LLM operations |
| `OPENAI_BASE_URL` | _(none)_ | Custom OpenAI-compatible base URL |
| `VOYAGE_API_KEY` | _(none)_ | Voyage AI key for embeddings |

### Persistent storage

The container stores `cortex.db` in `/data` by default. The `docker-compose.yml` creates a named volume (`evaos-data`) that survives container restarts and updates.

### Health check

```bash
curl http://localhost:8420/api/v1/health
```

The container exposes a built-in healthcheck on the same endpoint (30s interval, 5s timeout, 3 retries).

---

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup, testing, and PR guidelines.

---

## License

[MIT](LICENSE) — 100Yen Org
