Skip to content

keelgate.memory

Stability of each symbol (stable or provisional) is listed in the API contract. Narrative and semantics are in the integration contract.

Layered memory: working, episodic, semantic and procedural.

Attribution

Bases: BaseModel

Who wrote a version, and under which trace.

ConcurrentWriteError

Bases: MemoryStoreError

Another writer created the next version first. Re-read and retry.

Embedder

Bases: Protocol

Turns text into a vector of a fixed size (dim) for semantic search.

EmbeddingError

Bases: Exception

The embedding service failed or returned something unusable.

EpisodicMemory

Bases: _TierMemory

What the agent decided and what came of it. occurred_at cannot be in the future.

HashEmbedder

A deterministic bag-of-words embedder with no model and no network.

It hashes each word into one of dim buckets (with a hash-derived sign, which keeps unrelated words from piling up on one side) and L2-normalises. Texts that share words land close together, which is enough to test retrieval, as_of filtering and tenant isolation exactly. It captures no meaning beyond word overlap: use a real embedding model, behind the same protocol, for production retrieval quality.

InvalidMemoryWriteError

Bases: MemoryStoreError

The write is malformed for its tier.

Memory

Bases: Protocol

The interface every tier implements. All reads take an explicit as_of.

MemoryBackend

Bases: Protocol

Storage for memory records.

Append-only and bitemporal: a write is a new version, never an edit, and a read honours both when a fact was true and when it was recorded.

latest

latest(
    tenant_id: str, record_id: str
) -> MemoryRecord | None

The newest version regardless of time. Writers use this; readers use as_of.

MemoryRecord

Bases: BaseModel

One version of one memory: its content, who wrote it and under which trace, when it was recorded, and for semantic facts the window in which it is valid.

to_context_item

to_context_item(*, priority: int = 0) -> ContextItem

This record as an UNTRUSTED context item, dated when it became known.

MemoryStoreError

Bases: Exception

Base class for memory failures.

MemoryTier

Bases: StrEnum

The four layers of memory: working, episodic, semantic and procedural.

OllamaEmbedder

Bases: _HttpEmbedder

Embeds text with a local Ollama server (/api/embed). The vector size is checked on every response.

OpenAICompatibleEmbedder

Bases: _HttpEmbedder

Embeds text with OpenAI or any server speaking the OpenAI /embeddings format.

Covers vLLM and LM Studio. The vector size is checked on every response.

__init__

__init__(
    *,
    model: str,
    dim: int,
    base_url: str = "https://api.openai.com/v1",
    api_key: str | None = None,
    send_dimensions: bool = False,
    client: Client | None = None,
    timeout: float = 60.0,
) -> None

send_dimensions asks the model for dim outputs (OpenAI text-embedding-3 only).

PostgresMemoryBackend

Shared memory on Postgres with the pgvector extension.

Needs psycopg (extra keelgate[server]) and a database where CREATE EXTENSION vector has been run, which the dev stack does on first start. The Python pgvector package is not needed: vectors travel as text and are cast.

close

close() -> None

Connections are per-operation; nothing is held open.

ProceduralMemory

Bases: _TierMemory

Versioned skills and playbooks, addressed by name.

publish

publish(
    name: str, body: str, *, attribution: Attribution
) -> MemoryRecord

Publish a new version of the skill name (the first, if it is new).

skill

skill(name: str, *, as_of: datetime) -> MemoryRecord | None

The version of name that was current at as_of.

RecordNotFoundError

Bases: MemoryStoreError

No such record. Also what another tenant's record looks like: absent.

SemanticMemory

Bases: _TierMemory

Facts with validity windows, retrieved by embedding similarity.

A fact is returned at as_of only if it was recorded by then and as_of falls inside [valid_from, valid_to). A correction recorded today does not rewrite what was known last week.

end_fact

end_fact(
    record_id: str,
    valid_to: datetime,
    *,
    attribution: Attribution,
) -> MemoryRecord

Say a fact stopped holding at valid_to. Earlier reads are unaffected.

SqliteMemoryBackend

SQLite storage for memory: append-only, bitemporal, tenant-scoped, with exact vector search.

Good for local use and tests.

WorkingMemory

Bases: _TierMemory

Scratch space for one run. Keyed; writing a key again creates a new version.

cosine

cosine(a: Sequence[float], b: Sequence[float]) -> float

Cosine similarity; 0.0 when either vector is all zeros.