SQLite memory provider for axor-core
Project description
axor-memory-sqlite
SQLite memory provider for axor-core.
Persistent cross-session memory for governed agents. Zero extra dependencies — uses Python's built-in sqlite3.
Installation
pip install axor-memory-sqlite
Requires axor-core >= 0.1.0.
Quick Start
import axor_claude
from axor_core import AgentDefinition, AgentDomain, FragmentValue, MemoryFragment
from axor_memory_sqlite import SQLiteMemoryProvider
provider = SQLiteMemoryProvider("~/.axor/memory.db")
session = axor_claude.make_session(
api_key="sk-ant-...",
agent_def=AgentDefinition(
name="my-agent",
domain=AgentDomain.CODING,
personality="You are an expert Python engineer.",
memory_namespaces=("my-agent",), # loaded at every session start
),
memory_provider=provider,
)
result = await session.run("refactor the auth module")
# save what you want to remember next time
await provider.save([
MemoryFragment(
namespace="my-agent",
key="auth_module_status",
content="Auth module refactored to use JWT. Entry point: auth/jwt.py.",
value=FragmentValue.KNOWLEDGE,
),
])
FragmentValue — what gets remembered how
Every MemoryFragment has a value that controls how the compressor treats it when it appears in ContextView:
| Value | Compressor behavior | Typical use |
|---|---|---|
PINNED |
Never touched — survives all turns | User preferences, system rules, agent personality |
KNOWLEDGE |
Dedup + error collapse only — no truncation | Project docs, domain context, API specs |
WORKING |
Normal compression pipeline | Task findings, recent tool results |
EPHEMERAL |
Aggressive compression — evicted first | Debug output, one-turn scratch |
Eviction priority: EPHEMERAL → WORKING → KNOWLEDGE → PINNED (never evicted).
API
SQLiteMemoryProvider(db_path)
from axor_memory_sqlite import SQLiteMemoryProvider
provider = SQLiteMemoryProvider("~/.axor/memory.db") # persistent
provider = SQLiteMemoryProvider(":memory:") # in-memory, tests only
All methods are async. I/O runs in a thread pool — async callers are never blocked.
save(fragments)
Upsert by (namespace, key) — existing fragments are overwritten:
await provider.save([
MemoryFragment(
namespace="my-agent",
key="project_stack",
content="FastAPI + async SQLAlchemy + PostgreSQL",
value=FragmentValue.PINNED,
tags=["stack", "tech"],
),
])
load(query)
from axor_core import MemoryQuery, FragmentValue
# load all from namespace, pinned first
fragments = await provider.load(MemoryQuery(
namespaces=("my-agent",),
max_results=20,
))
# filter by value
pinned = await provider.load(MemoryQuery(
namespaces=("my-agent",),
values=(FragmentValue.PINNED, FragmentValue.KNOWLEDGE),
max_results=10,
))
Results are ordered by priority (PINNED first) then by accessed_at descending.
delete(namespace, keys)
n = await provider.delete("my-agent", ["stale_key_1", "stale_key_2"])
print(f"deleted {n} fragments")
evict(namespace, values, max_age_seconds)
Remove stale fragments by value and/or age:
# evict all ephemeral fragments
await provider.evict("my-agent", values=(FragmentValue.EPHEMERAL,))
# evict working fragments older than 24 hours
await provider.evict(
"my-agent",
values=(FragmentValue.WORKING,),
max_age_seconds=86400,
)
namespaces()
ns = await provider.namespaces()
# ["my-agent", "shared", "project-x"]
close()
await provider.close()
Call on shutdown. The provider can be used as an async context manager in tests:
async with SQLiteMemoryProvider(":memory:") as provider:
await provider.save([...])
Namespaces
Namespaces are logical groupings — they do not require explicit creation. A namespace exists as soon as you save a fragment with that name.
Recommended pattern:
| Namespace | Content |
|---|---|
{agent-name} |
Agent-specific memory — not shared |
shared |
Shared across all agents in a project |
project:{name} |
Project-specific facts |
user:{id} |
Per-user preferences |
# agent reads from its own namespace + shared
agent = AgentDefinition(
name="billing-agent",
memory_namespaces=("billing-agent", "shared"),
)
Schema
CREATE TABLE memory_fragments (
namespace TEXT NOT NULL,
key TEXT NOT NULL,
content TEXT NOT NULL,
value TEXT NOT NULL DEFAULT 'working',
token_count INTEGER NOT NULL DEFAULT 0,
tags TEXT NOT NULL DEFAULT '[]', -- JSON array
created_at TEXT NOT NULL,
accessed_at TEXT NOT NULL,
metadata TEXT NOT NULL DEFAULT '{}', -- JSON object
PRIMARY KEY (namespace, key)
);
The database file is a standard SQLite file — readable with any SQLite tool.
Testing
Use :memory: for tests — no file created, no cleanup needed:
import pytest
from axor_memory_sqlite import SQLiteMemoryProvider
from axor_core import MemoryFragment, FragmentValue, MemoryQuery
@pytest.mark.asyncio
async def test_memory():
p = SQLiteMemoryProvider(":memory:")
await p.save([
MemoryFragment(namespace="test", key="k1",
content="hello", value=FragmentValue.WORKING),
])
results = await p.load(MemoryQuery(namespaces=("test",), max_results=5))
assert len(results) == 1
assert results[0].content == "hello"
await p.close()
Requirements
- Python 3.11+
axor-core >= 0.1.0- No extra dependencies — uses stdlib
sqlite3+asyncio
License
MIT
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 axor_memory_sqlite-0.1.0.tar.gz.
File metadata
- Download URL: axor_memory_sqlite-0.1.0.tar.gz
- Upload date:
- Size: 6.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb568d54991face12c8e77814d4d0151a151fdb259de8debeaf1b5982c491979
|
|
| MD5 |
0eb66b1e5ec9690fcdf06a39f15c8603
|
|
| BLAKE2b-256 |
fb811efcc84c73eadba4c67f80f6919cb0919f70ebb2e33b4de50ee6021bc691
|
Provenance
The following attestation bundles were made for axor_memory_sqlite-0.1.0.tar.gz:
Publisher:
ci.yml on Bucha11/axor-memory-sqlite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
axor_memory_sqlite-0.1.0.tar.gz -
Subject digest:
eb568d54991face12c8e77814d4d0151a151fdb259de8debeaf1b5982c491979 - Sigstore transparency entry: 1293589548
- Sigstore integration time:
-
Permalink:
Bucha11/axor-memory-sqlite@d00d930d964869fe539fec545b2f709f363c9598 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Bucha11
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@d00d930d964869fe539fec545b2f709f363c9598 -
Trigger Event:
push
-
Statement type:
File details
Details for the file axor_memory_sqlite-0.1.0-py3-none-any.whl.
File metadata
- Download URL: axor_memory_sqlite-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
299e7cfd7ce83bb6a3d2cb0cf1374a975471e12e60d8f4f365bf3a41565bba8f
|
|
| MD5 |
25a85d48597fa76a8afbf60269bc3e8d
|
|
| BLAKE2b-256 |
7c6cc99576bbfeec6533ecf7bedecc614fce5336203c6c72bae4d55d8a99638c
|
Provenance
The following attestation bundles were made for axor_memory_sqlite-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on Bucha11/axor-memory-sqlite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
axor_memory_sqlite-0.1.0-py3-none-any.whl -
Subject digest:
299e7cfd7ce83bb6a3d2cb0cf1374a975471e12e60d8f4f365bf3a41565bba8f - Sigstore transparency entry: 1293589565
- Sigstore integration time:
-
Permalink:
Bucha11/axor-memory-sqlite@d00d930d964869fe539fec545b2f709f363c9598 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Bucha11
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@d00d930d964869fe539fec545b2f709f363c9598 -
Trigger Event:
push
-
Statement type: