#My QMD memory config not working

1 messages ยท Page 1 of 1 (latest)

grave salmon
#

This is my QMD config
"memory": { "backend": "qmd", "citations": "auto", "qmd": { "includeDefaultMemory": true, "paths": [ { "name": "workspace", "path": "/root/.openclaw/workspace", "pattern": "**/*.md" }, { "name": "memory", "path": "/root/.openclaw/workspace/memory", "pattern": "*.md" } ], "update": { "interval": "5m", "embedInterval": "30m", "onBoot": true, "debounceMs": 15000, "waitForBootSync": false }, "limits": { "maxResults": 5, "maxInjectedChars": 3000, "timeoutMs": 300000 } } }

It shows that the interval of auto indexing and auto embed is 5m and 30m
But actually it do not happen (i ask Claw to test it in the log)
tail -f ~/.openclaw/logs/openclaw.log | grep -i "memory\|qmd"

And it keeps asking me to use cronjob or manual update to achieve this

Where did I do wrong ?
Please help @deep elk

hollow gladeBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> โœ… Mark Solution

deep elkBOT
# grave salmon This is my QMD config `"memory": { "backend": "qmd", "citations": "auto", ...

A couple things are going on here โ€” your config is basically fine, but your test method makes it look like โ€œnothing happensโ€.

1) Successful QMD updates donโ€™t log anything

In the current implementation, the gateway only logs QMD failures (warn), not โ€œqmd update ran successfullyโ€. So:

tail -f ~/.openclaw/logs/openclaw.log | grep -i "memory\|qmd"

will often show nothing even if the 5m interval is working perfectly.

2) Youโ€™re likely tailing the wrong log file

The recommended way is:

openclaw logs --follow
#

File locations differ depending on service/daemon vs foreground runs (docs call this out).

3) Verify QMD is actually active (and not silently falling back)

Run:

openclaw status --all

Look for the Memory section and confirm it says backend: qmd (and ideally shows a lastUpdateAt timestamp).
If it says builtin / fallback, then QMD didnโ€™t start (most common cause: qmd binary not found in the gateway service PATH).

If QMD isnโ€™t on the daemon PATH, fix by either:

  • setting memory.qmd.command to the absolute path of qmd, or
  • ensuring the service environment PATH includes wherever you installed qmd (often ~/.bun/bin).

4) โ€œInterval doesnโ€™t happenโ€ โ€” how to prove it without logs

#

Check the QMD index file timestamp instead (it should change after updates):

ls -la ~/.openclaw/agents/main/qmd/index.sqlite
# or:
stat ~/.openclaw/agents/main/qmd/index.sqlite

If you paste these three, I can tell you exactly which case youโ€™re in

openclaw --version
openclaw gateway status
openclaw status --all

Relevant docs: https://docs.openclaw.ai/concepts/memory#qmd-backend-experimental

grave salmon
#

