Skip to content

Memory

MemoryProvider

Bases: ABC

Pluggable memory backend for AI context construction.

Implement this ABC to control how conversation history is retrieved for AI generation. The library ships with :class:SlidingWindowMemory (simple last-N events) as the default.

Lifecycle methods ingest, clear, and close are concrete no-ops so that simple implementations only need to override retrieve.

name property

name

Human-readable provider name.

recent_events_window property

recent_events_window

How many recent events this provider may read from RoomContext.

The framework uses the largest window across a room's bound channels to decide how many events to load into RoomContext.recent_events — so a provider that windows to last-N should report N (avoids loading and deserialising the whole ceiling every turn). Defaults to the full pool for providers that don't trim by event count (e.g. token-aware ones).

retrieve abstractmethod async

retrieve(room_id, current_event, context, *, channel_id=None)

Retrieve context for AI generation.

Parameters:

Name Type Description Default
room_id str

The room being processed.

required
current_event RoomEvent

The event that triggered AI generation.

required
context RoomContext

Full room context including recent events, bindings, and participants.

required
channel_id str | None

The AI channel requesting memory (useful when multiple AI channels share a room).

None

Returns:

Name Type Description
A MemoryResult

class:MemoryResult with messages and/or events to include

MemoryResult

in the AI context.

ingest async

ingest(room_id, event, *, channel_id=None)

Ingest an event into memory (optional).

Stateful providers (e.g. summarization, vector stores) can override this to update their internal state as events arrive. The default implementation is a no-op.

clear async

clear(room_id)

Clear all stored memory for a room (optional).

close async

close()

Release resources held by the provider (optional).

MemoryResult dataclass

MemoryResult(messages=list(), events=list(), notes=list(), speakers=list())

Result returned by a memory provider.

Memory providers can return pre-built AI messages (e.g. summaries, synthetic context) and/or raw room events that AIChannel will convert using its own content extraction logic (preserving vision support).

A provider may populate any of the fields. messages are prepended first, then events are converted and appended.

notes is what the provider retrieved for the current turn only (knowledge passages, say). It changes from one turn to the next, so the channel carries it with the turn's notes, after the input, rather than in the history a provider caches (RFC §20.2). A provider that wraps another and rebuilds its result carries the inner notes (dataclasses.replace keeps them).

speakers is the labels messages name participants by, as the runtime gives them (a summary's lines, Alice, @sms1): the channel counts them toward labelling the turns that follow, so a conversation a summary named several people in labels its turns (RFC §6.4).

SlidingWindowMemory

SlidingWindowMemory(max_events=50)

Bases: MemoryProvider

Return the most recent events from the room context.

This replicates the original AIChannel behavior of slicing context.recent_events[-max_events:].

BudgetAwareMemory

BudgetAwareMemory(inner, max_context_tokens, safety_margin_ratio=0.15, min_events=3, reserved_tokens=0)

Bases: _MemoryWrapper

Wraps a MemoryProvider and trims results to fit within a token budget.

The history's budget is what is left of the window once everything else in it is paid for — see :func:roomkit.memory.token_estimator.history_budget, which owns the arithmetic. Read for an AI channel's turn, the rest of the turn is what the channel measured (:func:current_turn_footprint, RFC §20): its input is reserved, and its reply budget when larger than the safety margin. reserved_tokens is a floor on that input (system prompt, tool schemas, the channel's notes), for a caller that knows a part the channel cannot; it is not added to the measure. The injected messages, the memory's notes and the current turn this wrapper passes through are measured here. A current turn that alone exceeds a known window raises a non-retryable ProviderError(context_overflow=True) before retrieval or generation: trimming history cannot make that message fit.

Events are trimmed from the oldest, preserving the most recent conversation.

The one way the result can still exceed the budget is min_events: the most recent few events are kept even when they don't fit, because returning an empty history is worse than returning one that needs compaction.

The turn's footprint

TurnFootprint dataclass

TurnFootprint(input_tokens, reply_tokens)

What a turn takes of the context window besides its history (RFC §20).

Measured by the AI channel as round 0 will send it, before it reads its memory. What a hook adds to the context afterwards is not in it.

Attributes:

Name Type Description
input_tokens int

The system prompt, the tools declared (Tool Search's collapse and the re-read tool included) and the notes the channel adds to the turn's input (the room's plan, the digest of the tools already used, the speaker attribution).

reply_tokens int

The reply budget the turn requests; 0 when the channel sets none and the provider applies its own.

current_turn_footprint

current_turn_footprint()

What the turn takes of the context window besides its history (RFC §20).

Measured by the AI channel before it reads its memory: a memory reading the room for a turn sizes the history to what the window leaves. Readable from that read on, through the turn's BEFORE_AI_GENERATION hooks. None outside an AI channel's turn, before the channel measured it, and in a tool handler, whose loop context is the call's own.

SummarizingMemory

SummarizingMemory(inner, provider, max_context_tokens, *, tier1_ratio=0.5, tier2_ratio=0.85, truncate_chars=2000, summary_max_tokens=1000, min_events=5, summary_cache_ttl_seconds=1800.0)

Bases: _MemoryWrapper

Two-tier memory provider that proactively manages context budget.

Wraps an inner MemoryProvider (typically SlidingWindowMemory) and applies two tiers of context reduction:

  • Tier 1 — truncate large event bodies in older messages when total estimated tokens exceed tier1_ratio * max_context_tokens.
  • Tier 2 — summarize older events via a lightweight AI provider when total tokens still exceed tier2_ratio * max_context_tokens.

Parameters:

Name Type Description Default
inner MemoryProvider

The wrapped memory provider.

required
provider AIProvider

A lightweight AI provider for summarization (e.g. Haiku).

required
max_context_tokens int

Total token budget for the AI context.

required
tier1_ratio float

Fraction of budget that triggers tier-1 truncation.

0.5
tier2_ratio float

Fraction of budget that triggers tier-2 summarization.

0.85
truncate_chars int

Max characters per old event body in tier 1.

2000
summary_max_tokens int

Max tokens for the LLM summary response.

1000
min_events int

Minimum events to keep before summarizing (tier 2).

5
summary_cache_ttl_seconds float

TTL for cached summaries.

1800.0

RetrievalMemory

RetrievalMemory(sources, inner, *, max_results=5, min_query_length=3)

Bases: _MemoryWrapper

Wraps an inner provider and enriches context with knowledge sources.

On retrieve, queries all configured knowledge sources concurrently, merges results by score, and returns the passages as the turn's note (MemoryResult.notes), each in a <knowledge> block: they ride the turn's input, not the history a provider caches (RFC §20.2).

On ingest, forwards to the inner provider and indexes text content in all knowledge sources.

Parameters:

Name Type Description Default
sources list[KnowledgeSource]

Knowledge sources to query on each retrieval.

required
inner MemoryProvider

The wrapped memory provider for conversation history.

required
max_results int

Maximum knowledge results to include in context.

5
min_query_length int

Minimum query length to trigger search.

3

MockMemoryProvider

MockMemoryProvider(messages=None, events=None, notes=None)

Bases: MemoryProvider

Mock memory provider that records calls and returns configured results.

Example::

mock = MockMemoryProvider(
    messages=[AIMessage(role="system", content="Summary of conversation")],
)
result = await mock.retrieve("room1", event, context)
assert len(mock.retrieve_calls) == 1