Metadata-Version: 2.5
Name: harness-memory
Version: 0.9.7
Summary: Pluggable memory system with hierarchical recall, FTS search, and multiple backend support.
Project-URL: Homepage, https://github.com/TencentCloud/harness-memory
Project-URL: Repository, https://github.com/TencentCloud/harness-memory
Project-URL: Issues, https://github.com/TencentCloud/harness-memory/issues
Project-URL: Changelog, https://github.com/TencentCloud/harness-memory/blob/main/CHANGELOG.md
Author: orcakit
License: MIT
License-File: LICENSE
Keywords: agent,fts,llm,memory,recall,sqlite
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Provides-Extra: chroma
Requires-Dist: chromadb>=0.4; extra == 'chroma'
Provides-Extra: cli
Requires-Dist: click>=8.0; extra == 'cli'
Provides-Extra: dashboard
Requires-Dist: click>=8.0; extra == 'dashboard'
Requires-Dist: fastapi>=0.110; extra == 'dashboard'
Requires-Dist: uvicorn[standard]>=0.29; extra == 'dashboard'
Provides-Extra: embeddings
Requires-Dist: sentence-transformers>=2.2; extra == 'embeddings'
Provides-Extra: langgraph
Requires-Dist: langgraph-checkpoint-sqlite>=2.0; extra == 'langgraph'
Requires-Dist: langgraph-checkpoint>=2.0; extra == 'langgraph'
Provides-Extra: langgraph-postgres
Requires-Dist: langgraph-checkpoint-postgres>=2.0; extra == 'langgraph-postgres'
Requires-Dist: langgraph-checkpoint>=2.0; extra == 'langgraph-postgres'
Requires-Dist: psycopg[binary]>=3.1; extra == 'langgraph-postgres'
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == 'postgres'
Provides-Extra: qdrant
Requires-Dist: qdrant-client>=1.7; extra == 'qdrant'
Description-Content-Type: text/markdown

<p align="center">
  <img src="assets/images/banner.jpeg" alt="Harness Memory Banner" width="600" />
</p>

<p align="center">
  <strong>A memory-tree based memory system — tiered recall, pluggable storage, and memory that migrates to OpenClaw / Hermes and beyond.</strong>
</p>

<p align="center">
  <a href="https://www.python.org/downloads/"><img alt="Python 3.11+" src="https://img.shields.io/badge/python-3.11%2B-blue?logo=python&logoColor=white" /></a>
  <a href="https://github.com/TencentCloud/harness-memory/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-green" /></a>
  <a href="https://pypi.org/project/harness-memory/"><img src="https://img.shields.io/pypi/v/harness-memory.svg" alt="PyPI version" /></a>
  <a href="https://github.com/astral-sh/ruff"><img alt="Code Style: Ruff" src="https://img.shields.io/badge/code%20style-ruff-000000?logo=ruff&logoColor=white" /></a>
  <a href="https://github.com/TencentCloud/harness-memory"><img alt="GitHub stars" src="https://img.shields.io/github/stars/TencentCloud/harness-memory?style=social" /></a>
</p>

<p align="center">
  <a href="#-highlights">Highlights</a> ·
  <a href="#-overview">Overview</a> ·
  <a href="#-core-technology">Core Technology</a> ·
  <a href="#-features">Features</a> ·
  <a href="#-quick-start">Quick Start</a> ·
  <a href="#-contents">Contents</a>
</p>

<p align="center">
  <b>English</b> · <a href="README_CN.md">中文</a>
</p>

---

**Harness Memory** is a pluggable long-term memory system for LLM agents, built around the **memory tree** model — a hierarchy of `root → branch → leaf` nodes. It does not talk to an LLM itself; it is a storage-and-recall layer any agent can drop in. What makes it special is **portability**: the storage backend is abstracted behind a `MemoryBackend` Protocol, and first-class host adapters let the same memory travel to other agents such as **OpenClaw** and **Hermes**.

