@jonathangu/openclawbrain 0.3.0 → 0.3.1
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 +140 -290
- package/docs/END_STATE.md +106 -94
- package/docs/EVIDENCE.md +71 -23
- package/docs/RELEASE_CONTRACT.md +46 -32
- package/docs/agent-tools.md +65 -34
- package/docs/architecture.md +128 -142
- package/docs/configuration.md +62 -25
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/channels-status.txt +20 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/config-snapshot.json +94 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/doctor.json +14 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/gateway-probe.txt +24 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/gateway-status.txt +31 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/init-capture.json +15 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/logs.txt +357 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/status-all.txt +61 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/status.json +275 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/summary.md +18 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/trace.json +222 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/validation-report.json +1515 -0
- package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/workspace-inventory.json +4 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/channels-status.txt +20 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/config-snapshot.json +94 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/doctor.json +14 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/gateway-probe.txt +24 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/gateway-status.txt +31 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/init-capture.json +15 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/logs.txt +362 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/status-all.txt +61 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/status.json +275 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/summary.md +21 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/trace.json +222 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/validation-report.json +4400 -0
- package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/workspace-inventory.json +4 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/channels-status.txt +31 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/config-snapshot.json +94 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/doctor.json +14 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/gateway-probe.txt +34 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/gateway-status.txt +41 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/logs.txt +441 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/status-all.txt +60 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/status.json +276 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/summary.md +13 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/trace.json +4 -0
- package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/validation-report.json +387 -0
- package/docs/tui.md +11 -4
- package/index.ts +194 -1
- package/package.json +1 -1
- package/src/brain-cli.ts +12 -1
- package/src/brain-harvest/scanner.ts +286 -16
- package/src/brain-harvest/self.ts +134 -6
- package/src/brain-runtime/evidence-detectors.ts +3 -1
- package/src/brain-runtime/harvester-extension.ts +3 -0
- package/src/brain-runtime/service.ts +2 -0
- package/src/brain-store/embedding.ts +29 -8
- package/src/brain-worker/worker.ts +40 -0
- package/src/engine.ts +1 -0
package/docs/agent-tools.md
CHANGED
|
@@ -1,37 +1,55 @@
|
|
|
1
1
|
# Agent tools
|
|
2
2
|
|
|
3
|
-
OpenClawBrain exposes two tool families:
|
|
3
|
+
OpenClawBrain exposes two different tool families:
|
|
4
4
|
|
|
5
|
-
1. **LCM recall tools** —
|
|
6
|
-
2. **Brain runtime tools** — teach the live routing layer
|
|
5
|
+
1. **LCM recall tools** — use these to recover compacted conversation history
|
|
6
|
+
2. **Brain runtime tools** — use these to teach or inspect the live learned-routing layer
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
That distinction matters. A lot of confusion comes from treating them like one system.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## 1. LCM recall tools
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Use these when you are trying to remember what happened in a conversation.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
### Default escalation pattern
|
|
15
|
+
1. `lcm_grep` — find relevant summaries or messages
|
|
16
|
+
2. `lcm_describe` — inspect a specific summary or large file cheaply
|
|
17
|
+
3. `lcm_expand_query` — recover compressed detail through bounded expansion
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
Use the cheapest tool that answers the question.
|
|
19
20
|
|
|
20
21
|
### `lcm_grep`
|
|
21
|
-
Search
|
|
22
|
+
Search messages and/or summaries by regex or full-text.
|
|
23
|
+
|
|
24
|
+
Use it when:
|
|
25
|
+
- you need to find where a topic came up
|
|
26
|
+
- you need candidate summary IDs before expanding
|
|
27
|
+
- you do not yet know whether the detail lives in raw messages or summaries
|
|
22
28
|
|
|
23
29
|
### `lcm_describe`
|
|
24
|
-
Read the
|
|
30
|
+
Read the content and metadata for a summary or stored file.
|
|
31
|
+
|
|
32
|
+
Use it when:
|
|
33
|
+
- you already have a summary ID
|
|
34
|
+
- you want the exact text of a compressed summary
|
|
35
|
+
- you want to inspect a stored large file without opening everything else
|
|
25
36
|
|
|
26
37
|
### `lcm_expand_query`
|
|
27
|
-
Answer a focused question by expanding
|
|
38
|
+
Answer a focused question by expanding summary DAG context through a bounded delegated sub-agent.
|
|
39
|
+
|
|
40
|
+
Use it when:
|
|
41
|
+
- the summary is too compressed to trust for specifics
|
|
42
|
+
- you need a precise answer with citations to summary IDs
|
|
43
|
+
- you are answering questions about prior decisions, dates, commands, or exact claims
|
|
28
44
|
|
|
29
45
|
### `lcm_expand`
|
|
30
|
-
Low-level DAG expansion tool used
|
|
46
|
+
Low-level DAG expansion tool used by the delegated expansion path.
|
|
47
|
+
|
|
48
|
+
Use it directly only when you know you need manual DAG traversal rather than the usual query flow.
|
|
31
49
|
|
|
32
|
-
## Brain runtime tools
|
|
50
|
+
## 2. Brain runtime tools
|
|
33
51
|
|
|
34
|
-
Use these when working with the learned routing layer
|
|
52
|
+
Use these when you are working with the learned routing layer itself, not when you are doing ordinary memory recall.
|
|
35
53
|
|
|
36
54
|
### `brain_teach`
|
|
37
55
|
Teach the brain a correction or reusable guidance.
|
|
@@ -40,6 +58,7 @@ Current truth:
|
|
|
40
58
|
- immediate retrieval is wired into the runtime
|
|
41
59
|
- taught nodes are embedded immediately when embeddings are configured
|
|
42
60
|
- taught corrections bind most strongly when invoked from a live tool session on the active conversation
|
|
61
|
+
- deterministic session-bound proof exists even though raw prompt-driven host proof is not the release boundary
|
|
43
62
|
|
|
44
63
|
Primary code:
|
|
45
64
|
- `src/brain-runtime/tools.ts`
|
|
@@ -47,15 +66,15 @@ Primary code:
|
|
|
47
66
|
- `test/brain-runtime/service.test.ts`
|
|
48
67
|
|
|
49
68
|
### `brain_status`
|
|
50
|
-
Inspect operator/runtime truth for the
|
|
69
|
+
Inspect current operator/runtime truth for the learned layer.
|
|
51
70
|
|
|
52
71
|
Typical surfaces include:
|
|
53
|
-
- enabled
|
|
72
|
+
- enabled/disabled state
|
|
54
73
|
- embedding configuration truth
|
|
55
74
|
- worker mode / PID / heartbeat / health
|
|
56
75
|
- current promoted pack metadata
|
|
57
76
|
- last assembly decision
|
|
58
|
-
- graph
|
|
77
|
+
- graph and health counters
|
|
59
78
|
|
|
60
79
|
Primary code:
|
|
61
80
|
- `src/brain-runtime/tools.ts`
|
|
@@ -63,14 +82,14 @@ Primary code:
|
|
|
63
82
|
- `src/brain-cli.ts`
|
|
64
83
|
|
|
65
84
|
### `brain_trace`
|
|
66
|
-
Inspect the most recent trace or a specific trace
|
|
85
|
+
Inspect the most recent trace or a specific trace ID.
|
|
67
86
|
|
|
68
87
|
Typical surfaces include:
|
|
69
88
|
- chosen seed
|
|
70
89
|
- seed scores
|
|
71
90
|
- fired nodes
|
|
72
91
|
- pack version
|
|
73
|
-
- route footer
|
|
92
|
+
- route summary/footer
|
|
74
93
|
- episode linkage
|
|
75
94
|
|
|
76
95
|
Primary code:
|
|
@@ -78,29 +97,41 @@ Primary code:
|
|
|
78
97
|
- `src/brain-runtime/service.ts`
|
|
79
98
|
- `src/brain-core/trace.ts`
|
|
80
99
|
|
|
81
|
-
## When to use
|
|
100
|
+
## When not to use brain tools
|
|
101
|
+
|
|
102
|
+
Do **not** reach for brain tools just because you need memory.
|
|
103
|
+
|
|
104
|
+
If the question is really:
|
|
105
|
+
- "what happened earlier?"
|
|
106
|
+
- "what decision did we already make?"
|
|
107
|
+
- "what was the command / date / file path?"
|
|
108
|
+
|
|
109
|
+
…then start with **LCM recall tools**, not `brain_teach`, `brain_status`, or `brain_trace`.
|
|
110
|
+
|
|
111
|
+
Brain tools are for:
|
|
112
|
+
- teaching the learned layer
|
|
113
|
+
- auditing runtime/operator truth
|
|
114
|
+
- inspecting a live routing decision
|
|
82
115
|
|
|
83
|
-
|
|
84
|
-
- Need to teach/update the current routing layer? use **`brain_teach`**
|
|
85
|
-
- Need current runtime/operator truth? use **`brain_status`**
|
|
86
|
-
- Need to inspect a specific routing decision? use **`brain_trace`**
|
|
116
|
+
They are **not** the general-purpose recall interface.
|
|
87
117
|
|
|
88
118
|
## Prompting guidance for agents
|
|
89
119
|
|
|
90
|
-
A good agent prompt should make
|
|
120
|
+
A good agent prompt should make the split explicit:
|
|
91
121
|
|
|
92
122
|
```markdown
|
|
93
123
|
## Memory and routing tools
|
|
94
124
|
|
|
95
125
|
For recall from compacted history:
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
126
|
+
- lcm_grep
|
|
127
|
+
- lcm_describe
|
|
128
|
+
- lcm_expand_query
|
|
99
129
|
|
|
100
130
|
For the live learned routing layer:
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
131
|
+
- brain_teach
|
|
132
|
+
- brain_status
|
|
133
|
+
- brain_trace
|
|
104
134
|
|
|
105
|
-
Use LCM tools for recall.
|
|
135
|
+
Use LCM tools for recall.
|
|
136
|
+
Use brain tools only when teaching or auditing the routing layer itself.
|
|
106
137
|
```
|
package/docs/architecture.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
-
This document
|
|
3
|
+
This document explains the architecture that OpenClawBrain is built on.
|
|
4
|
+
|
|
5
|
+
Important framing:
|
|
6
|
+
- the **transcript-memory substrate** is inherited from lossless-claw / LCM
|
|
7
|
+
- the **learned routing layer** is the OpenClawBrain-specific addition on top
|
|
8
|
+
- this doc covers both, so deeper sections will still talk in substrate terms where that is the real implementation boundary
|
|
9
|
+
|
|
10
|
+
## Architecture in one minute
|
|
11
|
+
|
|
12
|
+
OpenClawBrain has two cooperating layers:
|
|
13
|
+
|
|
14
|
+
1. **LCM substrate**
|
|
15
|
+
- persists messages and message parts
|
|
16
|
+
- compacts old history into a summary DAG
|
|
17
|
+
- assembles summaries plus fresh raw turns back into model context
|
|
18
|
+
- supports expansion back into compressed detail
|
|
19
|
+
|
|
20
|
+
2. **Learned routing layer**
|
|
21
|
+
- decides whether to use learned retrieval, shadow the route, or skip with an explicit reason
|
|
22
|
+
- retrieves from immutable promoted packs only
|
|
23
|
+
- records episodes and traces on the live path
|
|
24
|
+
- trains in the background from structured evidence and replay-gated promotion
|
|
25
|
+
|
|
26
|
+
The repo identity is OpenClawBrain. The substrate history is still real, but it should not be confused with the whole product story.
|
|
4
27
|
|
|
5
28
|
## Data model
|
|
6
29
|
|
|
@@ -9,216 +32,179 @@ This document describes how lossless-claw works internally — the data model, c
|
|
|
9
32
|
Every OpenClaw session maps to a **conversation**. The first time a session ingests a message, LCM creates a conversation record keyed by the runtime session ID.
|
|
10
33
|
|
|
11
34
|
Messages are stored with:
|
|
12
|
-
- **seq** —
|
|
35
|
+
- **seq** — monotonically increasing sequence number within the conversation
|
|
13
36
|
- **role** — `user`, `assistant`, `system`, or `tool`
|
|
14
|
-
- **content** —
|
|
15
|
-
- **tokenCount** —
|
|
16
|
-
- **createdAt** —
|
|
37
|
+
- **content** — plain-text extraction of the message
|
|
38
|
+
- **tokenCount** — estimated token count (~4 chars/token)
|
|
39
|
+
- **createdAt** — insertion timestamp
|
|
17
40
|
|
|
18
|
-
Each message also has **message_parts** — structured content blocks that preserve the original shape (text blocks, tool calls, tool results, reasoning, file content,
|
|
41
|
+
Each message also has **message_parts** — structured content blocks that preserve the original shape (text blocks, tool calls, tool results, reasoning, file content, and so on). That lets the assembler reconstruct rich content instead of only flattened text.
|
|
19
42
|
|
|
20
43
|
### The summary DAG
|
|
21
44
|
|
|
22
|
-
Summaries form a directed acyclic graph with two node types:
|
|
45
|
+
Summaries form a directed acyclic graph with two main node types:
|
|
23
46
|
|
|
24
|
-
**Leaf summaries** (depth 0, kind `"leaf"`)
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
47
|
+
**Leaf summaries** (depth 0, kind `"leaf"`)
|
|
48
|
+
- created from a chunk of raw messages
|
|
49
|
+
- linked to source messages via `summary_messages`
|
|
50
|
+
- contain a narrative summary with timestamps
|
|
51
|
+
- typically 800–1200 tokens
|
|
29
52
|
|
|
30
|
-
**Condensed summaries** (depth 1+, kind `"condensed"`)
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
53
|
+
**Condensed summaries** (depth 1+, kind `"condensed"`)
|
|
54
|
+
- created from a chunk of summaries at the same depth
|
|
55
|
+
- linked to parent summaries via `summary_parents`
|
|
56
|
+
- use progressively more abstract prompts as depth increases
|
|
57
|
+
- typically 1500–2000 tokens
|
|
35
58
|
|
|
36
59
|
Every summary carries:
|
|
37
|
-
- **summaryId** — `sum_` + 16 hex chars
|
|
38
|
-
- **conversationId** —
|
|
39
|
-
- **depth** —
|
|
40
|
-
- **earliestAt / latestAt** —
|
|
41
|
-
- **descendantCount** —
|
|
42
|
-
- **fileIds** —
|
|
43
|
-
- **tokenCount** —
|
|
60
|
+
- **summaryId** — `sum_` + 16 hex chars
|
|
61
|
+
- **conversationId** — which conversation it belongs to
|
|
62
|
+
- **depth** — hierarchy position
|
|
63
|
+
- **earliestAt / latestAt** — source time range
|
|
64
|
+
- **descendantCount** — total transitive ancestor coverage
|
|
65
|
+
- **fileIds** — referenced large files
|
|
66
|
+
- **tokenCount** — estimated tokens
|
|
44
67
|
|
|
45
68
|
### Context items
|
|
46
69
|
|
|
47
|
-
The
|
|
70
|
+
The `context_items` table maintains the ordered list of what the model sees for each conversation. Each entry is either a message reference or a summary reference.
|
|
48
71
|
|
|
49
|
-
When compaction creates a summary from a range of messages
|
|
72
|
+
When compaction creates a summary from a range of messages or summaries, the source items are replaced by a single summary item. That keeps the active context compact while preserving ordering.
|
|
50
73
|
|
|
51
74
|
## Compaction lifecycle
|
|
52
75
|
|
|
53
76
|
### Ingestion
|
|
54
77
|
|
|
55
|
-
When OpenClaw processes a turn, it calls the context engine
|
|
78
|
+
When OpenClaw processes a turn, it calls the context engine lifecycle hooks:
|
|
56
79
|
|
|
57
|
-
1. **bootstrap** —
|
|
58
|
-
2. **ingest
|
|
59
|
-
3. **afterTurn** —
|
|
80
|
+
1. **bootstrap** — reconciles the JSONL session file with the LCM database for crash recovery
|
|
81
|
+
2. **ingest / ingestBatch** — persists new messages and appends them to `context_items`
|
|
82
|
+
3. **afterTurn** — ingests new messages, then evaluates whether compaction should run
|
|
60
83
|
|
|
61
84
|
### Leaf compaction
|
|
62
85
|
|
|
63
|
-
The
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
8. If the summary is larger than the input (LLM failure), retry with the aggressive prompt. If still too large, fall back to deterministic truncation.
|
|
73
|
-
9. Persist the summary, link to source messages, and replace the message range in context_items.
|
|
86
|
+
The leaf pass converts raw messages into leaf summaries:
|
|
87
|
+
1. identify the oldest contiguous chunk of raw messages outside the protected fresh tail
|
|
88
|
+
2. cap the chunk at `leafChunkTokens`
|
|
89
|
+
3. concatenate message content with timestamps
|
|
90
|
+
4. pass prior summary context for continuity when available
|
|
91
|
+
5. summarize with the leaf prompt
|
|
92
|
+
6. normalize provider output into plain text
|
|
93
|
+
7. fall back deterministically if normalization is empty or poor
|
|
94
|
+
8. persist the summary and replace the source range in `context_items`
|
|
74
95
|
|
|
75
96
|
### Condensation
|
|
76
97
|
|
|
77
|
-
The
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
5. Persist with depth = targetDepth + 1, link to parent summaries, replace the range in context_items.
|
|
98
|
+
The condensed pass merges summaries at the same depth into a higher-level summary:
|
|
99
|
+
1. find the shallowest eligible depth with enough contiguous same-depth summaries
|
|
100
|
+
2. concatenate content with time-range headers
|
|
101
|
+
3. summarize with the depth-appropriate prompt
|
|
102
|
+
4. use the same escalation path (normal → aggressive → deterministic fallback)
|
|
103
|
+
5. persist the new summary and replace the source range in `context_items`
|
|
84
104
|
|
|
85
105
|
### Compaction modes
|
|
86
106
|
|
|
87
|
-
**Incremental
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
- Best-effort: failures don't break the conversation
|
|
92
|
-
|
|
93
|
-
**Full sweep (manual `/compact` or overflow):**
|
|
94
|
-
- Phase 1: Repeatedly runs leaf passes until no more eligible chunks
|
|
95
|
-
- Phase 2: Repeatedly runs condensation passes starting from the shallowest eligible depth
|
|
96
|
-
- Each pass checks for progress; stops if no tokens were saved
|
|
107
|
+
**Incremental**
|
|
108
|
+
- runs after turns when raw tokens outside the fresh tail exceed the configured threshold
|
|
109
|
+
- may continue with condensation passes depending on `incrementalMaxDepth`
|
|
110
|
+
- failures are best-effort and should not break the conversation
|
|
97
111
|
|
|
98
|
-
**
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
- Used by the overflow recovery path
|
|
112
|
+
**Full sweep**
|
|
113
|
+
- repeatedly runs leaf passes, then condensation passes, until no further savings are found
|
|
114
|
+
- used for manual `/compact` and overflow recovery
|
|
102
115
|
|
|
103
|
-
|
|
116
|
+
**Budget-targeted**
|
|
117
|
+
- runs bounded rounds of full sweeps until context falls under a target budget
|
|
104
118
|
|
|
105
|
-
|
|
119
|
+
### Three-level summarization escalation
|
|
106
120
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
121
|
+
Every summarization attempt follows the same escalation:
|
|
122
|
+
1. **normal** — standard prompt
|
|
123
|
+
2. **aggressive** — tighter prompt with lower token target
|
|
124
|
+
3. **fallback** — deterministic truncation
|
|
110
125
|
|
|
111
|
-
|
|
126
|
+
That guarantees compaction still makes progress when model output is weak or malformed.
|
|
112
127
|
|
|
113
128
|
## Context assembly
|
|
114
129
|
|
|
115
|
-
|
|
130
|
+
Before each model turn, the assembler builds the message array from summaries plus the fresh raw tail:
|
|
116
131
|
|
|
117
|
-
```
|
|
132
|
+
```text
|
|
118
133
|
[summary₁, summary₂, ..., summaryₙ, message₁, message₂, ..., messageₘ]
|
|
119
134
|
├── budget-constrained ──┤ ├──── fresh tail (always included) ────┤
|
|
120
135
|
```
|
|
121
136
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
6. Normalize assistant content to array blocks (Anthropic API compatibility).
|
|
130
|
-
7. Sanitize tool-use/result pairing (ensures every tool_result has a matching tool_use).
|
|
137
|
+
Steps:
|
|
138
|
+
1. fetch `context_items` in order
|
|
139
|
+
2. resolve each item into either reconstructed rich messages or XML-wrapped summaries
|
|
140
|
+
3. split into evictable prefix and protected fresh tail
|
|
141
|
+
4. always include the fresh tail, even if it is expensive
|
|
142
|
+
5. backfill the remaining budget from the newest evictable items
|
|
143
|
+
6. normalize assistant content blocks and sanitize tool pairing
|
|
131
144
|
|
|
132
|
-
|
|
145
|
+
## XML summary format
|
|
133
146
|
|
|
134
|
-
Summaries are
|
|
147
|
+
Summaries are shown to the model as user messages with XML wrappers, for example:
|
|
135
148
|
|
|
136
149
|
```xml
|
|
137
150
|
<summary id="sum_abc123" kind="leaf" depth="0" descendant_count="0"
|
|
138
151
|
earliest_at="2026-02-17T07:37:00" latest_at="2026-02-17T08:23:00">
|
|
139
152
|
<content>
|
|
140
|
-
...summary text
|
|
153
|
+
...summary text...
|
|
141
154
|
|
|
142
155
|
Expand for details about: exact error messages, full config diff, intermediate debugging steps
|
|
143
156
|
</content>
|
|
144
157
|
</summary>
|
|
145
158
|
```
|
|
146
159
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
```xml
|
|
150
|
-
<summary id="sum_def456" kind="condensed" depth="1" descendant_count="8" ...>
|
|
151
|
-
<parents>
|
|
152
|
-
<summary_ref id="sum_aaa111" />
|
|
153
|
-
<summary_ref id="sum_bbb222" />
|
|
154
|
-
</parents>
|
|
155
|
-
<content>...</content>
|
|
156
|
-
</summary>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
The XML attributes give the model enough metadata to reason about summary age, scope, and how to drill deeper. The `<parents>` section enables targeted expansion of specific source summaries.
|
|
160
|
+
That metadata gives the model temporal scope, hierarchy, and a hint about what can be expanded for detail.
|
|
160
161
|
|
|
161
162
|
## Expansion system
|
|
162
163
|
|
|
163
164
|
When summaries are too compressed for a task, agents use `lcm_expand_query` to recover detail.
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
6. The sub-agent returns a focused answer (default ≤ 2000 tokens) with cited summary IDs.
|
|
173
|
-
7. The grant is revoked and the sub-agent session is cleaned up.
|
|
174
|
-
|
|
175
|
-
### Security model
|
|
166
|
+
High-level flow:
|
|
167
|
+
1. agent calls `lcm_expand_query` with a prompt and either `summaryIds` or a search query
|
|
168
|
+
2. matching summaries are located if needed
|
|
169
|
+
3. a bounded delegated expansion grant is created
|
|
170
|
+
4. a sub-agent walks the DAG, source messages, and referenced files
|
|
171
|
+
5. the sub-agent returns a focused answer with cited summary IDs
|
|
172
|
+
6. the grant is revoked and cleaned up
|
|
176
173
|
|
|
177
|
-
|
|
174
|
+
This is the right tool family for compacted-memory recall. It is separate from the learned-routing tools like `brain_teach`, `brain_status`, and `brain_trace`.
|
|
178
175
|
|
|
179
|
-
-
|
|
180
|
-
- **Token caps** limit how much content the sub-agent can access
|
|
181
|
-
- **TTL** ensures grants expire even if cleanup fails
|
|
182
|
-
- **Revocation** happens on completion, cancellation, or sweep
|
|
176
|
+
## Large-file handling
|
|
183
177
|
|
|
184
|
-
|
|
178
|
+
Large file blocks are intercepted at ingestion when they exceed the configured threshold:
|
|
179
|
+
1. parse file blocks from message content
|
|
180
|
+
2. store oversized file content separately on disk
|
|
181
|
+
3. generate a lightweight exploration summary
|
|
182
|
+
4. insert a `large_files` record with metadata
|
|
183
|
+
5. replace the in-message payload with a compact reference
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Files embedded in user messages (typically via `<file>` blocks from tool output) are checked at ingestion:
|
|
189
|
-
|
|
190
|
-
1. Parse file blocks from message content.
|
|
191
|
-
2. For each block exceeding `largeFileTokenThreshold` (default 25k tokens):
|
|
192
|
-
- Generate a unique file ID (`file_` prefix)
|
|
193
|
-
- Store the content to `~/.openclaw/lcm-files/<conversation_id>/<file_id>.<ext>`
|
|
194
|
-
- Generate a ~200 token exploration summary (structural analysis, key sections, etc.)
|
|
195
|
-
- Insert a `large_files` record with metadata
|
|
196
|
-
- Replace the file block in the message with a compact reference
|
|
197
|
-
3. The `lcm_describe` tool can retrieve full file content by ID.
|
|
198
|
-
|
|
199
|
-
This prevents a single large file paste from consuming the entire context window while keeping the content accessible.
|
|
185
|
+
This keeps huge file pastes from consuming the entire active context while preserving access to the content.
|
|
200
186
|
|
|
201
187
|
## Session reconciliation
|
|
202
188
|
|
|
203
|
-
LCM handles crash recovery through
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
4. Import any messages after the anchor that are in JSONL but not in LCM.
|
|
209
|
-
|
|
210
|
-
This handles the case where OpenClaw wrote messages to the session file but crashed before LCM could persist them.
|
|
189
|
+
LCM handles crash recovery through bootstrap reconciliation:
|
|
190
|
+
1. read the JSONL session file
|
|
191
|
+
2. compare it to the LCM database
|
|
192
|
+
3. find the newest shared anchor message
|
|
193
|
+
4. import any later JSONL messages missing from the database
|
|
211
194
|
|
|
212
195
|
## Operation serialization
|
|
213
196
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
## Authentication
|
|
197
|
+
Mutating operations are serialized per session using a promise queue. That prevents races between concurrent ingest/compact activity for the same conversation without blocking different conversations.
|
|
217
198
|
|
|
218
|
-
|
|
199
|
+
## Learned-layer overlay
|
|
219
200
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
201
|
+
On top of the substrate above, OpenClawBrain adds:
|
|
202
|
+
- runtime decisioning (`use_brain`, `shadow`, explicit skip modes)
|
|
203
|
+
- correction-first learned retrieval from immutable promoted packs
|
|
204
|
+
- immediate `brain_teach` updates when embeddings are configured
|
|
205
|
+
- episode/trace recording
|
|
206
|
+
- structured evidence harvesting
|
|
207
|
+
- replay-gated promotion
|
|
208
|
+
- supervised child-worker learning boundary
|
|
223
209
|
|
|
224
|
-
|
|
210
|
+
That overlay is what turns the inherited transcript-memory system into OpenClawBrain as a product.
|