feat: add pre-compaction memory flush

This commit is contained in:
Peter Steinberger
2026-01-12 05:28:17 +00:00
parent cc8a2457c0
commit 7dbb21be8e
19 changed files with 583 additions and 22 deletions

View File

@@ -99,6 +99,8 @@ These are the standard files Clawdbot expects inside the workspace:
- Curated long-term memory.
- Only load in the main, private session (not shared/group contexts).
See [Memory](/concepts/memory) for the workflow and automatic memory flush.
- `skills/` (optional)
- Workspace-specific skills.
- Overrides managed/bundled skills when names collide.

View File

@@ -22,6 +22,9 @@ Youll see:
- `🧹 Auto-compaction complete` in verbose mode
- `/status` showing `🧹 Compactions: <count>`
Before compaction, Clawdbot can run a **silent memory flush** turn to store
durable notes to disk. See [Memory](/concepts/memory) for details and config.
## Manual compaction
Use `/compact` (optionally with instructions) to force a compaction pass:
```

66
docs/concepts/memory.md Normal file
View File

@@ -0,0 +1,66 @@
---
summary: "How Clawdbot memory works (workspace files + automatic memory flush)"
read_when:
- You want the memory file layout and workflow
- You want to tune the automatic pre-compaction memory flush
---
# Memory
Clawdbot memory is **plain Markdown in the agent workspace**. The files are the
source of truth; the model only “remembers” what gets written to disk.
## Memory files (Markdown)
The default workspace layout uses two memory layers:
- `memory/YYYY-MM-DD.md`
- Daily log (append-only).
- Read today + yesterday at session start.
- `MEMORY.md` (optional)
- Curated long-term memory.
- **Only load in the main, private session** (never in group contexts).
These files live under the workspace (`agents.defaults.workspace`, default
`~/clawd`). See [Agent workspace](/concepts/agent-workspace) for the full layout.
## When to write memory
- Decisions, preferences, and durable facts go to `MEMORY.md`.
- Day-to-day notes and running context go to `memory/YYYY-MM-DD.md`.
- If someone says “remember this,” write it down (dont keep it in RAM).
## Automatic memory flush (pre-compaction ping)
When a session is **close to auto-compaction**, Clawdbot triggers a **silent
agentic turn** that reminds the model to write durable memory **before** the
context is compacted. The default prompt encourages the model to respond with
`NO_REPLY` when theres nothing to store, so the user never sees this turn.
This is controlled by `agents.defaults.compaction.memoryFlush`:
```json5
{
agents: {
defaults: {
compaction: {
reserveTokensFloor: 20000,
memoryFlush: {
enabled: true,
softThresholdTokens: 4000,
systemPrompt: "Session nearing compaction. Store durable memories now.",
prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store."
}
}
}
}
}
```
Details:
- **Soft threshold**: flush triggers when the session token estimate crosses
`contextWindow - reserveTokensFloor - softThresholdTokens`.
- **Silent** by default: prompts include `NO_REPLY` so nothing is delivered.
- **One flush per compaction cycle** (tracked in `sessions.json`).
For the full compaction lifecycle, see
[Session management + compaction](/reference/session-management-compaction).

View File

@@ -608,6 +608,7 @@
"token-use",
"concepts/oauth",
"concepts/agent-workspace",
"concepts/memory",
"concepts/multi-agent",
"concepts/compaction",
"concepts/session",

View File

@@ -1368,6 +1368,40 @@ Example (adaptive tuned):
See [/concepts/session-pruning](/concepts/session-pruning) for behavior details.
#### `agents.defaults.compaction` (reserve headroom + memory flush)
`agents.defaults.compaction.reserveTokensFloor` enforces a minimum `reserveTokens`
value for Pi compaction (default: `20000`). Set it to `0` to disable the floor.
`agents.defaults.compaction.memoryFlush` runs a **silent** agentic turn before
auto-compaction, instructing the model to store durable memories on disk (e.g.
`memory/YYYY-MM-DD.md`). It triggers when the session token estimate crosses a
soft threshold below the compaction limit.
Defaults:
- `memoryFlush.enabled`: `true`
- `memoryFlush.softThresholdTokens`: `4000`
- `memoryFlush.prompt` / `memoryFlush.systemPrompt`: built-in defaults with `NO_REPLY`
Example (tuned):
```json5
{
agents: {
defaults: {
compaction: {
reserveTokensFloor: 24000,
memoryFlush: {
enabled: true,
softThresholdTokens: 6000,
systemPrompt: "Session nearing compaction. Store durable memories now.",
prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store."
}
}
}
}
}
```
Block streaming:
- `agents.defaults.blockStreamingDefault`: `"on"`/`"off"` (default off).
- Provider overrides: `*.blockStreaming` (and per-account variants) to force block streaming on/off.

View File

@@ -107,6 +107,8 @@ Key fields (not exhaustive):
- Token counters (best-effort / provider-dependent):
- `inputTokens`, `outputTokens`, `totalTokens`, `contextTokens`
- `compactionCount`: how often auto-compaction completed for this session key
- `memoryFlushAt`: timestamp for the last pre-compaction memory flush
- `memoryFlushCompactionCount`: compaction count when the last flush ran
The store is safe to edit, but the Gateway is the authority: it may rewrite or rehydrate entries as sessions run.
@@ -191,12 +193,15 @@ Pis compaction settings live in Pi settings:
Clawdbot also enforces a safety floor for embedded runs:
- If `compaction.reserveTokens < 20000`, Clawdbot bumps it to 20000.
- If `compaction.reserveTokens < reserveTokensFloor`, Clawdbot bumps it.
- Default floor is `20000` tokens.
- Set `agents.defaults.compaction.reserveTokensFloor: 0` to disable the floor.
- If its already higher, Clawdbot leaves it alone.
Why: leave enough headroom for multi-turn “housekeeping” (like memory writes) before compaction becomes unavoidable.
Implementation: `ensurePiCompactionReserveTokens()` in `src/agents/pi-settings.ts` (called from `src/agents/pi-embedded-runner.ts`).
Implementation: `ensurePiCompactionReserveTokens()` in `src/agents/pi-settings.ts`
(called from `src/agents/pi-embedded-runner.ts`).
---
@@ -223,22 +228,33 @@ As of `2026.1.10`, Clawdbot also suppresses **draft/typing streaming** when a pa
---
## Pre-compaction “memory flush” (design)
## Pre-compaction “memory flush” (implemented)
Goal: before auto-compaction happens, run a short sequence of turns that writes durable state to disk (e.g. `memory/YYYY-MM-DD.md` in the agent workspace) so compaction cant erase critical context.
Goal: before auto-compaction happens, run a silent agentic turn that writes durable
state to disk (e.g. `memory/YYYY-MM-DD.md` in the agent workspace) so compaction cant
erase critical context.
Two viable hooks:
Clawdbot uses the **pre-threshold flush** approach:
1) **Pre-threshold flush (Clawdbot-side)**
- Monitor session context usage.
- When it crosses a “soft threshold” (below Pis real compaction threshold), enqueue a silent “write memory now” directive to the agent.
- Use `NO_REPLY` so the user sees nothing.
1) Monitor session context usage.
2) When it crosses a “soft threshold” (below Pis compaction threshold), run a silent
“write memory now” directive to the agent.
3) Use `NO_REPLY` so the user sees nothing.
2) **Pi extension hook (`session_before_compact`)**
- Pis extension API exposes a `session_before_compact` event that receives compaction preparation details and can cancel or replace compaction.
- Clawdbot can ship an extension that reacts here and performs housekeeping (and/or produces a custom compaction result).
Config (`agents.defaults.compaction.memoryFlush`):
- `enabled` (default: `true`)
- `softThresholdTokens` (default: `4000`)
- `prompt` (user message for the flush turn)
- `systemPrompt` (extra system prompt appended for the flush turn)
Clawdbot currently documents the *concept* of daily memory in the workspace template (see [/concepts/agent-workspace](/concepts/agent-workspace)) but does not yet ship an automated pre-compaction flush loop.
Notes:
- The default prompt/system prompt include a `NO_REPLY` hint to suppress delivery.
- The flush runs once per compaction cycle (tracked in `sessions.json`).
- The flush runs only for embedded Pi sessions (CLI backends skip it).
- See [Memory](/concepts/memory) for the workspace file layout and write patterns.
Pi also exposes a `session_before_compact` hook in the extension API, but Clawdbots
flush logic lives on the Gateway side today.
---
@@ -251,4 +267,3 @@ Clawdbot currently documents the *concept* of daily memory in the workspace temp
- compaction settings (`reserveTokens` too high for the model window can cause earlier compaction)
- tool-result bloat: enable/tune session pruning
- Silent turns leaking? Confirm the reply starts with `NO_REPLY` (exact token) and youre on a build that includes the streaming suppression fix.

View File

@@ -102,6 +102,7 @@ clawdbot setup
```
Full workspace layout + backup guide: [Agent workspace](/concepts/agent-workspace)
Memory workflow: [Memory](/concepts/memory)
Optional: choose a different workspace with `agents.defaults.workspace` (supports `~`).

View File

@@ -197,6 +197,15 @@ ClawdHub installs into `./skills` under your current directory; Clawdbot treats
Yes. See [Sandboxing](/gateway/sandboxing). For Docker-specific setup (full gateway in Docker or sandbox images), see [Docker](/install/docker).
### How does memory work?
Clawdbot memory is just Markdown files in the agent workspace:
- Daily notes in `memory/YYYY-MM-DD.md`
- Curated long-term notes in `MEMORY.md` (main/private sessions only)
Clawdbot also runs a **silent pre-compaction memory flush** to remind the model
to write durable notes before auto-compaction. See [Memory](/concepts/memory).
## Where things live on disk
### Where does Clawdbot store its data?

View File

@@ -34,6 +34,7 @@ Use these hubs to discover every page, including deep dives and reference docs t
- [Architecture](/concepts/architecture)
- [Agent runtime](/concepts/agent)
- [Agent workspace](/concepts/agent-workspace)
- [Memory](/concepts/memory)
- [Agent loop](/concepts/agent-loop)
- [Streaming + chunking](/concepts/streaming)
- [Multi-agent routing](/concepts/multi-agent)