> Harness Memory's design goal: memory is a portable asset, not a lock-in. Capture it once, recall it anywhere — including in a different agent framework.

## ✨ Highlights

| | Feature | Description |
|---|---------|-------------|
| 🌳 | **Memory tree** | Hierarchical `root → branch → leaf` nodes for organized recall |
| 🧩 | **Portable by design** | `MemoryBackend` Protocol makes storage swappable |
| 🔄 | **Agent-agnostic** | Drop into any agent; OpenClaw & Hermes adapters ship in-box |
| 🚚 | **Cross-agent migration** | Pack to `.hmpkg`, adopt into OpenClaw / Hermes / another agent |
| 🔍 | **Recall pipeline** | M4 pipeline: parse → route → gather → rerank → diversify → suppress → budget → render |
| 💾 | **Pluggable storage** | SQLite + FTS5 by default; PostgreSQL / Chroma / Qdrant optional |
| 🪶 | **Zero core deps** | stdlib + `sqlite3`; extras add the rest |
| 🧠 | **Tiered distillation** | L0 raw → L1 candidate → L2 atom → L3 entity |

## 📌 Overview

A fact is recorded canonically as an `AtomCard` (L2) grouped under an `Entity` (L3). The memory tree is a lightweight index over those atoms: `root` and `branch` nodes hold directory-style labels, and each `leaf` points at an atom — its content is projected from the atom at read time, so there is never a second copy of the fact to drift out of sync. Recall walks the tree and surfaces the linked leaves most relevant to a query.

Because storage sits behind a Protocol, the same `Memory` object can run on a local SQLite file, a Postgres database, or a vector index — and because host adapters exist for OpenClaw and Hermes, the memory you build in one agent can be adopted by another.

## 🧠 Core Technology

| Layer | Technology |
|-------|-----------|
| **Language** | Python 3.11+ |
| **Core deps** | None — stdlib + `sqlite3` |
| **Model** | `MemoryNode` tree + `AtomCard` |
| **Recall** | M4 pipeline (`pipeline/recall/`) |
| **Storage** | `MemoryBackend` Protocol — SQLite/FTS5, Postgres, vector (Chroma/Qdrant) |
| **Host adapters** | `adapters/bridge/` host bridge for OpenClaw & Hermes |
| **LangGraph** | Optional checkpointer (SQLite / Postgres) |
| **Build / quality** | hatchling · ruff · mypy · pytest |

## 🧰 Features

### Memory tree
- `root → branch → leaf` hierarchy; leaves reference atoms, content is projected on read.
- Tiered distillation: **L0** raw event → **L1** candidate → **L2** `AtomCard` → **L3** entity page (plus an L2.5 episode/diary layer).

### Recall
- `recall_for_prompt(memory, query)` returns `result.rendered` + `result.snippets`.
- M4 pipeline routes the query, gathers candidates, reranks, diversifies, suppresses noise, and budgets tokens before rendering.

### Pluggable backends
- Default: SQLite + FTS5 (full-text search).
- Optional: PostgreSQL (`[postgres]`), ChromaDB (`[chroma]`), Qdrant (`[qdrant]`), local embeddings (`[embeddings]`), and a LangGraph checkpointer (`[langgraph]`).

### Portability — OpenClaw & Hermes
- **`MemoryBackend` Protocol** keeps storage swappable, so the engine is agent-agnostic.
- **`adapters/bridge/`** is a shared JSON-RPC bridge reused by OpenClaw; in-process hosts call the same `application/runtime.py` through `MemoryService`.
- **`plugins/openclaw/`** ships a TypeScript shell (`harnessmemory`); **`plugins/hermes/`** ships a Python plugin — both build on the same bridge.
- **CLI**: `harness-memory openclaw ...` manages the OpenClaw integration; the standalone `harness-memory-hermes install|doctor` package manages Hermes.

