agentrecall-db 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentrecall_db-0.1.0/.github/workflows/ci.yml +43 -0
- agentrecall_db-0.1.0/.github/workflows/release.yml +27 -0
- agentrecall_db-0.1.0/.gitignore +30 -0
- agentrecall_db-0.1.0/CHANGELOG.md +30 -0
- agentrecall_db-0.1.0/CONTRIBUTING.md +45 -0
- agentrecall_db-0.1.0/LICENSE +21 -0
- agentrecall_db-0.1.0/PKG-INFO +243 -0
- agentrecall_db-0.1.0/README.md +203 -0
- agentrecall_db-0.1.0/SPEC.md +354 -0
- agentrecall_db-0.1.0/agentrecall/__init__.py +33 -0
- agentrecall_db-0.1.0/agentrecall/cli.py +209 -0
- agentrecall_db-0.1.0/agentrecall/config.py +42 -0
- agentrecall_db-0.1.0/agentrecall/embeddings.py +84 -0
- agentrecall_db-0.1.0/agentrecall/errors.py +36 -0
- agentrecall_db-0.1.0/agentrecall/mcp_server.py +70 -0
- agentrecall_db-0.1.0/agentrecall/memory.py +261 -0
- agentrecall_db-0.1.0/agentrecall/models.py +70 -0
- agentrecall_db-0.1.0/agentrecall/search.py +82 -0
- agentrecall_db-0.1.0/agentrecall/store.py +493 -0
- agentrecall_db-0.1.0/examples/agent_loop.py +46 -0
- agentrecall_db-0.1.0/examples/quickstart.py +22 -0
- agentrecall_db-0.1.0/pyproject.toml +60 -0
- agentrecall_db-0.1.0/tests/conftest.py +17 -0
- agentrecall_db-0.1.0/tests/test_cli.py +71 -0
- agentrecall_db-0.1.0/tests/test_mcp.py +54 -0
- agentrecall_db-0.1.0/tests/test_memory.py +236 -0
- agentrecall_db-0.1.0/tests/test_search.py +119 -0
- agentrecall_db-0.1.0/tests/test_semantic.py +128 -0
- agentrecall_db-0.1.0/tests/test_store.py +105 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
core:
|
|
10
|
+
name: core (py${{ matrix.python-version }}, stdlib only)
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- name: Install (dev only — no semantic/mcp extras)
|
|
22
|
+
run: |
|
|
23
|
+
python -m pip install --upgrade pip
|
|
24
|
+
python -m pip install -e ".[dev]"
|
|
25
|
+
- name: Lint
|
|
26
|
+
run: ruff check .
|
|
27
|
+
- name: Test (FTS-only path; semantic/mcp tests auto-skip)
|
|
28
|
+
run: pytest -q
|
|
29
|
+
|
|
30
|
+
full:
|
|
31
|
+
name: full (semantic + mcp extras)
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.12"
|
|
38
|
+
- name: Install with all extras
|
|
39
|
+
run: |
|
|
40
|
+
python -m pip install --upgrade pip
|
|
41
|
+
python -m pip install -e ".[all,dev]"
|
|
42
|
+
- name: Test (includes sqlite-vec + MCP; model download may skip offline)
|
|
43
|
+
run: pytest -q
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes on every v* tag via PyPI Trusted Publishing (OIDC) — no API token stored.
|
|
4
|
+
# One-time setup on PyPI: add a "pending publisher" for project `agentrecall` with
|
|
5
|
+
# owner: shaxzodbek-uzb · repo: agentrecall · workflow: release.yml
|
|
6
|
+
# (https://pypi.org/manage/account/publishing/). After that, pushing a v* tag publishes.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
pypi:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write # required for Trusted Publishing
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- name: Build sdist + wheel
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install --upgrade build
|
|
25
|
+
python -m build
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
.env
|
|
11
|
+
|
|
12
|
+
# Tooling
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# agentrecall databases (don't commit local memory stores)
|
|
20
|
+
*.db
|
|
21
|
+
*.db-wal
|
|
22
|
+
*.db-shm
|
|
23
|
+
*.sqlite
|
|
24
|
+
*.sqlite3
|
|
25
|
+
|
|
26
|
+
# OS / editor
|
|
27
|
+
.DS_Store
|
|
28
|
+
*.swp
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — 2026-06-20
|
|
10
|
+
|
|
11
|
+
Initial release.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- `Memory` — agent memory backed by a single SQLite file, with `add`, `add_many`,
|
|
15
|
+
`search`, `get`, `update`, `delete`, `all`, `count`, and `forget`.
|
|
16
|
+
- Keyword recall via SQLite FTS5 (BM25) with **zero third-party dependencies**, plus a
|
|
17
|
+
`LIKE`-based fallback for SQLite builds without FTS5.
|
|
18
|
+
- Optional torch-free semantic search (`agentrecall[semantic]`): model2vec static
|
|
19
|
+
embeddings stored in sqlite-vec, fused with keyword results via Reciprocal Rank Fusion.
|
|
20
|
+
- Namespaces for per-user / per-agent isolation; tag and metadata storage; all-of tag
|
|
21
|
+
filtering; optional recency and importance ranking boosts.
|
|
22
|
+
- Injection-safe FTS query sanitization.
|
|
23
|
+
- MCP server (`agentrecall[mcp]`, `agentrecall serve`) exposing `remember` / `recall` /
|
|
24
|
+
`forget` / `list_memories` / `memory_stats` — an embeddings-capable alternative to the
|
|
25
|
+
keyword-only JSONL memory server.
|
|
26
|
+
- `agentrecall` CLI: `add`, `search`, `list`, `get`, `delete`, `forget`, `stats`,
|
|
27
|
+
`export`, `serve`.
|
|
28
|
+
|
|
29
|
+
[Unreleased]: https://github.com/shaxzodbek-uzb/agentrecall/compare/v0.1.0...HEAD
|
|
30
|
+
[0.1.0]: https://github.com/shaxzodbek-uzb/agentrecall/releases/tag/v0.1.0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing to agentrecall
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! agentrecall aims to stay **small, dependency-light, and honest**.
|
|
4
|
+
Contributions that keep the core to the Python stdlib and push everything else into optional
|
|
5
|
+
extras are the most likely to be merged.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/shaxzodbek-uzb/agentrecall
|
|
11
|
+
cd agentrecall
|
|
12
|
+
python -m venv .venv && source .venv/bin/activate
|
|
13
|
+
pip install -e ".[dev]" # core + pytest + ruff
|
|
14
|
+
pip install -e ".[all]" # add semantic + mcp to run those tests too
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Before you open a PR
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
ruff check .
|
|
21
|
+
ruff format .
|
|
22
|
+
pytest
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- **The core stays dependency-free.** Anything beyond the stdlib goes under
|
|
26
|
+
`[project.optional-dependencies]` and is imported lazily inside the function that needs it.
|
|
27
|
+
- **FTS-only tests must pass with no extras installed.** Guard semantic/MCP tests with
|
|
28
|
+
`pytest.importorskip(...)`.
|
|
29
|
+
- **No network at import or collection time.** Model downloads only happen inside an
|
|
30
|
+
explicitly-marked semantic test.
|
|
31
|
+
- Match the existing style; `SPEC.md` is the source of truth for public API names and
|
|
32
|
+
behavior — update it in the same PR if you change the surface.
|
|
33
|
+
|
|
34
|
+
## Good first contributions
|
|
35
|
+
|
|
36
|
+
- Adapters for popular agent frameworks (LangGraph, pydantic-ai, CrewAI) under `examples/`.
|
|
37
|
+
- Additional `Embedder` implementations (OpenAI, Ollama, fastembed) as opt-in extras.
|
|
38
|
+
- Benchmarks of recall quality vs. corpus size.
|
|
39
|
+
|
|
40
|
+
## Reporting bugs
|
|
41
|
+
|
|
42
|
+
Open an issue with the SQLite version (`python -c "import sqlite3; print(sqlite3.sqlite_version)"`),
|
|
43
|
+
your Python version, and a minimal reproduction.
|
|
44
|
+
|
|
45
|
+
By contributing you agree your work is licensed under the project's MIT license.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shaxzodbek Sobirov / Blaze
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentrecall-db
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent memory in a single SQLite file — no vector DB, no server, no cloud. Keyword recall on stdlib alone; torch-free hybrid semantic search via model2vec + sqlite-vec. Python lib + MCP server + CLI.
|
|
5
|
+
Project-URL: Homepage, https://github.com/shaxzodbek-uzb/agentrecall
|
|
6
|
+
Project-URL: Repository, https://github.com/shaxzodbek-uzb/agentrecall
|
|
7
|
+
Project-URL: Issues, https://github.com/shaxzodbek-uzb/agentrecall/issues
|
|
8
|
+
Author-email: Shaxzodbek Sobirov <shaxzodbek@blaze.uz>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent,claude,embeddings,fts5,llm,local-first,mcp,memory,model2vec,offline,rag,sqlite,sqlite-vec
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Provides-Extra: all
|
|
26
|
+
Requires-Dist: mcp>=1.2; extra == 'all'
|
|
27
|
+
Requires-Dist: model2vec>=0.3; extra == 'all'
|
|
28
|
+
Requires-Dist: numpy>=1.21; extra == 'all'
|
|
29
|
+
Requires-Dist: sqlite-vec>=0.1.6; extra == 'all'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
33
|
+
Provides-Extra: mcp
|
|
34
|
+
Requires-Dist: mcp>=1.2; extra == 'mcp'
|
|
35
|
+
Provides-Extra: semantic
|
|
36
|
+
Requires-Dist: model2vec>=0.3; extra == 'semantic'
|
|
37
|
+
Requires-Dist: numpy>=1.21; extra == 'semantic'
|
|
38
|
+
Requires-Dist: sqlite-vec>=0.1.6; extra == 'semantic'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# agentrecall
|
|
42
|
+
|
|
43
|
+
**Agent memory in a single SQLite file.** No vector database, no server, no cloud, no API key.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install agentrecall
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from agentrecall import Memory
|
|
51
|
+
|
|
52
|
+
with Memory("agent.db") as mem: # one SQLite file, nothing else running
|
|
53
|
+
mem.add("The user prefers dark mode", tags=["preference"])
|
|
54
|
+
mem.add("User's name is Aziz; lives in Tashkent", metadata={"kind": "fact"})
|
|
55
|
+
|
|
56
|
+
# The core install gives you fast keyword recall (SQLite FTS5). For meaning-based
|
|
57
|
+
# search that matches paraphrases, add the [semantic] extra — see below.
|
|
58
|
+
for hit in mem.search("dark mode preference", k=3):
|
|
59
|
+
print(hit.score, hit.content)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
That's the whole setup. `agent.db` is an ordinary SQLite file you can `cp`, `git diff`,
|
|
63
|
+
back up, inspect with any SQLite tool, and read from any language. Nothing else is running.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Why another memory library?
|
|
68
|
+
|
|
69
|
+
Most "memory layers" for agents are **infrastructure**. To get started you stand up a
|
|
70
|
+
vector database, run a server, sign up for a cloud, or hand over an API key — and many of
|
|
71
|
+
them call an LLM on every write to "extract" facts, which is slow, costs tokens, and is
|
|
72
|
+
non-deterministic.
|
|
73
|
+
|
|
74
|
+
`agentrecall` is the opposite. It is a **library**, the store is **one file**, recall is
|
|
75
|
+
**deterministic**, and **nothing leaves the machine**.
|
|
76
|
+
|
|
77
|
+
| | infra needed | semantic search | offline | stores | LLM call per write |
|
|
78
|
+
|---|---|---|---|---|---|
|
|
79
|
+
| **agentrecall** | **none** (1 file) | ✅ torch-free, opt-in | ✅ | SQLite | ❌ verbatim |
|
|
80
|
+
| mem0 | vector DB / cloud | ✅ | ⚠️ | vector + KV + graph | ✅ |
|
|
81
|
+
| Letta / MemGPT | server + Postgres | ✅ | ⚠️ | Postgres + pgvector | ✅ |
|
|
82
|
+
| Zep | server + datastore | ✅ | ⚠️ | knowledge graph | ✅ |
|
|
83
|
+
| official MCP memory server | none | ❌ keyword only | ✅ | JSONL flat file | ❌ |
|
|
84
|
+
|
|
85
|
+
Three things `agentrecall` does that nothing else combines:
|
|
86
|
+
|
|
87
|
+
1. **Zero infrastructure.** The core has **no third-party dependencies** — keyword recall
|
|
88
|
+
runs on Python's stdlib `sqlite3` (FTS5 + BM25). A fresh `pip install agentrecall` with
|
|
89
|
+
nothing else works.
|
|
90
|
+
2. **Semantic search with no torch, no GPU, no download server.** Add the `[semantic]`
|
|
91
|
+
extra and you get hybrid keyword + vector recall powered by
|
|
92
|
+
[model2vec](https://github.com/MinishLab/model2vec) static embeddings (~10 MB, CPU-only)
|
|
93
|
+
stored in [sqlite-vec](https://github.com/asg017/sqlite-vec). Still one file, still offline.
|
|
94
|
+
3. **Verbatim & deterministic.** `agentrecall` never calls an LLM to mutate your memories.
|
|
95
|
+
What you `add()` is what is stored — no silent fact-extraction, no cloud round-trip, no
|
|
96
|
+
surprise token bills.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Install
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pip install agentrecall # core: keyword recall, stdlib only
|
|
104
|
+
pip install "agentrecall[semantic]" # + torch-free semantic search (model2vec + sqlite-vec)
|
|
105
|
+
pip install "agentrecall[mcp]" # + MCP server
|
|
106
|
+
pip install "agentrecall[all]" # everything
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Semantic search (optional, torch-free)
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from agentrecall import Memory
|
|
113
|
+
|
|
114
|
+
# embeddings="auto" (the default) turns semantic on automatically *iff* the
|
|
115
|
+
# [semantic] extra is installed, and silently stays keyword-only otherwise.
|
|
116
|
+
mem = Memory("agent.db", embeddings="auto")
|
|
117
|
+
print(mem.semantic_enabled) # True once you've installed agentrecall[semantic]
|
|
118
|
+
|
|
119
|
+
mem.add("I love hiking in the mountains on weekends")
|
|
120
|
+
hits = mem.search("outdoor hobbies") # matches even with zero shared keywords
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Search is **hybrid**: keyword (FTS5/BM25) and vector (cosine) candidates are blended with
|
|
124
|
+
[Reciprocal Rank Fusion](https://learn.microsoft.com/azure/search/hybrid-search-ranking),
|
|
125
|
+
so you get the precision of keywords and the recall of embeddings. Bring your own embedder
|
|
126
|
+
(OpenAI, a local model, anything) by passing `embedder=` — any object with `.dim` and
|
|
127
|
+
`.embed(texts) -> list[list[float]]`.
|
|
128
|
+
|
|
129
|
+
Optional ranking boosts:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
mem = Memory("agent.db", recency_weight=0.5, importance_weight=0.3)
|
|
133
|
+
mem.add("Critical: API key rotates on the 1st", importance=3.0)
|
|
134
|
+
mem.search("api key", recency_weight=1.0) # per-call override
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Namespaces
|
|
138
|
+
|
|
139
|
+
Isolate memories per user, per agent, or per session with a namespace:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
alice = Memory("app.db", namespace="user:alice")
|
|
143
|
+
bob = Memory("app.db", namespace="user:bob") # same file, isolated memories
|
|
144
|
+
alice.add("prefers metric units")
|
|
145
|
+
bob.search("units") # never sees Alice's memories
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## As an MCP server
|
|
149
|
+
|
|
150
|
+
Give Claude (or any MCP client) persistent, searchable memory — an embeddings-capable
|
|
151
|
+
alternative to the official keyword-only JSONL memory server:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pip install "agentrecall[mcp]"
|
|
155
|
+
agentrecall serve --db ~/.agent-memory.db
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```jsonc
|
|
159
|
+
// Claude Desktop / Claude Code MCP config
|
|
160
|
+
{
|
|
161
|
+
"mcpServers": {
|
|
162
|
+
"memory": {
|
|
163
|
+
"command": "agentrecall",
|
|
164
|
+
"args": ["serve", "--db", "/Users/me/.agent-memory.db"]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Tools exposed: `remember`, `recall`, `forget`, `list_memories`, `memory_stats`.
|
|
171
|
+
|
|
172
|
+
## CLI
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
agentrecall add "Deadline is July 7" --tags project --importance 2
|
|
176
|
+
agentrecall search "when is the deadline" -k 3
|
|
177
|
+
agentrecall list --limit 10
|
|
178
|
+
agentrecall stats
|
|
179
|
+
agentrecall forget --keep-last 1000 # prune to the newest 1000 per namespace
|
|
180
|
+
agentrecall export --format md > memories.md
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Every command honours `--db`, `--namespace`, and the `AGENTRECALL_DB` /
|
|
184
|
+
`AGENTRECALL_NAMESPACE` / `AGENTRECALL_EMBEDDINGS` environment variables.
|
|
185
|
+
|
|
186
|
+
## API at a glance
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
mem.add(content, *, tags=None, metadata=None, importance=1.0, namespace=None) -> MemoryRecord
|
|
190
|
+
mem.add_many([str | dict, ...]) -> list[MemoryRecord]
|
|
191
|
+
mem.search(query, *, k=5, namespace=None, tags=None,
|
|
192
|
+
recency_weight=None, importance_weight=None) -> list[MemoryHit]
|
|
193
|
+
mem.get(id) / mem.update(id, ...) / mem.delete(id)
|
|
194
|
+
mem.all(*, namespace=None, tags=None, limit=None, offset=0) -> list[MemoryRecord]
|
|
195
|
+
mem.count(*, namespace=None) -> int
|
|
196
|
+
mem.forget(*, before=None, namespace=None, keep_last=None) -> int # deleted count
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`tags` filtering matches memories containing **all** of the requested tags.
|
|
200
|
+
|
|
201
|
+
## The database is just SQLite
|
|
202
|
+
|
|
203
|
+
No magic. Open it with anything:
|
|
204
|
+
|
|
205
|
+
```sql
|
|
206
|
+
sqlite3 agent.db "SELECT id, content, importance, created_at FROM memories ORDER BY created_at DESC LIMIT 5;"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Schema: a `memories` table (with JSON `tags`/`metadata` columns), an FTS5 index kept in
|
|
210
|
+
sync by triggers, and — only in semantic mode — a `sqlite-vec` vector table. See
|
|
211
|
+
[`SPEC.md`](SPEC.md) for the full contract.
|
|
212
|
+
|
|
213
|
+
## Scope & limits (honest defaults)
|
|
214
|
+
|
|
215
|
+
- **Agent-scale, not web-scale.** sqlite-vec uses a linear scan (no ANN index yet) — great
|
|
216
|
+
for thousands of memories per namespace, not millions of RAG chunks.
|
|
217
|
+
- **Sync, single-process.** Use one `Memory` per thread. `sqlite3` is fast and local; there
|
|
218
|
+
is no async API by design.
|
|
219
|
+
- **No knowledge graph / entity-relation modeling.** That's [Cognee](https://github.com/topoteretes/cognee)
|
|
220
|
+
and [Zep](https://www.getzep.com/)'s lane. `agentrecall` stays small on purpose.
|
|
221
|
+
- **No automatic summarization.** Memories are stored verbatim. If you want LLM-distilled
|
|
222
|
+
memories, distill before you `add()` — your call, your model, your tokens.
|
|
223
|
+
- **`add()` is append-only.** Re-adding the same text creates a new row (no content
|
|
224
|
+
dedupe). To revise a memory, keep the integer id returned by `add()` and call
|
|
225
|
+
`update(id, ...)` / `delete(id)`.
|
|
226
|
+
- **`forget(before=..., keep_last=...)` deletes the union** — rows older than `before`
|
|
227
|
+
*or* beyond the newest `keep_last` per namespace. With neither argument it's a no-op
|
|
228
|
+
(to wipe a store, just delete the file).
|
|
229
|
+
|
|
230
|
+
## Development
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
pip install -e ".[dev]"
|
|
234
|
+
pytest
|
|
235
|
+
ruff check .
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The keyword (FTS-only) test suite runs with **zero third-party dependencies**. Semantic
|
|
239
|
+
tests are skipped automatically when the `[semantic]` extra isn't installed.
|
|
240
|
+
|
|
241
|
+
## License
|
|
242
|
+
|
|
243
|
+
MIT © 2026 Shaxzodbek Sobirov / Blaze
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# agentrecall
|
|
2
|
+
|
|
3
|
+
**Agent memory in a single SQLite file.** No vector database, no server, no cloud, no API key.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install agentrecall
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from agentrecall import Memory
|
|
11
|
+
|
|
12
|
+
with Memory("agent.db") as mem: # one SQLite file, nothing else running
|
|
13
|
+
mem.add("The user prefers dark mode", tags=["preference"])
|
|
14
|
+
mem.add("User's name is Aziz; lives in Tashkent", metadata={"kind": "fact"})
|
|
15
|
+
|
|
16
|
+
# The core install gives you fast keyword recall (SQLite FTS5). For meaning-based
|
|
17
|
+
# search that matches paraphrases, add the [semantic] extra — see below.
|
|
18
|
+
for hit in mem.search("dark mode preference", k=3):
|
|
19
|
+
print(hit.score, hit.content)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
That's the whole setup. `agent.db` is an ordinary SQLite file you can `cp`, `git diff`,
|
|
23
|
+
back up, inspect with any SQLite tool, and read from any language. Nothing else is running.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Why another memory library?
|
|
28
|
+
|
|
29
|
+
Most "memory layers" for agents are **infrastructure**. To get started you stand up a
|
|
30
|
+
vector database, run a server, sign up for a cloud, or hand over an API key — and many of
|
|
31
|
+
them call an LLM on every write to "extract" facts, which is slow, costs tokens, and is
|
|
32
|
+
non-deterministic.
|
|
33
|
+
|
|
34
|
+
`agentrecall` is the opposite. It is a **library**, the store is **one file**, recall is
|
|
35
|
+
**deterministic**, and **nothing leaves the machine**.
|
|
36
|
+
|
|
37
|
+
| | infra needed | semantic search | offline | stores | LLM call per write |
|
|
38
|
+
|---|---|---|---|---|---|
|
|
39
|
+
| **agentrecall** | **none** (1 file) | ✅ torch-free, opt-in | ✅ | SQLite | ❌ verbatim |
|
|
40
|
+
| mem0 | vector DB / cloud | ✅ | ⚠️ | vector + KV + graph | ✅ |
|
|
41
|
+
| Letta / MemGPT | server + Postgres | ✅ | ⚠️ | Postgres + pgvector | ✅ |
|
|
42
|
+
| Zep | server + datastore | ✅ | ⚠️ | knowledge graph | ✅ |
|
|
43
|
+
| official MCP memory server | none | ❌ keyword only | ✅ | JSONL flat file | ❌ |
|
|
44
|
+
|
|
45
|
+
Three things `agentrecall` does that nothing else combines:
|
|
46
|
+
|
|
47
|
+
1. **Zero infrastructure.** The core has **no third-party dependencies** — keyword recall
|
|
48
|
+
runs on Python's stdlib `sqlite3` (FTS5 + BM25). A fresh `pip install agentrecall` with
|
|
49
|
+
nothing else works.
|
|
50
|
+
2. **Semantic search with no torch, no GPU, no download server.** Add the `[semantic]`
|
|
51
|
+
extra and you get hybrid keyword + vector recall powered by
|
|
52
|
+
[model2vec](https://github.com/MinishLab/model2vec) static embeddings (~10 MB, CPU-only)
|
|
53
|
+
stored in [sqlite-vec](https://github.com/asg017/sqlite-vec). Still one file, still offline.
|
|
54
|
+
3. **Verbatim & deterministic.** `agentrecall` never calls an LLM to mutate your memories.
|
|
55
|
+
What you `add()` is what is stored — no silent fact-extraction, no cloud round-trip, no
|
|
56
|
+
surprise token bills.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Install
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install agentrecall # core: keyword recall, stdlib only
|
|
64
|
+
pip install "agentrecall[semantic]" # + torch-free semantic search (model2vec + sqlite-vec)
|
|
65
|
+
pip install "agentrecall[mcp]" # + MCP server
|
|
66
|
+
pip install "agentrecall[all]" # everything
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Semantic search (optional, torch-free)
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from agentrecall import Memory
|
|
73
|
+
|
|
74
|
+
# embeddings="auto" (the default) turns semantic on automatically *iff* the
|
|
75
|
+
# [semantic] extra is installed, and silently stays keyword-only otherwise.
|
|
76
|
+
mem = Memory("agent.db", embeddings="auto")
|
|
77
|
+
print(mem.semantic_enabled) # True once you've installed agentrecall[semantic]
|
|
78
|
+
|
|
79
|
+
mem.add("I love hiking in the mountains on weekends")
|
|
80
|
+
hits = mem.search("outdoor hobbies") # matches even with zero shared keywords
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Search is **hybrid**: keyword (FTS5/BM25) and vector (cosine) candidates are blended with
|
|
84
|
+
[Reciprocal Rank Fusion](https://learn.microsoft.com/azure/search/hybrid-search-ranking),
|
|
85
|
+
so you get the precision of keywords and the recall of embeddings. Bring your own embedder
|
|
86
|
+
(OpenAI, a local model, anything) by passing `embedder=` — any object with `.dim` and
|
|
87
|
+
`.embed(texts) -> list[list[float]]`.
|
|
88
|
+
|
|
89
|
+
Optional ranking boosts:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
mem = Memory("agent.db", recency_weight=0.5, importance_weight=0.3)
|
|
93
|
+
mem.add("Critical: API key rotates on the 1st", importance=3.0)
|
|
94
|
+
mem.search("api key", recency_weight=1.0) # per-call override
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Namespaces
|
|
98
|
+
|
|
99
|
+
Isolate memories per user, per agent, or per session with a namespace:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
alice = Memory("app.db", namespace="user:alice")
|
|
103
|
+
bob = Memory("app.db", namespace="user:bob") # same file, isolated memories
|
|
104
|
+
alice.add("prefers metric units")
|
|
105
|
+
bob.search("units") # never sees Alice's memories
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## As an MCP server
|
|
109
|
+
|
|
110
|
+
Give Claude (or any MCP client) persistent, searchable memory — an embeddings-capable
|
|
111
|
+
alternative to the official keyword-only JSONL memory server:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install "agentrecall[mcp]"
|
|
115
|
+
agentrecall serve --db ~/.agent-memory.db
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```jsonc
|
|
119
|
+
// Claude Desktop / Claude Code MCP config
|
|
120
|
+
{
|
|
121
|
+
"mcpServers": {
|
|
122
|
+
"memory": {
|
|
123
|
+
"command": "agentrecall",
|
|
124
|
+
"args": ["serve", "--db", "/Users/me/.agent-memory.db"]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Tools exposed: `remember`, `recall`, `forget`, `list_memories`, `memory_stats`.
|
|
131
|
+
|
|
132
|
+
## CLI
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
agentrecall add "Deadline is July 7" --tags project --importance 2
|
|
136
|
+
agentrecall search "when is the deadline" -k 3
|
|
137
|
+
agentrecall list --limit 10
|
|
138
|
+
agentrecall stats
|
|
139
|
+
agentrecall forget --keep-last 1000 # prune to the newest 1000 per namespace
|
|
140
|
+
agentrecall export --format md > memories.md
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Every command honours `--db`, `--namespace`, and the `AGENTRECALL_DB` /
|
|
144
|
+
`AGENTRECALL_NAMESPACE` / `AGENTRECALL_EMBEDDINGS` environment variables.
|
|
145
|
+
|
|
146
|
+
## API at a glance
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
mem.add(content, *, tags=None, metadata=None, importance=1.0, namespace=None) -> MemoryRecord
|
|
150
|
+
mem.add_many([str | dict, ...]) -> list[MemoryRecord]
|
|
151
|
+
mem.search(query, *, k=5, namespace=None, tags=None,
|
|
152
|
+
recency_weight=None, importance_weight=None) -> list[MemoryHit]
|
|
153
|
+
mem.get(id) / mem.update(id, ...) / mem.delete(id)
|
|
154
|
+
mem.all(*, namespace=None, tags=None, limit=None, offset=0) -> list[MemoryRecord]
|
|
155
|
+
mem.count(*, namespace=None) -> int
|
|
156
|
+
mem.forget(*, before=None, namespace=None, keep_last=None) -> int # deleted count
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`tags` filtering matches memories containing **all** of the requested tags.
|
|
160
|
+
|
|
161
|
+
## The database is just SQLite
|
|
162
|
+
|
|
163
|
+
No magic. Open it with anything:
|
|
164
|
+
|
|
165
|
+
```sql
|
|
166
|
+
sqlite3 agent.db "SELECT id, content, importance, created_at FROM memories ORDER BY created_at DESC LIMIT 5;"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Schema: a `memories` table (with JSON `tags`/`metadata` columns), an FTS5 index kept in
|
|
170
|
+
sync by triggers, and — only in semantic mode — a `sqlite-vec` vector table. See
|
|
171
|
+
[`SPEC.md`](SPEC.md) for the full contract.
|
|
172
|
+
|
|
173
|
+
## Scope & limits (honest defaults)
|
|
174
|
+
|
|
175
|
+
- **Agent-scale, not web-scale.** sqlite-vec uses a linear scan (no ANN index yet) — great
|
|
176
|
+
for thousands of memories per namespace, not millions of RAG chunks.
|
|
177
|
+
- **Sync, single-process.** Use one `Memory` per thread. `sqlite3` is fast and local; there
|
|
178
|
+
is no async API by design.
|
|
179
|
+
- **No knowledge graph / entity-relation modeling.** That's [Cognee](https://github.com/topoteretes/cognee)
|
|
180
|
+
and [Zep](https://www.getzep.com/)'s lane. `agentrecall` stays small on purpose.
|
|
181
|
+
- **No automatic summarization.** Memories are stored verbatim. If you want LLM-distilled
|
|
182
|
+
memories, distill before you `add()` — your call, your model, your tokens.
|
|
183
|
+
- **`add()` is append-only.** Re-adding the same text creates a new row (no content
|
|
184
|
+
dedupe). To revise a memory, keep the integer id returned by `add()` and call
|
|
185
|
+
`update(id, ...)` / `delete(id)`.
|
|
186
|
+
- **`forget(before=..., keep_last=...)` deletes the union** — rows older than `before`
|
|
187
|
+
*or* beyond the newest `keep_last` per namespace. With neither argument it's a no-op
|
|
188
|
+
(to wipe a store, just delete the file).
|
|
189
|
+
|
|
190
|
+
## Development
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
pip install -e ".[dev]"
|
|
194
|
+
pytest
|
|
195
|
+
ruff check .
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The keyword (FTS-only) test suite runs with **zero third-party dependencies**. Semantic
|
|
199
|
+
tests are skipped automatically when the `[semantic]` extra isn't installed.
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT © 2026 Shaxzodbek Sobirov / Blaze
|