@openviking/openclaw-plugin 2026.5.21 → 2026.5.26

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 CHANGED
@@ -1,338 +1,338 @@
1
- # OpenViking for OpenClaw
2
-
3
- Use [OpenViking](https://github.com/volcengine/OpenViking) as OpenClaw's long-term context engine: automatic recall, session archive, memory extraction, semantic search, and RAG over a remote OpenViking server.
4
-
5
- ## Quick Start
6
-
7
- ```bash
8
- openclaw plugins install clawhub:@openviking/openclaw-plugin
9
- openclaw openviking setup --base-url http://my-server:1933 --api-key sk-xxx --json
10
- openclaw gateway restart
11
- openclaw openviking status --json
12
- ```
13
-
14
- That's it. The `setup` command activates the context-engine slot and validates the connection.
15
-
16
- ### Or ask your agent
17
-
18
- > Install the OpenClaw plugin @openviking/openclaw-plugin for OpenViking remote memory. My server is at `http://my-server:1933` and my API key is `sk-xxx`.
19
-
20
- The agent runs install → setup → restart → verify automatically. See [INSTALL-AGENT.md](./INSTALL-AGENT.md).
21
-
22
- ## How It Works
23
-
24
- | Stage | What happens |
25
- |-------|-------------|
26
- | **Every turn** (`afterTurn`) | Your messages are archived into an OpenViking session |
27
- | **On `/compact`** (`compact`) | Archived messages are extracted into long-term memories |
28
- | **Before each reply** (`assemble`) | Relevant memories are auto-retrieved and injected into context |
29
-
30
- ## Tools
31
-
32
- Once installed, the plugin provides these agent tools:
33
-
34
- | Tool | Purpose |
35
- |------|---------|
36
- | `memory_recall` | Explicit long-term memory search |
37
- | `memory_store` | Persist important information immediately |
38
- | `memory_forget` | Delete memories by URI or query |
39
- | `ov_archive_search` | Search across archives by keyword |
40
- | `ov_archive_expand` | Expand an archive back to raw messages |
41
- | `add_resource` | Import documents, URLs, or Git repos |
42
- | `add_skill` | Import agent skills |
43
- | `memory_search` | Search imported resources and skills |
44
-
45
- ## Data Flow & Privacy
46
-
47
- - **What is sent**: User/assistant message text from each turn (after stripping injected memory blocks and metadata noise).
48
- - **Where it goes**: Your configured OpenViking server (`baseUrl`). The plugin only sends data to that server; downstream model/provider data handling (embedding, VLM) depends on the server's configuration.
49
- - **Storage**: All data lives on your OpenViking server under `viking://user/*`, `viking://agent/*`, and `viking://session/*`.
50
- - **API Key**: Sent as `X-OpenViking-Key` header over your configured connection. Never logged or forwarded.
51
- - **Multi-tenant isolation**: Supports `accountId`, `userId`, and `agent_prefix` for per-tenant scoping.
52
-
53
- ## Verify
54
-
55
- ```bash
56
- openclaw openviking status --json # one-shot health check
57
- openclaw config get plugins.slots.contextEngine # should output: openviking
58
- ```
59
-
60
- ## Documentation
61
-
62
- | Doc | Description |
63
- |-----|-------------|
64
- | [INSTALL.md](./INSTALL.md) | Full install, upgrade, and uninstall guide |
65
- | [INSTALL-ZH.md](./INSTALL-ZH.md) | Chinese install guide |
66
- | [INSTALL-AGENT.md](./INSTALL-AGENT.md) | Agent-oriented operator guide |
67
-
68
- > **Plugin vs Skill**: This page is for `@openviking/openclaw-plugin` (the context-engine plugin). Do **not** use `clawhub install openviking` — that installs a different AgentSkill.
69
-
70
- ---
71
-
72
- <details>
73
- <summary><b>Technical Overview (for integrators and engineers)</b></summary>
74
-
75
- This plugin is registered as the `openviking` context engine in OpenClaw.
76
-
77
- ## Design Positioning
78
-
79
- - OpenClaw still owns the agent runtime, prompt orchestration, and tool execution.
80
- - OpenViking owns long-term memory retrieval, session archiving, archive summaries, and memory extraction.
81
- - `examples/openclaw-plugin` is not a narrow "memory lookup" plugin. It is an integration layer that spans the OpenClaw lifecycle.
82
-
83
- In the current implementation, the plugin plays four roles at once:
84
-
85
- - `context-engine`: implements `assemble`, `afterTurn`, and `compact`
86
- - hook layer: handles `session_start`, `session_end`, and `before_reset`
87
- - tool provider: registers memory/archive tools plus OpenViking resource and skill import tools
88
- - runtime manager: connects to and monitors a remote OpenViking service
89
-
90
- ## Overall Architecture
91
-
92
- ![Overall OpenClaw and OpenViking plugin architecture](./images/openclaw-plugin-engine-overview.png)
93
-
94
- The diagram above reflects the current implementation boundary:
95
-
96
- - OpenClaw remains the primary runtime on the left. The plugin does not take over agent execution.
97
- - The middle layer combines hooks, the context engine, tools, and runtime management in one plugin registration.
98
- - All HTTP traffic goes through `OpenVikingClient`, which centralizes `X-OpenViking-*` headers and routing logs.
99
- - The OpenViking service owns sessions, memories, archives, and Phase 2 extraction, with storage under `viking://user/*`, `viking://agent/*`, and `viking://session/*`.
100
-
101
- That split lets OpenClaw stay focused on reasoning and orchestration while OpenViking becomes the source of truth for long-lived context.
102
-
103
- ## Identity and Routing
104
-
105
- The plugin does not send one fixed agent ID to OpenViking. It tries to keep OpenClaw session identity and OpenViking routing aligned.
106
-
107
- The main rules are:
108
-
109
- - reuse `sessionId` directly when it is already a UUID
110
- - prefer `sessionKey` when deriving a stable `ovSessionId`
111
- - normalize unsafe path characters, or fall back to a stable SHA-256 when needed
112
- - resolve `X-OpenViking-Agent` per session, not per process
113
- - when `plugins.entries.openviking.config.agent_prefix` is non-empty, prefix the session agent as `<agent_prefix>_<sessionAgent>`
114
- - when OpenClaw does not provide a session agent, use its default agent `main`
115
- - send `X-OpenViking-Agent` on OpenViking requests, including startup health checks
116
- - only add `X-OpenViking-Account` / `X-OpenViking-User` when `accountId` / `userId` are explicitly configured
117
-
118
- This matters because the plugin is built to support multi-agent and multi-session OpenClaw usage without mixing memories across sessions.
119
-
120
- The recommended remote-mode configuration only needs:
121
-
122
- - `baseUrl`
123
- - `apiKey`
124
- - `agent_prefix`
125
-
126
- In this setup:
127
-
128
- - `apiKey` should usually be a user key
129
- - `accountId` / `userId` are advanced options only when the deployment needs explicit identity headers, such as root-key or trusted-server flows
130
- - `isolateUserScopeByAgent` / `isolateAgentScopeByUser` must match the server-side account namespace policy when using the PR #1356 canonical namespace model
131
- - `agentScopeMode` is a deprecated compatibility alias for older hash-based routing and should only be used against older servers
132
-
133
- ### Canonical namespace policy
134
-
135
- For OpenViking servers that include PR #1356, the plugin no longer treats agent or user scope as a locally computed hash. Instead it expands shorthand aliases into canonical URIs using the configured namespace policy:
136
-
137
- - `viking://user/memories`
138
- - `viking://user/<user_id>/memories` when `isolateUserScopeByAgent=false`
139
- - `viking://user/<user_id>/agent/<agent_id>/memories` when `isolateUserScopeByAgent=true`
140
- - `viking://agent/memories`
141
- - `viking://agent/<agent_id>/memories` when `isolateAgentScopeByUser=false`
142
- - `viking://agent/<agent_id>/user/<user_id>/memories` when `isolateAgentScopeByUser=true`
143
-
144
- The plugin cannot auto-discover this policy today because `/api/v1/system/status` does not expose it. Configure the two booleans explicitly so they stay aligned with the server-side account policy.
145
-
146
- ## assemble Recall Flow
147
-
148
- ![Automatic recall flow before prompt build](./images/openclaw-plugin-recall-flow.png)
149
-
150
- Auto-recall now runs through `assemble()`. OpenClaw calls the same context engine method in two shapes, and the plugin assigns different responsibilities to each shape:
151
-
152
- 1. Preflight assemble: params include `prompt`; `messages` is still old history. The plugin reads archive/session context back from OpenViking and rebuilds history.
153
- 2. transformContext assemble: params do not include `prompt`; the latest `messages` entry is already the current user turn. The plugin only runs long-term recall and prepends the memory block to that user message content.
154
-
155
- During recall, the plugin:
156
-
157
- 1. Extracts query text from the latest user message.
158
- 2. Resolves the agent routing for the current `sessionId/sessionKey`.
159
- 3. Runs a quick availability precheck so model requests do not stall when OpenViking is unavailable.
160
- 4. Queries both `viking://user/memories` and `viking://agent/memories` in parallel.
161
- 5. Deduplicates, threshold-filters, reranks, and trims the results under a token budget.
162
- 6. Prepends the selected memories as a `<relevant-memories>` block to the current user message; it does not append a standalone synthetic user message.
163
-
164
- The reranking logic is not pure vector-score sorting. The current implementation also considers:
165
-
166
- - whether a result is a leaf memory with `level == 2`
167
- - whether it looks like a preference memory
168
- - whether it looks like an event memory
169
- - lexical overlap with the current query
170
-
171
- ## Session Lifecycle
172
-
173
- ![Session lifecycle and compaction boundary](./images/openclaw-plugin-session-lifecycle.png)
174
-
175
- Session handling is the main axis of this design. In the current implementation it covers history assembly, incremental append, asynchronous commit, and blocking compaction readback.
176
-
177
- ### What `assemble()` does
178
-
179
- During preflight, `assemble()` is not just replaying old chat history. It reads session context back from OpenViking under a token budget, then rebuilds OpenClaw-facing messages:
180
-
181
- - `latest_archive_overview` becomes `[Session History Summary]`
182
- - `pre_archive_abstracts` becomes `[Archive Index]`
183
- - active session messages stay in message-block form
184
- - assistant tool parts become `toolCall` (input compatible: `toolUse`/`input` is normalized to `toolCall`/`arguments`)
185
- - tool output becomes separate `toolResult`
186
- - the final message list goes through a tool-use/result pairing repair pass
187
-
188
- That means OpenClaw sees "compressed history summary + archive index + active messages", not an ever-growing raw transcript.
189
-
190
- ### What `afterTurn()` does
191
-
192
- `afterTurn()` has a narrower job: append only the new turn into the OpenViking session.
193
-
194
- - it slices only the newly added messages
195
- - it keeps only `user` / `assistant` capture text
196
- - it preserves `toolCall` / `toolResult` content in the serialized turn text
197
- - it strips injected `<relevant-memories>` blocks and metadata noise before capture
198
- - it appends the sanitized turn text into the OpenViking session
199
-
200
- After that, the plugin checks `pending_tokens`. Once the session crosses `commitTokenThreshold`, it triggers `commit(wait=false)`:
201
-
202
- - archive generation and Phase 2 memory extraction continue asynchronously on the server
203
- - the current turn is not blocked waiting for extraction
204
- - if `logFindRequests` is enabled, the logs include the task id and follow-up extraction detail
205
-
206
- ### What `compact()` does
207
-
208
- `compact()` is the stricter synchronous boundary:
209
-
210
- - it calls `commit(wait=true)` and blocks for completion
211
- - when an archive exists, it re-reads `latest_archive_overview`
212
- - it returns updated token estimates, the latest archive id, and summary content
213
- - if the summary is too coarse, the model can call `ov_archive_expand` to reopen a specific archive
214
-
215
- So `afterTurn()` is closer to "incremental append plus threshold-triggered async commit", while `compact()` is the explicit "wait for archive and compaction to finish" boundary.
216
-
217
- ## Tools and Expandability
218
-
219
- Beyond automatic behavior, the plugin exposes seven tools directly:
220
-
221
- - `memory_recall`: explicit long-term memory search
222
- - `memory_store`: write text into an OpenViking session and trigger commit
223
- - `memory_forget`: delete by URI, or search first and remove a single strong match
224
- - `ov_archive_expand`: expand a concrete archive back into raw messages
225
- - `add_resource`: import a document, directory, URL, or Git repository as an OpenViking resource
226
- - `add_skill`: import or register an OpenViking agent skill
227
- - `memory_search`: search OpenViking resources and skills, especially after importing them
228
-
229
- They serve different roles:
230
-
231
- - automatic recall covers the default case where the model does not know what to search yet
232
- - `memory_recall` gives the model an explicit follow-up search path
233
- - `memory_store` is for immediately persisting clearly important information
234
- - `ov_archive_expand` is the "go back to archive detail" escape hatch when summaries are not enough
235
- - `add_resource` lets the agent save explicit document or repository import requests without asking the user to remember slash commands
236
- - `add_skill` imports skills into OpenViking, while `add_resource` imports resources
237
- - `memory_search` closes the loop after import by letting the user or agent confirm and consume resources and skills
238
-
239
- `ov_archive_expand` is especially important because `assemble()` normally returns archive summaries and indexes, not the full raw transcript.
240
-
241
- ### Resource and Skill Import
242
-
243
- Resource and skill imports are intentionally separate because they land in different OpenViking namespaces and use different server APIs:
244
-
245
- - resources go through `/api/v1/resources` and land under `viking://resources/...`
246
- - skills go through `/api/v1/skills` and land under `viking://agent/skills/...`
247
-
248
- The plugin also registers explicit slash commands for manual imports:
249
-
250
- ```text
251
- /add-resource ./README.md --to viking://resources/openviking-readme --wait
252
- /add-skill ./skills/install-openviking-memory --wait
253
- /memory-search "OpenViking install" --uri viking://resources/openviking-readme
254
- /memory-search "memory install skill" --uri viking://agent/skills
255
- ```
256
-
257
- Resource import supports remote URLs, Git URLs, local files, local directories, and uploaded zip files. OpenViking's built-in parsers cover common documents and media such as Markdown, text, PDF, HTML, Word, PowerPoint, Excel, EPUB, images, audio, and video. Directory imports also accept common code, documentation, and config file extensions such as `.py`, `.js`, `.ts`, `.go`, `.rs`, `.java`, `.cpp`, `.json`, `.yaml`, `.toml`, `.csv`, `.rst`, `.proto`, `.tf`, and `.vue`.
258
-
259
- For HTTP safety, the plugin never sends a direct local filesystem path to the OpenViking server. Local files and directories are first uploaded through `/api/v1/resources/temp_upload`; directories are zipped locally with a pure JavaScript zip implementation before upload.
260
-
261
- ## Runtime Mode
262
-
263
- ![Runtime modes and routing behavior](./images/openclaw-plugin-runtime-routing.png)
264
-
265
- The plugin operates exclusively in remote mode as a pure HTTP client:
266
-
267
- - `baseUrl` and optional `apiKey` come from plugin config
268
- - no local subprocess is started or managed
269
- - session context, memory search/read, commit, and archive expansion behavior stays the same
270
-
271
- The OpenViking service must be deployed and running independently before the plugin can connect to it.
272
-
273
- ## Relationship to the Older Design Draft
274
-
275
- The repo also contains a more future-looking design draft at `docs/design/openclaw-context-engine-refactor.md`. It is important not to conflate the two:
276
-
277
- - this README describes current implemented behavior
278
- - the older draft discusses a stronger future move into context-engine-owned lifecycle control
279
- - in the current version, the main automatic recall path lives in `assemble()`: preflight rebuilds history, transformContext injects long-term memories
280
- - in the current version, `afterTurn()` already appends to the OpenViking session, but commit remains threshold-triggered and asynchronous on that path
281
- - in the current version, `compact()` already uses `commit(wait=true)`, but it is still focused on synchronous commit plus readback rather than owning every orchestration concern
282
-
283
- That distinction matters, otherwise the future design draft is easy to misread as already shipped behavior.
284
-
285
- ## Operator and Debugging Surfaces
286
-
287
- If you need to debug this plugin, start with these entry points.
288
-
289
- ### Inspect the current setup
290
-
291
- ```bash
292
- openclaw openviking status --json
293
- openclaw plugins list
294
- openclaw config get plugins.entries.openviking.config
295
- openclaw config get plugins.slots.contextEngine
296
- ```
297
-
298
- ### Watch logs
299
-
300
- OpenClaw plugin logs:
301
-
302
- ```bash
303
- openclaw logs --follow
304
- ```
305
-
306
- OpenViking service logs:
307
-
308
- ```bash
309
- cat ~/.openviking/data/log/openviking.log
310
- ```
311
-
312
- ### Web Console
313
-
314
- ```bash
315
- python -m openviking.console.bootstrap --host 0.0.0.0 --port 8020 --openviking-url http://127.0.0.1:1933
316
- ```
317
-
318
- ### `ov tui`
319
-
320
- ```bash
321
- ov tui
322
- ```
323
-
324
- ### Common things to check
325
-
326
- | Symptom | More likely cause | First check |
327
- | --- | --- | --- |
328
- | `plugins.slots.contextEngine` is not `openviking` | The plugin slot was never set, or another plugin replaced it | `openclaw config get plugins.slots.contextEngine` |
329
- | Cannot connect to OpenViking service | `baseUrl` is wrong or the service is down | Check `baseUrl` in config and test connectivity manually |
330
- | recall behaves inconsistently across sessions | Routing identity is not what you expected | Enable `logFindRequests`, then inspect `openclaw logs --follow` |
331
- | long chats stop extracting memory | `pending_tokens` never crosses the threshold, or Phase 2 fails server-side | Check plugin config and `~/.openviking/data/log/openviking.log` |
332
- | summaries are too coarse for detailed questions | You need archive-level detail, not just summary | Use an ID from `[Archive Index]` with `ov_archive_expand` |
333
-
334
- ---
335
-
336
- For installation, upgrade, and uninstall operations, use [INSTALL.md](./INSTALL.md).
337
-
338
- </details>
1
+ # OpenViking for OpenClaw
2
+
3
+ Use [OpenViking](https://github.com/volcengine/OpenViking) as OpenClaw's long-term context engine: automatic recall, session archive, memory extraction, semantic search, and RAG over a remote OpenViking server.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ openclaw plugins install clawhub:@openviking/openclaw-plugin
9
+ openclaw openviking setup --base-url http://my-server:1933 --api-key sk-xxx --json
10
+ openclaw gateway restart
11
+ openclaw openviking status --json
12
+ ```
13
+
14
+ That's it. The `setup` command activates the context-engine slot and validates the connection.
15
+
16
+ ### Or ask your agent
17
+
18
+ > Install the OpenClaw plugin @openviking/openclaw-plugin for OpenViking remote memory. My server is at `http://my-server:1933` and my API key is `sk-xxx`.
19
+
20
+ The agent runs install → setup → restart → verify automatically. See [INSTALL-AGENT.md](./INSTALL-AGENT.md).
21
+
22
+ ## How It Works
23
+
24
+ | Stage | What happens |
25
+ |-------|-------------|
26
+ | **Every turn** (`afterTurn`) | Your messages are archived into an OpenViking session |
27
+ | **On `/compact`** (`compact`) | Archived messages are extracted into long-term memories |
28
+ | **Before each reply** (`assemble`) | Relevant memories are auto-retrieved and injected into context |
29
+
30
+ ## Tools
31
+
32
+ Once installed, the plugin provides these agent tools:
33
+
34
+ | Tool | Purpose |
35
+ |------|---------|
36
+ | `memory_recall` | Explicit long-term memory search |
37
+ | `memory_store` | Persist important information immediately |
38
+ | `memory_forget` | Delete memories by URI or query |
39
+ | `ov_archive_search` | Search across archives by keyword |
40
+ | `ov_archive_expand` | Expand an archive back to raw messages |
41
+ | `add_resource` | Import documents, URLs, or Git repos |
42
+ | `add_skill` | Import agent skills |
43
+ | `ov_search` | Search imported resources and skills |
44
+
45
+ ## Data Flow & Privacy
46
+
47
+ - **What is sent**: User/assistant message text from each turn (after stripping injected memory blocks and metadata noise).
48
+ - **Where it goes**: Your configured OpenViking server (`baseUrl`). The plugin only sends data to that server; downstream model/provider data handling (embedding, VLM) depends on the server's configuration.
49
+ - **Storage**: All data lives on your OpenViking server under `viking://user/*`, `viking://agent/*`, and `viking://session/*`.
50
+ - **API Key**: Sent as `X-OpenViking-Key` header over your configured connection. Never logged or forwarded.
51
+ - **Multi-tenant isolation**: Supports `accountId`, `userId`, and `agent_prefix` for per-tenant scoping.
52
+
53
+ ## Verify
54
+
55
+ ```bash
56
+ openclaw openviking status --json # one-shot health check
57
+ openclaw config get plugins.slots.contextEngine # should output: openviking
58
+ ```
59
+
60
+ ## Documentation
61
+
62
+ | Doc | Description |
63
+ |-----|-------------|
64
+ | [INSTALL.md](./INSTALL.md) | Full install, upgrade, and uninstall guide |
65
+ | [INSTALL-ZH.md](./INSTALL-ZH.md) | Chinese install guide |
66
+ | [INSTALL-AGENT.md](./INSTALL-AGENT.md) | Agent-oriented operator guide |
67
+
68
+ > **Plugin vs Skill**: This page is for `@openviking/openclaw-plugin` (the context-engine plugin). Do **not** use `clawhub install openviking` — that installs a different AgentSkill.
69
+
70
+ ---
71
+
72
+ <details>
73
+ <summary><b>Technical Overview (for integrators and engineers)</b></summary>
74
+
75
+ This plugin is registered as the `openviking` context engine in OpenClaw.
76
+
77
+ ## Design Positioning
78
+
79
+ - OpenClaw still owns the agent runtime, prompt orchestration, and tool execution.
80
+ - OpenViking owns long-term memory retrieval, session archiving, archive summaries, and memory extraction.
81
+ - `examples/openclaw-plugin` is not a narrow "memory lookup" plugin. It is an integration layer that spans the OpenClaw lifecycle.
82
+
83
+ In the current implementation, the plugin plays four roles at once:
84
+
85
+ - `context-engine`: implements `assemble`, `afterTurn`, and `compact`
86
+ - hook layer: handles `session_start`, `session_end`, and `before_reset`
87
+ - tool provider: registers memory/archive tools plus OpenViking resource and skill import tools
88
+ - runtime manager: connects to and monitors a remote OpenViking service
89
+
90
+ ## Overall Architecture
91
+
92
+ ![Overall OpenClaw and OpenViking plugin architecture](./images/openclaw-plugin-engine-overview.png)
93
+
94
+ The diagram above reflects the current implementation boundary:
95
+
96
+ - OpenClaw remains the primary runtime on the left. The plugin does not take over agent execution.
97
+ - The middle layer combines hooks, the context engine, tools, and runtime management in one plugin registration.
98
+ - All HTTP traffic goes through `OpenVikingClient`, which centralizes `X-OpenViking-*` headers and routing logs.
99
+ - The OpenViking service owns sessions, memories, archives, and Phase 2 extraction, with storage under `viking://user/*`, `viking://agent/*`, and `viking://session/*`.
100
+
101
+ That split lets OpenClaw stay focused on reasoning and orchestration while OpenViking becomes the source of truth for long-lived context.
102
+
103
+ ## Identity and Routing
104
+
105
+ The plugin does not send one fixed agent ID to OpenViking. It tries to keep OpenClaw session identity and OpenViking routing aligned.
106
+
107
+ The main rules are:
108
+
109
+ - reuse `sessionId` directly when it is already a UUID
110
+ - prefer `sessionKey` when deriving a stable `ovSessionId`
111
+ - normalize unsafe path characters, or fall back to a stable SHA-256 when needed
112
+ - resolve `X-OpenViking-Agent` per session, not per process
113
+ - when `plugins.entries.openviking.config.agent_prefix` is non-empty, prefix the session agent as `<agent_prefix>_<sessionAgent>`
114
+ - when OpenClaw does not provide a session agent, use its default agent `main`
115
+ - send `X-OpenViking-Agent` on OpenViking requests, including startup health checks
116
+ - only add `X-OpenViking-Account` / `X-OpenViking-User` when `accountId` / `userId` are explicitly configured
117
+
118
+ This matters because the plugin is built to support multi-agent and multi-session OpenClaw usage without mixing memories across sessions.
119
+
120
+ The recommended remote-mode configuration only needs:
121
+
122
+ - `baseUrl`
123
+ - `apiKey`
124
+ - `agent_prefix`
125
+
126
+ In this setup:
127
+
128
+ - `apiKey` should usually be a user key
129
+ - `accountId` / `userId` are advanced options only when the deployment needs explicit identity headers, such as root-key or trusted-server flows
130
+ - `isolateUserScopeByAgent` / `isolateAgentScopeByUser` must match the server-side account namespace policy when using the PR #1356 canonical namespace model
131
+ - `agentScopeMode` is a deprecated compatibility alias for older hash-based routing and should only be used against older servers
132
+
133
+ ### Canonical namespace policy
134
+
135
+ For OpenViking servers that include PR #1356, the plugin no longer treats agent or user scope as a locally computed hash. Instead it expands shorthand aliases into canonical URIs using the configured namespace policy:
136
+
137
+ - `viking://user/memories`
138
+ - `viking://user/<user_id>/memories` when `isolateUserScopeByAgent=false`
139
+ - `viking://user/<user_id>/agent/<agent_id>/memories` when `isolateUserScopeByAgent=true`
140
+ - `viking://agent/memories`
141
+ - `viking://agent/<agent_id>/memories` when `isolateAgentScopeByUser=false`
142
+ - `viking://agent/<agent_id>/user/<user_id>/memories` when `isolateAgentScopeByUser=true`
143
+
144
+ The plugin cannot auto-discover this policy today because `/api/v1/system/status` does not expose it. Configure the two booleans explicitly so they stay aligned with the server-side account policy.
145
+
146
+ ## assemble Recall Flow
147
+
148
+ ![Automatic recall flow before prompt build](./images/openclaw-plugin-recall-flow.png)
149
+
150
+ Auto-recall now runs through `assemble()`. OpenClaw calls the same context engine method in two shapes, and the plugin assigns different responsibilities to each shape:
151
+
152
+ 1. Preflight assemble: params include `prompt`; `messages` is still old history. The plugin reads archive/session context back from OpenViking and rebuilds history.
153
+ 2. transformContext assemble: params do not include `prompt`; the latest `messages` entry is already the current user turn. The plugin only runs long-term recall and prepends the memory block to that user message content.
154
+
155
+ During recall, the plugin:
156
+
157
+ 1. Extracts query text from the latest user message.
158
+ 2. Resolves the agent routing for the current `sessionId/sessionKey`.
159
+ 3. Runs a quick availability precheck so model requests do not stall when OpenViking is unavailable.
160
+ 4. Queries both `viking://user/memories` and `viking://agent/memories` in parallel.
161
+ 5. Deduplicates, threshold-filters, reranks, and trims the results under a token budget.
162
+ 6. Prepends the selected memories as a `<relevant-memories>` block to the current user message; it does not append a standalone synthetic user message.
163
+
164
+ The reranking logic is not pure vector-score sorting. The current implementation also considers:
165
+
166
+ - whether a result is a leaf memory with `level == 2`
167
+ - whether it looks like a preference memory
168
+ - whether it looks like an event memory
169
+ - lexical overlap with the current query
170
+
171
+ ## Session Lifecycle
172
+
173
+ ![Session lifecycle and compaction boundary](./images/openclaw-plugin-session-lifecycle.png)
174
+
175
+ Session handling is the main axis of this design. In the current implementation it covers history assembly, incremental append, asynchronous commit, and blocking compaction readback.
176
+
177
+ ### What `assemble()` does
178
+
179
+ During preflight, `assemble()` is not just replaying old chat history. It reads session context back from OpenViking under a token budget, then rebuilds OpenClaw-facing messages:
180
+
181
+ - `latest_archive_overview` becomes `[Session History Summary]`
182
+ - `pre_archive_abstracts` becomes `[Archive Index]`
183
+ - active session messages stay in message-block form
184
+ - assistant tool parts become `toolCall` (input compatible: `toolUse`/`input` is normalized to `toolCall`/`arguments`)
185
+ - tool output becomes separate `toolResult`
186
+ - the final message list goes through a tool-use/result pairing repair pass
187
+
188
+ That means OpenClaw sees "compressed history summary + archive index + active messages", not an ever-growing raw transcript.
189
+
190
+ ### What `afterTurn()` does
191
+
192
+ `afterTurn()` has a narrower job: append only the new turn into the OpenViking session.
193
+
194
+ - it slices only the newly added messages
195
+ - it keeps only `user` / `assistant` capture text
196
+ - it preserves `toolCall` / `toolResult` content in the serialized turn text
197
+ - it strips injected `<relevant-memories>` blocks and metadata noise before capture
198
+ - it appends the sanitized turn text into the OpenViking session
199
+
200
+ After that, the plugin checks `pending_tokens`. Once the session crosses `commitTokenThreshold`, it triggers `commit(wait=false)`:
201
+
202
+ - archive generation and Phase 2 memory extraction continue asynchronously on the server
203
+ - the current turn is not blocked waiting for extraction
204
+ - if `logFindRequests` is enabled, the logs include the task id and follow-up extraction detail
205
+
206
+ ### What `compact()` does
207
+
208
+ `compact()` is the stricter synchronous boundary:
209
+
210
+ - it calls `commit(wait=true)` and blocks for completion
211
+ - when an archive exists, it re-reads `latest_archive_overview`
212
+ - it returns updated token estimates, the latest archive id, and summary content
213
+ - if the summary is too coarse, the model can call `ov_archive_expand` to reopen a specific archive
214
+
215
+ So `afterTurn()` is closer to "incremental append plus threshold-triggered async commit", while `compact()` is the explicit "wait for archive and compaction to finish" boundary.
216
+
217
+ ## Tools and Expandability
218
+
219
+ Beyond automatic behavior, the plugin exposes seven tools directly:
220
+
221
+ - `memory_recall`: explicit long-term memory search
222
+ - `memory_store`: write text into an OpenViking session and trigger commit
223
+ - `memory_forget`: delete by URI, or search first and remove a single strong match
224
+ - `ov_archive_expand`: expand a concrete archive back into raw messages
225
+ - `add_resource`: import a document, directory, URL, or Git repository as an OpenViking resource
226
+ - `add_skill`: import or register an OpenViking agent skill
227
+ - `ov_search`: search OpenViking resources and skills, especially after importing them
228
+
229
+ They serve different roles:
230
+
231
+ - automatic recall covers the default case where the model does not know what to search yet
232
+ - `memory_recall` gives the model an explicit follow-up search path
233
+ - `memory_store` is for immediately persisting clearly important information
234
+ - `ov_archive_expand` is the "go back to archive detail" escape hatch when summaries are not enough
235
+ - `add_resource` lets the agent save explicit document or repository import requests without asking the user to remember slash commands
236
+ - `add_skill` imports skills into OpenViking, while `add_resource` imports resources
237
+ - `ov_search` closes the loop after import by letting the user or agent confirm and consume resources and skills
238
+
239
+ `ov_archive_expand` is especially important because `assemble()` normally returns archive summaries and indexes, not the full raw transcript.
240
+
241
+ ### Resource and Skill Import
242
+
243
+ Resource and skill imports are intentionally separate because they land in different OpenViking namespaces and use different server APIs:
244
+
245
+ - resources go through `/api/v1/resources` and land under `viking://resources/...`
246
+ - skills go through `/api/v1/skills` and land under `viking://agent/skills/...`
247
+
248
+ The plugin also registers explicit slash commands for manual imports:
249
+
250
+ ```text
251
+ /add-resource ./README.md --to viking://resources/openviking-readme --wait
252
+ /add-skill ./skills/install-openviking-memory --wait
253
+ /ov-search "OpenViking install" --uri viking://resources/openviking-readme
254
+ /ov-search "memory install skill" --uri viking://agent/skills
255
+ ```
256
+
257
+ Resource import supports remote URLs, Git URLs, local files, local directories, and uploaded zip files. OpenViking's built-in parsers cover common documents and media such as Markdown, text, PDF, HTML, Word, PowerPoint, Excel, EPUB, images, audio, and video. Directory imports also accept common code, documentation, and config file extensions such as `.py`, `.js`, `.ts`, `.go`, `.rs`, `.java`, `.cpp`, `.json`, `.yaml`, `.toml`, `.csv`, `.rst`, `.proto`, `.tf`, and `.vue`.
258
+
259
+ For HTTP safety, the plugin never sends a direct local filesystem path to the OpenViking server. Local files and directories are first uploaded through `/api/v1/resources/temp_upload`; directories are zipped locally with a pure JavaScript zip implementation before upload.
260
+
261
+ ## Runtime Mode
262
+
263
+ ![Runtime modes and routing behavior](./images/openclaw-plugin-runtime-routing.png)
264
+
265
+ The plugin operates exclusively in remote mode as a pure HTTP client:
266
+
267
+ - `baseUrl` and optional `apiKey` come from plugin config
268
+ - no local subprocess is started or managed
269
+ - session context, memory search/read, commit, and archive expansion behavior stays the same
270
+
271
+ The OpenViking service must be deployed and running independently before the plugin can connect to it.
272
+
273
+ ## Relationship to the Older Design Draft
274
+
275
+ The repo also contains a more future-looking design draft at `docs/design/openclaw-context-engine-refactor.md`. It is important not to conflate the two:
276
+
277
+ - this README describes current implemented behavior
278
+ - the older draft discusses a stronger future move into context-engine-owned lifecycle control
279
+ - in the current version, the main automatic recall path lives in `assemble()`: preflight rebuilds history, transformContext injects long-term memories
280
+ - in the current version, `afterTurn()` already appends to the OpenViking session, but commit remains threshold-triggered and asynchronous on that path
281
+ - in the current version, `compact()` already uses `commit(wait=true)`, but it is still focused on synchronous commit plus readback rather than owning every orchestration concern
282
+
283
+ That distinction matters, otherwise the future design draft is easy to misread as already shipped behavior.
284
+
285
+ ## Operator and Debugging Surfaces
286
+
287
+ If you need to debug this plugin, start with these entry points.
288
+
289
+ ### Inspect the current setup
290
+
291
+ ```bash
292
+ openclaw openviking status --json
293
+ openclaw plugins list
294
+ openclaw config get plugins.entries.openviking.config
295
+ openclaw config get plugins.slots.contextEngine
296
+ ```
297
+
298
+ ### Watch logs
299
+
300
+ OpenClaw plugin logs:
301
+
302
+ ```bash
303
+ openclaw logs --follow
304
+ ```
305
+
306
+ OpenViking service logs:
307
+
308
+ ```bash
309
+ cat ~/.openviking/data/log/openviking.log
310
+ ```
311
+
312
+ ### Web Console
313
+
314
+ ```bash
315
+ python -m openviking.console.bootstrap --host 0.0.0.0 --port 8020 --openviking-url http://127.0.0.1:1933
316
+ ```
317
+
318
+ ### `ov tui`
319
+
320
+ ```bash
321
+ ov tui
322
+ ```
323
+
324
+ ### Common things to check
325
+
326
+ | Symptom | More likely cause | First check |
327
+ | --- | --- | --- |
328
+ | `plugins.slots.contextEngine` is not `openviking` | The plugin slot was never set, or another plugin replaced it | `openclaw config get plugins.slots.contextEngine` |
329
+ | Cannot connect to OpenViking service | `baseUrl` is wrong or the service is down | Check `baseUrl` in config and test connectivity manually |
330
+ | recall behaves inconsistently across sessions | Routing identity is not what you expected | Enable `logFindRequests`, then inspect `openclaw logs --follow` |
331
+ | long chats stop extracting memory | `pending_tokens` never crosses the threshold, or Phase 2 fails server-side | Check plugin config and `~/.openviking/data/log/openviking.log` |
332
+ | summaries are too coarse for detailed questions | You need archive-level detail, not just summary | Use an ID from `[Archive Index]` with `ov_archive_expand` |
333
+
334
+ ---
335
+
336
+ For installation, upgrade, and uninstall operations, use [INSTALL.md](./INSTALL.md).
337
+
338
+ </details>