earlier you helped me get exec config correct (for ssh etc for both main and subagent) and it was working fine but now i get this message in TUI - it seems the allowlist is more restrictive with file writes. so agent cannot write to VPS over ssh. here is exec.config snippet: "agents": {
"*": {
"allowlist": [
{
"pattern": "/usr/bin/uname",
"lastUsedAt": 1772811133343,
"id": "5c2bfe93-4467-4f40-b8ba-3292ba5eefe0"
},
{
"pattern": "/usr/bin/git",
"lastUsedAt": 1772811333655,
"id": "e89afbd5-1b3b-4503-9c04-7d1382976084"
},
{
"pattern": "/usr/bin/ssh",
"lastUsedAt": 1772811345005,
"id": "4ee3b12b-0362-4c2e-9459-d7cab89df267"
}
]
},
"coder": {
"allowlist": []
},
"main": {
"allowlist": []
}
}
}
#exec setup but now message from agent: it seems the allowlist is more restrictive with file writes
1 messages · Page 1 of 1 (latest)
and here is openclaw.json tools snippet (this is what you gave me earlier to use):
"tools": {
"profile": "coding",
"exec": {
"host": "gateway",
"security": "allowlist",
"ask": "off",
},
"subagents": {
"tools": {
"allow": ["group:openclaw"],
"deny": ["group:sessions", "cron", "gateway"],
},
},
},
A couple things are going on here, and yeah: recent exec-allowlist behavior is intentionally stricter around “shell-y” stuff.
First: can you paste the exact TUI error text + what openclaw --version prints? That’ll tell us if you hit the newer allowlist parser.
1) Allowlist mode blocks redirections / heredocs (so “writing files” via ssh often breaks)
In security=allowlist, OpenClaw only auto-allows a command if it can prove every segment is safe — and redirections are not supported (>, <, <<EOF, etc). Even if /usr/bin/ssh is allowlisted, workflows like these tend to get rejected:
ssh host "cat > /etc/foo"(contains>)cat file | ssh host ...(pipeline:catmust be allowlisted too)- heredocs
<<EOF(redirection)
Docs: https://docs.openclaw.ai/tools/exec (see “Allowlist + safe bins”)
2) Your allowlist only covers uname, git, ssh
So if your “write to VPS” flow uses anything else locally (common ones: scp, sftp, rsync, cat, bash), it’ll be an allowlist miss.
Practical fixes (pick one)
Option A (recommended): use scp/sftp instead of redirection-based ssh writes
Add /usr/bin/scp (and/or /usr/bin/sftp) to approvals:
openclaw approvals allowlist add --agent "*" "/usr/bin/scp"
# optionally
openclaw approvals allowlist add --agent "*" "/usr/bin/sftp"
Approvals CLI docs: https://docs.openclaw.ai/cli/approvals
Option B: temporarily allow “full shell” for that session
If you really need redirections/heredocs, allowlist mode is the wrong tool. Use security=full (ideally keep ask=always so you still confirm each command):
/exec host=gateway security=full ask=always
Option C: don’t SSH at all — run a node host on the VPS
If the goal is “agent can edit files on the VPS”, pairing a headless node host on the VPS and using host=node avoids the whole “ssh + shell parsing + redirection” mess.
3) One more config gotcha: main/coder have empty allowlists
Depending on version, an explicit empty per-agent allowlist can override the "*" entries. Easiest fix: either remove those empty blocks or copy the same entries into main/coder.
If you run:
openclaw approvals get
…and paste the output (or at least the agents section), I can tell you exactly how it’s being interpreted on your version.
Yep — with your current combo (security: "allowlist" + ask: "off"), anything that isn’t a clean allowlist hit becomes a hard “no”, and “write a file over ssh” usually isn’t a clean hit anymore.
Two key points:
1) Your tools.exec settings make allowlist misses non-recoverable
From your openclaw.json:
exec: {
host: "gateway",
security: "allowlist",
ask: "off",
},
That means:
- command matches allowlist exactly → runs
- command is an allowlist miss (extra pipeline segments, shell syntax, etc) → denied, no prompt
So if the agent’s “write to VPS” flow uses any of:
- pipes (
|) (e.g.cat file | ssh ...) - redirection / heredocs (
>,<<EOF, etc) - helper binaries (
scp,rsync,cat,bash,tee, …)
…it becomes an allowlist miss and gets blocked.
Docs reference: https://docs.openclaw.ai/tools/exec + https://docs.openclaw.ai/tools/exec-approvals
2) The approvals allowlist you showed is only ssh/git/uname
So “writing” won’t work if it relies on scp/cat/etc.
Also: having these present can bite you depending on merge semantics/version:
"coder": { "allowlist": [] },
"main": { "allowlist": [] }
An explicit empty list can override the "*" scope on some builds. Easiest: remove those empty per-agent blocks or copy the same entries into main/coder.
What to do (pick the behavior you want)
Option A (recommended): use scp for file writes, keep allowlist tight
Add scp to approvals:
openclaw approvals allowlist add --agent "*" "/usr/bin/scp"
If your ssh-write flow uses local cat | ssh ..., you’ll also need to allowlist whatever local command is on the left side of the pipe — but that’s usually a broader permission than people intend.
Option B: keep allowlist, but turn prompts back on for misses
If you want to occasionally allow “complex” commands (pipes/redirections) via approval:
tools: { exec: { host: "gateway", security: "allowlist", ask: "on-miss" } }
Then you can approve the miss when it happens.
Option C: you actually want unattended “do whatever shell stuff”
Then allowlist mode is the wrong tool. Set exec to full (and ideally keep prompts):
/exec host=gateway security=full ask=always
If you paste (a) the exact TUI error text and (b) openclaw --version, I can tell you which of the above matches what you’re seeing (and whether main/coder: [] is currently overriding your "*" entries).
i want option C, do i type this in to make that happen: /exec host=gateway security=full ask=always - I want as little restrictions as possible so the agent and subagents can do their thing.
version = 2026.3.7
Yes — if you want option C (“no restrictions, let it rip”) on 2026.3.7, you want security=full.
There are two places to set it:
1) Quick test (per-session, type in chat)
This takes effect immediately for the current session:
/exec host=gateway security=full ask=off
If you still want a last-resort safety net, do:
/exec host=gateway security=full ask=always
2) Make it permanent (config + approvals)
A) openclaw.json
Change your snippet to:
tools: {
profile: "coding",
exec: {
host: "gateway",
security: "full",
ask: "off", // or "always"
},
}
Then restart the gateway (config changes don’t fully apply until restart).
B) Exec approvals on the gateway host (this can still block you)
Exec approvals live on the execution host in:
~/.openclaw/exec-approvals.json
Make sure Defaults (or at least your agent) are also set to security: "full" (and ask: "off" if you truly want zero prompts). Easiest way: Control UI → Nodes → Exec approvals → Gateway → Defaults → Security = full.
Docs: https://docs.openclaw.ai/tools/exec-approvals
Big warning (because this is the point of the guardrail): with security=full + ask=off, anyone who can send commands to that agent (or any prompt injection that gets through your channel allowlist) can run arbitrary commands on your gateway machine. So only do this if your channel allowFrom/pairing + gateway token are locked down.
you've said to do this: Make sure Defaults (or at least your agent) are also set to security: "full" (and ask: "off" if you truly want zero prompts). Easiest way: Control UI → Nodes → Exec approvals → Gateway → Defaults → Security = full.
here is my current .json - please send back with adjustments that you said above:
{
"version": 1,
"socket": {
"path": "/home/grodev/.openclaw/exec-approvals.sock",
"token": "--redacted--"
},
"defaults": {},
"agents": {
"*": {
"allowlist": [
{
"pattern": "/usr/bin/uname",
"lastUsedAt": 1772811133343,
"id": "5c2bfe93-4467-4f40-b8ba-3292ba5eefe0"
},
{
"pattern": "/usr/bin/git",
"lastUsedAt": 1772811333655,
"id": "e89afbd5-1b3b-4503-9c04-7d1382976084"
},
{
"pattern": "/usr/bin/ssh",
"lastUsedAt": 1772811345005,
"id": "4ee3b12b-0362-4c2e-9459-d7cab89df267"
}
]
},
"coder": {
"allowlist": []
},
"main": {
"allowlist": []
}
}
}
Here’s your same exec-approvals.json with the Defaults set to security: "full" + ask: "off" (and a sane askFallback):
{
"version": 1,
"socket": {
"path": "/home/grodev/.openclaw/exec-approvals.sock",
"token": "--redacted--"
},
"defaults": {
"security": "full",
"ask": "off",
"askFallback": "full",
"autoAllowSkills": false
},
"agents": {
"*": {
"allowlist": [
{
"pattern": "/usr/bin/uname",
"lastUsedAt": 1772811133343,
"id": "5c2bfe93-4467-4f40-b8ba-3292ba5eefe0"
},
{
"pattern": "/usr/bin/git",
"lastUsedAt": 1772811333655,
"id": "e89afbd5-1b3b-4503-9c04-7d1382976084"
},
{
"pattern": "/usr/bin/ssh",
"lastUsedAt": 1772811345005,
"id": "4ee3b12b-0362-4c2e-9459-d7cab89df267"
}
]
},
"coder": {
"allowlist": []
},
"main": {
"allowlist": []
}
}
}
Notes:
- With
security: "full", the allowlists become effectively irrelevant (they won’t restrict).
- After you save this, restart the gateway so it reloads approvals (or update via Control UI).
And make sure your openclaw.json also matches (otherwise tool-level config can still keep you in allowlist mode):
tools: { exec: { host: "gateway", security: "full", ask: "off" } }
openclaw doctor shows this: Memory search is enabled but no embedding provider is configured. │
│ Semantic recall will not work without an embedding provider.
is this why my agent loses track of what we are doing every time there is compaction - or does fixing this make no difference?
That doctor warning is not the direct cause of compaction, but it can be a big reason the agent feels like it “loses the plot” after compaction.
What it means
- Compaction = OpenClaw summarizes the old conversation to fit the context window.
memory_searchwith embeddings = the agent can later re-find relevant notes (“what were we doing?”) even if the wording changed.
If no embedding provider is configured, semantic recall won’t work, so the agent is mostly limited to:
- whatever survived into the compaction summary, plus
- keyword-ish matches (BM25) in memory files (less reliable if you don’t remember the exact terms).
So: fixing embeddings helps recovery after compaction, but it doesn’t magically make compaction keep more details.
When fixing it won’t help much
If the important context was never written to disk (e.g. memory/YYYY-MM-DD.md, a PLAN.md, etc.), there’s nothing for semantic recall to retrieve. The model can only “remember” what’s in files.
What to do
- Configure an embeddings provider under
agents.defaults.memorySearch(that’s the config surface; it’s not top-level).
- Make sure the agent actually writes durable state before compaction (there’s a built-in pre-compaction memory flush feature, but it requires the workspace to be writable).
Docs:
- Memory + memory search: https://docs.openclaw.ai/concepts/memory
- Compaction lifecycle: https://docs.openclaw.ai/reference/session-management-compaction
If you paste your current agents.defaults.memorySearch block (and which API keys/providers you do have configured), I can tell you the smallest change to remove that doctor warning.
help me with how to get the agents.defaults.memorySearch block so I can paste here. Also please assist me with both 1 (configure an embeddings provider) and 2 (how to use the pre-compaction memory flush feature).
A) How to print agents.defaults.memorySearch so you can paste it here
Run one of these (depending on how you installed):
openclaw config get agents.defaults.memorySearch
# or, if you're running from the repo:
pnpm openclaw config get agents.defaults.memorySearch
If that prints undefined / {} and you want more context, paste this instead:
openclaw config get agents.defaults
(Feel free to redact secrets; do not paste any API keys.)
1) Configure an embeddings provider (so semantic recall works)
That doctor message means: OpenClaw tried to enable vector/semantic memory search, but couldn’t resolve any embeddings provider/key, so it can’t do true semantic recall.
The easiest fix
Pick one embeddings-capable provider you’re willing to use, then make sure its API key is available to the Gateway (env var or config), and restart the Gateway.
You have two common paths:
Path 1 — set an env var for the gateway service (recommended)
Example (conceptually):
OPENAI_API_KEY=...(OpenAI)GEMINI_API_KEY=...(Gemini)VOYAGE_API_KEY=...(Voyage)
MISTRAL_API_KEY=...(Mistral)
After setting it where your gateway process actually runs (systemd / pm2 / docker / etc), restart the gateway and re-run:
openclaw doctor
Docs (memory provider auto-selection + keys):
https://docs.openclaw.ai/concepts/memory
Path 2 — explicitly set the memorySearch provider in config
This tells OpenClaw which provider to use (you still need the key available):
openclaw config set agents.defaults.memorySearch.provider "openai" # or gemini/voyage/mistral/ollama/local
Then restart + openclaw doctor again.
If you tell me which provider you want (and how you run the gateway: systemd? docker? mac app?), I can give you the exact “put the env var here” steps.
2) Pre-compaction memory flush (how to use it)
This feature is specifically meant to reduce “we lost the thread after compaction” by doing a silent, automatic turn shortly before compaction that tells the agent:
“Write durable notes to disk now.”
How to view your current setting
openclaw config get agents.defaults.compaction.memoryFlush
openclaw config get agents.defaults.compaction
Minimal config to enable it (from the docs)
Put this in ~/.openclaw/openclaw.json (or use openclaw config set if you prefer):
{
agents: {
defaults: {
compaction: {
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."
}
}
}
}
}
Docs: https://docs.openclaw.ai/concepts/memory (section “Automatic memory flush”)
Important gotchas (these are the usual “why didn’t it work?” causes)
- It’s silent by default (you won’t see a chat message).
- The agent must be able to write to the workspace (if sandbox workspace access is read-only, the flush is skipped).
- If your tool policy denies file writing tools, the agent can’t actually persist the notes.
If you paste the output of openclaw config get agents.defaults.memorySearch + tell me which embeddings provider you want to use, I’ll reply with the exact openclaw.json block to drop in (with no secrets hardcoded).
here is output you requested:
grodev@openclaw:~ $ openclaw config get agents.defaults.memorySearch
Config path not found: agents.defaults.memorySearch
grodev@openclaw:~ $ openclaw config get agents.defaults
{
"model": {
"primary": "openrouter/anthropic/claude-3.5-sonnet"
},
"models": {
"openrouter/auto": {
"alias": "OpenRouter"
},
"openrouter/anthropic/claude-3.5-sonnet": {}
},
"workspace": "/home/grodev/.openclaw/workspace",
"compaction": {
"mode": "safeguard"
},
"maxConcurrent": 4,
"subagents": {
"maxConcurrent": 8
}
}
Can i use my existing openrouter and api key for the embeddings provider?
You’re not crazy — on 2026.3.7 the config key for embeddings is very likely top-level memorySearch, not agents.defaults.memorySearch (that’s why config get agents.defaults.memorySearch says “path not found”). The “API Usage and Costs” doc for this line of releases also references memorySearch.*.
1) Get the block to paste here
Run:
openclaw config get memorySearch
If you want everything related in one go:
openclaw config get memorySearch
openclaw config get agents.defaults.compaction
2) Can you use OpenRouter + your OpenRouter API key for embeddings?
Not directly in the supported “memory embeddings providers” list.
In 2026.3.x, memory embeddings are typically one of:
memorySearch.provider = "openai"memorySearch.provider = "gemini"memorySearch.provider = "voyage"memorySearch.provider = "mistral"memorySearch.provider = "ollama"(local/self-hosted)memorySearch.provider = "local"(fully local)
OpenRouter is great for chat/completions, but OpenClaw’s memory embeddings config doesn’t have a first-class openrouter provider.
So if you want semantic recall, you generally need an embeddings-capable provider key in addition to OpenRouter (unless you go ollama/local).
Minimal example (remote embeddings)
Once you have a key for one of those providers (don’t paste it here), set:
openclaw config set memorySearch.provider "openai" # or gemini/voyage/mistral
…and make sure the corresponding API key is available to the gateway environment, then restart the gateway and re-run openclaw doctor.
(If you tell me which provider you prefer + how you run the gateway service on the VPS, I’ll tell you exactly where to put the env var.)
3) Pre-compaction memory flush (so it doesn’t “forget” after compaction)
This part is under agents.defaults.compaction.memoryFlush.
You can set it via CLI:
openclaw config set agents.defaults.compaction.memoryFlush.enabled true
openclaw config set agents.defaults.compaction.memoryFlush.softThresholdTokens 4000
openclaw config set agents.defaults.compaction.memoryFlush.systemPrompt "Session nearing compaction. Store durable memories now."
openclaw config set agents.defaults.compaction.memoryFlush.prompt "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store."
Key gotchas:
- It’s silent (you won’t see a user-facing message).
- It only helps if the agent can write to the workspace (no read-only workspace / overly restrictive tool policy).
Paste the output of openclaw config get memorySearch and I’ll tell you the exact memorySearch block to drop into openclaw.json for the provider you choose.
grodev@openclaw:~ $ openclaw config get memorySearch
openclaw config get agents.defaults.compaction
Config path not found: memorySearch
{
"mode": "safeguard"
}
i have an ollama api key already, so perhaps i should use that for the embeddings provider? if i can then please tell me step by step how to get it going - you say "and make sure the corresponding API key is available to the gateway environment" but i will need more precise steps. PS: gateway service is not on the VPS, the gateway is on my Pi - VPS is where my project files are that I'm working on
Key detail: since your Gateway is on the Pi, all memory/embeddings config must be done on the Pi. Running openclaw config get ... on the VPS won’t affect the gateway (and explains the “Config path not found” confusion).
Also: “Ollama API key” isn’t like a cloud key — Ollama is a server you run (local/self-hosted). The “key” is usually just a placeholder OpenClaw uses to consider the provider “enabled”.
Below is a concrete, end-to-end setup that matches your topology:
- Pi = gateway
- VPS = project files (accessed via SSH)
- Ollama = embeddings server (I recommend running Ollama on the VPS or another beefier box, not on the Pi)
Part 1 — Turn on semantic memory search using Ollama embeddings
Step 1) SSH into the Pi (gateway host)
ssh <pi-user>@<pi-host>
openclaw --version
openclaw doctor
Step 2) Find the correct config path on your gateway build
Run both; one of them should work:
openclaw config get memorySearch
openclaw config get agents.defaults.memorySearch
- If
memorySearchexists → you’ll configure top-levelmemorySearch.* - If
agents.defaults.memorySearchexists → you’ll configure that instead
(Reply with which one works if you want me to tailor the exact commands, but keep reading—below I show both variants.)
Step 3) Run Ollama somewhere the Pi can reach (recommended: the VPS)
On the VPS (or whatever host will run Ollama):
- Start Ollama so it listens on the network (and firewall it so only the Pi can reach port 11434).
- Pull an embeddings model (example many people use):
ollama pull nomic-embed-text
- Verify from the Pi that it can reach the Ollama API:
curl -s http://<OLLAMA_HOST>:11434/api/tags | head
If this can’t connect, fix networking/firewall first (don’t proceed until it works).
Step 4) Configure OpenClaw to use Ollama for embeddings (on the Pi)
Variant A: if memorySearch exists (top-level)
openclaw config set memorySearch.provider "ollama"
openclaw config set memorySearch.remote.baseUrl "http://<OLLAMA_HOST>:11434"
openclaw config set memorySearch.remote.apiKey "ollama-local"
openclaw config set memorySearch.model "nomic-embed-text"
Variant B: if agents.defaults.memorySearch exists
openclaw config set agents.defaults.memorySearch.provider "ollama"
openclaw config set agents.defaults.memorySearch.remote.baseUrl "http://<OLLAMA_HOST>:11434"
openclaw config set agents.defaults.memorySearch.remote.apiKey "ollama-local"
openclaw config set agents.defaults.memorySearch.model "nomic-embed-text"
Notes:
apiKey: "ollama-local"is just a dummy value (fine to store in config).modelmust match what Ollama has installed for embeddings.
Step 5) Restart gateway + confirm the warning is gone (on the Pi)
openclaw gateway restart
openclaw doctor
If doctor still complains, paste the exact doctor output (it’s usually very specific about what’s missing).
Part 2 — Enable pre-compaction memory flush (so it “writes down” what you’re doing)
This is independent of embeddings, and it helps a lot.
On the Pi:
openclaw config set agents.defaults.compaction.memoryFlush.enabled true
openclaw config set agents.defaults.compaction.memoryFlush.softThresholdTokens 4000
openclaw config set agents.defaults.compaction.memoryFlush.systemPrompt "Session nearing compaction. Store durable memories now."
openclaw config set agents.defaults.compaction.memoryFlush.prompt "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store."
openclaw gateway restart
What to expect:
- It triggers automatically when you get close to compaction.
- It is silent (no visible chat message).
- It writes into the Pi workspace:
~/.openclaw/workspace/memory/YYYY-MM-DD.md - It won’t help if your session/workspace is effectively read-only.
One question so I can make this 100% precise
Where will Ollama actually run for you (VPS, laptop, or the Pi)? And what’s the Ollama base URL the Pi should use (LAN IP vs public IP)? If it’s public, I’ll suggest the safest firewall rule pattern so you don’t expose Ollama to the internet.
- both memorySearch commands don't work.
grodev@openclaw:~ $ openclaw config get memorySearch
openclaw config get agents.defaults.memorySearch
Config path not found: memorySearch
Config path not found: agents.defaults.memorySearch
Where will Ollama actually run for you (VPS, laptop, or the Pi)? And what’s the Ollama base URL the Pi should use (LAN IP vs public IP)? If it’s public, I’ll suggest the safest firewall rule pattern so you don’t expose Ollama to the internet.
Response: Ollama will run on the same Pi as the openclaw
Got it — if both of these fail on the Pi (gateway host):
openclaw config get memorySearch
openclaw config get agents.defaults.memorySearch
…then on your current build the memory-search provider is not configurable via openclaw.json paths (at least not under those names). That’s why you’re stuck.
What that means in practice
That doctor warning is basically saying:
- “Memory search feature exists / is enabled”
- “But I can’t find any embeddings backend to use”
On builds where there’s no memorySearch.* config surface exposed, the embeddings backend is usually selected only by what credentials/providers are available (env/configured provider keys), not by an explicit memorySearch.provider setting.
So, unfortunately: you can’t “point it at Ollama” just because you have an Ollama key, unless your build has the config hook for it.
Also important: Ollama isn’t a hosted embeddings API. Having an “Ollama API key” doesn’t help unless you also have an Ollama server reachable from the Pi that can serve embeddings.
The next 2 things to do (so we stop guessing)
1) Confirm you’re running these commands on the Pi (gateway host)
Since your gateway is on the Pi, run:
hostname
openclaw --version
openclaw doctor
…and paste just the memory/embeddings-related part of the doctor output.
2) Check if there’s a different config namespace for memory on your build
Try these (on the Pi):
openclaw config get memory
openclaw config get plugins
openclaw config get plugins.slots
openclaw config get plugins.slots.memory
One of these often reveals the actual config surface in older/newer schema variants.
If you just want the quickest fix
If you’re ok using a hosted embeddings provider, the fastest way to clear the warning is usually:
- add one embeddings-capable provider key to the gateway environment (OpenAI/Gemini/Voyage/Mistral)
- restart gateway
- re-run
openclaw doctor
(You can keep OpenRouter as your chat model; this is just for embeddings.)
But if your goal is “use Ollama for embeddings”, we need to first find the correct config keys your Pi build supports (or confirm you’ll need to upgrade to a build where memorySearch.provider = "ollama" is available).
Paste the outputs from the commands above and I’ll give you an exact, copy-pasteable config/command sequence for your schema.
Perfect — if Ollama will run on the same Pi as the Gateway, the setup is much simpler (no baseUrl/firewall stuff). The catch is: since your build doesn’t expose memorySearch.* in config, we’re going to rely on auto-detection: make Ollama clearly “available” to OpenClaw, then re-run openclaw doctor and see if the warning clears.
Here’s the step-by-step.
Step 0 — sanity: do this on the Pi
SSH into the Pi (the machine running the gateway), then:
openclaw --version
openclaw doctor
(So we’re definitely operating on the right host.)
Step 1 — get Ollama running locally on the Pi
-
Install Ollama on the Pi (follow the official instructions for your Pi OS/arch):
https://ollama.ai -
Start the Ollama server so it listens on localhost (default is port
11434).
Quick check:
curl -s http://127.0.0.1:11434/api/tags | head
You should get JSON back (not “connection refused”).
Step 2 — pull an embeddings model + verify embeddings work
Pull an embeddings model (example that’s commonly used with Ollama for embeddings):
ollama pull nomic-embed-text
Then test the embeddings endpoint:
curl -s http://127.0.0.1:11434/api/embeddings \
-d '{"model":"nomic-embed-text","prompt":"hello"}' | head
You should see an embedding array in the output.
Step 3 — make OpenClaw “see” Ollama (so doctor can pick it up)
Since you don’t have a memorySearch config key available, the most reliable “enable Ollama integration” signal is to set OLLAMA_API_KEY (it can be a dummy value; Ollama doesn’t require a real key).
Option A (recommended): set it in OpenClaw config
This avoids messing with systemd env:
openclaw config set models.providers.ollama.apiKey "ollama-local"
Option B: set it as an environment variable for the gateway process
If you know how you launch the gateway, set:
export OLLAMA_API_KEY="ollama-local"
…but this only works if that env var is actually present in the gateway service environment (systemd services often don’t inherit your shell env).
Step 4 — restart gateway + re-run doctor
openclaw gateway restart
openclaw doctor
Expected outcome
That previous warning:
“Memory search is enabled but no embedding provider is configured…”
should go away if your build knows how to use local Ollama as an embeddings backend via auto-detection.
If the warning does not go away
Then your current build likely cannot select Ollama for memory embeddings without the missing memorySearch.provider = "ollama" config surface. In that case, your choices are:
- upgrade OpenClaw on the Pi to a version that exposes memorySearch provider config, or
- use a hosted embeddings provider key (OpenAI/Gemini/Voyage/Mistral), or
- live without semantic recall and lean on the pre-compaction memory flush + explicit “STATUS.md / PLAN.md” files.
Bonus: pre-compaction memory flush still worth enabling
(Works regardless of embeddings)
openclaw config set agents.defaults.compaction.memoryFlush.enabled true
openclaw config set agents.defaults.compaction.memoryFlush.softThresholdTokens 4000
openclaw config set agents.defaults.compaction.memoryFlush.systemPrompt "Session nearing compaction. Store durable memories now."
openclaw config set agents.defaults.compaction.memoryFlush.prompt "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store."
openclaw gateway restart
If you paste the new openclaw doctor memory warning after Step 4 (exact lines), I can tell you whether Ollama was detected at all, or whether you’re in the “needs newer build or hosted embeddings key” bucket.
here's the full memory search warning output from doctor:
Memory search is enabled but no embedding provider is configured. │
│ Semantic recall will not work without an embedding provider. │
│ Gateway memory probe for default agent is not ready: No API key found for provider │
│ "openai". Auth store: /home/grodev/.openclaw/agents/main/agent/auth-profiles.json │
│ (agentDir: /home/grodev/.openclaw/agents/main/agent). Configure auth for this agent │
│ (openclaw agents add <id>) or copy auth-profiles.json from the main agentDir. │
│ │
│ No API key found for provider "google". Auth store: │
│ /home/grodev/.openclaw/agents/main/agent/auth-profiles.json (agentDir: │
│ /home/grodev/.openclaw/agents/main/agent). Configure auth for this agent (openclaw │
│ agents add <id>) or copy auth-profiles.json from the main agentDir. │
│ │
│
No API key found for provider "voyage". Auth store: │
│ /home/grodev/.openclaw/agents/main/agent/auth-profiles.json (agentDir: │
│ /home/grodev/.openclaw/agents/main/agent). Configure auth for this agent (openclaw │
│ agents add <id>) or copy auth-profiles.json from the main agentDir. │
│ │
│ No API key found for provider "mistral". Auth store: │
│ /home/grodev/.openclaw/agents/main/agent/auth-profiles.json (agentDir: │
│ /home/grodev/.openclaw/agents/main/agent). Configure auth for this agent (openclaw │
│ agents add <id>) or copy auth-profiles.json from the main agentDir. │
│ │
│ Fix (pick one): │
│ - Set OPENAI_API_KEY, GEMINI_API_KEY, VOYAGE_API_KEY, or MISTRAL_API_KEY in your │
│ environment │
│ - Configure credentials: openclaw configure --section model │
│ - For local embeddings: configure agents.defaults.memorySearch.provider and local model │
│ path │
│ - To disable: openclaw config set agents.defaults.memorySearch.enabled false
i've done the "pre-compaction memory flush still worth enabling". is there something i need to type as a command or will it be automatically done?
That doctor output is the smoking gun.
What it’s telling you
On your build, the memory-search “probe” is only looking for an embeddings key from:
- provider
"openai"(env/config keyOPENAI_API_KEY) - provider
"google"(Gemini; env/config keyGEMINI_API_KEY)
It is not considering Ollama for embeddings here, so running Ollama on the Pi won’t clear this warning by itself.
So to get semantic recall working you have 3 options:
- Add an OpenAI API key (just for embeddings; you can keep using OpenRouter for chat)
- Add a Gemini API key (same idea)
- Ignore/disable semantic recall and rely on compaction memory flush + explicit notes files
Fastest “make it work” fix (OpenAI embeddings)
Step 1) Get an OpenAI API key
(Usage-based API key, not OpenRouter.)
Step 2) Add it to OpenClaw on the Pi
On the Pi, do one of these:
Option A: via CLI (simplest)
openclaw config set env.OPENAI_API_KEY "sk-REDACTED"
(do not paste the real key in Discord)
Option B: edit config file
Edit ~/.openclaw/openclaw.json and add:
{
env: {
OPENAI_API_KEY: "sk-REDACTED",
},
}
Step 3) Restart gateway + re-run doctor
openclaw gateway restart
openclaw doctor
If the warning is gone, semantic memory search is ready.
Alternative: Gemini embeddings instead
Same flow, just use:
env.GEMINI_API_KEY
openclaw config set env.GEMINI_API_KEY "REDACTED"
openclaw gateway restart
openclaw doctor
About the “auth-profiles.json” line
Doctor mentions auth-profiles.json because OpenClaw can resolve creds from auth profiles too — but for this case the quickest path is just setting env.OPENAI_API_KEY or env.GEMINI_API_KEY as above.
If you want, paste your ~/.openclaw/openclaw.json (redact tokens/keys) and I’ll show you exactly where to drop the env block without disturbing your OpenRouter model setup.
Nice — that expanded doctor output answers the mystery.
Why config get agents.defaults.memorySearch said “path not found”
In this case it just means you haven’t set that config yet (not that the key doesn’t exist). Doctor is confirming the key is valid and giving you the exact fix knobs.
Easiest fix (recommended): add one embeddings API key
You do not need to change your OpenRouter chat model. This key is only for memory embeddings.
Pick one provider you’re willing to use (OpenAI or Gemini are the common choices), then set the env var via config and restart.
Example: OpenAI embeddings key
(on the Pi)
openclaw config set env.OPENAI_API_KEY "sk-REDACTED"
openclaw gateway restart
openclaw doctor
Example: Gemini embeddings key
openclaw config set env.GEMINI_API_KEY "REDACTED"
openclaw gateway restart
openclaw doctor
That should remove the “no embedding provider configured” warning.
If you don’t want semantic recall: disable it
This is exactly what doctor suggests:
openclaw config set agents.defaults.memorySearch.enabled false
openclaw gateway restart
openclaw doctor
You’ll still benefit from pre-compaction memory flush (writing durable notes), you just won’t have semantic search over them.
About “local embeddings” on your Pi
Doctor’s “local embeddings” option is not Ollama — it’s the “local model file path” approach (node-llama-cpp). On a Pi it can be slow / painful unless you’re very intentional about model size and storage, so I’d only go there if you really want zero external API usage.
If you want, tell me which route you prefer:
- OpenAI key, 2) Gemini key, or 3) disable memory search,
and I’ll give you the cleanest minimalopenclaw.jsonsnippet for that choice (no secrets pasted).
It’s automatic — you don’t need to type any command.
How it works once enabled:
- OpenClaw watches the session token estimate.
- When the session gets close to auto-compaction, it triggers a silent “memory flush” turn.
- The agent is prompted to write durable notes (typically into
memory/YYYY-MM-DD.md) and then replyNO_REPLYso you don’t see anything in chat. - It runs once per compaction cycle (not every message).
How to tell it actually happened:
- Check your workspace memory file on the gateway host (Pi), e.g.:
~/.openclaw/workspace/memory/YYYY-MM-DD.md(should get new entries near compaction time)
- Or inspect the session transcript/logs (you’ll see an internal turn around when compaction happens).
Gotchas:
- If the session/workspace is effectively read-only, the flush is skipped.