# Enable context offload

> Turn on offload.enabled, register plugins.slots.contextEngine, apply after-tool-call patch, and confirm Mermaid injection and data under context-offload.

- Repository: TencentCloud/TencentDB-Agent-Memory
- GitHub: https://github.com/TencentCloud/TencentDB-Agent-Memory
- Human docs: https://grok-wiki.com/public/docs/tencentcloud-tencentdb-agent-memory-14fefdd76c97
- Complete Markdown: https://grok-wiki.com/public/docs/tencentcloud-tencentdb-agent-memory-14fefdd76c97/llms-full.txt

## Source Files

- `src/offload/index.ts`
- `scripts/openclaw-after-tool-call-messages.patch.sh`
- `scripts/setup-offload.sh`
- `openclaw.plugin.json`
- `src/config.ts`
- `README.md`

---

---
title: "Enable context offload"
description: "Turn on offload.enabled, register plugins.slots.contextEngine, apply after-tool-call patch, and confirm Mermaid injection and data under context-offload."
---

Context offload is an independent short-term compression path inside `@tencentdb-agent-memory/memory-tencentdb`. When `plugins.entries.memory-tencentdb.config.offload.enabled` is true, `registerOffload()` in `src/offload/index.ts` registers hooks (`after_tool_call`, L3 compression, Mermaid injection) and, for normal modes, claims OpenClaw’s `plugins.slots.contextEngine` with id `memory-tencentdb`. Offload data defaults to `~/.openclaw/context-offload` and is separate from long-term memory under `~/.openclaw/memory-tdai`.

<Note>
Offload defaults to **off**. Long-term L0–L3 memory keeps working when offload is disabled. Enabling offload does not require Tencent VectorDB; local mode uses the host agent model / `models.providers` credentials (BYOK).
</Note>

## Prerequisites

| Requirement | Detail |
| :--- | :--- |
| Node | `>= 22.16.0` |
| OpenClaw | Plugin compat `>= 2026.3.13` (package peer: `openclaw >= 2026.3.7`) |
| Plugin installed | `openclaw plugins install @tencentdb-agent-memory/memory-tencentdb` (or linked from source) |
| Config file | `~/.openclaw/openclaw.json` present and valid JSON |
| LLM for L1/L1.5/L2 | **Local mode:** `offload.model` or `agents.defaults.model` as `provider/model-id`, with matching `models.providers[provider].baseUrl` + `apiKey` (or auth profile). **Backend mode:** `offload.backendUrl` (+ optional `backendApiKey`) |

## Enable checklist

Three pieces must all be true for full offload (tool-pair capture, Mermaid canvas, L3 compression via Context Engine):

| # | Surface | Required value |
| :---: | :--- | :--- |
| 1 | `plugins.entries.memory-tencentdb.config.offload.enabled` | `true` |
| 2 | `plugins.slots.contextEngine` | `"memory-tencentdb"` |
| 3 | OpenClaw `after_tool_call` messages patch | Injects `messages: ctx.params.session?.messages` into the hook event |

If the slot is missing or points elsewhere, `registerOffload` sets `_contextEngineRejected` and **all offload hooks become no-ops**. If the patch is missing, `after_tool_call` still runs but cannot reliably read session messages for L1 buffering and Mermaid injection.

```mermaid
flowchart TB
  subgraph config ["~/.openclaw/openclaw.json"]
    EN["offload.enabled = true"]
    SLOT["plugins.slots.contextEngine = memory-tencentdb"]
    MODE["offload.mode: local | backend | collect"]
  end

  subgraph host ["OpenClaw runtime"]
    PATCH["after_tool_call patch\nmessages: session.messages"]
    REG["registerOffload()"]
    CE["registerContextEngine(memory-tencentdb)"]
    HOOKS["hooks: after_tool_call,\nassemble / L3 / MMD inject"]
  end

  subgraph disk ["DEFAULT_DATA_ROOT"]
    ROOT["~/.openclaw/context-offload"]
    AGENT["agentName/"]
    REFS["refs/*.md"]
    MMD["mmds/*.mmd"]
    JSONL["offload-sessionId.jsonl"]
  end

  EN --> REG
  SLOT --> CE
  PATCH --> HOOKS
  REG --> CE
  REG --> HOOKS
  HOOKS --> REFS
  HOOKS --> MMD
  HOOKS --> JSONL
  AGENT --> REFS
  AGENT --> MMD
  AGENT --> JSONL
  ROOT --> AGENT
```

## Quick enable with setup script

`scripts/setup-offload.sh` is the one-shot path for **backend** offload. It backs up `openclaw.json`, runs the patch, sets the slot, writes offload fields, and sets compaction to `safeguard`.

```bash
# From the installed package or a source checkout
bash scripts/setup-offload.sh --enable \
  --user-id <userId> \
  --backend-url http://host:port \
  [--backend-api-key <token>]

bash scripts/setup-offload.sh --status
bash scripts/setup-offload.sh --disable
```