`openclaw --version
openclaw gateway status
openclaw status --all
2026.2.9

๐Ÿฆž OpenClaw 2026.2.9 (33c75cb) โ€” Ship fast, log faster.

โ”‚
โ—‡
Service: systemd (enabled)
File logs: ~/.openclaw/logs/openclaw.log
Command: /usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js gateway --port <PORT>
Service file: ~/.config/systemd/user/openclaw-gateway.service
Service env: OPENCLAW_GATEWAY_PORT=<PORT>

Config (cli): ~/.openclaw/openclaw.json
Config (service): ~/.openclaw/openclaw.json

Gateway: bind=loopback (127.0.0.1), port=<PORT> (service args)
Probe target: ws://127.0.0.1:<PORT>
Dashboard: http://127.0.0.1:<PORT>/
Probe note: Loopback-only gateway; only local clients can connect.

Runtime: running (pid <PID>, state active, sub running, last exit 0, reason 0)
RPC probe: ok

Listening: 127.0.0.1:<PORT>
Troubles: run openclaw status
Troubleshooting: https://docs.openclaw.ai/troubleshooting

๐Ÿฆž OpenClaw 2026.2.9 (33c75cb) โ€” curl for conversations.

โ”‚
OpenClaw status --all

Overview

#

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Item โ”‚ Value โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Version โ”‚ 2026.2.9 โ”‚
โ”‚ OS โ”‚ linux <KERNEL_VERSION> (x64) โ”‚
โ”‚ Node โ”‚ <NODE_VERSION> โ”‚
โ”‚ Config โ”‚ ~/.openclaw/openclaw.json โ”‚
โ”‚ Dashboard โ”‚ http://127.0.0.1:<PORT>/ โ”‚
โ”‚ Tailscale โ”‚ serve ยท Running ยท <REDACTED_HOST>.ts.net ยท https://<REDACTED_HOST>.ts.net โ”‚
โ”‚ Channel โ”‚ stable (default) โ”‚
โ”‚ Update โ”‚ pnpm ยท npm latest 2026.2.9 โ”‚
โ”‚ Gateway โ”‚ local ยท ws://127.0.0.1:<PORT> ยท reachable <LATENCY> ยท auth token โ”‚
โ”‚ Security โ”‚ Run: openclaw security audit --deep โ”‚
โ”‚ Gateway self โ”‚ <REDACTED_MACHINE_NAME> (<REDACTED_IP>) app unknown linux <KERNEL_VERSION> โ”‚
โ”‚ Gateway service โ”‚ systemd installed ยท enabled ยท running (pid <PID>) โ”‚
โ”‚ Node service โ”‚ systemd not installed โ”‚
โ”‚ Agents โ”‚ 3 total ยท 0 bootstrapping ยท 1 active ยท 20 sessions โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

#

Channels
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Channel โ”‚ Enabled โ”‚ State โ”‚ Detail โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Telegram โ”‚ ON โ”‚ OK โ”‚ token configร—3 (sha256:<REDACTED_HASH> ยท len <LEN>) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Telegram accounts
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Account โ”‚ Status โ”‚ Notes โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ account1 โ”‚ OK โ”‚ token:config โ”‚
โ”‚ account2 โ”‚ OK โ”‚ token:config โ”‚
โ”‚ account3 โ”‚ OK โ”‚ token:config โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Agents
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Agent โ”‚ Bootstrap โ”‚ Sessions โ”‚ Active โ”‚ Store โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ agent1 โ”‚ OK โ”‚ 14 โ”‚ 1m ago โ”‚ ~/.openclaw/agents/agent1/... โ”‚
โ”‚ agent2 โ”‚ OK โ”‚ 3 โ”‚ 2d ago โ”‚ ~/.openclaw/agents/agent2/... โ”‚
โ”‚ agent3 โ”‚ OK โ”‚ 3 โ”‚ 2d ago โ”‚ ~/.openclaw/agents/agent3/... โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

#

Diagnosis (read-only)

Gateway connection details:
Gateway target: ws://127.0.0.1:<PORT>
Source: local loopback
Config: /root/.openclaw/openclaw.json
Bind: loopback

โœ“ Config: /root/.openclaw/openclaw.json
โœ“ Restart sentinel: none
! Port <PORT>
Port <PORT> is already in use.

  • pid <PID> root: openclaw-gateway (127.0.0.1:<PORT>)
  • Gateway already running locally.
    โœ“ Tailscale: serve ยท Running ยท <REDACTED_HOST>.ts.net
    ips: <REDACTED_IPv4>, <REDACTED_IPv6>
    https: https://<REDACTED_HOST>.ts.net
    โœ“ Skills: 12 eligible ยท 0 missing ยท /root/.openclaw/workspace
    โœ“ Channel issues (none)

Pasteable debug report. Auth tokens redacted.`

#

๐Ÿ“Š ANALYSIS:

๐Ÿ” REALITY STATE:

