SynapticDB
A single-file memory store that gives AI agents hybrid search, learned associations, and confidence-aware recall.
Why
AI agents need to retrieve useful context and recognize when no useful context exists. SynapticDB combines keyword search, vector search, and a graph of associations in one SQLite file. Each result includes an absolute confidence value, so an agent can reject weak matches instead of treating every ranked result as an answer.
SynapticDB v0.1 is alpha software. Hybrid search and confidence scoring are measured and working. The association graph is implemented, but current benchmark results do not show that the graph improves recall on its own.
Install
Install the built-in local embedding model:
pip install "synapticdb[embeddings]"
Install the smaller core package when you provide an embedding function:
pip install synapticdb
Requires Python 3.10 or newer. The embeddings extra downloads the 384-dimensional all-MiniLM-L6-v2 model on first use.
Quick start
from synapticdb import SynapticDB
with SynapticDB("synaptic.db") as memories:
memories.store("Client X requires SOC2 for vendor deployments")
result = memories.recall("deployment requirements for Client X")
print(result.memories[0].content)
Client X requires SOC2 for vendor deployments
The database, full-text index, embeddings, associations, and recall history all live in synaptic.db. Use ":memory:" instead for a temporary in-process database.
Features
- Run without a service — SQLite stores the complete memory system in one portable file.
- Match words and meaning — BM25 keyword search and cosine vector search are fused into one ranking.
- Reject weak answers — absolute confidence values support one threshold across different queries.
- Learn relationships — temporal, co-retrieval, feedback, and manual links build an association graph.
- Bring your own embeddings — a custom local or hosted embedding function can replace the built-in model.
Usage
Add memory to an OpenAI response
Install the OpenAI Python SDK and set OPENAI_API_KEY in your environment:
pip install "synapticdb[embeddings]" openai
export OPENAI_API_KEY="your-api-key"
The example retrieves memory for user_input, adds the memory to the OpenAI request, and stores the completed exchange:
from openai import OpenAI
from synapticdb import SynapticDB
client = OpenAI()
user_input = "What does Client X require for vendor deployments?"
with SynapticDB("agent-memory.db") as memories:
memories.store("Client X requires SOC 2 for vendor deployments.")
recalled = memories.recall(user_input, top_k=3)
context = "\n".join(memory.content for memory in recalled.memories)
response = client.responses.create(
model="gpt-5.6",
input=(
"Use the memory below to answer the user.\n\n"
f"Memory:\n{context}\n\n"
f"User: {user_input}"
),
)
answer = response.output_text
print(answer)
memories.store(f"User: {user_input}\nAssistant: {answer}")
The OpenAI client reads OPENAI_API_KEY from the environment. See the OpenAI API quickstart for key setup.
Return nothing when evidence is weak
min_confidence filters results before SynapticDB records retrieval learning. A recall can return fewer than top_k memories, including none.
result = memories.recall(
"deployment requirements for Client X",
top_k=5,
min_confidence=0.6,
)
relevant = result.memories
if not relevant:
print("No reliable answer found")
score ranks memories within one recall. confidence measures query-to-memory similarity and can be compared across recalls.
Store metadata and filter results
memories.store(
"Client X requires SOC 2 for vendor deployments",
metadata={"client": "x", "topic": "compliance"},
)
result = memories.recall(
"deployment requirements",
where={"client": "x"},
)
Teach explicit relationships
requirement = memories.store("Client X requires SOC 2")
deployment = memories.store("Project Atlas deploys to Client X")
memories.connect(requirement.id, deployment.id)
result = memories.recall("What affects the Atlas deployment?")
memories.feedback(result.query_id, positive=True)
Positive feedback strengthens the relationships used by a recall. Negative feedback weakens them without creating new links.
Export results as JSON
payload = result.to_dict()
json_text = result.to_json()
Every public result model retains typed Python fields. JSON exports convert UUIDs and timestamps to strings. get(), connect(), forget(), and feedback() accept UUID objects or their string forms.
How it works
One recall() follows five bounded steps:
- FTS5 BM25 ranks keyword matches, and cosine similarity ranks embedding matches.
- Reciprocal rank fusion combines both result lists.
- The highest-ranked memories seed spreading activation across the association graph.
- Graph maturity controls how much activation contributes to the final ranking.
- SynapticDB returns each memory with its ranking score, confidence, and retrieval source.
A cold or empty graph falls back to hybrid search. Edge weights decay over time, and periodic maintenance prunes weak edges.
Benchmark
The committed chained benchmark compares SynapticDB with a locked BM25, FAISS, and cross-encoder baseline. SynapticDB answers 17 of 25 associative queries, compared with 10 of 25 for the baseline. Both answer all 25 direct queries.
A confidence floor of 0.6 keeps 41 of 42 correct answers and rejects all 12 unanswerable questions in the benchmark. Confidence AUC is 0.994.
Reproduce the results after the first model download:
uv sync --extra bench
uv run --extra bench python -m bench --profile chained --retriever synaptic
The run takes about 35 seconds on the development machine. See the benchmark documentation for profiles, measurements, and stored records.
What an associative answer looks like
For one associative holdout query, the locked baseline misses the answer. SynapticDB returns it at rank 6 with confidence 0.640.
Query: Why does the observatory dome trigger wind protection during calm weather?
Answer: Converting knots before publishing reduced false closure alerts while preserving every genuinely windy shutdown.
The query and answer share almost no words. The association graph connects them through two intermediate memories:
- Wind data reaches the controller through the Boreal weather adapter.
- Boreal labels readings as meters per second but forwards knot values unchanged.
The graph records a useful reasoning path, but it did not create this benchmark win. SynapticDB's hybrid search already returned the answer before the graph existed.
What does not work yet
- Semantic seeding is disabled. A threshold sweep produced no unique wins. At
0.60, only 4 of 1,069 semantic edges landed on a real associative chain. - Co-retrieval and feedback are not measured end to end. Both update edges, but benchmark warm-up topics do not overlap the holdout paths. Adding overlap would leak training data into evaluation.
- Decay and pruning are not measured end to end. Future-dated ingestion and write-only maintenance prevent the benchmark from aging edges. Unit tests cover both behaviors.
- Confidence depends on embedding quality. Measure a threshold on your own data before using confidence as a production decision boundary.
Alternatives
If you only need vector search, start with a mature tool such as Chroma, LanceDB, or sqlite-vec. Choose SynapticDB when you want fused keyword and vector search in one SQLite file, plus a confidence value that can suppress weak answers. Treat the association graph as an experimental research feature.
Development
git clone https://github.com/xhillman/synapticdb.git
cd synapticdb
uv sync --extra dev
uv run --extra dev ruff format --check .
uv run --extra dev ruff check .
uv run --extra dev mypy
uv run --extra dev python -W error -m pytest
uv run --extra dev python -W error -m bench --profile smoke --retriever fixture --check --no-write
uv run --extra dev python -W error -m bench --profile smoke --retriever synaptic --check --no-write
Build the wheel and source distribution with uv run --extra dev python -m build.
Contributing
Contributions are welcome. Open an issue before starting a large change so the proposed scope can be reviewed first.
License
MIT © Xavier Hillman. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file synapticdb-0.1.1.tar.gz.
File metadata
- Download URL: synapticdb-0.1.1.tar.gz
- Upload date:
- Size: 171.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79723da5086f0f23b6d464ed9b0f94514732ceb3c7816a8d7f9dbc886098243b
|
|
| MD5 |
15ccc2bf86c3be349c9c284f08167a61
|
|
| BLAKE2b-256 |
60ef111c97773f9c3768aa43da881d1325365feb17f340822739eb5392498d2e
|
Provenance
The following attestation bundles were made for synapticdb-0.1.1.tar.gz:
Publisher:
release.yml on xhillman/synapticdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synapticdb-0.1.1.tar.gz -
Subject digest:
79723da5086f0f23b6d464ed9b0f94514732ceb3c7816a8d7f9dbc886098243b - Sigstore transparency entry: 2553709852
- Sigstore integration time:
-
Permalink:
xhillman/synapticdb@7a4f318d8c8db825fc5db5f1cac2633506609485 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xhillman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7a4f318d8c8db825fc5db5f1cac2633506609485 -
Trigger Event:
push
-
Statement type:
File details
Details for the file synapticdb-0.1.1-py3-none-any.whl.
File metadata
- Download URL: synapticdb-0.1.1-py3-none-any.whl
- Upload date:
- Size: 42.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1a7683dae10b95f65b1f28f72d24f4cd49138136ea52f5aaa7d039fff24753f
|
|
| MD5 |
1493d43e25bb7e205b00f510d74131c6
|
|
| BLAKE2b-256 |
d9a04fb016db9ea1eba99208f8df0d3d77b82d4cb0e4b01a27e3f9ff3145c69c
|
Provenance
The following attestation bundles were made for synapticdb-0.1.1-py3-none-any.whl:
Publisher:
release.yml on xhillman/synapticdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synapticdb-0.1.1-py3-none-any.whl -
Subject digest:
d1a7683dae10b95f65b1f28f72d24f4cd49138136ea52f5aaa7d039fff24753f - Sigstore transparency entry: 2553709985
- Sigstore integration time:
-
Permalink:
xhillman/synapticdb@7a4f318d8c8db825fc5db5f1cac2633506609485 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xhillman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7a4f318d8c8db825fc5db5f1cac2633506609485 -
Trigger Event:
push
-
Statement type: