A lightweight, self-consolidating cognitive memory layer for AI agents. Combines SQLite, vector search, and a knowledge graph with a biologically-inspired sleep/forget cycle.
Project description
Shaheen DB
pip install shaheen-db
Shaheen DB is a local-first cognitive memory database for AI agents.
It is named after my adorable cousin, Shaheen. The name was already taken in the family, so the database has big expectations to live up to.
Shaheen is not another vector database. It stores observations, evolves beliefs, keeps history, tracks contradictions, remembers relationships, and helps agents recall useful context over time.
The core idea:
Memories are evidence. Beliefs are evolving interpretations of evidence.
What Changed
Most memory systems store old messages and search them later.
Shaheen does more:
User says in 2025:
"My favorite language is Rust."
User says in 2026:
"Actually Zig is my favorite language now."
Shaheen stores both messages, but it also creates:
Current belief:
- favorite_language = Zig
History:
- 2025-01-12: favorite_language = Rust
- 2026-02-03: favorite_language = Zig
Contradiction:
- Rust -> Zig
So your agent can answer:
"What language do I prefer now?" -> Zig
"What language did I prefer in 2025?" -> Rust
without guessing.
Install
Core install:
pip install shaheen-db
Local semantic recall with FastEmbed/ONNX:
pip install shaheen-db[fastembed]
Claude extraction support:
pip install shaheen-db[anthropic]
From this repo:
pip install -e .[dev]
Python 3.12+ is required.
Two Ways To Use Shaheen
Shaheen can be used in two styles.
Simple Agent Mode
Use this when you want Shaheen to provide memory context to an AI agent.
from shaheen import Shaheen
memory = Shaheen("agent.db")
turns_since_sleep = 0
def handle_message(user_message: str) -> str:
global turns_since_sleep
# 1. Store the raw observation immediately.
memory.remember(user_message, subject="user")
turns_since_sleep += 1
# 2. Consolidate every few turns so Shaheen can update beliefs,
# contradictions, timelines, and graph relationships.
if turns_since_sleep >= 10:
memory.consolidate(subject="user")
turns_since_sleep = 0
# 3. Retrieve useful memory context for the agent.
context = memory.recall(user_message, subject="user")
answer = llm.chat(
message=user_message,
context=context.to_prompt(),
)
# 4. Optionally store the assistant response too.
memory.remember(answer, subject="assistant")
return answer
For small apps, this threshold-based pattern is enough. For production apps, you can run memory.consolidate(subject="user") in a background worker, idle-time job, or scheduled task.
The usual loop is:
remember -> consolidate -> recall
Manual Cognitive Database Mode
Use this when you want direct control over beliefs, timelines, contradictions, and relationships.
from shaheen import Shaheen
memory = Shaheen("agent.db")
memory.remember(
"My favorite language is Rust.",
subject="user",
observed_at="2025-01-12",
)
memory.consolidate(subject="user")
memory.remember(
"Actually Zig is my favorite language now.",
subject="user",
observed_at="2026-02-03",
)
memory.consolidate(subject="user")
current = memory.belief("favorite_language", subject="user")
old = memory.belief("favorite_language", subject="user", at="2025-06-01")
print(current.value)
# Zig
print(old.value)
# Rust
Core APIs
remember
Stores an observation.
receipt = memory.remember(
"I prefer concise answers.",
subject="user",
)
print(receipt.memory_id)
subject="user" means the memory is about the user. You can also use subjects like:
subject="assistant"
subject="project:shaheen"
subject="user:alice"
consolidate
Turns raw observations into beliefs and relationships.
report = memory.consolidate(subject="user")
print(report.processed)
print(report.created_beliefs)
print(report.contradictions)
recall
Builds useful context for an agent.
result = memory.recall(
"What language should I use for a systems project?",
subject="user",
)
print(result.context)
Example:
Current beliefs:
- favorite_language = Zig (confidence: 0.85, importance: 0.85)
Relevant memories:
- [2026-02-03] Actually Zig is my favorite language now. (score: 0.52)
Historical recall:
result = memory.recall(
"What was my favorite language?",
subject="user",
at="2025-06-01",
)
print(result.context)
belief and beliefs
Ask what Shaheen currently believes.
belief = memory.belief("favorite_language", subject="user")
print(belief.value)
for belief in memory.beliefs(subject="user"):
print(belief.key, belief.value, belief.confidence)
preferences
List learned preferences.
for preference in memory.preferences(subject="user"):
print(preference.key, preference.value)
timeline
See how a belief changed.
timeline = memory.timeline("favorite_language", subject="user")
for event in timeline.events:
print(event.timestamp.date(), event.value, event.confidence)
contradictions
Inspect belief changes.
for contradiction in memory.contradictions(subject="user"):
print(contradiction.old_value, "->", contradiction.new_value)
relationships
Shaheen stores graph relationships.
memory.remember(
"I am building Shaheen and Shaheen uses SQLite.",
subject="user",
)
memory.consolidate(subject="user")
for relationship in memory.relationships(subject="user"):
print(relationship.source, relationship.type, relationship.target)
Output:
user BUILDS shaheen
shaheen USES sqlite
explain
Ask why Shaheen believes something.
print(memory.explain("favorite_language", subject="user"))
Example:
Shaheen believes favorite_language = Zig. Previous value was Rust.
reinforce and forget
Strengthen or archive a memory.
reinforced = memory.reinforce(receipt.memory_id, amount=3)
archived = memory.forget(receipt.memory_id)
stats and benchmark
print(memory.stats())
bench = memory.benchmark(iterations=100, subject="bench")
print(bench["insertion_per_second"])
Embeddings
Shaheen works without embeddings by default.
memory = Shaheen("agent.db")
This keeps the base package lightweight. You still get:
- memory insertion;
- consolidation;
- beliefs;
- belief history;
- contradictions;
- graph relationships;
- lexical recall;
- temporal recall.
Turn on local semantic recall with FastEmbed:
pip install shaheen-db[fastembed]
memory = Shaheen("agent.db", embeddings="fastembed")
embeddings=True is shorthand for FastEmbed:
memory = Shaheen("agent.db", embeddings=True)
Use the legacy/provider embedding adapter:
memory = Shaheen("agent.db", embeddings="provider")
Embeddings improve fuzzy natural-language recall. They are optional.
Extractors And AI Providers
The extractor turns raw memories into structured beliefs and graph relationships.
Default extractor, no API key:
memory = Shaheen("agent.db")
# same as:
memory = Shaheen("agent.db", extractor="heuristic")
This is deterministic, offline, and testable.
Use an LLM extractor when you want richer extraction:
memory = Shaheen("agent.db", extractor="llm")
extractor="llm" auto-selects from SHAHEEN_LLM_PROVIDER.
You can also choose explicitly:
memory = Shaheen("agent.db", extractor="openai")
memory = Shaheen("agent.db", extractor="gemini")
memory = Shaheen("agent.db", extractor="claude")
If the provider is missing or fails, Shaheen falls back to the heuristic extractor.
OpenAI-Compatible
Works with OpenAI, OpenRouter, Groq, DeepSeek, Ollama, LM Studio, and other OpenAI-compatible APIs.
export SHAHEEN_LLM_PROVIDER="openai"
export SHAHEEN_LLM_API_KEY="your-key"
export SHAHEEN_LLM_MODEL="gpt-4o-mini"
memory = Shaheen("agent.db", extractor="llm")
# or
memory = Shaheen("agent.db", extractor="openai")
Local OpenAI-compatible server:
export SHAHEEN_LLM_PROVIDER="openai"
export SHAHEEN_LLM_BASE_URL="http://localhost:11434/v1"
export SHAHEEN_LLM_API_KEY="ollama"
export SHAHEEN_LLM_MODEL="llama3"
Gemini
export SHAHEEN_LLM_PROVIDER="gemini"
export GEMINI_API_KEY="your-gemini-key"
export SHAHEEN_LLM_MODEL="gemini-2.5-flash"
memory = Shaheen("agent.db", extractor="llm")
# or
memory = Shaheen("agent.db", extractor="gemini")
Claude
Install the optional Anthropic extra:
pip install shaheen-db[anthropic]
Configure:
export SHAHEEN_LLM_PROVIDER="anthropic"
export ANTHROPIC_API_KEY="your-anthropic-key"
export SHAHEEN_LLM_MODEL="claude-3-5-sonnet-20241022"
memory = Shaheen("agent.db", extractor="llm")
# or
memory = Shaheen("agent.db", extractor="claude")
Development
pip install -e .[dev]
python -m pytest -q
python -m ruff check shaheen tests demo.py
python -m mypy shaheen demo.py
python demo.py
Current verification:
32 tests passing
Ruff passing
Mypy passing
Demo passing
Package build passing
Twine check passing
Architecture
See:
Key decisions:
- SQLite-first, adapter-ready;
- no legacy migration promise;
- belief history is never destroyed;
- graph relationships are first-class;
- LLM extraction is optional with deterministic fallback;
- embeddings are optional and FastEmbed is the recommended local path.
License
Shaheen DB is open-source software licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
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 shaheen_db-1.0.0.tar.gz.
File metadata
- Download URL: shaheen_db-1.0.0.tar.gz
- Upload date:
- Size: 42.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e40b10896d30c0b48bf444461ecef91c0a547bc92f5cd36cbba2f942e5df9ddd
|
|
| MD5 |
567385c77f3cb03e47807f1ee4b3ec64
|
|
| BLAKE2b-256 |
6411ff50e0a9255afee53ea1107f05bc93782cd265a0cbe5f6d3109dab311c5d
|
File details
Details for the file shaheen_db-1.0.0-py3-none-any.whl.
File metadata
- Download URL: shaheen_db-1.0.0-py3-none-any.whl
- Upload date:
- Size: 40.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a390016e4517d4c0830f2f73c21b7b6a0e60d46e42b33a4fcba81dbbffd6d839
|
|
| MD5 |
068a0a8b28df2d2a392322f815d7a399
|
|
| BLAKE2b-256 |
b9d08700ad2d0f71b1a51ad39e07a21dc534968bba783cf8c3d95e7cf07f08b6
|