Check Result
QMD Binary โœ… Yes (/usr/bin/qmd)
Index File โœ… yes (508 KB)
Collections โœ… 7 collections created
Files Indexed โœ… 77 files
Last Update โŒ 17h ago (auto-update not running!)
Vectors โŒ 0 embedded (embed not running!)
Pending โš ๏ธ 52 files need embedding

๐ŸŽฏ CAUSE:

You were right! Auto-update not running, this is real issue:

  1. โœ… QMD installed
  2. โœ… Collections created
  3. โœ… Files indexed
  4. โŒ Auto-update interval (5m) no trigger
  5. โŒ Auto-embed (30m) no trigger

๐Ÿ“‹ EVIDENCE for BUG REPORT:

$ qmd status
Updated: 17h ago โ† Auto-update not running!
Vectors: 0 embedded โ† Auto-embed not running!
Pending: 52 need embedding

๐Ÿ’ก TEMPORARY FIX:

Run this manually to fix:

export XDG_CONFIG_HOME="$HOME/.openclaw/agents/main/qmd/xdg-config"
export XDG_CACHE_HOME="$HOME/.openclaw/agents/main/qmd/xdg-cache"
qmd update && qmd embed

๐Ÿ› BUG REPORT UPDATE:

Issue: interval: "5m" and embedInterval: "30m" not trigger despite right config .

Evidence:

โ€ข Index last updated: 17 hours ago
โ€ข 0 vectors embedded (52 pending)
โ€ข Manual qmd update && qmd embed works

@deep elk

deep elkBOT
# grave salmon `openclaw --version openclaw gateway status openclaw status --all 2026.2.9 ๐Ÿฆž O...

Your gateway/service looks healthy (RPC probe ok, config path matches). The missing piece is: we still havenโ€™t confirmed whether the gateway is actually running the QMD backend or silently falling back to builtin.

Also: grepping the log for qmd wonโ€™t show anything on success โ€” QMD only logs on warnings/failures, not โ€œupdate ranโ€.

1) Check what backend youโ€™re really on

Please run this and paste the output:

openclaw memory status --agent main --json

Youโ€™re looking for:

  • status.backend: "qmd" โœ… means QMD is active
  • or a fallback field / not-qmd backend โŒ means it couldnโ€™t start QMD and switched to builtin

If you want it to actively try an index run (and surface errors), do:

#
openclaw memory status --agent main --deep --index --verbose

2) Most common cause: qmd not on PATH for the systemd service

When you install qmd via bun it usually lands in ~/.bun/bin/qmd, which systemd services often donโ€™t have in PATH.

Check in your shell:

command -v qmd
qmd --version

If command -v qmd prints something like /root/.bun/bin/qmd, then add this to your OpenClaw config:

#
memory: {
  backend: "qmd",
  qmd: {
    command: "/root/.bun/bin/qmd",
    // ...the rest of your qmd config...
  }
}

Then restart:

openclaw gateway restart

3) Prove the 5m timer is working (without relying on logs)

#

After youโ€™ve confirmed backend=qmd, watch the index DB mtime:

stat ~/.openclaw/agents/main/qmd/index.sqlite

Wait >5 minutes, run stat again โ€” the mtime should advance if interval updates are firing.

Docs reference (QMD backend): https://docs.openclaw.ai/concepts/memory#qmd-backend-experimental

If you paste the openclaw memory status --agent main --json output, I can tell you immediately whether this is a PATH/fallback issue or something else (collections/paths/permissions/timeouts).

deep elkBOT
# grave salmon โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€...

The output you pasted is only the Overview table from openclaw status --all โ€” it doesnโ€™t include the Memory Search section, which is the part that tells us whether QMD is actually active.

Two important gotchas with QMD:

  1. You wonโ€™t see โ€œqmd update ranโ€ in logs when it succeeds.
    The gateway only logs QMD on warnings/failures (e.g. โ€œqmd update failedโ€, โ€œqmd memory unavailable; falling backโ€ฆโ€). So grepping the logs for qmd|memory often shows nothing even when itโ€™s working.

  2. The QMD โ€œinterval/onBootโ€ timers only exist once the QMD manager is initialized in the gateway process (i.e. once memory search is actually being used/initialized). If nothing ever instantiates the QMD manager, thereโ€™s nothing running the interval loop โ€” which is why you get advice like โ€œuse cron/manual updateโ€.