### Cross-agent migration
`operations/migration/portable/` packs memory into a `.hmpkg` and adopts it into a target host:

```bash
harness-memory portable list-sources                            # discover migratable stores
harness-memory portable pack  --from agent:my-agent --out my-agent.hmpkg
harness-memory portable adopt my-agent.hmpkg --as openclaw
harness-memory portable doctor --host openclaw --compare-with my-agent.hmpkg
```

`adopt` resolves the target store and namespace for OpenClaw, Hermes, another
agent, or a plain `harnessmemory` backend — for OpenClaw it defaults to the
namespace the installed plugin actually reads (from `openclaw.json`); override
with `--as openclaw:<namespace>`. Imports are idempotent, back up the target db
first, and can rewrite the `host` field (`--host-rewrite target`).

## 🚀 Quick Start

### Prerequisites
- **Python 3.11+**

### 1. Install

```bash
pip install harness-memory                       # core (SQLite + FTS5)
pip install "harness-memory[postgres]"           # PostgreSQL backend
pip install "harness-memory[chroma,embeddings]"  # vector index + embeddings
pip install "harness-memory[langgraph]"          # LangGraph checkpointer
pip install "harness-memory[cli]"                # CLI (incl. openclaw / hermes)
```

### 2. Store & recall

```python
from harness_memory import Memory
from harness_memory.pipeline.recall import recall_for_prompt

m = Memory(namespace="my-agent")  # defaults to ~/.harness-memory/session.sqlite
m.store("User prefers Python over Java", topic="preferences")

# Recall is FTS-based (no stemming) — query with words that appear in the memory.
result = recall_for_prompt(m, "Python preference")
print(result.rendered)
```

### 3. Use with another agent

```bash
# OpenClaw — wire the plugin slot, then bring your memory along
harness-memory openclaw setup
harness-memory portable adopt my-agent.hmpkg --as openclaw

# Hermes
pip install harness-memory-hermes
harness-memory-hermes install --hermes-source /path/to/hermes-agent
harness-memory portable adopt my-agent.hmpkg --as hermes
```

## 📑 Contents

