Install
openclaw skills install memory-hybrid-stackUse this skill to read/write the hybrid memory stack (Postgres facts, Redis realtime state, Qdrant vector recall) that lives under `infra/memory-stack`. Provides shell helpers for SQL, key-value, and Qdrant HTTP calls plus schema/usage guidance. Trigger when the assistant needs durable facts, volatile status, or semantic recall beyond Markdown memory.
openclaw skills install memory-hybrid-stackThis stack splits agent memory across three stores:
facts) — structured, durable knowledge with optional embeddings.state) — low-latency values that expire (locks, session flags, device status).vectors) — semantic recall for long-form text chunks, keyed by collection oc_memory.All services run via Docker Compose (infra/memory-stack/docker-compose.yml). Connection defaults live in infra/memory-stack/.env; scripts in this skill auto-source that file unless you override MEMORY_STACK_ENV / MEMORY_STACK_ROOT.
cd infra/memory-stack && docker compose ps (all three should be healthy).cd skills/memory-hybrid-stack/scripts or call scripts via absolute path..env).references/connection-map.md when needed.| Layer | Script | Purpose |
|---|---|---|
| Postgres facts | scripts/facts_sql.sh | Run SQL/psql with pgvector enabled |
| Redis state | scripts/state_kv.sh | Get/Set/Delete simple keys with optional TTL |
| Qdrant vectors | scripts/qdrant_request.sh | Make raw HTTP calls (GET/POST/PUT/DELETE) with inline JSON or @file payloads |
postgres://oc_memory:…@localhost:55432/oc_facts. Credentials auto-loaded from .env.# Run ad-hoc SQL (string argument)
./scripts/facts_sql.sh "SELECT subject, object->>'value' AS value FROM facts WHERE tags @> ARRAY['preference'];"
# Pipe a multiline query
cat <<'SQL' | ./scripts/facts_sql.sh
INSERT INTO facts (subject, predicate, object, source, confidence, tags)
VALUES (
'user:xiaobai',
'prefers_language',
jsonb_build_object('value', 'zh-CN'),
'chat/2026-03-18',
0.92,
ARRAY['preference','language']
)
ON CONFLICT (subject, predicate)
DO UPDATE SET object = EXCLUDED.object, updated_at = now();
SQL
Tips:
object JSON, e.g. { "value": "...", "summary": "..." }.embedding column when you already have a 1536-d vector (set via UPDATE facts SET embedding = '[...]'::vector WHERE id = ...).tags text[]) so downstream filters are cheap.state:<entity>:<attribute>; keep payloads as JSON strings for readability.# Fetch
./scripts/state_kv.sh get state:user:xiaobai:current-task
# Set with 10-minute TTL
./scripts/state_kv.sh set state:user:xiaobai:current-task '{"summary":"researching", "started_at":"2026-03-18T19:00:00Z"}' 600
# Delete
./scripts/state_kv.sh del state:user:xiaobai:current-task
Guidelines:
state:lock:calendar-sync) with low TTL to avoid deadlocks.http://localhost:6335, gRPC http://localhost:6336.oc_memory (1536-d cosine). Created via scripts/init_qdrant.sh.# Check collections
./scripts/qdrant_request.sh GET /collections
# Upsert points from a file
cat > /tmp/points.json <<'JSON'
{
"points": [
{
"id": "memo-001",
"vector": [/* 1536 floats */],
"payload": {
"subject": "user:xiaobai",
"text": "Prefers in-depth, sourced answers.",
"tags": ["preference"],
"timestamp": "2026-03-18T19:05:00Z"
}
}
]
}
JSON
./scripts/qdrant_request.sh PUT /collections/oc_memory/points @/tmp/points.json
# Semantic search (vector or filter payload inline)
./scripts/qdrant_request.sh POST /collections/oc_memory/points/search '{
"vector": [/* query vector */],
"limit": 5,
"with_payload": true,
"filter": {"must": [{"key": "subject", "match": {"value": "user:xiaobai"}}]}
}'
Notes:
@/path/file.json.text-embedding-3-small); ensure dimension = 1536.timestamp) to enforce recency filtering.tags (Postgres) with Qdrant payload keys so cross-store correlation is simple.docker compose ps shows unhealthy containers → check host ports (stack uses 55432/56379/6335/6336 to avoid clashes with ai-stack-*)..env → copy .env.example → .env, or set env vars manually.memory-qdrant:local (curl installed) or adjust healthcheck.