# openmemo-openclaw

**Memory Infrastructure for OpenClaw AI Agents**

[![PyPI version](https://badge.fury.io/py/openmemo-openclaw.svg)](https://pypi.org/project/openmemo-openclaw/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

---

<div align="center">

## 🎮 [▶ Try the Live Interactive Demo](https://openmemoai.github.io/openmemo-openclaw-adapter/)

**See what happens to your AI agent after `pip install openmemo-openclaw`**

Install → First Task → Workflow Reuse → Optimization — animated, step by step

*Zero setup · Runs in your browser*

</div>

---

## What is openmemo-openclaw?

`openmemo-openclaw` is the official adapter that connects **OpenMemo** (the open-source Memory OS) to **OpenClaw**-based AI agents.

After one install, your agents:

- **Remember** past tasks, decisions, preferences, and workflows
- **Avoid repeating** completed work via task deduplication
- **Automatically reuse** successful playbooks
- **Show memory cards** in real-time as memory is created, reused, or optimized
- **Stream events** across the full agent lifecycle (start → recall → store → complete)

---

## Quick Start

```bash
pip install openmemo-openclaw
```

```python
from openmemo_openclaw import OpenMemoAdapter

# Initialize — memory starts automatically
adapter = OpenMemoAdapter()

# ✅ Write memories (tracked by Inspector, Policy Engine filtered)
adapter.write_memory("User prefers concise responses", scene="chat", memory_type="preference")
adapter.write_memory("Deployment uses Docker Compose", scene="devops", memory_type="workflow")

# ✅ Recall context for your agent
context = adapter.get_context("What are the deployment steps?")

# ✅ Full lifecycle hooks (auto-write + auto-recall)
adapter.on_user_message("Deploy my app")
adapter.on_task_complete("Deployed successfully via Docker Compose")
```

**That's it.** On startup, the adapter automatically:
1. Detects any memories written before it was installed → silently imports them
2. Intercepts all memory writes → ensures every write is tracked and visible in Inspector
3. Opens the Memory Inspector at `http://localhost:8765/inspector`

> **Important:** Always use `adapter.write_memory()` to write memories — never call the OpenMemo SDK directly. Direct API calls bypass tracking and won't appear in the Inspector.

---

## User Journey

After installing the adapter, agents go through a progressive memory experience:

```
Step 1: Install
  → Smart Memory Rules configured
  → Activation Panel shown to user

Step 2: First Task
  → Cold start (0 memory hits)
  → Task completes → memories stored
  → "Memory Created" card shown

Step 3: Next Similar Task
  → Warm start (memory recalled)
  → Workflow automatically matched
  → "Workflow Reused" indicator shown

Step 4: Optimization Detected
  → Repeated steps identified and skipped
  → "Optimization Detected" card shown
  → Tokens saved, time reduced
```

---

## Architecture

```
┌─────────────────────────────────────────────────────────┐
│                    OpenClawAdapter                       │
│                                                          │
│  on_user_message() ──► PolicyEngine ──► _do_write()     │
│         │                                    │           │
│         ▼                                    ▼           │
│   EventBridge.emit()              ActivationStore.hook() │
│         │                                    │           │
│         ▼                                    ▼           │
│   UIController.show_*()           InsightCard generated  │
│                                                          │
│  Inspector API (port 8765)                               │
│    /events/recent  /ui/cards  /demo/simulate             │
└─────────────────────────────────────────────────────────┘
```

### Core Layers

| Layer | Module | Purpose |
|-------|--------|---------|
| **Adapter** | `adapter.py` | Main entry point, wraps agent functions |
| **Memory Policy** | `memory_policy/` | Smart rules for what to store vs ignore |
| **Activation System** | `activation/` | Lifecycle hooks → insight cards |
| **Event Bridge** | `event_bridge.py` | Pub-sub event bus across all hooks |
| **UI Controller** | `ui_controller.py` | Renders memory cards in real-time |
| **Inspector** | `inspector.py` | HTTP server + demo simulation API |

---

## Memory Policy Layer

The Memory Policy layer decides **what to store and what to ignore**.

### Default Smart Memory Mode

```python
# What gets stored by default
STORE:
  - successful workflows
  - user preferences
  - key decisions
  - task patterns

IGNORE:
  - failed/noisy signals
  - temporary context
  - duplicate entries
```

### Custom Rules

```python
from openmemo_openclaw.memory_policy import PolicyEngine, RuleStore

rule_store = RuleStore()
rule_store.add_rule({
    "condition": "task_status == 'success' and memory_type == 'workflow'",
    "action": "store",
    "priority": 1,
})

engine = PolicyEngine(rule_store=rule_store)
adapter = OpenClawAdapter(policy_engine=engine)
```

### Inspector API

```
GET  /policy/current        → current policy config
POST /policy/generate       → auto-generate rules from history
POST /policy/update         → update active rules
```

---

## Activation System

The Activation System fires **lifecycle hooks** and generates **UI insight cards** at key moments.

### Hooks

| Hook | Trigger | Card Generated |
|------|---------|---------------|
| `on_install()` | Adapter initialized | Activation Panel + Rule Card |
| `on_task_start()` | First-ever task | Guided First Task card |
| `on_task_complete()` | Task finishes with memories | Memory Created / Optimization Detected |
| `on_workflow_adopted()` | Past workflow reused | Reuse Indicator card |

### Example

```python
from openmemo_openclaw.activation import ActivationStore

activation = ActivationStore()

# First task
guidance = activation.on_task_start(task_id="t-001", query="Deploy backend")

# Task complete — insight card generated automatically
insight = activation.on_task_complete(
    summary="Backend deployed via Docker Compose",
    memories_stored=3,
    workflows_reused=0,
    task_id="t-001",
)
# insight = {"type": "memory_created", "title": "✨ Memory Created", ...}
```

### Inspector API

```
GET /activation/status       → current activation state
GET /activation/first-task   → first-task guidance data
```

---

## Event Bridge

The Event Bridge is a **pub-sub event bus** that emits structured events across the entire agent lifecycle.

### Event Types

| Event | When |
|-------|------|
| `on_task_start` | Agent begins a task |
| `on_memory_recall` | Memory retrieval occurs |
| `on_memory_store` | New memory written |
| `on_workflow_adopt` | Past workflow matched + applied |
| `on_task_complete` | Task finishes |
| `on_policy_block` | Policy engine blocks a write |

### Usage

```python
from openmemo_openclaw.event_bridge import EventBridge

bridge = EventBridge()

# Subscribe to events
@bridge.subscribe("on_task_complete")
def handle_complete(event):
    print(f"Task {event['task_id']} done: {event['metadata']}")

# Emit from your agent
bridge.emit("on_task_start", task_id="t-001", metadata={"query": "Deploy backend"})
bridge.emit("on_memory_recall", task_id="t-001", metadata={"count": 3})
bridge.emit("on_task_complete", task_id="t-001", metadata={"status": "success"})
```

### Inspector API

```
GET /events/recent?n=100    → recent events list
GET /events/stats           → event counts by type
```

---

## UI Controller

The UI Controller **renders memory cards** in real-time as agents work.

### Card Types

| Type | Color | Trigger |
|------|-------|---------|
| `activation_panel` | 🟢 Green | System initialized |
| `rule_card` | 🔵 Blue | Memory rules configured |
| `guided_first_task` | 🟣 Purple | First task detected |
| `insight_memory_created` | 🩵 Cyan | Memories written after task |
| `insight_optimization_detected` | 🟡 Amber | Workflow reuse saved steps |
| `reuse_indicator` | 🟡 Amber | Past workflow matched |

### Usage

```python
from openmemo_openclaw.ui_controller import UIController
from openmemo_openclaw.activation import ActivationStore

ui = UIController()
activation = ActivationStore()

# After task completes
insight = activation.on_task_complete(
    summary="Task done",
    memories_stored=2,
    workflows_reused=1,
    steps_skipped=2,
)
card = ui.show_insight(insight)
# card = {"type": "insight_optimization_detected", "title": "🚀 Optimization Detected", ...}

# Get current card
current = ui.get_current_card()

# Get all cards
all_cards = ui.get_all_cards(limit=20)
```

### Inspector API

```
GET /ui/current             → latest card
GET /ui/cards?n=30          → all cards gallery
```

---

## Memory Inspector

The Inspector is a **built-in monitoring dashboard** running at `http://localhost:8765`.

### Sections

| Section | What it shows |
|---------|--------------|
| Impact Metrics | Memories stored, recalled, reused, tokens saved |
| **Memory Experience Demo** | Run a full simulated 4-step agent flow |
| **Event Stream** | Live event feed with color-coded badges |
| **UI Cards Gallery** | All generated memory cards |
| Task Inspector | Task trace + memory timeline |
| Top Memories | Highest-quality stored memories |

### Run the Demo

Open the Inspector at `/inspector` and click **▶ Run Demo** to see:

1. **Step 1 — Install**: Memory Rules configured, Activation Panel shown
2. **Step 2 — First Task**: Cold start, memory created, insight card emitted
3. **Step 3 — Workflow Reuse**: Warm start, matching workflow applied, reuse card
4. **Step 4 — Optimization**: Steps auto-skipped, efficiency gain calculated

### Inspector API

```
POST /demo/simulate         → run full 4-step simulation
POST /demo/reset            → clear simulation state
GET  /events/recent?n=100   → live event stream
GET  /ui/cards?n=30         → UI cards gallery
GET  /policy/current        → memory policy config
GET  /activation/status     → activation state
```

### Start the Inspector

```python
from openmemo_openclaw import OpenClawAdapter

adapter = OpenClawAdapter()
adapter.start_inspector(port=8765)
# → http://localhost:8765
```

---

## Complete Example

```python
from openmemo_openclaw import OpenClawAdapter

# Initialize — memory rules auto-configured, activation panel shown
adapter = OpenClawAdapter(api_key="your-key")
adapter.start_inspector(port=8765)

def my_agent(message: str) -> str:
    # your agent logic here
    return f"Result for: {message}"

# First task — cold start, memory stored after
result = adapter.on_user_message(
    user_message="Deploy backend service using Docker Compose",
    agent_func=my_agent,
)
# → "Memory Created" card emitted

# Second similar task — warm start, workflow reused
result = adapter.on_user_message(
    user_message="Deploy backend service again",
    agent_func=my_agent,
)
# → "Workflow Reused" card emitted
# → "Optimization Detected" card emitted (steps skipped)
```

---

## What's Different vs Chat History / RAG

| Feature | Chat History | RAG | **openmemo-openclaw** |
|---------|-------------|-----|----------------------|
| Persistent memory across sessions | ❌ | ❌ | ✅ |
| Task deduplication | ❌ | ❌ | ✅ |
| Scene-aware recall | ❌ | ❌ | ✅ |
| Smart write policy (store/ignore rules) | ❌ | ❌ | ✅ |
| Lifecycle UI cards | ❌ | ❌ | ✅ |
| Live event stream | ❌ | ❌ | ✅ |
| Memory Inspector dashboard | ❌ | ❌ | ✅ |

---

## Changelog

### v2.8.0 — Zero-Friction Memory Tracking (Full 3-Layer Protection)

Eliminates the root cause: users can no longer accidentally write memories that are invisible to the Inspector, regardless of how they call the SDK.

**Level 1 — Silent Startup Auto-Sync (`_auto_sync_on_startup`)**
- On every adapter initialization, silently checks for pre-existing untracked memories
- Automatically imports them into FeedbackStore — zero user action, zero configuration
- Users upgrading from v2.7 or earlier: Inspector shows correct counts immediately on restart

**Level 2 — Write Path Interceptor (`_setup_write_intercept`)**
- Wraps `_client.write_memory()` at the instance level on startup
- Any write — whether via `adapter.write_memory()`, `on_task_complete()`, or direct `client.write_memory()` — is automatically tracked
- Uses `_in_do_write` flag to prevent double-counting from the internal `_do_write()` pipeline
- "Wrong path" no longer exists: all paths now lead to tracking

**Level 3 — Quickstart Redesign (README)**
- `write_memory()` is now the first example users see — correct pattern from day one
- Clear warning box: never call the OpenMemo SDK directly
- Startup behavior documented inline

### v2.7.0 — Storage Health Guard (3-Layer Systemic Fix)

Solves the root problem where the Inspector shows **0 memories** while memories were being written directly via API (bypassing OpenMemo tracking).

**Layer 1 — Install-time Health Check (`adapter.py`)**
- `on_install()` now runs `_check_storage_consistency()` automatically
- Detects mismatch between backend storage count vs. FeedbackStore tracked count
- Emits `on_storage_mismatch` event to EventBridge + logs a clear warning with fix instructions

**Layer 2 — Inspector Storage Check + One-Click Sync (`inspector.py` + `inspector_html.py`)**
- New `GET /inspector/storage-check` — returns `{external_count, tracked_count, untracked_count, mismatch, status}`
- New `POST /inspector/sync` — one-click import of all backend memories into OpenMemo tracking; metrics update immediately
- Inspector UI shows an amber warning banner when mismatch is detected; green "consistent" banner when healthy
- Auto-checks every 60 seconds; EN/ZH i18n supported

**Layer 3 — Public Write Path Protection (`adapter.py`)**
- New `adapter.write_memory(content, scene, memory_type, metadata)` — the **correct, safe external write path**
- All writes through this method are guaranteed to: (1) pass Policy Engine filter, (2) be tracked by FeedbackStore, (3) emit EventBridge events
- Fully documented with a clear warning against direct API writes

**Also fixed:** `GET /inspector/metrics` now returns both `memories_stored` and `total_memories` (alias), fixing a UI display inconsistency.

**Migration for existing users:**
```python
# If you have memories in storage but Inspector shows 0:
# Option A: One-click via Inspector UI → visit http://localhost:8765/inspector
# Option B: API call
import requests
requests.post("http://localhost:8765/inspector/sync")

# Option C: Use write_memory() for all future external writes
adapter.write_memory("User prefers concise responses", scene="chat", memory_type="preference")
```

### v2.6.0 — Event Bridge + UI Controller

- **`event_bridge.py`**: Unified pub-sub event bus — 7 event types (`on_task_start`, `on_memory_recall`, `on_memory_store`, `on_workflow_adopt`, `on_task_complete`, `on_policy_block`), `subscribe()` / `emit()` / `get_recent()` / `get_stats()`
- **`ui_controller.py`**: Real-time UI card renderer — 6 card types indexed by type, `get_current_card()` / `get_all_cards()` / `get_stats()`
- **`adapter.py`**: All hooks emit to EventBridge; UIController renders all card types; full lifecycle instrumentation
- **Inspector API**: `GET /events/recent`, `GET /events/stats`, `GET /ui/current`, `GET /ui/cards`
- **Inspector HTML**: Live Event Stream table + UI Cards Gallery + **▶ Run Demo** interactive simulation button

### v2.5.0 — Memory Policy + Activation System

- **`memory_policy/`**: `policy_engine.py`, `rule_store.py`, `rule_generator.py` — Smart Memory Mode with default store/ignore rules; `_do_write()` gate in adapter
- **`activation/`**: `activation_store.py` — 4 lifecycle hooks (`on_install`, `on_task_start`, `on_task_complete`, `on_workflow_adopted`), auto-generates InsightCards
- **Inspector API**: `GET /policy/current`, `POST /policy/generate`, `POST /policy/update`, `GET /activation/status`, `GET /activation/first-task`
- **Inspector HTML**: Activation Status section with Memory Rule Card + System Status + Insight Card

### v2.4.0 — Inspector V3 + Feedback Tracking

- **`inspector_html.py`**: Full V3 UI — Impact Metrics, Task Trace, Timeline, Memory Details, Top Memories
- **`inspector.py`**: V3 API endpoints — `/inspector/metrics`, `/task-trace`, `/timeline`, `/memory-profile`, `/top-memories`
- **`feedback_store.py`**: Lightweight in-memory event tracking with per-task traces and quality scores (`quality_score = adoption×0.4 + success×0.4 + recency×0.2`)
- **`adapter.py`**: FeedbackStore integration + UserMemory extraction/recall hooks

### v2.3.0 and earlier

See [PyPI release history](https://pypi.org/project/openmemo-openclaw/#history).

---

## Installation

```bash
# First-time install
pip install openmemo-openclaw

# Upgrade to latest
pip install openmemo-openclaw --upgrade
```

**Requirements:**
- Python 3.9+
- `openmemo >= 0.23.0`

---

## Contributing

We welcome contributions! Open an issue or submit a pull request.

---

## License

MIT — see [LICENSE](LICENSE)

---

**Built on [OpenMemo](https://github.com/openmemoai/openmemo) — The Memory OS for AI Agents.**