| Flag | Required | Effect |
| :--- | :---: | :--- |
| `--enable` / `--disable` / `--status` | one of | Mode selection |
| `--user-id` | for enable | Written to `offload.userId` (backend `X-User-Id`) |
| `--backend-url` | for enable | Must start with `http://` or `https://` |
| `--backend-api-key` | no | Optional `offload.backendApiKey`; omitted key removes an existing key |

Enable steps (in order):

1. **Patch** — runs `scripts/openclaw-after-tool-call-messages.patch.sh`. Exit non-zero aborts enable (exit code 2).
2. **Slot** — `plugins.slots.contextEngine = "memory-tencentdb"`.
3. **Offload config** — `enabled: true`, `backendUrl`, `userId`, `backendTimeoutMs` defaulted if missing (`120000` in the script).
4. **Compaction** — `agents.defaults.compaction.mode = "safeguard"`.

After enable, **restart the OpenClaw gateway** so the slot and hooks load.

<Warning>
`setup-offload.sh --enable` requires `backendUrl` and is oriented to backend mode. For **local** mode (no remote offload API), use the manual config below and omit `backendUrl` so `parseConfig` resolves `mode: "local"`.
</Warning>

## Manual enable

### 1. Turn on offload

Edit `~/.openclaw/openclaw.json`:

```json
{
  "plugins": {
    "entries": {
      "memory-tencentdb": {
        "enabled": true,
        "config": {
          "offload": {
            "enabled": true
          }
        }
      }
    }
  }
}
```

Minimum key for registration: `offload.enabled: true`. With no `backendUrl` and no explicit `mode`, runtime mode is **`local`**.

### 2. Register the context engine slot

```json
{
  "plugins": {
    "slots": {
      "contextEngine": "memory-tencentdb"
    }
  }
}
```

The plugin id and slot id must both be `memory-tencentdb` (not the legacy `openclaw-context-offload` owner string used only inside `OffloadContextEngine.info`).

### 3. Apply the after-tool-call patch

```bash
bash scripts/openclaw-after-tool-call-messages.patch.sh
# optional: path to a specific OpenClaw install
bash scripts/openclaw-after-tool-call-messages.patch.sh /path/to/openclaw
# debug failed matches
DEBUG=1 bash scripts/openclaw-after-tool-call-messages.patch.sh
```

What the patch does:

- Locates the OpenClaw package root (CLI path, pnpm shims, common global dirs).
- Finds `dist/**/*.js` files containing `after_tool_call` + `durationMs`.
- Injects `messages: ctx.params.session?.messages` into the hook event object.
- **Idempotent** — already-patched files are skipped.
- Backups: `*.pre-offload-patch.bak` next to patched files.
- Exit **0** if at least one file was patched or already patched; **1** if nothing could be patched.

Package install also runs this script from `postinstall` (`|| true`), so a failed silent postinstall does **not** block npm install — re-run the script explicitly if offload misbehaves.

### 4. Recommended companion settings

| Setting | Suggested | Why |
| :--- | :--- | :--- |
| `agents.defaults.compaction.mode` | `"safeguard"` | Set by `setup-offload.sh`; Context Engine owns compaction (`ownsCompaction: true`) |
| `offload.model` | `provider/model-id` | Local L1/L1.5/L2 when not using main agent model |
| `offload.backendUrl` | HTTPS/HTTP service | Switches auto-mode to `backend` when `mode` omitted |
| `offload.userId` | stable id | Backend store key; else primary non-loopback IPv4 |

## Modes

`parseConfig` resolves `offload.mode`:

| `mode` | When | Context Engine | L1/L1.5/L2 | L3 compression |
| :--- | :--- | :---: | :---: | :---: |
| `local` | Default if no `backendUrl` | Registered (slot required) | Local LLM via AI SDK | Yes |
| `backend` | Explicit or auto when `backendUrl` set | Registered | Remote backend | Yes |
| `collect` | Explicit `"collect"` | **Not** registered | Async collection | **No** (legacy compaction) |

In `collect` mode, if `slots.contextEngine` is still `"memory-tencentdb"`, the plugin logs a warning: the engine is not registered; remove the slot or switch mode.

## Core config keys

Runtime defaults come from `src/config.ts` (`OffloadConfig`):

| Key | Default | Notes |
| :--- | :--- | :--- |
| `enabled` | `false` | Master switch |
| `mode` | auto `local` / `backend` | Or explicit `local` \| `backend` \| `collect` |
| `model` | host default | `provider/model-id` |
| `temperature` | `0.2` | Offload LLM |
| `disableThinking` | `false` | Local mode only |
| `forceTriggerThreshold` | `4` | Pending tool pairs → force L1 |
| `dataDir` | unset | Absolute path; else `~/.openclaw/context-offload` |
| `defaultContextWindow` | `200000` | Fallback window |
| `maxPairsPerBatch` | `20` | L1 batch cap |
| `l2NullThreshold` | `4` | `node_id=null` count → L2 |
| `l2TimeoutSeconds` | `300` | Time-based L2 trigger |
| `mildOffloadRatio` | `0.5` | Mild L3 threshold (fraction of window) |
| `aggressiveCompressRatio` | `0.85` | Aggressive L3 threshold |
| `mmdMaxTokenRatio` | `0.2` | Mermaid injection token budget |
| `backendUrl` / `backendApiKey` | unset | Backend routing + auth |
| `backendTimeoutMs` | `120000` | Runtime default (schema text may differ) |
| `offloadRetentionDays` | `0` | Reclaim off unless `>= 3` |
| `logMaxSizeMb` | `50` | Debug log cap under data root |
| `userId` | auto IP fallback | Backend identity header |