Next step (this will immediately reveal whatโ€™s wrong)

Run and paste:

openclaw memory status --agent main --json

What weโ€™re looking for:

#
  • backend: "qmd" โ†’ QMD is active
  • If you see builtin provider and/or a fallback reason โ†’ QMD didnโ€™t start (most commonly: qmd not found on the systemd service PATH)

If itโ€™s a PATH issue (most common)

Check where qmd is:

command -v qmd
qmd --version

If itโ€™s something like ~/.bun/bin/qmd, systemd often canโ€™t see that. Fix by setting an absolute path:

memory: {
  backend: "qmd",
#
  qmd: {
    command: "/root/.bun/bin/qmd",
    // โ€ฆ
  }
}

then:

openclaw gateway restart

If QMD is active but youโ€™re โ€œnot seeing it runโ€

Thatโ€™s expected (no success logs). To prove itโ€™s updating, we can either:

  • check the QMD status field (custom.qmd.lastUpdateAt in the --json output), or
#
  • watch the index file timestamp:
    stat ~/.openclaw/agents/main/qmd/index.sqlite
    

Paste the openclaw memory status --agent main --json output and Iโ€™ll tell you exactly which branch youโ€™re in.

grave salmon
#

openclaw memory status --agent main --json
[
{
"agentId": "main",
"status": {
"backend": "qmd",
"provider": "qmd",
"model": "qmd",
"requestedProvider": "qmd",
"files": 79,
"chunks": 79,
"dirty": false,
"workspaceDir": "/root/.openclaw/workspace",
"dbPath": "/root/.openclaw/agents/main/qmd/xdg-cache/qmd/index.sqlite",
"sources": [
"memory"
],
"sourceCounts": [
{
"source": "memory",
"files": 79,
"chunks": 79
}
],
"vector": {
"enabled": true,
"available": true
},
"batch": {
"enabled": false,
"failures": 0,
"limit": 0,
"wait": false,
"concurrency": 0,
"pollIntervalMs": 0,
"timeoutMs": 0
},
"custom": {
"qmd": {
"collections": 7,
"lastUpdateAt": null
}
}
},
"scan": {
"sources": [
{
"source": "memory",
"totalFiles": 16,
"issues": []
}
],
"totalFiles": 16,
"issues": []
}
}
]

deep elkBOT
# grave salmon Channels โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€...

That paste still doesnโ€™t show the Memory Search section (which is the only part that tells us if QMD is active or if youโ€™re silently on builtin/fallback).

Letโ€™s force an unambiguous answer.

1) Show which backend youโ€™re actually running

Run:

openclaw memory status --agent agent1

(or --json if you prefer)

You should see Provider: qmd / backend: qmd if QMD is actually in use.

If it shows builtin (or a fallback reason), QMD never started โ†’ the interval timers wonโ€™t run.

#

2) Force a QMD run (and surface the real error if any)

This will actively try qmd update/qmd embed and print progress:

openclaw memory status --agent agent1 --deep --index --verbose

If QMD isnโ€™t reachable, youโ€™ll get the concrete error (missing binary, PATH, permission, bad collection path, timeout, etc).

3) Likely config issue: your paths point at /root/... but youโ€™re on a systemd --user service

Your service is systemd user, so itโ€™s usually not running as root. In that case, indexing /root/.openclaw/workspace will fail (or be empty/unreadable).

Also: with includeDefaultMemory: true, you do not need to add the workspace+memory paths at all โ€” OpenClaw already creates QMD collections for:

  • WORKSPACE/MEMORY.md
  • WORKSPACE/memory.md
  • WORKSPACE/memory/**/*.md
#

So as a test, remove those custom paths entries (or change them to ~/.openclaw/workspace), restart the gateway, then run the openclaw memory status ... --index command above.

4) Most common cause: qmd not on PATH for systemd

If the index command reports it canโ€™t run qmd, check:

command -v qmd
qmd --version

If it lives in something like ~/.bun/bin/qmd, systemd often wonโ€™t see it. Fix by setting:

memory: { qmd: { command: "/home/<you>/.bun/bin/qmd" } }

(and restart gateway)

#

Paste the output of either:

  • openclaw memory status --agent agent1
  • or openclaw memory status --agent agent1 --deep --index --verbose

โ€ฆand Iโ€™ll tell you exactly whatโ€™s preventing the interval updates.

grave salmon
#

Results:

  1. QMD Location:

    • Shell: /usr/bin/qmd
    • Systemd PATH: includes /usr/bin โœ…
    • Binary: /usr/bin/qmd (symlink to ../lib/node_modules/qmd/qmd)
  2. Index Mtime Test:

    • Last manual update: 03:05:17
    • Current time: 03:18:36
    • Elapsed: 13 minutes
    • Expected: 2 auto-updates (5m interval)
    • Actual: 0 auto-updates (mtime unchanged)

Conclusion: Auto-update not firing despite QMD being in PATH and config being correct. Manual updates work perfectly. @deep elk

deep elkBOT
#

That openclaw memory status --json output is the key:

  • โœ… backend: "qmd" / provider: "qmd" โ†’ QMD is enabled and working
  • dbPath: /root/.openclaw/agents/main/qmd/xdg-cache/qmd/index.sqlite โ†’ this is the real index DB location
  • custom.qmd.lastUpdateAt: null is not proof that updates never run โ€” itโ€™s just an in-memory field for that one manager instance. The openclaw memory status command spins up a fresh manager, prints status, then exits, so youโ€™ll often see null.

Why it looks like the 5m / 30m timers โ€œdonโ€™t happenโ€

Two gotchas in the current design:

  1. Successful QMD updates are silent in logs
    Youโ€™ll only see log lines when something fails (qmd update failed, qmd boot update failed, qmd embed failed).

  2. The QMD interval loop only starts after the QMD manager is initialized inside the running gateway
    That usually happens the first time the gateway executes memory_search (or anything that calls the memory manager).
    If you restart the gateway and then never hit memory_search, nothing โ€œboot/intervalโ€ runs because nothing created the QMD manager yet.

How to โ€œkickโ€ QMD on gateway boot (no cron needed, just a one-time warmup)

#

Call memory_search once via the Gatewayโ€™s Tools Invoke API (this runs inside the gateway process, unlike openclaw memory โ€ฆ which is a separate CLI process):

curl -sS http://127.0.0.1:<PORT>/tools/invoke \
  -H "Authorization: Bearer <YOUR_GATEWAY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"memory_search","args":{"query":"warmup"}}'

Docs: https://docs.openclaw.ai/gateway/tools-invoke-http-api

After that, the gateway process should have the QMD manager alive, and the interval / embedInterval timers can actually run.

How to prove the interval is working

  1. Append a unique marker to a file that QMD indexes (e.g. WORKSPACE/MEMORY.md)
  2. Wait > 5 minutes
  3. Query that marker via memory_search (again via tools/invoke or by asking the bot a question that forces recall)
#

If it shows up without manually running openclaw memory index, the interval is working.

Small config note

With includeDefaultMemory: true, you donโ€™t need to add workspace+memory again in paths unless youโ€™re trying to index extra folders beyond MEMORY.md + memory/**/*.md. Not wrong, just redundant.

If you want QMD to always start its timers immediately on gateway startup without needing a first memory_search, thatโ€™s likely an OpenClaw behavior/docs mismatch worth filing as an issue: https://github.com/openclaw/openclaw/issues

grave salmon
#

openclaw memory status --agent agent1

๐Ÿฆž OpenClaw 2026.2.9 (33c75cb) โ€” I'm like tmux: confusing at first, then suddenly you can't live without me.

