SynapCores v1.8.5 — Agent memory as three SQL functions
If you've shipped an agent on SynapCores, you've written this code at least once:
CREATE TABLE IF NOT EXISTS my_agent_memory (
id TEXT PRIMARY KEY,
content TEXT,
embedding VECTOR(384),
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW(),
accessed_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX ... USING HNSW (embedding);
-- … then every memory write becomes EMBED() + INSERT,
-- every recall becomes EMBED() + COSINE_SIMILARITY() + ORDER BY + LIMIT + UPDATE accessed_at,
-- every plugin re-implements all of it.
OpenClaw did it. The Hermes plugin was about to do it. synapcores-agent did it. Three implementations of the same thing, three places to break, three places where embedding-model defaults drifted.
v1.8.5 collapses that into three first-class SQL functions.
-- Store text in a namespace, returns a memory id
SELECT MEMORY_STORE('default', 'I prefer Python over Java') AS memory_id;
-- Semantically retrieve similar memories (table-valued)
SELECT id, content, similarity
FROM MEMORY_RECALL('default', 'what languages do I like', 5);
-- Hard-delete a memory by id, returns BOOLEAN
SELECT MEMORY_FORGET('default', 'mem_abc123') AS deleted;
That's it. No DDL. No index management. No embedding-model wiring. The engine owns the table layout, the embedding call, the cosine ranking, and the accessed_at bump. Per-tenant scoped via the standard storage path.
Why this is a release, not a recipe
Three reasons we moved this into the engine instead of leaving it as documentation:
1. It removes ~150 LOC of plumbing per plugin. The new MEMORY_STORE / RECALL / FORGET replaces hand-rolled CREATE TABLE + EMBED + HNSW + cosine ranking + bookkeeping. We migrated @synapcores/openclaw-memory v0.4.0 to use it — the plugin shrank, the contract got typed, and the embedding-model default is now whatever the engine is configured with.
2. It gives every agent a portable contract. Once MEMORY_* is in the SQL surface, every plugin that wants long-term memory — including the Hermes integration we're shipping next — has one function to call. The MCP sql_manual tool lists the three primitives with examples, so LLMs introspecting your engine can discover them at runtime.
3. It ships with three SDK companions. The release isn't just engine — the surfaces went out together:
@synapcores/sdk@0.5.0(Node) exposesclient.memory.store / recall / forgetsynapcores 0.5.0(Python) exposes the same surface@synapcores/openclaw-memory@0.4.0is the first plugin migrated to it
Same memory namespace, same row layout, regardless of which SDK or plugin writes to it.
Try it in 60 seconds
After upgrading, against any running engine:
-- Persist three preferences
SELECT MEMORY_STORE('user_42', 'Prefers Python over Java for systems work');
SELECT MEMORY_STORE('user_42', 'On a low-carb diet');
SELECT MEMORY_STORE('user_42', 'Strong opinions about Postgres vs MySQL');
-- Ask for what they like programming-wise
SELECT id, content, similarity
FROM MEMORY_RECALL('user_42', 'what programming language', 3);
-- → row 1: "Prefers Python over Java..." similarity ~0.45
-- → row 2: "Strong opinions about Postgres..." similarity ~0.20
-- → row 3: "On a low-carb diet" similarity ~0.05
MEMORY_STORE auto-creates a per-namespace backing table _memory_<namespace> on the first call, embeds the content via your configured embedding model (default all-minilm:latest, dim 384), and returns a sortable id (mem_<base32 ts>_<6 alphanum>). MEMORY_RECALL is a table-valued function — it scans the namespace, computes cosine similarity per row, and returns the top top_k rows ordered by similarity DESC. MEMORY_FORGET returns BOOLEAN; the backing row is gone.
Namespaces must match ^[A-Za-z_][A-Za-z0-9_]*$ and are per-tenant — the same default namespace in two tenants stores in different RocksDB columns.
From the same SDK
The Node and Python SDKs hide the SQL entirely:
// @synapcores/sdk@0.5.0
const memId = await client.memory.store('user_42',
'Prefers Python over Java');
const hits = await client.memory.recall('user_42',
'what programming language', 3);
// hits → [{ id, content, similarity }, ...]
await client.memory.forget('user_42', memId);
# synapcores 0.5.0
mem_id = client.memory.store("user_42",
"Prefers Python over Java")
hits = client.memory.recall("user_42",
"what programming language", top_k=3)
client.memory.forget("user_42", mem_id)
If you're building a memory-having agent, the SDK surface is one line per operation, the same shape in both languages, and the LLM doesn't need to know any SQL.
What changed in the engine
Seven commits on top of v1.8.4-ce:
| Commit | What |
|---|---|
f592475b |
Parser + planner + AST surface for MEMORY_* |
50f42d99 |
Wire MEMORY_* through both physical-plan and AI-function paths |
d83c7ebc |
Register MEMORY_* in sql_manual MCP tool |
e1991d42 |
Integration tests for STORE / RECALL / FORGET |
72ec5867 |
Require AI service for MEMORY_STORE / MEMORY_RECALL |
acd48eac |
MEMORY_RECALL.accessed_at bump non-destructive |
f09b5dc3 |
AIDB_SQL_MANUAL.md MEMORY_* reference (engine + frontend) |
Live-tested end-to-end against the release binary on the i5-10400F canary (no AVX-512, no GPU offload — the box we gate every release on):
MEMORY_STORE($1, $2)returns a validmem_<ts>_<rand>idMEMORY_RECALL($1, $2, $3)returns cosine-ranked rows; relevant matches score in[0.4, 0.95]MEMORY_FORGET($1, $2)returns BOOLEAN and the backing row is gone- Parameterized SQL (
$1, $2, $3) binds correctly through all three primitives - 17/19 Python SDK live integration tests pass (the two fails are an embedding-model similarity-threshold sharpness issue and a known
DocumentStorage::deletequirk — neither blocks the release)
Try it now
# Linux x86_64 / aarch64 (plus Ubuntu 24 builds), macOS aarch64
curl -fsSL https://get.synapcores.com | sh
# Pin to v1.8.5-ce explicitly
curl -fsSL https://get.synapcores.com | SYNAPCORES_VERSION=v1.8.5-ce sh
# Docker
docker run -d \
-p 8080:8080 \
-e AIDB_ACCEPT_LICENSE=1 \
-v synapcores_data:/opt/synapcores/aidb_data \
synapcores/community:v1.8.5-ce
Pre-v1.8.5 servers are unaffected — the primitives are additive; nothing existing changes shape. Upgrade is in-place — no data migration required. The OpenClaw plugin v0.4.0 declares openclaw.compat.synapcoresEngine: ">=1.8.5-ce", so existing OpenClaw users will get the new client-side surface as soon as they upgrade the engine.
Full reference: docs.synapcores.com/releases/v1.8.5-ce · SQL reference — Memory primitives · GitHub release.
Questions, bugs, or "what about model X" requests: github.com/mataluis2k/aidb/issues.
— The SynapCores team