- [Highlights](#-highlights)
- [Overview](#-overview)
- [Core Technology](#-core-technology)
- [Features](#-features)
- [Quick Start](#-quick-start)
- **Reference**
  - [Architecture](#-architecture)
  - [CLI reference](#-cli-reference)
  - [Development](#-development)
- **Project Info**
  - [Contributing](#-contributing)
  - [Related projects](#-related-projects)
  - [License](#-license)

## 🏗️ Architecture

```
harness_memory/
 ├─ core.py                 Memory facade + backend factory
 ├─ service.py              in-process adapter over application runtime
 ├─ application/            MemoryRuntime, config, host files, path projection
 ├─ pipeline/               extractor · promotion · page · episode · recall · lifecycle
 ├─ storage/                MemoryBackend Protocol · sqlite · postgres · vector
 ├─ ports/                  LLMClient protocol and clients
 ├─ adapters/               bridge · CLI · dashboard
 └─ operations/migration/   export/import/rename/portable pack → .hmpkg → adopt
```

## 📖 CLI reference

Global options come **before** the subcommand and select which store to act on:

```bash
harness-memory [--backend sqlite|postgres] [--db PATH] [--dsn DSN] \
               [--namespace NAME] [--json] [--config FILE] <command> ...
```

`--json` makes any command emit machine-readable output. Every group supports `--help`.
Env-var equivalents: `HARNESS_MEMORY_BACKEND` / `_DB` / `_DSN` / `_NAMESPACE` / `_CONFIG`.

### Search & recall

| Command | Description |
|---------|-------------|
| `recall "<query>"` | Run the full recall pipeline from the terminal (what an agent would see) |
| `atom search "<query>"` | FTS over atom assertion + quote + search terms |
| `raw search "<query>"` | FTS over raw event content |
| `episode search "<query>"` | FTS over episodes (summary, quote, people, topics) |
| `memory recall "<query>"` | Recall over the manual memory-node tree |

### Inspect the memory layers

| Command | Description |
|---------|-------------|
| `raw list / show / add` | L0 raw events — the evidence everything else derives from |
| `candidate list / show / extract` | L1 candidates; `extract` runs the extractor over a session's raw events |
| `candidate promote / review / fallback` | Drive the 5-check promotion worker, the interactive review queue, or the 7-day auto-promote rules |
| `atom list / show` | L2 atoms (promoted facts) |
| `entity list / show` | L3 entities and their non-deprecated atoms |
| `page show / list-dirty / regen / edit` | L3 entity pages; `regen` drives the LLM regenerator, `edit` opens `$EDITOR` |
| `episode list / get` | L2.5 diary episodes |
| `digest generate / list / show` | Daily/weekly/monthly digests over episodes |
| `journal list` | L4 append-only audit log |
| `memory store / get / update / delete / tree` | Manual memory-node tree (user-authored notes) |
| `thread show <thread-id>` | Per-thread active-entity LRU stack |

### Storage maintenance

Cleanup and space reclaim are separate concerns: `gc` / `consolidate` / `thread prune` **delete rows**, `db` **gives the freed space back to the OS**. None of them run automatically — schedule them yourself.

| Command | Description |
|---------|-------------|
| `db check` | Read-only health report: wasted space, and exactly what `db vacuum` would reclaim. Safe any time |
| `db vacuum` | Reclaim freed space in small, bounded batches — safe to run with live traffic |
| `db compact --yes` | Deep compaction; holds an exclusive lock, so only run during an idle window |
| `gc run [--dry-run]` | Delete rejected candidates, deprecated atoms and orphan raw events past their retention windows |
| `thread prune [--keep-last N] [--keep-days N]` | Trim LangGraph checkpoint history (the largest single source of file growth) |
| `consolidate run` | Intra-entity semantic dedup |

### Migration & backup

| Command | Description |
|---------|-------------|
| `portable list-sources` | Discover migratable memory stores on this machine |
| `portable pack --from <host:name>` | Export memory to a `.hmpkg` |
| `portable adopt <pkg> --as <host[:ns]>` | Import a `.hmpkg` into a target host |
| `portable doctor --host <host[:ns]>` | Health-check the target store, optionally comparing counts with a `.hmpkg` |
| `export` / `import` | Dump / restore the active namespace as JSONL |
| `migrate` | Rename or copy a namespace |
| `backfill` | Replay the candidate extractor over historical raw events |

### Host integration & tooling

| Command | Description |
|---------|-------------|
| `openclaw setup / doctor / uninstall / print-config` | Manage the OpenClaw integration |
| `harness-memory-hermes install / doctor` (separate `harness-memory-hermes` package) | Manage the Hermes integration |
| `dashboard` | Launch the local web dashboard (`[dashboard]` extra) |
| `config show / set / path` | Inspect and edit `~/.harness-memory/config.json` |

## 🛠️ Development

**Prerequisites:** Python 3.11+, [uv](https://docs.astral.sh/uv/)

```bash
make install          # uv sync --group dev
make all              # lint + typecheck + test
```

## 🤝 Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Run `make all` before submitting
4. Open a Pull Request

## 🔗 Related projects

| Project | Description |
|---------|-------------|
| [harness-agent](https://github.com/TencentCloud/harness-agent) | Agent runtime that consumes the memory |
| [harness-browser](https://github.com/TencentCloud/harness-browser) | Browser automation for memory-backed agents |
| [harness-gateway](https://github.com/TencentCloud/harness-gateway) | Multi-platform IM channel bridge |
| [Octop](https://github.com/TencentCloud/orca) | The self-hosted assistant that composes the Harness stack |

## 📄 License

This project is licensed under the [MIT License](LICENSE).