03:21:16 [memory] qmd collection add failed for memory-root: spawn qmd ENOENT
03:21:16 [memory] qmd collection add failed for memory-alt: spawn qmd ENOENT
03:21:16 [memory] qmd collection add failed for memory-dir: spawn qmd ENOENT
03:21:16 [memory] qmd collection add failed for workspace: spawn qmd ENOENT
03:21:16 [memory] qmd collection add failed for memory: spawn qmd ENOENT
03:21:16 [memory] qmd collection add failed for memory: spawn qmd ENOENT
03:21:16 [memory] qmd collection add failed for memory: spawn qmd ENOENT
03:21:16 [memory] failed to read qmd index stats: Error: unable to open database file
03:21:16 [memory] qmd boot update failed: Error: spawn qmd ENOENT
Memory Search (agent1)
Provider: qmd (requested: qmd)
Model: qmd
Sources: memory
Indexed: 0/0 files ยท 0 chunks
Dirty: no
Store: ~/.openclaw/agents/agent1/qmd/xdg-cache/qmd/index.sqlite
Workspace: ~/.openclaw/workspace-agent1
By source:
memory ยท 0/0 files ยท 0 chunks
Vector: ready
Batch: disabled (failures 0/0)
Issues:
memory directory missing (~/.openclaw/workspace-agent1/memory)

deep elkBOT
#

Your openclaw memory status --json proves the important part:

  • backend: "qmd" and it has indexed docs (files: 79) โ†’ QMD is enabled and usable.
  • The lastUpdateAt: null there is expected in your case because waitForBootSync=false means the boot update is fire-and-forget; the CLI command prints status and exits before the background boot update would ever finish (in that CLI process).

Why your โ€œmtime unchanged โ‡’ no auto-updatesโ€ test can be misleading

qmd update is incremental. If no Markdown files changed, it may do essentially nothing and not touch index.sqlite, so the mtime can stay unchanged even if the timer fired.

Also, your embedInterval=30m, and you only waited ~13m โ€” so โ€œno embed activityโ€ is normal.

A reliable test (forces a change and doesnโ€™t rely on logs/mtime)

  1. Create a brand new memory file with a unique string (donโ€™t run any manual update after this):
echo "qmd-autotest-$(date +%s)" >> /root/.openclaw/workspace/memory/qmd_autotest.md
#
  1. Wait 6+ minutes (longer than your interval: 5m).

  2. Search for that exact string:

openclaw memory search "qmd-autotest-" --agent main

If it shows up without you running qmd update / openclaw memory index, then the auto-update timer is working.

The real gotcha: QMD โ€œintervalโ€ is an in-process timer

The 5m/30m schedule is implemented as a setInterval inside the QmdMemoryManager. That timer only exists in a long-lived process that created the manager.

  • The CLI (openclaw memory status/index/search) starts a manager, then exits โ†’ timers die with the process.
  • The Gateway will only have that timer if something in the running gateway actually instantiates the memory manager (typically via memory_search tool usage).

If you want to guarantee the gateway has instantiated it after restart, do a one-time warmup call inside the gateway (HTTP tools invoke):

#
curl -sS http://127.0.0.1:<PORT>/tools/invoke \
  -H "Authorization: Bearer <YOUR_GATEWAY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"memory_search","args":{"query":"warmup"}}'

Docs: https://docs.openclaw.ai/gateway/tools-invoke-http-api

About โ€œopenclaw memory status hangsโ€

When that happens itโ€™s usually QMD being blocked on something (db lock / long-running qmd process). Quick checks:

pgrep -af qmd
lsof /root/.openclaw/agents/main/qmd/xdg-cache/qmd/index.sqlite | head
#

If you paste those outputs + whether the โ€œautotestโ€ search works after 6 minutes, we can pin down if itโ€™s (A) timers never started in the gateway, or (B) timers started but a stuck QMD subprocess blocks further updates.

#

Those spawn qmd ENOENT lines are a big clue โ€” and itโ€™s not necessarily โ€œqmd not in PATHโ€.

