Metadata-Version: 2.4
Name: memos-os
Version: 2.3.10
Summary: Memory Operating System for LLM Agents — persistent, smart, local-first memory
Author-email: Mars375 <proto.labs.rnd@gmail.com>
License: MIT
Keywords: llm,agent,memory,rag,vector-search
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.25
Requires-Dist: cryptography>=42.0
Provides-Extra: local
Requires-Dist: sentence-transformers>=2.7; extra == "local"
Provides-Extra: chroma
Requires-Dist: chromadb>=0.4; extra == "chroma"
Provides-Extra: qdrant
Requires-Dist: qdrant-client>=1.17.1; extra == "qdrant"
Provides-Extra: pinecone
Requires-Dist: pinecone-client>=3.0; extra == "pinecone"
Provides-Extra: parquet
Requires-Dist: pyarrow>=12.0; extra == "parquet"
Provides-Extra: server
Requires-Dist: fastapi>=0.104; extra == "server"
Requires-Dist: uvicorn>=0.44.0; extra == "server"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: httpx; extra == "dev"
Requires-Dist: ruff==0.15.12; extra == "dev"
Requires-Dist: freezegun>=1.5.1; extra == "dev"
Requires-Dist: pyarrow>=12.0; extra == "dev"
Dynamic: license-file

# MemOS — Memory Operating System for AI Agents

> Persistent, structured, self-maintaining memory for any LLM agent.
> Local-first. Framework-agnostic. Connects via MCP to Claude Code, OpenClaw, Cursor, or any HTTP client.

