Building Custom AI Skills with InstructLab Taxonomy
Create domain-specific AI capabilities using InstructLab's taxonomy system—from writing skill definitions to generating synthetic training data and validating fine-tuned models.
After configuring memory search, you might try to inspect the SQLite database and find — nothing:
sqlite3 ~/.openclaw/memory/main.sqlite "SELECT COUNT(*) FROM embedding_cache;"Error: unable to open database "/home/azureuser/.openclaw/memory/main.sqlite":
unable to open database fileThis happens because the memory directory doesn’t exist yet on the host. The gateway creates its database inside the container at /home/node/.openclaw/memory/, not on the host at /home/azureuser/.openclaw/memory/.
OpenClaw’s Docker Compose typically mounts the host’s ~/.openclaw into the container:
volumes:
- ~/.openclaw:/home/node/.openclawThis means:
/home/azureuser/.openclaw/memory//home/node/.openclaw/memory/node user (UID 1000)mkdir -p ~/.openclaw/memory
mkdir -p ~/.openclaw/memory/notesThe container runs as user node (UID 1000). The directories need to be readable and writable by that UID:
chmod 770 ~/.openclaw/memory
chmod 770 ~/.openclaw/memory/notessudo chown -R 1000:1000 ~/.openclaw/memoryThis maps ownership to the container’s node user. Without this, the gateway process can’t create or write the SQLite database.
docker compose restart openclaw-gatewayfind ~/.openclaw/memory -maxdepth 2 -type f \
\( -name "*.sqlite" -o -name "*.db" \) -lsExpected output:
1670790 0 -rw-r--r-- 1 azureuser azureuser 0 Feb 25 23:37
/home/azureuser/.openclaw/memory/main.sqliteNote: The file may initially be 0 bytes. The gateway creates the file on startup but only initializes the schema when the first memory operation occurs.
The most reliable way to verify is to test write access from inside the container:
docker exec -it openclaw-openclaw-gateway-1 sh -lc '
echo test > /home/node/.openclaw/memory/._write_test && \
ls -la /home/node/.openclaw/memory && \
rm -f /home/node/.openclaw/memory/._write_test
'Expected output:
total 16
drwxrwx--- 3 node node 4096 Feb 25 23:41 .
drwxrwxr-x 11 node node 4096 Feb 25 23:36 ..
-rw-r--r-- 1 node node 5 Feb 25 23:41 ._write_test
-rw-rw---- 1 node node 0 Feb 25 23:37 main.sqlite
drwxrwx--- 2 node node 4096 Feb 25 23:37 notesIf you see the ._write_test file, the container can write to the memory directory.
Before troubleshooting permissions, check what the gateway sees:
docker exec -it openclaw-openclaw-gateway-1 sh -lc '
ls -la /home/node/.openclaw && \
ls -la /home/node/.openclaw/memory || true
'A healthy installation shows:
drwxrwxr-x 11 node node 4096 .
drwx------ 3 node node 4096 agents
drwxr-xr-x 2 node node 4096 canvas
drwxr-xr-x 2 node node 4096 completions
drwx------ 2 node node 4096 credentials
drwxr-xr-x 2 node node 4096 cron
drwxrwxr-x 2 node node 4096 identity
drwx------ 2 node node 4096 logs
drwx------ 3 node node 4096 memory ← Must be owned by node
-rw------- 1 node node 2810 openclaw.json
drwxrwxr-x 4 node node 4096 workspaceKey things to verify:
memory directory is owned by node:nodememory directory has at least rwx for owneropenclaw.json is owned by node (same UID)If you want to inspect the database from the host, install sqlite3 first:
sudo apt install sqlite3Then query:
sqlite3 ~/.openclaw/memory/main.sqlite "PRAGMA journal_mode;"
# Expected: delete
sqlite3 ~/.openclaw/memory/main.sqlite \
"SELECT name FROM sqlite_master WHERE type IN ('table','index','trigger','view');"Warning: Don’t query the SQLite file while the gateway is actively writing to it. Use
docker compose stop openclaw-gatewayfirst for safe inspection, or use thememoryCLI commands instead.
OpenClaw provides CLI commands for memory operations that are safer than raw SQLite access:
# Search memory
docker compose run --rm openclaw-cli memory search "your query"
# Reindex all memory files
docker compose run --rm openclaw-cli memory reindex
# List memory contents
docker compose run --rm openclaw-cli memory list| Scenario | Fix |
|---|---|
main.sqlite is 0 bytes | Normal — schema created on first write |
Permission denied inside container | sudo chown -R 1000:1000 ~/.openclaw/memory |
| File exists but UID mismatch | Check container’s UID: docker exec openclaw-openclaw-gateway-1 id |
| Directory doesn’t exist in container | Volume mount may be wrong — check docker compose.yml |
| Database locked errors | Stop concurrent access; only one process should write |
The most common issue is a UID mismatch between the host and container:
Host user (azureuser) = UID 1000
Container user (node) = UID 1000 ← Must match!If your host user isn’t UID 1000, you have two options:
Option A: Change ownership to the container’s UID
sudo chown -R 1000:1000 ~/.openclaw/memoryOption B: Run the container with your host UID
# In docker-compose.yml
services:
openclaw-gateway:
user: "${UID}:${GID}"The SQLite database and notes directory contain all of your agent’s long-term memory. Include them in your backup plan:
# Backup memory store
tar czf openclaw-memory-backup-$(date +%Y%m%d).tar.gz \
~/.openclaw/memory/
# Restore
tar xzf openclaw-memory-backup-*.tar.gz -C ~/AI & Cloud Advisor with 18+ years experience. Author of 8 technical books, creator of Ansible Pilot. Speaker at KubeCon EU & Red Hat Summit 2026.
Create domain-specific AI capabilities using InstructLab's taxonomy system—from writing skill definitions to generating synthetic training data and validating fine-tuned models.
How to access the OpenClaw Control UI dashboard from an Azure VM — via SSH tunnel (secure) or public IP. Covers device pairing, dashboard authentication, and the browser-based management interface.
End-to-end guide to building a complete persistent memory system for your OpenClaw AI agent. Combine memory flush, hybrid search, file-backed notes, SQLite indexing, and session hooks into a cohesive knowledge architecture.