In OpenClawโ€™s QMD manager, every qmd โ€ฆ call is spawned with:

  • command = memory.qmd.command (default "qmd")
  • cwd = agent workspaceDir

So you also get ENOENT if the cwd directory doesnโ€™t exist.

Whatโ€™s happening for agent1

Your output shows:

  • Workspace: ~/.openclaw/workspace-agent1
  • Issues: memory directory missing (~/.openclaw/workspace-agent1/memory)
  • and then every QMD spawn fails with ENOENT

That strongly suggests ~/.openclaw/workspace-agent1 (or its parent) is missing/not accessible, so Node canโ€™t spawn the process with that cwd.

#

Fix

Create the agent workspace + memory dir (safe):

mkdir -p ~/.openclaw/workspace-agent1/memory
touch ~/.openclaw/workspace-agent1/MEMORY.md

Then re-run:

openclaw memory status --agent agent1

If that was the issue, the spawn qmd ENOENT warnings should disappear immediately.

Why main looked fine

#

Your earlier --agent main --json showed an existing index under /root/.openclaw/agents/main/..., so mainโ€™s workspace /root/.openclaw/workspace exists and QMD can run there. agent1 is a different workspace, and right now itโ€™s not set up.

About โ€œauto-update not firingโ€

Once QMD can spawn successfully, donโ€™t use index.sqlite mtime as the only signal โ€” qmd update can be a no-op if nothing changed.

A good test is:

  1. Add a unique line to a memory file in that agentโ€™s workspace
  2. Wait > 5 minutes
  3. Run openclaw memory search "<unique token>" --agent agent1

If you still think the interval isnโ€™t firing after the workspace exists, paste:

ls -ld ~/.openclaw/workspace-agent1
openclaw memory status --agent agent1 --deep --index --verbose
grave salmon
#

Test completed:

  1. Created autotest file at 03:26:43 UTC
  2. Sent HTTP warmup call to gateway
  3. Waited 9 minutes ( > 5m interval)

Result:
$ qmd search "qmd-autotest-1770694003"
No results found.

โ†’ Auto-update NOT working even after warmup!

QMD status shows:

  • 81 files indexed
  • Updated: 8m ago (from manual update at 03:05)
  • File created 9 minutes ago still not indexed

Evidence: Auto-update interval not firing despite warmup.
@deep elk

#

โœ… SUCCESS!

HTTP warmup worked! After curl to /tools/invoke:

$ qmd ls workspace | grep autotest
24 B Feb 10 03:26 qmd://workspace/memory/qmd_autotest.md โœ…

$ qmd get qmd://workspace/memory/qmd_autotest.md
qmd-autotest-1770694003 โœ…

$ qmd status | grep Updated
Updated: 9m ago โœ…

โ†’ Auto-update IS working after HTTP warmup!

Note: Search returns no results because embedInterval=30m
hasn't fired yet. File is indexed but not embedded.

deep elkBOT
# grave salmon Test completed: 1. Created autotest file at 03:26:43 UTC 2. Sent HTTP warmup ca...

Your test is very likely checking the wrong QMD index (and possibly the wrong command), so it looks like โ€œauto-update isnโ€™t firingโ€ even when the gateway index is fine.

1) qmd CLI โ‰  the same index OpenClaw uses (unless you set XDG vars)

OpenClaw runs QMD with perโ€‘agent XDG dirs:

  • XDG_CONFIG_HOME=~/.openclaw/agents/<agentId>/qmd/xdg-config
  • XDG_CACHE_HOME=~/.openclaw/agents/<agentId>/qmd/xdg-cache (this is where index.sqlite lives)

If you run qmd โ€ฆ in your shell without those env vars, youโ€™re querying QMDโ€™s default home (typically ~/.cache/qmd/...) โ€” not OpenClawโ€™s index โ€” so you wonโ€™t see the gatewayโ€™s updates.

2) Use the correct QMD command (query) against OpenClawโ€™s index

Run this (replace main with the agent youโ€™re testing if needed):

STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config"
#
export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache"

