Skip to main content

SQLite memory provider for axor-core

Project description

axor-memory-sqlite

CI PyPI Python License: MIT

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: EPHEMERALWORKINGKNOWLEDGEPINNED (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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

axor_memory_sqlite-0.1.0.tar.gz (6.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

axor_memory_sqlite-0.1.0-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

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

Hashes for axor_memory_sqlite-0.1.0.tar.gz
Algorithm Hash digest
SHA256 eb568d54991face12c8e77814d4d0151a151fdb259de8debeaf1b5982c491979
MD5 0eb66b1e5ec9690fcdf06a39f15c8603
BLAKE2b-256 fb811efcc84c73eadba4c67f80f6919cb0919f70ebb2e33b4de50ee6021bc691

See more details on using hashes here.

Provenance

The following attestation bundles were made for axor_memory_sqlite-0.1.0.tar.gz:

Publisher: ci.yml on Bucha11/axor-memory-sqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file axor_memory_sqlite-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for axor_memory_sqlite-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 299e7cfd7ce83bb6a3d2cb0cf1374a975471e12e60d8f4f365bf3a41565bba8f
MD5 25a85d48597fa76a8afbf60269bc3e8d
BLAKE2b-256 7c6cc99576bbfeec6533ecf7bedecc614fce5336203c6c72bae4d55d8a99638c

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page