## Disable

```bash
bash scripts/setup-offload.sh --disable
```

Or manually:

1. Set `offload.enabled` to `false`.
2. Delete `plugins.slots.contextEngine` (or free the slot for another engine).
3. Restart the gateway.

The after-tool-call patch is **not** reverted by disable; leave it in place or restore from `*.pre-offload-patch.bak` only if you must.

## Verify

### Status script

```bash
bash scripts/setup-offload.sh --status
```

Expect: Context Engine Slot `memory-tencentdb`, Offload enabled, backend/user fields as configured, compaction `safeguard` when enabled via the script.

### Logs

After gateway restart, look for:

| Signal | Meaning |
| :--- | :--- |
| `[context-offload] Registering offload module...` | `registerOffload` entered |
| `Context engine registered successfully` | Slot acquired |
| `LLM mode: local (...)` or `LLM mode: backend (...)` | Client selected |
| `>>> after_tool_call START` | Tool pairs buffering |
| `after_tool_call MMD: INJECTED` / `UPDATED` | Mermaid in session messages |
| `assemble CALLED` / L3 cascade logs | Context Engine assemble path |
| `Config plugins.slots.contextEngine=... ALL offload functions disabled` | **Slot misconfigured** |
| `registerContextEngine returned { ok: false` | **Slot occupied** |
| `after_tool_call patch check: NOT EFFECTIVE` | **Patch missing/failed** |

### On-disk data

Default root: `~/.openclaw/context-offload` (override with `offload.dataDir`).

:::files
~/.openclaw/context-offload/
└── <agentName>/
    ├── state.json
    ├── offload-<sessionId>.jsonl
    ├── refs/
    │   └── *.md
    └── mmds/
        └── *.mmd
:::

| Path | Role |
| :--- | :--- |
| `refs/*.md` | Full tool results (bottom layer) |
| `offload-*.jsonl` | L1 summaries + `node_id` / `result_ref` |
| `mmds/*.mmd` | Mermaid task canvas (top layer) |
| `state.json` | Active MMD, counters, session state |

After tool-heavy turns, expect new `refs` files, growing jsonl lines, and eventually `.mmd` files when L2 runs (`l2NullThreshold` / `l2TimeoutSeconds`).

### Smoke conversation

1. Restart OpenClaw gateway.
2. Run a session that executes several tools (search, shell, etc.).
3. Confirm logs show `after_tool_call` + optional MMD inject.
4. Confirm files under `~/.openclaw/context-offload/<agent>/`.
5. In the next model turn, context should prefer Mermaid symbols over full tool dumps when L3 thresholds fire.

## Failure modes

| Symptom | Likely cause | Fix |
| :--- | :--- | :--- |
| No `[context-offload]` logs | `offload.enabled` false or plugin not loaded | Enable config; confirm plugin entry enabled; restart |
| All hooks no-op | Slot not `memory-tencentdb` or CE rejected | Set `plugins.slots.contextEngine`; free conflicting owner |
| Tool pairs not buffered / patch NOT EFFECTIVE | Patch not applied or OpenClaw layout unsupported | Re-run patch; `DEBUG=1`; re-apply after OpenClaw upgrade |
| L1/L1.5/L2 disabled, L3 only | Local model/provider missing or backend URL missing | Fix `offload.model` + `models.providers`, or set `backendUrl` |
| Collect mode: no compression | Expected for `mode: "collect"` | Switch to `local`/`backend` and keep the slot |
| Empty data dir | No tools yet, or hooks disabled | Exercise tool calls; check rejection logs first |
| Patch fails on every OpenClaw upgrade | dist rebuilt without injection | Re-run `openclaw-after-tool-call-messages.patch.sh` |

## Related pages

<CardGroup>
  <Card title="Context offload" href="/context-offload">
    Symbolic short-term design: tool-pair offload, L1/L1.5/L2 Mermaid canvas, L3 thresholds, node_id drill-down.
  </Card>
  <Card title="Installation" href="/installation">
    Plugin install/update, Node/OpenClaw prerequisites, postinstall patch behavior.
  </Card>
  <Card title="Configuration reference" href="/configuration-reference">
    Full offload and plugin schema, defaults, and degrade rules.
  </Card>
  <Card title="Data directories" href="/data-directories">
    On-disk layout for memory-tdai vs context-offload trees.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Offload slot/patch failures and recovery probes.
  </Card>
</CardGroup>