qmd collection list --json
qmd query "qmd-autotest-1770694003" --json
# (if needed, target a specific collection, e.g.)
qmd query "qmd-autotest-1770694003" -c memory-dir --json

That is the only way qmd CLI will reflect what OpenClawโ€™s gateway is actually indexing.

3) Make sure your autotest file is actually indexable

Double-check itโ€™s a .md file inside a collection mask, e.g.:

ls -la /root/.openclaw/workspace/memory | tail -n 20
#

If you created a file without .md, QMD will ignore it (your masks are **/*.md / *.md).

4) Separate issue you hit: agent1 is broken because its workspace is missing

This is why you saw:

qmd collection add failed โ€ฆ spawn qmd ENOENT

In this codepath, ENOENT can happen when the cwd workspace dir doesnโ€™t exist (spawn fails because cwd is missing). Your output showed:

Workspace: ~/.openclaw/workspace-agent1 and โ€œmemory directory missing โ€ฆโ€

Fix:

mkdir -p ~/.openclaw/workspace-agent1/memory
touch ~/.openclaw/workspace-agent1/MEMORY.md
#

If you run the XDG-scoped qmd query โ€ฆ above and it still doesnโ€™t find the token after >5m, then weโ€™ve got a real โ€œinterval not firingโ€ bug โ€” but right now the evidence you posted is consistent with โ€œyou queried a different QMD home/index than the gateway uses.โ€

grave salmon
#

HTTP tools invoke fix the bug for me
my agents told me i need to do that everytime gateway restart, is it true ?
is this a default of QMD feature ?

#

@deep elk

deep elkBOT
# grave salmon HTTP tools invoke fix the bug for me my agents told me i need to do that everyti...

Two โ€œgotchasโ€ with QMD make this look broken even when it isnโ€™t:

1) Successful QMD auto-updates are basically silent

In current OpenClaw, the QMD timer (memory.qmd.update.interval / embedInterval) only logs when something fails (warnings like qmd update failedโ€ฆ). If qmd update succeeds, you usually wonโ€™t see anything in openclaw.log, so tail -f ... | grep qmd can look โ€œdeadโ€.

How to verify itโ€™s actually running:
Run this on the gateway host and paste the output:

openclaw --version
openclaw memory status --json

In the JSON, check:

  • status.backend should be "qmd" (if itโ€™s "builtin" then QMD is not active)
  • status.custom.qmd.lastUpdateAt should become a recent timestamp after QMD runs
#

(That lastUpdateAt is the best โ€œproofโ€ that the interval/onBoot update happened.)

Docs: https://docs.openclaw.ai/concepts/memory#qmd-backend-experimental

2) The QMD manager (and its interval timer) starts lazily

The interval timer is started when the QMD memory manager is initialized (i.e., when memory is actually used), not necessarily the instant the gateway process boots.

So after a gateway restart, if nothing triggers memory search, you might not see any QMD activity until the first time the agent uses memory tools.

A simple โ€œkickโ€ is:

  • ask the agent to do a memory_search once, or
  • run openclaw memory status once (this also forces the manager to initialize)

If it still doesnโ€™t run: most common real cause = qmd not on PATH for the gateway service

When OpenClaw runs as a service/container, its PATH can differ from your shell. Then QMD fails to start and OpenClaw falls back to builtin memory.

To confirm, look for log lines like:

#
  • qmd memory unavailable; falling back to builtin: ...

Fix options:

  • Set an absolute path:
memory: {
  qmd: { command: "/absolute/path/to/qmd" }
}
  • Or ensure qmd is installed for the same user that runs the gateway (and available in that serviceโ€™s PATH).

About โ€œHTTP tools invoke fixed itโ€ / โ€œdo I need that every restart?โ€

Thatโ€™s not a โ€œdefault QMD requirementโ€.

What likely happened is: invoking that tool caused the agent to do a memory operation once (which initialized QMD), so QMD started working for that process lifetime. After a restart, you may need any first memory usage again to initialize it.