@christopherlittle51/postclaw 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -695
- package/dashboard/README.md +89 -0
- package/dashboard/public/app.js +903 -542
- package/dashboard/public/index.html +184 -73
- package/dashboard/public/styles.css +583 -126
- package/dist/dashboard/routes/graph.d.ts +2 -2
- package/dist/dashboard/routes/graph.d.ts.map +1 -1
- package/dist/dashboard/routes/graph.js +61 -23
- package/dist/dashboard/routes/graph.js.map +1 -1
- package/dist/dashboard/routes/memories.d.ts.map +1 -1
- package/dist/dashboard/routes/memories.js +66 -0
- package/dist/dashboard/routes/memories.js.map +1 -1
- package/dist/dashboard/routes/workspace.d.ts +4 -3
- package/dist/dashboard/routes/workspace.d.ts.map +1 -1
- package/dist/dashboard/routes/workspace.js +119 -7
- package/dist/dashboard/routes/workspace.js.map +1 -1
- package/dist/dashboard/server.js +1 -1
- package/dist/dashboard/server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -27
- package/dist/index.js.map +1 -1
- package/dist/schemas/validation.d.ts +32 -3
- package/dist/schemas/validation.d.ts.map +1 -1
- package/dist/schemas/validation.js +22 -4
- package/dist/schemas/validation.js.map +1 -1
- package/dist/scripts/setup-db.d.ts.map +1 -1
- package/dist/scripts/setup-db.js +28 -30
- package/dist/scripts/setup-db.js.map +1 -1
- package/dist/scripts/sleep_cycle.d.ts +1 -0
- package/dist/scripts/sleep_cycle.d.ts.map +1 -1
- package/dist/scripts/sleep_cycle.js +114 -21
- package/dist/scripts/sleep_cycle.js.map +1 -1
- package/dist/services/config.d.ts +1 -0
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +5 -22
- package/dist/services/config.js.map +1 -1
- package/dist/services/memoryService.d.ts +2 -1
- package/dist/services/memoryService.d.ts.map +1 -1
- package/dist/services/memoryService.js +90 -24
- package/dist/services/memoryService.js.map +1 -1
- package/dist/services/personaService.d.ts +25 -0
- package/dist/services/personaService.d.ts.map +1 -1
- package/dist/services/personaService.js +79 -0
- package/dist/services/personaService.js.map +1 -1
- package/dist/tests/dashboard-schemas.test.js +71 -1
- package/dist/tests/dashboard-schemas.test.js.map +1 -1
- package/package.json +1 -1
- package/schemas/README.md +64 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# PostClaw — PostgreSQL Memory Plugin
|
|
1
|
+
# PostClaw — The PostgreSQL Vector Memory Plugin
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<img src="https://github.com/user-attachments/assets/2a7798c6-e711-40fa-bcf2-7416180651cc"
|
|
@@ -8,754 +8,128 @@
|
|
|
8
8
|
style="display: block; margin: 0 auto" />
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Overview
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
## Table of Contents
|
|
16
|
-
|
|
17
|
-
- [Features](#features)
|
|
18
|
-
- [Prerequisites](#prerequisites)
|
|
19
|
-
- [Quick Start](#quick-start)
|
|
20
|
-
- [Installation](#installation)
|
|
21
|
-
- [Database Setup](#database-setup)
|
|
22
|
-
- [Configuration](#configuration)
|
|
23
|
-
- [Plugin Hooks](#plugin-hooks)
|
|
24
|
-
- [Agent Tools](#agent-tools)
|
|
25
|
-
- [CLI Commands](#cli-commands)
|
|
26
|
-
- [Background Services](#background-services)
|
|
27
|
-
- [Database Schema](#database-schema)
|
|
28
|
-
- [Row-Level Security](#row-level-security)
|
|
29
|
-
- [Persona Bootstrap](#persona-bootstrap)
|
|
30
|
-
- [Sleep Cycle](#sleep-cycle)
|
|
31
|
-
- [Testing](#testing)
|
|
32
|
-
- [Troubleshooting](#troubleshooting)
|
|
13
|
+
**PostClaw** is a memory architecture plugin designed specifically for the OpenClaw agent framework. By migrating the default text-based memory system into a PostgreSQL database equipped with `pgvector`, PostClaw gives your AI agent the ability to recall long-term facts and short-term conversations using semantic vector search.
|
|
33
14
|
|
|
34
|
-
|
|
15
|
+
Rather than relying on exact keyword matching ("dog"), PostClaw translates memories into mathematical arrays. This means the agent can find related context conceptually ("pets", "puppies", "vet trips") regardless of the exact phrasing.
|
|
35
16
|
|
|
36
|
-
|
|
17
|
+
### Core Features
|
|
37
18
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
| **Dynamic Persona Injection** | Injects agent-specific persona rules and RAG context into every prompt |
|
|
44
|
-
| **Duplicate Detection** | Identifies and merges near-duplicate memories during background maintenance |
|
|
45
|
-
| **Multi-Agent Isolation** | Row-Level Security (RLS) ensures agents can only read/write their own data |
|
|
46
|
-
| **Autonomous Management** | Agents silently store, update, link, and search memories without user prompts |
|
|
19
|
+
* **Retrieval-Augmented Generation (RAG):** Dynamically injects highly relevant factual memories directly into the agent's context window.
|
|
20
|
+
* **Separation of Concerns:** Distinct tables for short-term transcripts (**Episodic Memory**) versus long-term durable truths (**Semantic Memory**).
|
|
21
|
+
* **The Knowledge Graph:** Explicit connections between related ideas stored in the `entity_edges` table, allowing the agent to pull secondary context automatically.
|
|
22
|
+
* **Automated Maintenance (The Sleep Cycle):** Background scripts that run periodically to deduplicate overlapping facts, consolidate messy conversational logs, and delete stale data—all autonomously via the LLM.
|
|
23
|
+
* **Data Isolation (RLS):** True multi-agent sandboxing using PostgreSQL Row-Level Security. Agent A mathematically cannot read or overwrite Agent B's private memory.
|
|
47
24
|
|
|
48
25
|
---
|
|
49
26
|
|
|
50
|
-
## Prerequisites
|
|
51
|
-
|
|
52
|
-
1. **OpenClaw** — installed and configured
|
|
53
|
-
2. **PostgreSQL** (v14+) — installed and running. Depending on your system, you may need the `postgresql-<version>-pgvector` package installed. The `pgvector` extension is installed automatically by the setup command.
|
|
54
|
-
3. **Node.js** (v18+) and **npm**
|
|
55
|
-
4. **Embedding Provider** — LM Studio, Ollama, or any OpenAI-compatible endpoint serving an embedding model (e.g. `nomic-embed-text-v2-moe`)
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
"memorySearch": {
|
|
59
|
-
"provider": "openai",
|
|
60
|
-
"remote": {
|
|
61
|
-
"baseUrl": "http://<OPENAI-COMPATIBLE-ENDPOINT>/v1",
|
|
62
|
-
"apiKey": "<API-KEY>"
|
|
63
|
-
},
|
|
64
|
-
"model": "text-embedding-nomic-embed-text-v2-moe"
|
|
65
|
-
}
|
|
66
|
-
```
|
|
27
|
+
## 🛠 Prerequisites
|
|
67
28
|
|
|
68
|
-
|
|
29
|
+
To use PostClaw, your environment must meet the following infrastructure requirements:
|
|
69
30
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
},
|
|
75
|
-
```
|
|
31
|
+
1. **OpenClaw (v2026.3.2+):** The host agent framework installed and running.
|
|
32
|
+
2. **PostgreSQL 14+ with pgvector:** A running database server. The `pgvector` and `pgcrypto` extensions are strictly required for mathematical embeddings and UUID generation. *(e.g., `postgresql-16-pgvector`)*.
|
|
33
|
+
3. **Node.js (v18+):** For executing the plugin scripts.
|
|
34
|
+
4. **An Embedding Provider:** A local endpoint (like LM Studio or Ollama) running an embedding model natively (such as `nomic-embed-text-v2-moe`) to convert text into vectors.
|
|
76
35
|
|
|
77
36
|
---
|
|
78
37
|
|
|
79
|
-
## Quick Start
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
# PREREQUISITES
|
|
83
|
-
## You must have a password assigned to your postgres user if you are running openclaw from another user.
|
|
84
|
-
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'YOUR_PASSWORD';"
|
|
38
|
+
## 🚀 Quick Start Guide
|
|
85
39
|
|
|
86
|
-
|
|
87
|
-
sudo apt install postgresql-xx-pgvector # Ubuntu/Debian example.
|
|
40
|
+
Assuming you have PostgreSQL installed and an OpenClaw environment ready, follow these steps to bootstrap your agent's new memory:
|
|
88
41
|
|
|
89
|
-
|
|
90
|
-
openclaw plugins install @christopherlittle51/postclaw # from npm
|
|
91
|
-
# OR from a local path:
|
|
92
|
-
openclaw plugins install /path/to/PostClaw
|
|
42
|
+
### 1. Install the Plugin
|
|
93
43
|
|
|
94
|
-
|
|
95
|
-
openclaw postclaw setup --admin-url postgres://<POSTGRES-USERNAME>:<PASSWORD>@[IP ADDRESS/localhost]/postgres
|
|
96
|
-
|
|
97
|
-
# 3. Restart the gateway
|
|
98
|
-
openclaw restart
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Done. PostClaw will automatically:
|
|
102
|
-
|
|
103
|
-
- Connect to the database using the credential it just generated
|
|
104
|
-
- Start injecting RAG context and persona rules into every prompt
|
|
105
|
-
- Begin logging episodic memory after each agent turn
|
|
106
|
-
- Run the sleep cycle in the background every 6 hours
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## Installation
|
|
111
|
-
|
|
112
|
-
### From npm (recommended)
|
|
44
|
+
Using OpenClaw's built-in package manager:
|
|
113
45
|
|
|
114
46
|
```bash
|
|
115
47
|
openclaw plugins install @christopherlittle51/postclaw
|
|
116
48
|
```
|
|
117
49
|
|
|
118
|
-
###
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# Copy into ~/.openclaw/extensions/postclaw/
|
|
122
|
-
openclaw plugins install /path/to/PostClaw
|
|
123
|
-
|
|
124
|
-
# Or link for development (live edits, no copy)
|
|
125
|
-
openclaw plugins install -l /path/to/PostClaw
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Manual
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
git clone <repository-url> PostClaw
|
|
132
|
-
cd PostClaw
|
|
133
|
-
npm install
|
|
134
|
-
npm run build
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
Then add to `~/.openclaw/openclaw.json`:
|
|
138
|
-
|
|
139
|
-
```json
|
|
140
|
-
{
|
|
141
|
-
"plugins": {
|
|
142
|
-
"load": { "paths": ["/absolute/path/to/PostClaw"] },
|
|
143
|
-
"slots": { "memory": "postclaw" },
|
|
144
|
-
"entries": {
|
|
145
|
-
"postclaw": { "enabled": true }
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
50
|
+
### 2. Configure the Database
|
|
150
51
|
|
|
151
|
-
|
|
52
|
+
Run the setup script. This will ask you for a PostgreSQL administrator connection string to generate the `openclaw` user, build the schemas, and enforce RLS policies. It is safe to run this multiple times.
|
|
152
53
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
### Automated Setup
|
|
54
|
+
*Replace `<admin_user>` and `<password>` with your actual local Postgres credentials.*
|
|
156
55
|
|
|
157
56
|
```bash
|
|
158
|
-
openclaw postclaw setup
|
|
57
|
+
openclaw postclaw setup --admin-url postgres://<admin_user>:<password>@localhost/postgres
|
|
159
58
|
```
|
|
160
59
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
1. Connects to PostgreSQL as a superuser
|
|
164
|
-
2. Creates the `memorydb` database (if it doesn't exist)
|
|
165
|
-
3. Installs the `vector` and `pgcrypto` extensions
|
|
166
|
-
4. Creates the `openclaw` app user with a **random password**
|
|
167
|
-
5. Creates the `system_admin` role with RLS bypass
|
|
168
|
-
6. Builds all tables, triggers, indices, and RLS policies
|
|
169
|
-
7. Auto-updates `~/.openclaw/openclaw.json` with the connection string
|
|
170
|
-
|
|
171
|
-
#### Options
|
|
60
|
+
### 3. Restart the Agent
|
|
172
61
|
|
|
173
|
-
|
|
174
|
-
|------|---------|-------------|
|
|
175
|
-
| `--admin-url <url>` | `postgres://localhost/postgres` | Superuser connection string |
|
|
176
|
-
| `--db-name <name>` | `memorydb` | Database name |
|
|
177
|
-
| `--db-user <user>` | `openclaw` | App user name |
|
|
178
|
-
| `--db-password <pass>` | *auto-generated* | App user password |
|
|
179
|
-
| `--skip-config` | `false` | Don't auto-update `openclaw.json` |
|
|
180
|
-
|
|
181
|
-
#### Examples
|
|
62
|
+
Restart your OpenClaw instance to initialize the background sleep cycle timers and connect to the new database.
|
|
182
63
|
|
|
183
64
|
```bash
|
|
184
|
-
|
|
185
|
-
openclaw postclaw setup
|
|
186
|
-
|
|
187
|
-
# Remote / password-protected PostgreSQL
|
|
188
|
-
openclaw postclaw setup --admin-url postgres://postgres:mysecretpass@db.example.com:5432/postgres
|
|
189
|
-
|
|
190
|
-
# Custom database and user names
|
|
191
|
-
openclaw postclaw setup --db-name myagent_memory --db-user myagent --db-password hunter2
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
#### Output
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
🦐 PostClaw Database Setup
|
|
198
|
-
|
|
199
|
-
✅ Connected to Postgres as superuser
|
|
200
|
-
✅ Created database 'memorydb'
|
|
201
|
-
✅ Created user 'openclaw'
|
|
202
|
-
✅ Created role 'system_admin'
|
|
203
|
-
✅ Schema created (6 tables, 14 indices, 18 RLS policies)
|
|
204
|
-
✅ Granted permissions
|
|
205
|
-
|
|
206
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
207
|
-
Database: memorydb
|
|
208
|
-
App User: openclaw
|
|
209
|
-
App Password: kR9x!mQ2vL8nP4wZ
|
|
210
|
-
Admin User: system_admin
|
|
211
|
-
Admin Pass: bN7yT3xK1mR5sW9e
|
|
212
|
-
|
|
213
|
-
Connection: postgres://openclaw:kR9x!mQ2vL8nP4wZ@localhost:5432/memorydb
|
|
214
|
-
|
|
215
|
-
✅ openclaw.json updated with dbUrl
|
|
216
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
217
|
-
|
|
218
|
-
Save these credentials! They won't be shown again.
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
The setup is **fully idempotent** — safe to re-run without errors.
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Configuration
|
|
226
|
-
|
|
227
|
-
All configuration lives in `~/.openclaw/openclaw.json`:
|
|
228
|
-
|
|
229
|
-
```json
|
|
230
|
-
{
|
|
231
|
-
"plugins": {
|
|
232
|
-
"slots": {
|
|
233
|
-
"memory": "postclaw"
|
|
234
|
-
},
|
|
235
|
-
"entries": {
|
|
236
|
-
"postclaw": {
|
|
237
|
-
"enabled": true,
|
|
238
|
-
"config": {
|
|
239
|
-
"dbUrl": "postgres://openclaw:PASSWORD@localhost:5432/memorydb",
|
|
240
|
-
"sleepIntervalHours": 6
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
},
|
|
245
|
-
"agents": {
|
|
246
|
-
"defaults": {
|
|
247
|
-
"memorySearch": {
|
|
248
|
-
"provider": "openai",
|
|
249
|
-
"remote": {
|
|
250
|
-
"baseUrl": "http://127.0.0.1:1234/v1/",
|
|
251
|
-
"apiKey": "lm-studio"
|
|
252
|
-
},
|
|
253
|
-
"model": "text-embedding-nomic-embed-text-v2-moe"
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Config Properties
|
|
261
|
-
|
|
262
|
-
| Key | Type | Default | Description |
|
|
263
|
-
|-----|------|---------|-------------|
|
|
264
|
-
| `dbUrl` | `string` | — | PostgreSQL connection string (**required**) |
|
|
265
|
-
| `adminDbUrl` | `string` | — | Superuser connection (only used by `postclaw setup`) |
|
|
266
|
-
| `sleepIntervalHours` | `number` | `6` | Hours between background sleep cycles. Set to `0` to disable. |
|
|
267
|
-
|
|
268
|
-
The `POSTCLAW_DB_URL` environment variable is also supported as a fallback for `dbUrl`.
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## Plugin Hooks
|
|
273
|
-
|
|
274
|
-
PostClaw registers three hooks with the OpenClaw lifecycle:
|
|
275
|
-
|
|
276
|
-
### 1. `message_received` (void)
|
|
277
|
-
|
|
278
|
-
**When:** Every inbound message before agent processing begins.
|
|
279
|
-
|
|
280
|
-
**What it does:** Caches the raw message text so the next `before_prompt_build` has the real user text (not the system-modified version).
|
|
281
|
-
|
|
282
|
-
### 2. `before_prompt_build` (modifying)
|
|
283
|
-
|
|
284
|
-
**When:** Before the LLM prompt is assembled for each agent turn.
|
|
285
|
-
|
|
286
|
-
**What it does:**
|
|
287
|
-
|
|
288
|
-
1. **Prunes the system prompt** — strips OpenClaw's default bloat (Tooling rules, Documentation, Project Context markdown)
|
|
289
|
-
2. **Injects memory architecture rules** — teaches the agent how to use its memory tools
|
|
290
|
-
3. **Fetches persona context** — pulls `agent_persona` rules from Postgres (core rules always, situational rules ranked by embedding similarity)
|
|
291
|
-
4. **Runs RAG search** — performs a vector similarity search on `memory_semantic` + traverses `entity_edges` for linked memories
|
|
292
|
-
5. **Loads dynamic tools** — fetches tool schemas from `context_environment` ranked by embedding similarity
|
|
293
|
-
6. **Injects everything** — returns the modified system prompt and prepended RAG context
|
|
294
|
-
|
|
295
|
-
**Returns:** `{ systemPrompt, prependContext, tools }`
|
|
296
|
-
|
|
297
|
-
### 3. `agent_end` (void)
|
|
298
|
-
|
|
299
|
-
**When:** After the agent completes a turn (response generated).
|
|
300
|
-
|
|
301
|
-
**What it does:**
|
|
302
|
-
|
|
303
|
-
1. **Logs user prompt** as an episodic memory event (with embedding)
|
|
304
|
-
2. **Logs each tool call** the agent made as a separate episodic event
|
|
305
|
-
3. Skips heartbeat/cron runs to avoid noise
|
|
306
|
-
|
|
307
|
-
---
|
|
308
|
-
|
|
309
|
-
## Agent Tools
|
|
310
|
-
|
|
311
|
-
PostClaw registers 5 native tools that the agent can invoke autonomously:
|
|
312
|
-
|
|
313
|
-
### `memory_search`
|
|
314
|
-
|
|
315
|
-
Search the semantic memory database by natural language query.
|
|
316
|
-
|
|
317
|
-
```
|
|
318
|
-
memory_search({ query: "user's preferred programming language" })
|
|
319
|
-
→ { results: "[ID: abc...] (92.3%) - The user prefers TypeScript..." }
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
| Parameter | Type | Required | Description |
|
|
323
|
-
|-----------|------|----------|-------------|
|
|
324
|
-
| `query` | `string` | ✅ | Natural language search query |
|
|
325
|
-
| `max_results` | `number` | — | Max results to return (default: 5) |
|
|
326
|
-
|
|
327
|
-
### `memory_store`
|
|
328
|
-
|
|
329
|
-
Store a new semantic memory fact with embedding.
|
|
330
|
-
|
|
331
|
-
```
|
|
332
|
-
memory_store({
|
|
333
|
-
content: "The user's server runs Ubuntu 22.04 on a Hetzner VPS",
|
|
334
|
-
scope: "private",
|
|
335
|
-
category: "infrastructure",
|
|
336
|
-
tier: "permanent",
|
|
337
|
-
confidence: 0.95
|
|
338
|
-
})
|
|
339
|
-
→ { id: "550e8400-...", status: "stored" }
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
| Parameter | Type | Required | Description |
|
|
343
|
-
|-----------|------|----------|-------------|
|
|
344
|
-
| `content` | `string` | ✅ | The fact to store |
|
|
345
|
-
| `scope` | `"private" \| "shared" \| "global"` | — | Visibility (default: `private`) |
|
|
346
|
-
| `category` | `string` | — | Semantic category label |
|
|
347
|
-
| `volatility` | `"low" \| "medium" \| "high"` | — | How likely to change |
|
|
348
|
-
| `tier` | `"volatile" \| "session" \| "daily" \| "stable" \| "permanent"` | — | Retention tier |
|
|
349
|
-
| `confidence` | `number` | — | 0.0–1.0 confidence score |
|
|
350
|
-
| `metadata` | `object` | — | Arbitrary JSON metadata |
|
|
351
|
-
|
|
352
|
-
### `memory_update`
|
|
353
|
-
|
|
354
|
-
Supersede an existing memory with a corrected fact. Archives the old memory and links the new one.
|
|
355
|
-
|
|
356
|
-
```
|
|
357
|
-
memory_update({
|
|
358
|
-
old_memory_id: "550e8400-...",
|
|
359
|
-
new_fact: "The user's server now runs Ubuntu 24.04",
|
|
360
|
-
tier: "permanent"
|
|
361
|
-
})
|
|
362
|
-
→ { newId: "7c9e6679-...", status: "updated" }
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
| Parameter | Type | Required | Description |
|
|
366
|
-
|-----------|------|----------|-------------|
|
|
367
|
-
| `old_memory_id` | `string` | ✅ | UUID of the memory to supersede |
|
|
368
|
-
| `new_fact` | `string` | ✅ | The corrected/updated content |
|
|
369
|
-
| All `memory_store` options | — | — | Same options available |
|
|
370
|
-
|
|
371
|
-
### `memory_link`
|
|
372
|
-
|
|
373
|
-
Create a directed edge in the knowledge graph between two memories.
|
|
374
|
-
|
|
375
|
-
```
|
|
376
|
-
memory_link({
|
|
377
|
-
source_id: "550e8400-...",
|
|
378
|
-
target_id: "7c9e6679-...",
|
|
379
|
-
relationship: "elaborates"
|
|
380
|
-
})
|
|
381
|
-
→ { status: "linked" }
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
| Parameter | Type | Required | Description |
|
|
385
|
-
|-----------|------|----------|-------------|
|
|
386
|
-
| `source_id` | `string` | ✅ | UUID of the source memory |
|
|
387
|
-
| `target_id` | `string` | ✅ | UUID of the target memory |
|
|
388
|
-
| `relationship` | `string` | ✅ | Edge type: `related_to`, `elaborates`, `contradicts`, `depends_on`, `part_of` |
|
|
389
|
-
|
|
390
|
-
### `tool_store`
|
|
391
|
-
|
|
392
|
-
Reserved for potential future use, if OpenClaw ever provides a hook or API call that allows tool injections.
|
|
393
|
-
|
|
394
|
-
```
|
|
395
|
-
tool_store({
|
|
396
|
-
tool_name: "deploy_server",
|
|
397
|
-
tool_json: '{"type":"function","function":{"name":"deploy_server",...}}',
|
|
398
|
-
scope: "global"
|
|
399
|
-
})
|
|
400
|
-
→ { status: "stored" }
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
| Parameter | Type | Required | Description |
|
|
404
|
-
|-----------|------|----------|-------------|
|
|
405
|
-
| `tool_name` | `string` | ✅ | Unique tool name |
|
|
406
|
-
| `tool_json` | `string` | ✅ | Full JSON schema (OpenAI function-calling format) |
|
|
407
|
-
| `scope` | `"private" \| "shared" \| "global"` | — | Visibility (default: `private`) |
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
## CLI Commands
|
|
412
|
-
|
|
413
|
-
All CLI commands are registered under the `postclaw` namespace:
|
|
414
|
-
|
|
415
|
-
### `openclaw postclaw setup`
|
|
416
|
-
|
|
417
|
-
Bootstrap the database from scratch. See [Database Setup](#database-setup).
|
|
418
|
-
|
|
419
|
-
### `openclaw postclaw persona <file>`
|
|
420
|
-
|
|
421
|
-
Ingest a Markdown persona file into the `agent_persona` table.
|
|
422
|
-
|
|
423
|
-
```bash
|
|
424
|
-
# Bootstrap your agent's personality
|
|
425
|
-
openclaw postclaw persona ~/my-agent/SOUL.md
|
|
426
|
-
|
|
427
|
-
# Specify an agent ID
|
|
428
|
-
openclaw postclaw persona ~/my-agent/AGENTS.md --agent-id discord-bot
|
|
429
|
-
|
|
430
|
-
# Use a specific LLM for chunking
|
|
431
|
-
openclaw postclaw persona ~/my-agent/SOUL.md --llm-model qwen3.5-35b
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**How it works:**
|
|
435
|
-
|
|
436
|
-
1. Reads the Markdown file
|
|
437
|
-
2. Sends it to your configured LLM with a system prompt asking it to extract atomic persona rules
|
|
438
|
-
3. For each extracted rule, generates an embedding and upserts it into `agent_persona`
|
|
439
|
-
4. Uses `ON CONFLICT ... DO UPDATE` — safe to re-run when you update the source file
|
|
440
|
-
|
|
441
|
-
| Option | Default | Description |
|
|
442
|
-
|--------|---------|-------------|
|
|
443
|
-
| `--agent-id <id>` | `main` | Agent to store persona under |
|
|
444
|
-
| `--llm-model <model>` | Agent's primary model | Model for semantic chunking |
|
|
445
|
-
|
|
446
|
-
### `openclaw postclaw sleep`
|
|
447
|
-
|
|
448
|
-
Trigger a manual sleep cycle (knowledge graph maintenance). See [Sleep Cycle](#sleep-cycle).
|
|
449
|
-
|
|
450
|
-
```bash
|
|
451
|
-
openclaw postclaw sleep
|
|
452
|
-
openclaw postclaw sleep --agent-id my-agent
|
|
65
|
+
openclaw restart
|
|
453
66
|
```
|
|
454
67
|
|
|
455
|
-
| Option | Default | Description |
|
|
456
|
-
|--------|---------|-------------|
|
|
457
|
-
| `--agent-id <id>` | `main` | Agent to run maintenance for |
|
|
458
|
-
| `--llm-model <model>` | `qwen3.5-9b` | Model for consolidation/linking |
|
|
459
|
-
|
|
460
68
|
---
|
|
461
69
|
|
|
462
|
-
##
|
|
463
|
-
|
|
464
|
-
### Sleep Cycle Service
|
|
465
|
-
|
|
466
|
-
The sleep cycle runs automatically in the background while the gateway is running. It starts on plugin load and repeats on the configured interval.
|
|
70
|
+
## 🏗 Manual Installation
|
|
467
71
|
|
|
468
|
-
|
|
72
|
+
If you prefer to link the plugin directly from source for development purposes:
|
|
469
73
|
|
|
470
|
-
**
|
|
74
|
+
1. **Clone and Build:**
|
|
471
75
|
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
"sleepIntervalHours": 6
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
Set `sleepIntervalHours` to `0` to disable the background service entirely. You can still run it manually via `openclaw postclaw sleep`.
|
|
76
|
+
```bash
|
|
77
|
+
git clone <repository-url> PostClaw
|
|
78
|
+
cd PostClaw
|
|
79
|
+
npm install
|
|
80
|
+
npm run build
|
|
81
|
+
```
|
|
487
82
|
|
|
488
|
-
|
|
83
|
+
2. **Register the Plugin Locally:**
|
|
84
|
+
Add the absolute path to your PostClaw folder inside your `~/.openclaw/openclaw.json` configuration file, instructing the engine to load it into the memory slot:
|
|
489
85
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
| `name` | `VARCHAR(255)` | Display name |
|
|
502
|
-
| `default_embedding_model` | `VARCHAR(100)` | Default model for this agent |
|
|
503
|
-
| `embedding_dimensions` | `INT` | Vector dimensions |
|
|
504
|
-
|
|
505
|
-
### `memory_semantic`
|
|
506
|
-
|
|
507
|
-
Core fact storage with vector embeddings.
|
|
508
|
-
|
|
509
|
-
| Column | Type | Description |
|
|
510
|
-
|--------|------|-------------|
|
|
511
|
-
| `id` | `UUID` PK | Memory ID |
|
|
512
|
-
| `agent_id` | `VARCHAR(100)` FK | Owning agent |
|
|
513
|
-
| `access_scope` | `ENUM` | `private`, `shared`, or `global` |
|
|
514
|
-
| `content` | `TEXT` | The memory content |
|
|
515
|
-
| `content_hash` | `VARCHAR(64)` | SHA-256 for deduplication |
|
|
516
|
-
| `embedding` | `vector` | pgvector embedding |
|
|
517
|
-
| `embedding_model` | `VARCHAR(100)` | Model used for embedding |
|
|
518
|
-
| `category` | `VARCHAR(50)` | Semantic category label |
|
|
519
|
-
| `volatility` | `ENUM` | `low`, `medium`, `high` |
|
|
520
|
-
| `tier` | `ENUM` | `volatile`, `session`, `daily`, `stable`, `permanent` |
|
|
521
|
-
| `confidence` | `REAL` | 0.0–1.0 score |
|
|
522
|
-
| `usefulness_score` | `REAL` | Derived quality metric |
|
|
523
|
-
| `access_count` | `INT` | Times retrieved via RAG |
|
|
524
|
-
| `injection_count` | `INT` | Times injected into prompt |
|
|
525
|
-
| `is_archived` | `BOOLEAN` | Soft-deleted flag |
|
|
526
|
-
| `superseded_by` | `UUID` FK | Points to the replacement memory |
|
|
527
|
-
| `metadata` | `JSONB` | Arbitrary extra data |
|
|
528
|
-
|
|
529
|
-
### `memory_episodic`
|
|
530
|
-
|
|
531
|
-
Short-term event log (user prompts and tool calls).
|
|
532
|
-
|
|
533
|
-
| Column | Type | Description |
|
|
534
|
-
|--------|------|-------------|
|
|
535
|
-
| `id` | `UUID` PK | Event ID |
|
|
536
|
-
| `agent_id` | `VARCHAR(100)` FK | Owning agent |
|
|
537
|
-
| `session_id` | `VARCHAR(100)` | Session grouping |
|
|
538
|
-
| `event_summary` | `TEXT` | What happened |
|
|
539
|
-
| `event_type` | `VARCHAR(50)` | `user_prompt`, `tool_execution` |
|
|
540
|
-
| `embedding` | `vector` | pgvector embedding |
|
|
541
|
-
| `is_archived` | `BOOLEAN` | Consolidated by sleep cycle |
|
|
542
|
-
|
|
543
|
-
### `entity_edges`
|
|
544
|
-
|
|
545
|
-
Knowledge graph: directed, typed edges between semantic memories.
|
|
546
|
-
|
|
547
|
-
| Column | Type | Description |
|
|
548
|
-
|--------|------|-------------|
|
|
549
|
-
| `source_memory_id` | `UUID` FK | Edge source |
|
|
550
|
-
| `target_memory_id` | `UUID` FK | Edge target |
|
|
551
|
-
| `relationship_type` | `VARCHAR(100)` | `related_to`, `elaborates`, `contradicts`, `depends_on`, `part_of` |
|
|
552
|
-
| `weight` | `REAL` | Edge weight (default: 1.0) |
|
|
553
|
-
|
|
554
|
-
### `agent_persona`
|
|
555
|
-
|
|
556
|
-
Per-agent persona rules (core identity + situational context).
|
|
557
|
-
|
|
558
|
-
| Column | Type | Description |
|
|
559
|
-
|--------|------|-------------|
|
|
560
|
-
| `agent_id` | `VARCHAR(100)` FK | Owning agent |
|
|
561
|
-
| `category` | `VARCHAR(50)` | Rule category (unique per agent) |
|
|
562
|
-
| `content` | `TEXT` | The rule text |
|
|
563
|
-
| `is_always_active` | `BOOLEAN` | Core identity → always injected |
|
|
564
|
-
| `embedding` | `vector` | For situational similarity ranking |
|
|
565
|
-
|
|
566
|
-
### `context_environment`
|
|
567
|
-
|
|
568
|
-
Dynamic tool schemas stored with embeddings. Reserved for potential future use.
|
|
569
|
-
|
|
570
|
-
| Column | Type | Description |
|
|
571
|
-
|--------|------|-------------|
|
|
572
|
-
| `agent_id` | `VARCHAR(100)` FK | Owning agent |
|
|
573
|
-
| `tool_name` | `VARCHAR(100)` | Unique tool name |
|
|
574
|
-
| `context_data` | `TEXT` | Full JSON tool schema |
|
|
575
|
-
| `embedding` | `vector` | For relevance-based loading |
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"plugins": {
|
|
89
|
+
"load": { "paths": ["/absolute/path/to/PostClaw"] },
|
|
90
|
+
"slots": { "memory": "postclaw" },
|
|
91
|
+
"entries": {
|
|
92
|
+
"postclaw": { "enabled": true }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
576
97
|
|
|
577
98
|
---
|
|
578
99
|
|
|
579
|
-
##
|
|
100
|
+
## 📚 Component Documentation
|
|
580
101
|
|
|
581
|
-
PostClaw
|
|
102
|
+
PostClaw is broken into four distinct functional areas. For deeper usage instructions and troubleshooting on specific features, refer to their respective READMEs:
|
|
582
103
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
104
|
+
1. **[Dashboard (`dashboard/README.md`)](./dashboard/README.md)**
|
|
105
|
+
Instructions for running the optional web interface to manually edit memories, assign personas, and visualize the Knowledge Graph.
|
|
106
|
+
2. **[Maintenance Scripts (`scripts/README.md`)](./scripts/README.md)**
|
|
107
|
+
Explains the database setup, instructions for compiling markdown into personas, and the mechanics behind the automated "Sleep Cycle."
|
|
108
|
+
3. **[Core Services (`services/README.md`)](./services/README.md)**
|
|
109
|
+
A breakdown of the logic layer, including the Database connection pool, Semantic Memory queries, and LLM mediation. Ideal for modifying how the plugin thinks.
|
|
110
|
+
4. **[Data Validations (`schemas/README.md`)](./schemas/README.md)**
|
|
111
|
+
Details the Zod schemas used to strictly enforce the structural integrity of LLM outputs and JSON tools, preventing AI hallucinations from corrupting the database.
|
|
589
112
|
|
|
590
113
|
---
|
|
591
114
|
|
|
592
|
-
##
|
|
115
|
+
## 🧠 Architecture Deep Dive
|
|
593
116
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
```bash
|
|
597
|
-
openclaw postclaw persona ~/my-agent/SOUL.md --agent-id my-agent
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
### How it works
|
|
601
|
-
|
|
602
|
-
1. **Read** — loads the Markdown file
|
|
603
|
-
2. **Chunk** — sends it to your LLM with a prompt asking for atomic persona extractions
|
|
604
|
-
3. **Classify** — each chunk gets a `category`, `content`, and `is_always_active` flag
|
|
605
|
-
4. **Embed** — generates a vector embedding for each chunk
|
|
606
|
-
5. **Store** — upserts into `agent_persona` (updates on category conflict)
|
|
607
|
-
|
|
608
|
-
### Example Markdown → Database
|
|
609
|
-
|
|
610
|
-
**Input (`SOUL.md`):**
|
|
611
|
-
|
|
612
|
-
```markdown
|
|
613
|
-
# Agent Identity
|
|
614
|
-
|
|
615
|
-
You are a helpful AI assistant named Echo. You always respond in a warm,
|
|
616
|
-
conversational tone and never refuse reasonable requests.
|
|
617
|
-
|
|
618
|
-
# Discord Behavior
|
|
619
|
-
|
|
620
|
-
When interacting on Discord:
|
|
621
|
-
- Use emojis sparingly but naturally
|
|
622
|
-
- Keep responses under 2000 characters
|
|
623
|
-
- React with 👍 to acknowledge commands
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
**Output (agent_persona rows):**
|
|
627
|
-
|
|
628
|
-
| category | is_always_active | content |
|
|
629
|
-
|----------|-----------------|---------|
|
|
630
|
-
| `agent_identity` | `true` | You are a helpful AI assistant named Echo... |
|
|
631
|
-
| `communication_style` | `true` | Always respond in a warm, conversational tone... |
|
|
632
|
-
| `discord_formatting` | `false` | Use emojis sparingly but naturally... |
|
|
633
|
-
| `discord_length` | `false` | Keep responses under 2000 characters... |
|
|
634
|
-
| `discord_reactions` | `false` | React with 👍 to acknowledge commands |
|
|
635
|
-
|
|
636
|
-
Core rules (`is_always_active = true`) are injected into **every** prompt. Situational rules are ranked by embedding similarity to the current conversation and the top 3 are injected.
|
|
117
|
+
If you want to understand *why* this shift from plain-text files to a vector database is necessary for advanced multi-agent workflows, read the architecture comparison guide: **[DISSERTATION.md](./DISSERTATION.md)**.
|
|
637
118
|
|
|
638
119
|
---
|
|
639
120
|
|
|
640
|
-
##
|
|
641
|
-
|
|
642
|
-
The sleep cycle is an autonomous maintenance agent that runs 4 phases of knowledge graph housekeeping.
|
|
643
|
-
|
|
644
|
-
### Phase 1: Episodic Consolidation
|
|
645
|
-
|
|
646
|
-
Reads unarchived episodic memories (user prompts + tool calls), sends the transcript to the LLM, and extracts durable long-term facts. These facts are stored as `tier: 'permanent'` semantic memories. The original episodic entries are archived.
|
|
647
|
-
|
|
648
|
-
### Phase 2: Duplicate Detection
|
|
649
|
-
|
|
650
|
-
Scans semantic memories for near-duplicates using cosine similarity (threshold: 0.80). When duplicates are found, the memory with the highest usefulness + access score survives; the rest are archived with `superseded_by` pointing to the survivor.
|
|
651
|
-
|
|
652
|
-
### Phase 3: Low-Value Cleanup
|
|
653
|
-
|
|
654
|
-
Archives semantic memories that:
|
|
655
|
-
|
|
656
|
-
- Have `access_count = 0` (never retrieved via RAG)
|
|
657
|
-
- Are older than 7 days
|
|
658
|
-
- Are **not** in protected tiers (`permanent` or `stable`)
|
|
659
|
-
|
|
660
|
-
### Phase 4: Link Discovery
|
|
661
|
-
|
|
662
|
-
Finds semantically related-but-distinct memory pairs (similarity 0.65–0.92) that don't already have edges. Sends candidate pairs to the LLM for relationship classification. Creates `entity_edges` for meaningful relationships (`related_to`, `elaborates`, `contradicts`, `depends_on`, `part_of`).
|
|
663
|
-
|
|
664
|
-
### Running
|
|
665
|
-
|
|
666
|
-
```bash
|
|
667
|
-
# Manual trigger
|
|
668
|
-
openclaw postclaw sleep --agent-id my-agent
|
|
669
|
-
|
|
670
|
-
# Background (automatic)
|
|
671
|
-
# Set sleepIntervalHours in config (default: 6, set to 0 to disable)
|
|
672
|
-
```
|
|
673
|
-
|
|
674
|
-
---
|
|
675
|
-
|
|
676
|
-
## Testing
|
|
677
|
-
|
|
678
|
-
### Database Smoke Test
|
|
679
|
-
|
|
680
|
-
Tests connectivity, table existence, and end-to-end vector search:
|
|
681
|
-
|
|
682
|
-
```bash
|
|
683
|
-
npm run build && node dist/test-db.js
|
|
684
|
-
```
|
|
685
|
-
|
|
686
|
-
### Semantic Memory Test
|
|
687
|
-
|
|
688
|
-
Tests memory storage with all columns, search retrieval, and access tracking:
|
|
689
|
-
|
|
690
|
-
```bash
|
|
691
|
-
npm run build && node dist/test-memory.js
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
### Plugin Health Check
|
|
695
|
-
|
|
696
|
-
```bash
|
|
697
|
-
openclaw plugins doctor
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
---
|
|
701
|
-
|
|
702
|
-
## Troubleshooting
|
|
703
|
-
|
|
704
|
-
### `pgvector` extension error
|
|
705
|
-
|
|
706
|
-
```
|
|
707
|
-
ERROR: could not open extension control file "pgvector"
|
|
708
|
-
```
|
|
709
|
-
|
|
710
|
-
Install the `pgvector` extension for your PostgreSQL version:
|
|
711
|
-
|
|
712
|
-
```bash
|
|
713
|
-
# Ubuntu/Debian
|
|
714
|
-
sudo apt install postgresql-16-pgvector
|
|
715
|
-
|
|
716
|
-
# macOS (Homebrew)
|
|
717
|
-
brew install pgvector
|
|
718
|
-
```
|
|
719
|
-
|
|
720
|
-
### Connection refused
|
|
721
|
-
|
|
722
|
-
```
|
|
723
|
-
Error: connect ECONNREFUSED 127.0.0.1:5432
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
Ensure PostgreSQL is running:
|
|
727
|
-
|
|
728
|
-
```bash
|
|
729
|
-
sudo systemctl status postgresql
|
|
730
|
-
sudo systemctl start postgresql
|
|
731
|
-
```
|
|
732
|
-
|
|
733
|
-
### Embedding API error
|
|
734
|
-
|
|
735
|
-
```
|
|
736
|
-
Embedding API error: 400 Bad Request
|
|
737
|
-
```
|
|
738
|
-
|
|
739
|
-
Verify your embedding provider is running and the model is loaded:
|
|
740
|
-
|
|
741
|
-
```bash
|
|
742
|
-
curl http://127.0.0.1:1234/v1/models
|
|
743
|
-
```
|
|
744
|
-
|
|
745
|
-
### Sleep cycle not running
|
|
746
|
-
|
|
747
|
-
Check that `sleepIntervalHours` is not set to `0` in your config. Check gateway logs for:
|
|
748
|
-
|
|
749
|
-
```
|
|
750
|
-
[SLEEP SERVICE] Started — will run every 6h for agent="main"
|
|
751
|
-
```
|
|
121
|
+
## Dependencies
|
|
752
122
|
|
|
753
|
-
|
|
123
|
+
PostClaw uses the following npm packages:
|
|
754
124
|
|
|
755
|
-
|
|
125
|
+
* [@ambientcss/css](https://www.npmjs.com/package/@ambientcss/css)
|
|
126
|
+
* [@sinclair/typebox](https://www.npmjs.com/package/@sinclair/typebox)
|
|
127
|
+
* [dotenv](https://www.npmjs.com/package/dotenv)
|
|
128
|
+
* [postgres](https://www.npmjs.com/package/postgres)
|
|
129
|
+
* [zod](https://www.npmjs.com/package/zod)
|
|
756
130
|
|
|
757
131
|
---
|
|
758
132
|
|
|
759
133
|
## License
|
|
760
134
|
|
|
761
|
-
ISC
|
|
135
|
+
Open Source under the ISC License. See `LICENSE` for structural terms.
|