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.
@@ -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