@cognee/cognee-openclaw 2026.6.11 → 2026.7.9
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 +226 -97
- package/dist/src/breaker.d.ts +20 -0
- package/dist/src/breaker.js +80 -0
- package/dist/src/breaker.js.map +1 -0
- package/dist/src/client.d.ts +42 -1
- package/dist/src/client.js +80 -5
- package/dist/src/client.js.map +1 -1
- package/dist/src/config.d.ts +6 -2
- package/dist/src/config.js +23 -9
- package/dist/src/config.js.map +1 -1
- package/dist/src/plugin.js +588 -172
- package/dist/src/plugin.js.map +1 -1
- package/dist/src/scope.d.ts +8 -0
- package/dist/src/scope.js +22 -0
- package/dist/src/scope.js.map +1 -1
- package/dist/src/server.d.ts +66 -0
- package/dist/src/server.js +416 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/sync.js +52 -8
- package/dist/src/sync.js.map +1 -1
- package/dist/src/types.d.ts +16 -1
- package/dist/src/types.js.map +1 -1
- package/openclaw.plugin.json +46 -6
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -8,10 +8,12 @@ OpenClaw plugin that adds Cognee-backed memory with **multi-scope support** (com
|
|
|
8
8
|
- **Scope-aware routing**: Memory files are automatically routed to the correct dataset based on directory structure
|
|
9
9
|
- **Multi-scope recall**: Before each agent run, searches across all configured scopes and injects labeled context
|
|
10
10
|
- **Session tracking**: Multi-turn conversation context via Cognee's session system
|
|
11
|
+
- **Agent lifecycle registration**: Registers/unregisters each agent session with the Cognee server on every prompt turn; combined with `COGNEE_AGENT_MODE=true` on the server, Cognee shuts down automatically when all agents disconnect
|
|
11
12
|
- **14 search types**: From simple semantic search (CHUNKS) to chain-of-thought graph reasoning (GRAPH_COMPLETION_COT) to auto-selection (FEELING_LUCKY)
|
|
13
|
+
- **Lazy dataset resolution**: On first prompt, if a dataset UUID is not cached locally, the plugin queries the Cognee server by name so you can connect to any pre-existing dataset without manual configuration
|
|
12
14
|
- **Health check**: Verifies Cognee API connectivity before operations
|
|
13
15
|
- **Auto-index**: Syncs memory markdown files to Cognee via `/remember` (add new, update changed, forget removed, skip unchanged). The `/remember` endpoint runs ingest, graph build, and graph enrichment in one server-side call.
|
|
14
|
-
- **In-session memory**:
|
|
16
|
+
- **In-session memory**: Every tool call is stored as a `TraceEntry` and every prompt/answer pair as a `QAEntry` in Cognee's session cache (`captureSession`, on by default); with `AUTO_FEEDBACK=true` set on the Cognee container, follow-up messages are auto-classified as feedback and attached to the previous QA; `session_end` triggers `/improve` to bridge the session cache into the graph
|
|
15
17
|
- **One-command setup**: `openclaw cognee setup` configures Cognee as the sole memory provider
|
|
16
18
|
- **CLI commands**: `openclaw cognee setup`, `openclaw cognee index`, `openclaw cognee status`, `openclaw cognee health`, `openclaw cognee scopes`, `openclaw cognee forget`, `openclaw cognee improve`
|
|
17
19
|
|
|
@@ -19,33 +21,54 @@ OpenClaw plugin that adds Cognee-backed memory with **multi-scope support** (com
|
|
|
19
21
|
|
|
20
22
|
OpenClaw will auto-load any plugin it discovers if `plugins.allow` is not set. To restrict which plugins can load, add an explicit allowlist to your `~/.openclaw/openclaw.json`:
|
|
21
23
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"plugins": {
|
|
27
|
+
"allow": ["cognee-openclaw"]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
27
30
|
```
|
|
28
31
|
|
|
32
|
+
> **Important**: `plugins.allow` must be a JSON **array**, not an object. `{"cognee-openclaw": true}` is invalid and will cause a config parse error.
|
|
33
|
+
|
|
29
34
|
Without this, any plugin found in your environment could be loaded automatically.
|
|
30
35
|
|
|
31
36
|
## Installation
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
### Published package
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Pin to an exact version to avoid unintended updates (supply-chain best practice)
|
|
42
|
+
openclaw plugins install @cognee/cognee-openclaw@2026.3.0
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Development install (symlink)
|
|
46
|
+
|
|
47
|
+
When developing or modifying the plugin, install as a symlink so that `npm run build` takes effect immediately without reinstalling:
|
|
34
48
|
|
|
35
49
|
```bash
|
|
36
50
|
cd integrations/openclaw
|
|
37
51
|
npm install
|
|
38
52
|
npm run build
|
|
39
|
-
openclaw plugins install
|
|
53
|
+
openclaw plugins install --link .
|
|
40
54
|
```
|
|
41
55
|
|
|
42
|
-
|
|
56
|
+
> **Why `--link`?** A standard install copies the built files once. Any subsequent `npm run build` updates the source but not the installed copy — so OpenClaw keeps running the stale version. With `--link`, the installed path **is** the source directory, so every build is reflected on the next gateway start.
|
|
43
57
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
After install, verify the install entry in `~/.openclaw/openclaw.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
"installs": {
|
|
62
|
+
"cognee-openclaw": {
|
|
63
|
+
"source": "path",
|
|
64
|
+
"sourcePath": "/path/to/integrations/openclaw",
|
|
65
|
+
"installPath": "/path/to/integrations/openclaw"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
47
68
|
```
|
|
48
69
|
|
|
70
|
+
`sourcePath === installPath` confirms the symlink is in place.
|
|
71
|
+
|
|
49
72
|
## Quick Start
|
|
50
73
|
|
|
51
74
|
After installing, run the setup command to configure Cognee as the memory provider:
|
|
@@ -60,81 +83,175 @@ openclaw cognee setup --hybrid
|
|
|
60
83
|
|
|
61
84
|
**Default mode** disables built-in memory providers — all recall comes from Cognee.
|
|
62
85
|
|
|
63
|
-
**Hybrid mode** keeps `memory-core` enabled in config, but on OpenClaw versions with exclusive memory slots only the slot winner loads at runtime.
|
|
64
|
-
This plugin registers its own memory flush plan, so pre-compaction flush works when Cognee owns the memory slot.
|
|
86
|
+
**Hybrid mode** keeps `memory-core` enabled in config, but on OpenClaw versions with exclusive memory slots only the slot winner loads at runtime. This plugin registers its own memory flush plan, so pre-compaction flush works when Cognee owns the memory slot.
|
|
65
87
|
|
|
66
88
|
Then configure the Cognee connection in `~/.openclaw/openclaw.json`:
|
|
67
89
|
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
cognee-openclaw
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"plugins": {
|
|
93
|
+
"allow": ["cognee-openclaw"],
|
|
94
|
+
"entries": {
|
|
95
|
+
"cognee-openclaw": {
|
|
96
|
+
"enabled": true,
|
|
97
|
+
"hooks": {
|
|
98
|
+
"allowPromptInjection": true
|
|
99
|
+
},
|
|
100
|
+
"config": {
|
|
101
|
+
"baseUrl": "http://localhost:8011",
|
|
102
|
+
"datasetName": "agent_sessions"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"memory-core": { "enabled": false },
|
|
106
|
+
"memory-lancedb": { "enabled": false }
|
|
107
|
+
},
|
|
108
|
+
"slots": {
|
|
109
|
+
"memory": "cognee-openclaw"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> **`hooks.allowPromptInjection: true` is required.** Without it, OpenClaw blocks the plugin from reading the prompt content in the `before_prompt_build` hook — recall is silently skipped and no memories are injected. This key was named `allowConversationAccess` in versions before OpenClaw 2026.4.2; the old key is silently rejected, so if you copied config from an older guide, update to `allowPromptInjection`. Restart the gateway after adding or changing the flag.
|
|
116
|
+
|
|
117
|
+
### Multi-Agent Quick Start
|
|
118
|
+
|
|
119
|
+
For a gateway with multiple named agents sharing a default dataset:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"plugins": {
|
|
124
|
+
"allow": ["cognee-openclaw"],
|
|
125
|
+
"entries": {
|
|
126
|
+
"cognee-openclaw": {
|
|
127
|
+
"enabled": true,
|
|
128
|
+
"hooks": { "allowPromptInjection": true }
|
|
129
|
+
},
|
|
130
|
+
"memory-core": { "enabled": false },
|
|
131
|
+
"memory-lancedb": { "enabled": false }
|
|
132
|
+
},
|
|
133
|
+
"slots": { "memory": "cognee-openclaw" }
|
|
134
|
+
},
|
|
135
|
+
"auth": {
|
|
136
|
+
"profiles": {
|
|
137
|
+
"openai:manual": { "provider": "openai", "mode": "token" }
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"models": {
|
|
141
|
+
"providers": {
|
|
142
|
+
"openai": {
|
|
143
|
+
"baseUrl": "https://api.openai.com/v1",
|
|
144
|
+
"models": [{ "id": "gpt-4o-mini", "name": "GPT-4o mini" }]
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"agents": {
|
|
149
|
+
"defaults": {
|
|
150
|
+
"model": { "primary": "openai/gpt-4o-mini" },
|
|
151
|
+
"models": { "openai/gpt-4o-mini": {} }
|
|
152
|
+
},
|
|
153
|
+
"list": [
|
|
154
|
+
{ "id": "Will", "name": "Will" },
|
|
155
|
+
{ "id": "Elizabeth", "name": "Elizabeth" }
|
|
156
|
+
]
|
|
157
|
+
},
|
|
158
|
+
"gateway": {
|
|
159
|
+
"auth": { "mode": "token", "token": "your-gateway-token" }
|
|
160
|
+
}
|
|
161
|
+
}
|
|
79
162
|
```
|
|
80
163
|
|
|
81
|
-
>
|
|
164
|
+
> **Required fields when adding a `models.providers.<provider>` block**: `baseUrl` is required by the config schema. Omitting it causes a validation error that prevents the gateway from starting.
|
|
165
|
+
|
|
166
|
+
#### Default: all agents share one dataset
|
|
167
|
+
|
|
168
|
+
By default — no matter how many agents are configured — every agent reads and writes the **same dataset** (`agent_sessions`), exactly like the claude-code and codex Cognee integrations. Agents stay distinguishable within it: each agent session registers separately and its conversation is keyed by its own Cognee session id, so recall and session bridging never mix sessions up. Shared memory is usually what you want: agents benefit from each other's knowledge.
|
|
169
|
+
|
|
170
|
+
#### Opt-in: per-agent isolated datasets
|
|
171
|
+
|
|
172
|
+
To give each agent its own dataset (own graph, own recall space), set **both** of these in the plugin config:
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
"config": {
|
|
176
|
+
"perAgentMemory": true,
|
|
177
|
+
"agentDatasetPrefix": "myorg-agent"
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
With this, agent `Will` writes to dataset `myorg-agent-will`, agent `Elizabeth` to `myorg-agent-elizabeth`, and each agent's recall only searches its own dataset (plus any shared `company`/`user` scopes you configure). Use `agentDatasetTemplate` (e.g. `"{agentId}"`) instead of the prefix if you need full control over the dataset names.
|
|
182
|
+
|
|
183
|
+
> **Both settings are required.** `perAgentMemory: true` on its own does nothing — isolation only activates when an `agentDatasetPrefix` or `agentDatasetTemplate` is also set. Per-agent memory is never enabled automatically.
|
|
82
184
|
|
|
83
185
|
### Cognee Cloud
|
|
84
186
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
187
|
+
Cognee Cloud tenants (staging and production) serve the **same `/api/v1/*` API as a self-hosted server**, so connecting to the cloud is just the default configuration pointed at your tenant URL, with an API key:
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"plugins": {
|
|
192
|
+
"entries": {
|
|
193
|
+
"cognee-openclaw": {
|
|
194
|
+
"enabled": true,
|
|
195
|
+
"config": {
|
|
196
|
+
"baseUrl": "https://tenant-xxx.aws.cognee.ai",
|
|
197
|
+
"apiKey": "${COGNEE_API_KEY}"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
96
203
|
```
|
|
97
204
|
|
|
98
205
|
Or via environment variables:
|
|
99
206
|
|
|
100
207
|
```bash
|
|
101
|
-
export
|
|
102
|
-
export COGNEE_BASE_URL=https://tenant-xxx.cloud.cognee.ai/api
|
|
208
|
+
export COGNEE_BASE_URL=https://tenant-xxx.aws.cognee.ai
|
|
103
209
|
export COGNEE_API_KEY=your-api-key
|
|
104
210
|
```
|
|
105
211
|
|
|
106
|
-
**
|
|
212
|
+
Do **not** set `mode: "cloud"` — leave it at the default. All operations (file sync, updates, recall, session capture, agent registration, improve) work against cloud tenants through the standard paths.
|
|
213
|
+
|
|
214
|
+
> **`COGNEE_API_KEY` is mandatory for any remote/cloud server.** On a local server the plugin auto-mints a key on first use (a one-time JWT login as the default user bootstraps the mint); remote servers expose no login route, so there is nothing to mint with — every request authenticates via `X-Api-Key`. The variable must be present in the environment the **gateway process** starts from — a daemonized gateway does not see `export`s from your current shell. Set it, then `openclaw gateway stop && openclaw gateway start`.
|
|
215
|
+
|
|
216
|
+
> **Deprecated: `mode: "cloud"` / `COGNEE_MODE=cloud`.** This mode targets a legacy path scheme (`baseUrl` ending `/api`, alias routes like `/recall` without the `/api/v1` prefix) that no current Cognee Cloud deployment serves — the platform control plane exposes no data routes, and tenants use the standard `/api/v1/*` paths. The mode is kept only for backward compatibility with older deployments; on current tenants it will 404. Newer capabilities (session capture, agent registration) are not implemented for the legacy scheme and never will be.
|
|
107
217
|
|
|
108
|
-
|
|
218
|
+
## Environment Variables
|
|
219
|
+
|
|
220
|
+
| Variable | Default | Description |
|
|
221
|
+
|----------|---------|-------------|
|
|
222
|
+
| `COGNEE_BASE_URL` | `http://localhost:8011` | Cognee API base URL |
|
|
223
|
+
| `COGNEE_PLUGIN_DATASET` | `agent_sessions` | Dataset name for single-scope mode. Overridden by `datasetName` in config if set. Same variable name used by the claude-code and codex Cognee integrations. |
|
|
224
|
+
| `COGNEE_MODE` | `local` | **Deprecated** — leave at `"local"` for self-hosted *and* cloud tenants. `"cloud"` targets a legacy path scheme no current deployment serves (see "Cognee Cloud") |
|
|
225
|
+
| `COGNEE_API_KEY` | — | API key (cloud mode or authenticated self-hosted) |
|
|
226
|
+
| `COGNEE_USERNAME` | — | Login username (self-hosted with auth) |
|
|
227
|
+
| `COGNEE_PASSWORD` | — | Login password (self-hosted with auth) |
|
|
228
|
+
| `OPENCLAW_USER_ID` | — | User identifier for user-scoped memory |
|
|
229
|
+
| `OPENCLAW_AGENT_ID` | `default` | Agent identifier for agent-scoped memory |
|
|
109
230
|
|
|
110
231
|
## Multi-Scope Memory
|
|
111
232
|
|
|
112
233
|
For production use, enable multi-scope mode by setting any scope-specific dataset name:
|
|
113
234
|
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- company
|
|
135
|
-
|
|
136
|
-
# Default scope for files not matching any route
|
|
137
|
-
defaultWriteScope: "agent"
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"plugins": {
|
|
238
|
+
"entries": {
|
|
239
|
+
"cognee-openclaw": {
|
|
240
|
+
"enabled": true,
|
|
241
|
+
"config": {
|
|
242
|
+
"baseUrl": "http://localhost:8011",
|
|
243
|
+
"companyDataset": "acme-shared",
|
|
244
|
+
"userDatasetPrefix": "acme-user",
|
|
245
|
+
"agentDatasetPrefix": "acme-agent",
|
|
246
|
+
"userId": "${OPENCLAW_USER_ID}",
|
|
247
|
+
"agentId": "code-assistant",
|
|
248
|
+
"recallScopes": ["agent", "user", "company"],
|
|
249
|
+
"defaultWriteScope": "agent"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
138
255
|
```
|
|
139
256
|
|
|
140
257
|
### Memory Scope Hierarchy
|
|
@@ -158,14 +275,14 @@ MEMORY.md -> agent scope
|
|
|
158
275
|
|
|
159
276
|
Custom routing via config:
|
|
160
277
|
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
scope: company
|
|
165
|
-
|
|
166
|
-
scope:
|
|
167
|
-
|
|
168
|
-
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"scopeRouting": [
|
|
281
|
+
{ "pattern": "memory/shared/**", "scope": "company" },
|
|
282
|
+
{ "pattern": "memory/personal/**", "scope": "user" },
|
|
283
|
+
{ "pattern": "memory/**", "scope": "agent" }
|
|
284
|
+
]
|
|
285
|
+
}
|
|
169
286
|
```
|
|
170
287
|
|
|
171
288
|
### Multi-Scope Recall
|
|
@@ -188,8 +305,16 @@ This lets the agent distinguish between personal context, shared knowledge, and
|
|
|
188
305
|
|
|
189
306
|
| Option | Type | Default | Description |
|
|
190
307
|
|--------|------|---------|-------------|
|
|
191
|
-
| `baseUrl` | string | `http://localhost:
|
|
308
|
+
| `baseUrl` | string | `http://localhost:8011` | Cognee API base URL (also: `COGNEE_BASE_URL`) |
|
|
192
309
|
| `apiKey` | string | `$COGNEE_API_KEY` | API key for authentication |
|
|
310
|
+
| `username` | string | `$COGNEE_USERNAME` | Login username |
|
|
311
|
+
| `password` | string | `$COGNEE_PASSWORD` | Login password |
|
|
312
|
+
|
|
313
|
+
### Dataset
|
|
314
|
+
|
|
315
|
+
| Option | Type | Default | Description |
|
|
316
|
+
|--------|------|---------|-------------|
|
|
317
|
+
| `datasetName` | string | `agent_sessions` | Dataset name for single-scope mode (also: `COGNEE_PLUGIN_DATASET`) |
|
|
193
318
|
|
|
194
319
|
### Memory Scopes
|
|
195
320
|
|
|
@@ -198,11 +323,13 @@ This lets the agent distinguish between personal context, shared knowledge, and
|
|
|
198
323
|
| `companyDataset` | string | — | Dataset for company-wide memory. Setting this enables multi-scope mode |
|
|
199
324
|
| `userDatasetPrefix` | string | — | Prefix for user datasets (becomes `{prefix}-{userId}`) |
|
|
200
325
|
| `agentDatasetPrefix` | string | — | Prefix for agent datasets (becomes `{prefix}-{agentId}`) |
|
|
326
|
+
| `agentDatasetTemplate` | string | — | Template for per-agent dataset with `{agentId}` placeholder; takes precedence over `agentDatasetPrefix` |
|
|
201
327
|
| `userId` | string | `$OPENCLAW_USER_ID` | User identifier for user-scoped memory |
|
|
202
|
-
| `agentId` | string | `default` | Agent identifier for agent-scoped memory |
|
|
328
|
+
| `agentId` | string | `default` | Agent identifier for agent-scoped memory (also: `OPENCLAW_AGENT_ID`) |
|
|
203
329
|
| `recallScopes` | string[] | `["agent","user","company"]` | Scopes to search during recall, in priority order |
|
|
204
330
|
| `defaultWriteScope` | string | `agent` | Default scope for files not matching any route |
|
|
205
331
|
| `scopeRouting` | object[] | (see above) | Path-to-scope routing rules |
|
|
332
|
+
| `perAgentMemory` | boolean | `false` | Give each agent its own dataset. Strictly opt-in (never auto-enabled); requires `agentDatasetPrefix` or `agentDatasetTemplate` to also be set — see "Multi-Agent Quick Start". By default all agents share one dataset. |
|
|
206
333
|
|
|
207
334
|
### Sessions
|
|
208
335
|
|
|
@@ -210,22 +337,25 @@ This lets the agent distinguish between personal context, shared knowledge, and
|
|
|
210
337
|
|--------|------|---------|-------------|
|
|
211
338
|
| `enableSessions` | boolean | `true` | Enable session-based conversation tracking |
|
|
212
339
|
| `persistSessionsAfterEnd` | boolean | `true` | Persist session Q&A into the knowledge graph |
|
|
340
|
+
| `captureSession` | boolean | `true` | Store each tool call as a `TraceEntry` and each prompt/answer pair as a `QAEntry` in Cognee's session cache (requires `enableSessions`) |
|
|
213
341
|
|
|
214
342
|
### Search
|
|
215
343
|
|
|
216
344
|
| Option | Type | Default | Description |
|
|
217
345
|
|--------|------|---------|-------------|
|
|
218
|
-
| `searchType` | string | `
|
|
346
|
+
| `searchType` | string | `HYBRID_COMPLETION` | Search strategy (see below) |
|
|
219
347
|
| `maxResults` | number | `3` | Max memories to inject per scope (sent as `top_k` to Cognee) |
|
|
220
348
|
| `minScore` | number | `0.3` | Minimum relevance score filter |
|
|
349
|
+
| `maxTokens` | number | `512` | Token cap for recall per scope |
|
|
221
350
|
| `searchPrompt` | string | `""` | System prompt to guide search |
|
|
222
|
-
|
|
|
351
|
+
| `recallInjectionPosition` | string | `prependContext` | Where recalled memories are injected: `prependSystemContext`, `appendSystemContext`, or `prependContext` |
|
|
223
352
|
|
|
224
353
|
### Search Types
|
|
225
354
|
|
|
226
355
|
| Type | Description |
|
|
227
356
|
|------|-------------|
|
|
228
|
-
| `
|
|
357
|
+
| `HYBRID_COMPLETION` | **Default** — combined vector + graph retrieval |
|
|
358
|
+
| `GRAPH_COMPLETION` | Graph traversal + LLM reasoning; slower but deeper — best for offline/CLI queries rather than the per-prompt recall path |
|
|
229
359
|
| `CHUNKS` | Semantic vector search, returns raw stored text (no generation) |
|
|
230
360
|
| `FEELING_LUCKY` | Auto-selects a strategy per query (may pick generative modes) |
|
|
231
361
|
| `GRAPH_COMPLETION_COT` | Chain-of-thought reasoning over graph (iterative) |
|
|
@@ -233,7 +363,6 @@ This lets the agent distinguish between personal context, shared knowledge, and
|
|
|
233
363
|
| `GRAPH_SUMMARY_COMPLETION` | Graph with pre-computed summaries |
|
|
234
364
|
| `RAG_COMPLETION` | Traditional RAG with document chunks |
|
|
235
365
|
| `TRIPLET_COMPLETION` | Subject-predicate-object search |
|
|
236
|
-
| `CHUNKS` | Pure semantic vector search |
|
|
237
366
|
| `CHUNKS_LEXICAL` | Keyword/lexical search |
|
|
238
367
|
| `SUMMARIES` | Pre-computed hierarchical summaries |
|
|
239
368
|
| `TEMPORAL` | Time-aware graph search |
|
|
@@ -248,9 +377,9 @@ This lets the agent distinguish between personal context, shared knowledge, and
|
|
|
248
377
|
| `autoRecall` | boolean | `true` | Inject memories before agent runs |
|
|
249
378
|
| `autoIndex` | boolean | `true` | Sync memory files on startup, after agent runs, and on session end |
|
|
250
379
|
| `improveOnSessionEnd` | boolean | `true` | On `session_end`, call `/improve` with the session id to bridge session-cache QAs into the graph |
|
|
251
|
-
| ~~`autoCognify`~~ | boolean | `true` | **Deprecated** — `/remember` runs the cognify step server-side
|
|
252
|
-
| ~~`autoMemify`~~ | boolean | `false` | **Deprecated** — graph enrichment now runs server-side via `/remember`
|
|
253
|
-
| ~~`deleteMode`~~ | string | `soft` | **Deprecated** — `/forget` always runs
|
|
380
|
+
| ~~`autoCognify`~~ | boolean | `true` | **Deprecated** — `/remember` runs the cognify step server-side |
|
|
381
|
+
| ~~`autoMemify`~~ | boolean | `false` | **Deprecated** — graph enrichment now runs server-side via `/remember` |
|
|
382
|
+
| ~~`deleteMode`~~ | string | `soft` | **Deprecated** — `/forget` always runs soft delete |
|
|
254
383
|
|
|
255
384
|
### Timeouts
|
|
256
385
|
|
|
@@ -259,6 +388,17 @@ This lets the agent distinguish between personal context, shared knowledge, and
|
|
|
259
388
|
| `requestTimeoutMs` | number | `60000` | HTTP timeout for Cognee requests |
|
|
260
389
|
| `ingestionTimeoutMs` | number | `300000` | HTTP timeout for add/update requests |
|
|
261
390
|
|
|
391
|
+
### Recall budget & circuit breaker
|
|
392
|
+
|
|
393
|
+
Recall runs on the prompt hot path, so it is bounded: each recall call gets a short timeout, the whole recall step gets a wall-clock budget, and repeated failures open a circuit breaker that skips recall until the server recovers. Memories missed under the budget are dropped for that turn only — writes (traces, QA, file sync, improve) are never budgeted. The breaker state is shared with the claude-code and codex integrations via `~/.cognee-plugin/recall-breaker.json`, so all plugins using one Cognee server back off together.
|
|
394
|
+
|
|
395
|
+
| Option | Type | Default | Description |
|
|
396
|
+
|--------|------|---------|-------------|
|
|
397
|
+
| `recallTimeoutMs` | number | `2500` | Per recall HTTP call timeout (no retries) |
|
|
398
|
+
| `recallBudgetMs` | number | `4000` | Overall wall-clock budget for the recall step per prompt |
|
|
399
|
+
| `recallBreakerThreshold` | number | `5` | Consecutive failures (network/timeout/5xx) before the breaker opens |
|
|
400
|
+
| `recallBreakerCooldownMs` | number | `120000` | How long recall is skipped once the breaker opens |
|
|
401
|
+
|
|
262
402
|
Note: Files are stored in Cognee using sanitized relative paths as filenames (e.g., `MEMORY.md.txt` for `MEMORY.md`, `memory.tools.md.txt` for `memory/tools.md`) for easy identification and to avoid path separator issues.
|
|
263
403
|
|
|
264
404
|
## CLI Commands
|
|
@@ -266,7 +406,7 @@ Note: Files are stored in Cognee using sanitized relative paths as filenames (e.
|
|
|
266
406
|
```bash
|
|
267
407
|
# Configure Cognee as the memory provider (run once after install)
|
|
268
408
|
openclaw cognee setup # Cognee only
|
|
269
|
-
openclaw cognee setup --hybrid # Keep built-ins enabled in config
|
|
409
|
+
openclaw cognee setup --hybrid # Keep built-ins enabled in config
|
|
270
410
|
|
|
271
411
|
# Manually sync memory files to Cognee
|
|
272
412
|
openclaw cognee index
|
|
@@ -289,26 +429,13 @@ openclaw cognee improve # current dataset, all sessions
|
|
|
289
429
|
openclaw cognee improve --session-id <id> # scope to one session
|
|
290
430
|
```
|
|
291
431
|
|
|
292
|
-
## How It Works
|
|
293
|
-
|
|
294
|
-
1. **On startup**: Health check, then scan `memory/` directory and call `/api/v1/remember` (one batched multipart upload per scope). Cognee runs add + cognify + improve server-side.
|
|
295
|
-
2. **Before each prompt**: Call `/api/v1/recall` for each configured scope in parallel, merge results with scope labels, inject as `<cognee_memories>` context. The openclaw session id is passed through; Cognee uses it to auto-capture the turn as a session QA and (with `AUTO_FEEDBACK=true`) auto-attach feedback to the prior QA when one is detected.
|
|
296
|
-
3. **After each agent run**: Re-scan memory files; new files batch into `/remember`, changed files go through `PATCH /update` (self-hosted) with fallback to `/remember`, removed files are dropped via `/forget`.
|
|
297
|
-
4. **On session end**: Final sync sweep. With `improveOnSessionEnd` on, also dispatches `/improve` for the just-ended session id to bridge session QAs into the permanent graph.
|
|
298
|
-
5. **State tracking**:
|
|
299
|
-
- `~/.openclaw/memory/cognee/datasets.json` — dataset ID mapping
|
|
300
|
-
- `~/.openclaw/memory/cognee/scoped-sync-indexes.json` — per-scope file hashes and data IDs
|
|
301
|
-
- `~/.openclaw/memory/cognee/sync-index.json` — legacy single-scope index
|
|
302
|
-
|
|
303
|
-
Memory files detected at: `MEMORY.md` and `memory/**/*.md` (recursive)
|
|
304
|
-
|
|
305
432
|
## Development
|
|
306
433
|
|
|
307
434
|
```bash
|
|
308
435
|
cd integrations/openclaw
|
|
309
436
|
npm install
|
|
310
437
|
npm run build
|
|
311
|
-
openclaw plugins install
|
|
438
|
+
openclaw plugins install --link .
|
|
312
439
|
```
|
|
313
440
|
|
|
314
441
|
For live rebuilds during development:
|
|
@@ -317,6 +444,8 @@ For live rebuilds during development:
|
|
|
317
444
|
npm run dev
|
|
318
445
|
```
|
|
319
446
|
|
|
447
|
+
After each build, restart the OpenClaw gateway to pick up the new code.
|
|
448
|
+
|
|
320
449
|
## Testing
|
|
321
450
|
|
|
322
451
|
```bash
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const DEFAULT_BREAKER_PATH: string;
|
|
2
|
+
/**
|
|
3
|
+
* A failure should trip the breaker only when it signals an unavailable or
|
|
4
|
+
* overloaded server: network errors, timeouts/aborts, and 5xx responses.
|
|
5
|
+
* 4xx (auth, stale dataset ids) are the caller's problem and must NOT trip —
|
|
6
|
+
* mirrors the claude/codex `_cognee_client.py` rules.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isBreakerError(error: unknown): boolean;
|
|
9
|
+
export declare class RecallBreaker {
|
|
10
|
+
private readonly threshold;
|
|
11
|
+
private readonly cooldownMs;
|
|
12
|
+
private readonly path;
|
|
13
|
+
constructor(threshold: number, cooldownMs: number, path?: string);
|
|
14
|
+
private load;
|
|
15
|
+
private save;
|
|
16
|
+
/** Seconds until the breaker closes again; 0 when recall may proceed. */
|
|
17
|
+
openForSeconds(): Promise<number>;
|
|
18
|
+
recordFailure(message: string): Promise<void>;
|
|
19
|
+
recordSuccess(): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Recall circuit breaker — same design and state file as the claude-code and
|
|
6
|
+
// codex integrations (~/.cognee-plugin/recall-breaker.json), so all Cognee
|
|
7
|
+
// plugins sharing one server trip and recover together. Shape:
|
|
8
|
+
// { failures: number, cooldown_until: epoch-seconds, last_error?: string }
|
|
9
|
+
// Opens after `threshold` consecutive breaker-eligible failures; stays open
|
|
10
|
+
// for `cooldownMs`, then half-opens (next recall attempt runs).
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
export const DEFAULT_BREAKER_PATH = join(homedir(), ".cognee-plugin", "recall-breaker.json");
|
|
13
|
+
/**
|
|
14
|
+
* A failure should trip the breaker only when it signals an unavailable or
|
|
15
|
+
* overloaded server: network errors, timeouts/aborts, and 5xx responses.
|
|
16
|
+
* 4xx (auth, stale dataset ids) are the caller's problem and must NOT trip —
|
|
17
|
+
* mirrors the claude/codex `_cognee_client.py` rules.
|
|
18
|
+
*/
|
|
19
|
+
export function isBreakerError(error) {
|
|
20
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
21
|
+
const status = /\((\d{3})\)/.exec(msg)?.[1];
|
|
22
|
+
if (status)
|
|
23
|
+
return status.startsWith("5");
|
|
24
|
+
return true; // no HTTP status → network error, timeout, or abort
|
|
25
|
+
}
|
|
26
|
+
export class RecallBreaker {
|
|
27
|
+
threshold;
|
|
28
|
+
cooldownMs;
|
|
29
|
+
path;
|
|
30
|
+
constructor(threshold, cooldownMs, path = DEFAULT_BREAKER_PATH) {
|
|
31
|
+
this.threshold = threshold;
|
|
32
|
+
this.cooldownMs = cooldownMs;
|
|
33
|
+
this.path = path;
|
|
34
|
+
}
|
|
35
|
+
async load() {
|
|
36
|
+
try {
|
|
37
|
+
const raw = JSON.parse(await readFile(this.path, "utf-8"));
|
|
38
|
+
return {
|
|
39
|
+
failures: typeof raw.failures === "number" ? raw.failures : 0,
|
|
40
|
+
cooldown_until: typeof raw.cooldown_until === "number" ? raw.cooldown_until : 0,
|
|
41
|
+
last_error: typeof raw.last_error === "string" ? raw.last_error : undefined,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return { failures: 0, cooldown_until: 0 };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async save(state) {
|
|
49
|
+
try {
|
|
50
|
+
await mkdir(dirname(this.path), { recursive: true });
|
|
51
|
+
await writeFile(this.path, JSON.stringify(state), "utf-8");
|
|
52
|
+
}
|
|
53
|
+
catch { /* best-effort */ }
|
|
54
|
+
}
|
|
55
|
+
/** Seconds until the breaker closes again; 0 when recall may proceed. */
|
|
56
|
+
async openForSeconds() {
|
|
57
|
+
const state = await this.load();
|
|
58
|
+
const remaining = state.cooldown_until - Date.now() / 1000;
|
|
59
|
+
return remaining > 0 ? remaining : 0;
|
|
60
|
+
}
|
|
61
|
+
async recordFailure(message) {
|
|
62
|
+
const state = await this.load();
|
|
63
|
+
state.failures += 1;
|
|
64
|
+
state.last_error = message.slice(0, 300);
|
|
65
|
+
if (state.failures >= this.threshold) {
|
|
66
|
+
// Failures are NOT reset on trip (same as claude/codex): after the
|
|
67
|
+
// cooldown the breaker half-opens, and a single failed probe re-trips
|
|
68
|
+
// immediately instead of paying `threshold` slow attempts again.
|
|
69
|
+
state.cooldown_until = Date.now() / 1000 + this.cooldownMs / 1000;
|
|
70
|
+
}
|
|
71
|
+
await this.save(state);
|
|
72
|
+
}
|
|
73
|
+
async recordSuccess() {
|
|
74
|
+
const state = await this.load();
|
|
75
|
+
if (state.failures === 0 && state.cooldown_until === 0)
|
|
76
|
+
return; // avoid write churn on the happy path
|
|
77
|
+
await this.save({ failures: 0, cooldown_until: 0 });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breaker.js","sourceRoot":"","sources":["../../src/breaker.ts"],"names":[],"mappings":"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"}
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CogneeDeleteMode, CogneeMode, CogneeSearchResult, CogneeSearchType } from "./types.js";
|
|
2
2
|
export declare class CogneeHttpClient {
|
|
3
3
|
readonly baseUrl: string;
|
|
4
|
-
private
|
|
4
|
+
private apiKey?;
|
|
5
5
|
private readonly username?;
|
|
6
6
|
private readonly password?;
|
|
7
7
|
private readonly timeoutMs;
|
|
@@ -11,6 +11,15 @@ export declare class CogneeHttpClient {
|
|
|
11
11
|
private loginPromise;
|
|
12
12
|
constructor(baseUrl: string, apiKey?: string, username?: string, password?: string, timeoutMs?: number, ingestionTimeoutMs?: number, mode?: CogneeMode);
|
|
13
13
|
private get isCloud();
|
|
14
|
+
/**
|
|
15
|
+
* Inject an API key resolved/minted after construction (resolveOrMintApiKey).
|
|
16
|
+
* From then on every request authenticates with X-Api-Key and the JWT login
|
|
17
|
+
* fallback is never used again — the key is the principal identity, matching
|
|
18
|
+
* the claude-code/codex integrations. JWT login remains only as the one-time
|
|
19
|
+
* bootstrap that mints a key on a fresh LOCAL server (cloud has no login
|
|
20
|
+
* route, which is why COGNEE_API_KEY is mandatory there).
|
|
21
|
+
*/
|
|
22
|
+
setApiKey(key: string): void;
|
|
14
23
|
login(): Promise<void>;
|
|
15
24
|
ensureAuth(): Promise<void>;
|
|
16
25
|
private buildHeaders;
|
|
@@ -121,7 +130,39 @@ export declare class CogneeHttpClient {
|
|
|
121
130
|
topK?: number;
|
|
122
131
|
sessionId?: string;
|
|
123
132
|
scope?: string | string[];
|
|
133
|
+
onlyContext?: boolean;
|
|
134
|
+
/** Per-call timeout for the prompt hot path. When set, retries are
|
|
135
|
+
* disabled so a slow server fails fast instead of eating the budget. */
|
|
136
|
+
timeoutMs?: number;
|
|
124
137
|
}): Promise<CogneeSearchResult[]>;
|
|
138
|
+
rememberEntry(params: {
|
|
139
|
+
datasetName: string;
|
|
140
|
+
sessionId: string;
|
|
141
|
+
entry: Record<string, unknown>;
|
|
142
|
+
}): Promise<{
|
|
143
|
+
entryId?: string;
|
|
144
|
+
}>;
|
|
145
|
+
registerAgent(params: {
|
|
146
|
+
agentSessionName: string;
|
|
147
|
+
sessionId?: string;
|
|
148
|
+
datasetNames?: string[];
|
|
149
|
+
}): Promise<{
|
|
150
|
+
ok: boolean;
|
|
151
|
+
connectionId?: string;
|
|
152
|
+
}>;
|
|
153
|
+
unregisterAgent(params: {
|
|
154
|
+
agentSessionName: string;
|
|
155
|
+
}): Promise<{
|
|
156
|
+
ok: boolean;
|
|
157
|
+
activeAgents: number;
|
|
158
|
+
}>;
|
|
159
|
+
listApiKeys(): Promise<{
|
|
160
|
+
key: string;
|
|
161
|
+
name?: string;
|
|
162
|
+
}[]>;
|
|
163
|
+
createApiKey(name: string): Promise<{
|
|
164
|
+
key: string;
|
|
165
|
+
}>;
|
|
125
166
|
listDatasets(): Promise<{
|
|
126
167
|
id: string;
|
|
127
168
|
name: string;
|