[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://python.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Version](https://img.shields.io/badge/version-v2.3.10-purple.svg)](https://github.com/Mars375/memos/releases)
[![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](https://github.com/Mars375/memos/actions)
[![CI](https://github.com/Mars375/memos/actions/workflows/test.yml/badge.svg)](https://github.com/Mars375/memos/actions/workflows/test.yml)
[![Docker](https://github.com/Mars375/memos/actions/workflows/docker.yml/badge.svg)](https://github.com/Mars375/memos/actions/workflows/docker.yml)
[![PyPI](https://img.shields.io/pypi/v/memos-os.svg)](https://pypi.org/project/memos-os/)

---

## What's new in v2.3.10

- **Lean Docker image** — the official image omits the optional local embedding stack that pulled Torch/CUDA wheels into runtime builds
- **Faster Docker CI** — dependency wheels are cached before project source is copied, PRs run a real smoke image, and Buildx cache uses a trusted scope
- **Smaller runtime context** — `.dockerignore` keeps repository-only files out of Docker builds while preserving the non-root `/data/.memos` runtime contract
- **Validation** — lint, Python 3.11/3.12/3.13 tests, and Docker build checks are green

See [CHANGELOG.md](CHANGELOG.md) for full history.

---

## Installation

```bash
pip install memos-os
```

With local semantic recall (no external services):
```bash
pip install "memos-os[local]"    # sentence-transformers, backend="local"
```

With vector backend (recommended for production):
```bash
pip install "memos-os[chroma]"   # ChromaDB + Ollama embeddings
pip install "memos-os[qdrant]"   # Qdrant
pip install "memos-os[chroma,qdrant,pinecone,parquet,server]"  # full stack
```

---

## Quick start

```bash
# Store a memory
memos learn "FastAPI is better than Flask for async workloads" --tags python,backend

# Search semantically
memos recall "which web framework should I use?"

# Start the REST API + dashboard
memos serve --port 8100
# → http://localhost:8100/dashboard
```

---

## Golden path

The full lifecycle from storing a memory to maintaining it over time.

```python
from memos import MemOS
from memos.context import ContextStack
from memos.kg_bridge import KGBridge

mem = MemOS(backend="chroma", embed_host="http://localhost:11434")
cs = ContextStack(mem)
bridge = KGBridge(mem)

# 1. Learn — store memories with tags and importance
mem.learn("User prefers dark mode in all apps", tags=["preference", "ui"], importance=0.8)
mem.learn("Deploy with Docker on ARM64 homelab", tags=["devops", "docker"], importance=0.6)
mem.learn("Alice leads the backend team", tags=["team", "people"], importance=0.7)

# 2. Recall — semantic search
results = mem.recall("who handles the server side?", top=3)
for r in results:
    print(f"[{r.score:.2f}] {r.item.content}")
# [0.91] Alice leads the backend team (tags: team, people)

# 3. context_for — targeted context for a specific LLM call
ctx = cs.context_for("how should I deploy this app?", max_chars=1500, top=5)
# Returns a string with identity + relevant memories:
# === RELEVANT MEMORIES (2 results for: 'how should I deploy this app?') ===
# [0.87] Deploy with Docker on ARM64 homelab (tags: devops, docker)

# 4. wake_up — inject at session start
prompt_fragment = cs.wake_up(max_chars=2000, l1_top=15, include_stats=True)
# Returns L0 identity + L1 top-importance memories as a string
# ready to paste into a system prompt

# 5. Reinforce and decay — keep memories healthy over time
# Reinforce useful memories via the public CLI / MCP surface
# and prune stale ones via the public maintenance API.
preview = mem.prune(threshold=0.1, dry_run=True)
print(f"{len(preview)} memories would be pruned")

# When ready: apply the cleanup
removed = mem.prune(threshold=0.1)
print(f"Pruned {len(removed)} stale memories")
```

---

## Python SDK

```python
from memos import MemOS

# In-memory (zero dependencies, great for testing)
mem = MemOS()

# JSON persistence
mem = MemOS(backend="json", persist_path="~/.memos/store.json")

# Local-first semantic recall, no Ollama/Chroma required
mem = MemOS(backend="local", persist_path="~/.memos/store.json")

# ChromaDB with local Ollama embeddings
mem = MemOS(backend="chroma", embed_host="http://localhost:11434")

# Qdrant
mem = MemOS(backend="qdrant", qdrant_path="/data/memos")

# Store
mem.learn("User prefers dark mode", tags=["preference", "ui"], importance=0.8)

# Recall
results = mem.recall("what does the user like?", top=5)
for r in results:
    print(f"[{r.score:.2f}] {r.item.content}")

# Forget
mem.forget("memory-id")           # by id
mem.delete_tag("old-project")     # remove this tag from all memories
mem.forget_tag("old-project")     # delete all memories carrying this tag
mem.prune(threshold=0.2)          # decay-based cleanup

# Stats
s = mem.stats()
# MemoryStats(total_memories=142, avg_relevance=0.71, decay_candidates=8)
```

---

## Which recall API should I use?

| Function | Best for | Returns | When NOT to use |
|----------|----------|---------|-----------------|
| `mem.recall()` | General search, browsing results | `list[RecallResult]` with scores | You need a ready-made prompt string |
| `memory_search` (MCP) | Same as `recall()`, but over MCP | JSON via MCP protocol | You're using the Python SDK directly |
| `context_for()` | Augmenting a single LLM call | `str` (identity + top results) | You need structured data to process |
| `recall_enriched()` | Answers needing entity context | `dict` with memories + KG facts | No KG data exists or entity resolution isn't needed |

```python
from memos.context import ContextStack
from memos.kg_bridge import KGBridge

cs = ContextStack(mem)
bridge = KGBridge(mem)

# recall() — structured results you iterate over
results = mem.recall("docker deployment", top=5)
for r in results:
    print(r.item.content, r.score)

# context_for() — one string, ready for a system prompt
ctx = cs.context_for("docker deployment", max_chars=1000, top=5)

# recall_enriched() — memories + knowledge graph facts in one dict
enriched = bridge.recall_enriched("who is Alice?", top=5, min_score=0.3)
print(enriched["facts"])       # KG triples about Alice
print(enriched["memory_count"])
```

---

## MCP — connect any agent

MemOS exposes a universal MCP endpoint. Any agent that speaks MCP can use it without any code changes.

### HTTP (recommended)

**Claude Code** — add to `~/.claude.json`:
```json
{
  "mcpServers": {
    "memos": { "type": "http", "url": "http://localhost:8100/mcp" }
  }
}
```

**OpenClaw** — add to `~/.openclaw/openclaw.json`:
```json
{
  "mcp": {
    "servers": {
      "memos": { "type": "http", "url": "http://localhost:8100/mcp" }
    }
  }
}
```

**Any MCP client** — `POST http://localhost:8100/mcp` with JSON-RPC 2.0 body.

Discovery: `GET http://localhost:8100/.well-known/mcp.json`

### Stdio (Claude Code local)

```json
{
  "mcpServers": {
    "memos": { "command": "memos", "args": ["mcp-stdio"] }
  }
}
```

Or run standalone: `memos mcp-serve --port 8200`

### Available MCP tools

| Tool | Description |
|------|-------------|
| `memory_search` | Semantic search — `query`, `top_k`, `tags` |
| `memory_save` | Store a memory — `content`, `tags`, `importance` |
| `memory_forget` | Delete by `id` or `tag` |
| `memory_stats` | Counts, avg importance, decay candidates |
| `memory_wake_up` | Identity + top memories ready to inject at session start |
| `memory_context_for` | Context optimised for a specific query |
| `memory_decay` | Run decay cycle (dry-run by default) |
| `memory_reinforce` | Boost a memory's importance score |
| `kg_add_fact` | Add a temporal triple to the Knowledge Graph |
| `kg_query_entity` | All active facts for an entity |
| `kg_timeline` | Chronological fact history for an entity |
| `memory_recall_enriched` | Memories + KG facts in one call |

---

## REST API

Start the server: `memos serve --port 8100`

Interactive docs: `http://localhost:8100/docs`

```
POST   /api/v1/learn                Store a memory
POST   /api/v1/learn/batch          Bulk store
POST   /api/v1/recall               Semantic search
GET    /api/v1/recall/stream        SSE streaming recall
GET    /api/v1/search               Keyword search
GET    /api/v1/stats                Memory statistics
GET    /api/v1/tags                 List all tags
POST   /api/v1/tags/delete          Delete tag from all memories (body: {"tag": "..."})
DELETE /api/v1/memory/{id}          Delete a memory
POST   /api/v1/prune                Decay-based cleanup
GET    /api/v1/graph                Knowledge graph (nodes + edges for D3.js)
GET    /api/v1/export/parquet       Download .parquet backup
POST   /mcp                         MCP JSON-RPC endpoint
GET    /.well-known/mcp.json        MCP discovery
GET    /dashboard                   Second Brain UI
GET    /health                      Minimal liveness check
GET    /api/v1/health               Full health check with uptime and auth state
```

---

## Configuration

All options can be set via environment variables:

```bash
MEMOS_BACKEND=chroma              # memory | json | chroma | qdrant | pinecone
MEMOS_PERSIST_PATH=~/.memos/      # path for json/sqlite storage
MEMOS_CACHE_PATH=~/.memos/embeddings.db  # path for local embedding cache

# ChromaDB
MEMOS_CHROMA_URL=http://chroma:8000
MEMOS_EMBED_HOST=http://localhost:11434   # Ollama — bypasses server-side ONNX
MEMOS_EMBED_MODEL=nomic-embed-text

# Qdrant
MEMOS_QDRANT_HOST=localhost
MEMOS_QDRANT_PORT=6333

# Pinecone
MEMOS_PINECONE_API_KEY=***
MEMOS_PINECONE_INDEX_NAME=agent-memories
```

---

## Docker

Single container (local backend, no dependencies):
```bash
docker run -p 8100:8000 \
  -e MEMOS_BACKEND=local \
  -v memos-data:/data/.memos \
  ghcr.io/mars375/memos:latest
```

The official Docker image keeps the runtime lean by omitting the optional `memos-os[local]` embedding stack, which pulls in large ML dependencies such as Torch. The `local` Docker example above uses JSON-backed local storage; for semantic embeddings in containers, point MemOS at an external Ollama/Chroma setup or build a custom image with the `local` extra.

Full stack with ChromaDB + Ollama embeddings:
```bash
git clone https://github.com/Mars375/memos
cd memos
docker run -p 8100:8000 \
  -e MEMOS_BACKEND=chroma \
  -e MEMOS_CHROMA_URL=http://host.docker.internal:8000 \
  -e MEMOS_EMBED_HOST=http://host.docker.internal:11434 \
  --add-host=host.docker.internal:host-gateway \
  -v memos-data:/data/.memos \
  ghcr.io/mars375/memos:latest
```

The container runs as a non-root `memos` user. Mount persistent data at `/data/.memos` so the runtime user can write stores, caches, and generated sidecar files.

If you want MemOS plus ChromaDB/Qdrant together, use your own compose/orchestrator setup — the repository no longer ships a root `docker-compose.yml`.

---

## Import conversations

Mine your existing conversations into MemOS:

```bash
# Auto-detect format
memos mine conversations.json

# Supported formats
memos mine export.json      --format claude      # Claude Projects export
memos mine conversations.json --format chatgpt   # ChatGPT export
memos mine messages.json    --format discord
memos mine result.json      --format telegram    # Telegram Desktop export
memos mine channel.jsonl    --format slack
memos mine ~/.openclaw/workspace-labs/ --format openclaw

# Options
memos mine ~/notes/ --dry-run --tags project-x --chunk-size 600
```

Python API:
```python
from memos.ingest.miner import Miner

miner = Miner(mem, chunk_size=800, chunk_overlap=100)
result = miner.mine_auto("conversations/")   # auto-detect
# MineResult(imported=127, dupes=12, cached=0, empty=3, errors=0)
```

---

## Knowledge Graph

Store and query temporal facts between entities:

```bash
memos kg-add "Alice" "works-at" "Acme Corp" --from 2024-01-01
memos kg-query Alice
memos kg-path Alice Carol --max-hops 3
memos kg-neighbors Alice --depth 2
memos kg-timeline Alice
```

```python
from memos.knowledge_graph import KnowledgeGraph

kg = KnowledgeGraph()
kg.add_fact("Alice", "works-at", "Acme Corp", valid_from="2024-01-01")
facts = kg.query("Alice")
paths = kg.find_paths("Alice", "Carol", max_hops=3)
```

---

## Living Wiki

Compile memories into entity-based markdown pages with backlinks:

```bash
memos wiki-living update          # scan memories, create/update entity pages
memos wiki-living read Alice      # print Alice's page
memos wiki-living search "python" # search across all pages
memos wiki-living lint            # find orphans, contradictions, empty pages
```

---

## Memory decay

Memories age automatically. Important ones persist; stale ones fade.

```bash
memos decay                # preview what would decay (dry-run by default)
memos decay --apply        # apply decay
memos prune --threshold 0.1  # delete memories below importance threshold
```

---

## Versioning and time-travel

Every write is versioned. Query the past, diff changes, roll back.

```bash
memos history <memory-id>
memos diff <memory-id> --latest
memos rollback <memory-id> --version 1 --yes
memos recall-at "user preferences" --at 2d    # as of 2 days ago
memos snapshot-at 1w                          # all memories 1 week ago
```

---

## Multi-namespace (multi-agent)

Each agent gets its own isolated namespace in the Python API:

```python
from memos import MemOS

alice = MemOS()
alice.namespace = "agent-alice"
alice.learn("Alice's memory")

bob = MemOS()
bob.namespace = "agent-bob"
bob.learn("Bob's memory")

alice.recall("what do I know?")
```

---

## Development

```bash
git clone https://github.com/Mars375/memos
cd memos
pip install -e ".[dev]"  # includes pyarrow, so parquet tests run out of the box

# Lint
ruff check src/ tests/
ruff format src/ tests/

# Tests (Python 3.11 / 3.12 / 3.13)
pytest -q --tb=short          # ~2400 tests
pytest tests/test_core.py     # specific module
```

---

## Architecture

MemOS is built around three core layers plus focused facade mixins on the main `MemOS` class:

- **Capture** — Mine conversations and events into structured memory units via the CLI, SDK, or MCP.
- **Engine** — Storage, recall, decay, reinforcement, versioning, and knowledge graph. Pluggable backends (in-memory, JSON, ChromaDB, Qdrant, Pinecone).
- **Knowledge Surface** — Living wiki, graph view, and context packs (`wake_up`, `context_for`, `recall_enriched`) that serve the right context at the right time.

Recent cleanup extracted dedicated `FeedbackFacade`, `IOFacade`, `MaintenanceFacade`, `SharingFacade`, and `VersioningFacade` mixins so `core.py` stays focused on the CRUD/orchestration nucleus.

See [ROADMAP.md](ROADMAP.md) for planned features and [PRD.md](PRD.md) for product requirements.

---

## License

MIT — [Mars375](https://github.com/Mars375)
