actrone_memory package

Subpackages

Submodules

Module contents

actrone-memory, Two-tier persistent memory for AI agents.

Local-first by default: MemoryManager.create() runs with zero external services and no API key (in-process store, plus the best local embedder available: in-process ONNX if the onnx extra is installed, then sentence-transformers, then a dependency-free lexical hashing fallback). Set backend="redis_qdrant" and an embedding provider for the durable path.

class actrone_memory.MemoryManager(l1, l2, embedder, config, summariser=None, extractor=None, reranker=None)[source]

Bases: object

Two-tier persistent agent memory: Redis L1 (hot) + Qdrant L2 (cold semantic).

Do not instantiate directly. Use MemoryManager.create() or the create_memory_manager() context manager.

Usage:

mm = await MemoryManager.create()
await mm.store_turn(agent_id, session_id, user_msg, assistant_msg)
ctx = await mm.retrieve_context(agent_id, session_id, query, token_budget=4096)
await mm.close()

Or let create_memory_manager() close it for you:

async with create_memory_manager() as mm:
    ...
Parameters:
property relevance_threshold: float

The admission threshold applied to long-term memories.

config.relevance_threshold when set, else the embedder’s calibrated threshold, else the library default.

async store_turn(agent_id, session_id, user_message, assistant_message, tool_results=None)[source]

Persist a conversation turn to Redis L1.

Also triggers background summarisation to Qdrant L2 once the session reaches summarise_after_turns turns.

Parameters:
  • agent_id (str) – Unique identifier for the agent (e.g. "support-bot").

  • session_id (str) – Unique identifier for the conversation session.

  • user_message (str) – The user’s raw message text.

  • assistant_message (str) – The agent’s response text.

  • tool_results (list[ToolResult] | None) – Optional tool call results from this turn.

Returns:

The turn ID (UUID string).

Raises:
Return type:

str

async retrieve_context(agent_id, session_id, query, token_budget)[source]

Fetch relevant context for the next LLM call using the 4-phase pipeline.

Phase 1, Parallel fetch: Redis L1 (recent turns) + Qdrant L2 (semantic search) run concurrently to minimise latency (<50 ms P99).

Phase 2, Budget allocation: the token budget is divided between system prompt, episodic memory, session turns, and the current turn using the fractions in MemoryConfig.

Phase 3, Relevance ranking: Qdrant results are filtered at the configured threshold and re-ranked by 0.7 × cosine_similarity + 0.3 × recency_score.

Phase 4, Priority pruning: if results exceed the allocated budget, oldest session turns are dropped first, then lowest-ranked memories. The system-prompt budget is never consumed by this method.

Parameters:
  • agent_id (str) – Agent identifier.

  • session_id (str) – Session identifier.

  • query (str) – The user’s current message; drives L2 semantic search.

  • token_budget (int) – Total tokens available for context. Must be > 0.

Returns:

RetrievedContext with recent_turns, episodic_memories, and budget stats.

Raises:
Return type:

RetrievedContext

async inject_memory(agent_id, content, importance=0.8, session_id='injected', topic_tags=None, source='injected', sensitivity='none')[source]

Write a fact directly into L2 long-term memory.

Use this to seed an agent with background knowledge before a conversation starts, e.g. user preferences, company policies, domain facts.

Parameters:
  • agent_id (str) – The agent that should have access to this memory.

  • content (str) – Text of the memory. Write it as a clear, self-contained sentence.

  • importance (float) – Score from 0.0 to 1.0. Higher values surface this memory more readily. Recommended ≥ 0.8 for facts you always want recalled.

  • session_id (str) – Label for where this memory came from. Defaults to "injected".

  • topic_tags (list[str] | None) – Optional keywords describing the memory topic.

  • source (str) – Provenance attribution, where this fact originated (e.g. "injected", "import:crm", "tool:web_search").

  • sensitivity (Literal['none', 'low', 'pii', 'sensitive']) – PII/sensitivity classification for governance and right-to-erasure ("none" | "low" | "pii" | "sensitive").

Returns:

The memory ID (UUID). Save this to delete the memory later.

Raises:
Return type:

str

async delete_memory(agent_id, memory_id)[source]

Permanently remove a memory from Qdrant L2 by ID.

Parameters:
  • agent_id (str) – Agent that owns the memory (used for audit logging).

  • memory_id (str) – ID returned by inject_memory() or from search_memories().

Raises:
Return type:

None

async erase_agent_memories(agent_id, session_id=None)[source]

Local right-to-erasure, irreversibly delete an agent’s long-term memories.

This is the governance seed that graduates to hosted provable erasure: in the OSS library it performs a hard local delete. If session_id is given, the session’s short-term (L1) turns are cleared too; otherwise only the durable L2 store is wiped (L1 turns are ephemeral and expire on their TTL).

Parameters:
  • agent_id (str) – The agent whose long-term memories to erase.

  • session_id (str | None) – Optional session whose short-term turns to also clear.

Raises:
Return type:

None

async clear_session(agent_id, session_id)[source]

Delete all Redis L1 turns for a session.

Long-term Qdrant memories (summaries, injected facts) are NOT deleted, they persist across sessions by design.

Raises:
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

None

async search_memories(agent_id, query, limit=10)[source]

Semantic search over Qdrant L2 for a given agent.

Results are ranked by the same formula used in retrieve_context(): 0.7 × cosine_similarity + 0.3 × recency_score.

Parameters:
  • agent_id (str) – Agent whose memories to search.

  • query (str) – Search query in plain text.

  • limit (int) – Maximum number of results to return.

Returns:

List of MemoryEntry objects, sorted by descending relevance score.

Raises:
Return type:

list[MemoryEntry]

async get_session_metadata(agent_id, session_id)[source]

Return basic stats about a session (turn count, created_at, last_active).

Returns None if the session does not exist or has expired from Redis.

Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

SessionMetadata | None

async get_recent_turns(agent_id, session_id, n=None)[source]

Return recent session turns, oldest first, capped at n.

The raw history read that framework memory adapters build on (for example a LangChain BaseChatMessageHistory or a LlamaIndex memory), so they do not have to reach into the L1 store directly. Defaults to everything L1 still retains.

Raises:
Parameters:
  • agent_id (str)

  • session_id (str)

  • n (int | None)

Return type:

list[Turn]

async extract_memories(agent_id, session_id, n=None)[source]

Extract durable facts from a session’s recent turns and store them.

Turns → atomic facts (content_type="fact", source="extracted"), each with an LLM-classified sensitivity. This is the “credible beyond turn storage” capability; it is LLM-gated, a FactExtractor must be configured (MemoryConfig.extract_facts=True with the OpenAI provider), otherwise a ConfigurationError is raised.

Parameters:
  • agent_id (str) – Agent identifier.

  • session_id (str) – Session whose turns to mine for facts.

  • n (int | None) – How many recent turns to consider (defaults to the summarise window).

Returns:

The memory IDs of the stored facts (empty if nothing durable was found).

Raises:
Return type:

list[str]

async classmethod create(config=None, *, l1=None, l2=None, embedder=None, extractor=None, reranker=None)[source]

Build a ready MemoryManager for the configured backend.

The default backend is "memory", a zero-service, in-process store, and the default embedding provider is "local", which picks the best local embedder available (in-process ONNX, then sentence-transformers, then a dependency-free lexical hashing fallback). So create() needs no Redis, no Qdrant, and no API key (parity with the TypeScript on-ramp). Pass embedding_provider="hashing" to force the fallback and skip any model download. Set backend="redis_qdrant" (env ACTRONE_BACKEND=redis_qdrant) for the durable, horizontally-scalable production path.

Reads configuration from environment variables when config is None.

Parameters:
  • config (MemoryConfig | None) – Settings to use. Read from the environment when None.

  • l1 (L1Store | None) – Custom hot-tier store satisfying the L1Store protocol.

  • l2 (L2Store | None) – Custom long-term store satisfying the L2Store protocol.

  • embedder (Embedder | None) – Custom Embedder, used instead of the configured provider.

  • extractor (FactExtractor | None) – Custom FactExtractor, used instead of the OpenAI one the config would build. Lets you extract facts without an OpenAI key.

  • reranker (CrossEncoderReranker | None) – Custom reranker, used instead of the one rerank_enabled builds.

Return type:

MemoryManager

Only Redis and Qdrant adapters ship with this package. l1 / l2 are the supported way to run any other engine (pgvector, Weaviate, Valkey, and so on) without constructing the manager by hand: anything satisfying the protocol works. Whatever you inject is used as-is, and the corresponding backend is not built or connected, so injecting both stores never opens a Redis or Qdrant connection. You own the lifecycle of an injected store; close() still calls its close().

Raises:
Parameters:
Return type:

MemoryManager

async close()[source]

Close all connections to Redis and Qdrant.

Drains in-flight background tasks (e.g. session summarisation) up to MemoryConfig.shutdown_grace_seconds. Tasks that have not finished within the grace window are cancelled so the process can exit.

Return type:

None

class actrone_memory.MemoryConfig(_case_sensitive=None, _nested_model_default_partial_update=None, _env_prefix=None, _env_prefix_target=None, _env_file=WindowsPath('.'), _env_file_encoding=None, _env_ignore_empty=None, _env_nested_delimiter=None, _env_nested_max_split=None, _env_parse_none_str=None, _env_parse_enums=None, _cli_prog_name=None, _cli_parse_args=None, _cli_settings_source=None, _cli_parse_none_str=None, _cli_hide_none_type=None, _cli_avoid_json=None, _cli_enforce_required=None, _cli_use_class_docs_for_groups=None, _cli_exit_on_error=None, _cli_prefix=None, _cli_flag_prefix_char=None, _cli_implicit_flags=None, _cli_ignore_unknown_args=None, _cli_kebab_case=None, _cli_shortcuts=None, _secrets_dir=None, _build_sources=None, *, backend='memory', redis_url='redis://localhost:6379', qdrant_url='http://localhost:6333', qdrant_api_key=None, redis_max_connections=10, redis_socket_timeout=5.0, redis_socket_connect_timeout=5.0, qdrant_timeout=10.0, embedding_provider='local', openai_api_key=None, embedding_model='text-embedding-3-small', embedding_dimensions=1536, hashing_dimensions=256, embedding_cache_ttl_seconds=604800, summarisation_model='gpt-4o-mini', session_ttl_hours=24, max_session_turns=50, qdrant_collection='agent_memories', max_episodic_memories=500, relevance_threshold=None, relevance_weight=0.7, recency_weight=0.3, hybrid_retrieval=True, rerank_enabled=False, rerank_model='Xenova/ms-marco-MiniLM-L-6-v2', rerank_top_k=20, extract_facts=False, auto_summarise=True, summarise_after_turns=20, summarise_cooldown_seconds=300, strict_background_errors=False, shutdown_grace_seconds=30.0, token_counter='heuristic', budget_fraction_system=0.3, budget_fraction_episodic=0.25, budget_fraction_session=0.35, budget_fraction_current_turn=0.1)[source]

Bases: BaseSettings

All configuration for actrone-memory.

Values are read from environment variables with the ACTRONE_ prefix. You can also pass values directly when constructing this object.

Required only when embedding_provider="openai":

ACTRONE_OPENAI_API_KEY

All other settings have sensible defaults. The default provider is "local", a local-first, zero-egress dense embedder that needs no API key (see below).

Parameters:
  • _case_sensitive (bool | None)

  • _nested_model_default_partial_update (bool | None)

  • _env_prefix (str | None)

  • _env_prefix_target (EnvPrefixTarget | None)

  • _env_file (DotenvType | None)

  • _env_file_encoding (str | None)

  • _env_ignore_empty (bool | None)

  • _env_nested_delimiter (str | None)

  • _env_nested_max_split (int | None)

  • _env_parse_none_str (str | None)

  • _env_parse_enums (bool | None)

  • _cli_prog_name (str | None)

  • _cli_parse_args (bool | list[str] | tuple[str, ...] | None)

  • _cli_settings_source (CliSettingsSource[Any] | None)

  • _cli_parse_none_str (str | None)

  • _cli_hide_none_type (bool | None)

  • _cli_avoid_json (bool | None)

  • _cli_enforce_required (bool | None)

  • _cli_use_class_docs_for_groups (bool | None)

  • _cli_exit_on_error (bool | None)

  • _cli_prefix (str | None)

  • _cli_flag_prefix_char (str | None)

  • _cli_implicit_flags (bool | Literal['dual', 'toggle'] | None)

  • _cli_ignore_unknown_args (bool | None)

  • _cli_kebab_case (bool | Literal['all', 'no_enums'] | None)

  • _cli_shortcuts (Mapping[str, str | list[str]] | None)

  • _secrets_dir (PathType | None)

  • _build_sources (tuple[tuple[PydanticBaseSettingsSource, ...], dict[str, Any]] | None)

  • backend (Literal['memory', 'redis_qdrant'])

  • redis_url (str)

  • qdrant_url (str)

  • qdrant_api_key (SecretStr | None)

  • redis_max_connections (int)

  • redis_socket_timeout (float)

  • redis_socket_connect_timeout (float)

  • qdrant_timeout (float)

  • embedding_provider (Literal['openai', 'local', 'hashing'])

  • openai_api_key (SecretStr | None)

  • embedding_model (str)

  • embedding_dimensions (int)

  • hashing_dimensions (int)

  • embedding_cache_ttl_seconds (int)

  • summarisation_model (str)

  • session_ttl_hours (int)

  • max_session_turns (int)

  • qdrant_collection (str)

  • max_episodic_memories (int)

  • relevance_threshold (float | None)

  • relevance_weight (float)

  • recency_weight (float)

  • hybrid_retrieval (bool)

  • rerank_enabled (bool)

  • rerank_model (str)

  • rerank_top_k (int)

  • extract_facts (bool)

  • auto_summarise (bool)

  • summarise_after_turns (int)

  • summarise_cooldown_seconds (int)

  • strict_background_errors (bool)

  • shutdown_grace_seconds (float)

  • token_counter (Literal['heuristic', 'tiktoken'])

  • budget_fraction_system (float)

  • budget_fraction_episodic (float)

  • budget_fraction_session (float)

  • budget_fraction_current_turn (float)

model_config = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': '.env', 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'ACTRONE_', 'env_prefix_target': 'variable', 'extra': 'ignore', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['memory', 'redis_qdrant']
redis_url: str
qdrant_url: str
qdrant_api_key: SecretStr | None
redis_max_connections: int
redis_socket_timeout: float
redis_socket_connect_timeout: float
qdrant_timeout: float
embedding_provider: Literal['openai', 'local', 'hashing']
openai_api_key: SecretStr | None
embedding_model: str
embedding_dimensions: int
hashing_dimensions: int
embedding_cache_ttl_seconds: int
summarisation_model: str
session_ttl_hours: int
max_session_turns: int
qdrant_collection: str
max_episodic_memories: int
relevance_threshold: float | None
relevance_weight: float
recency_weight: float
hybrid_retrieval: bool
rerank_enabled: bool
rerank_model: str
rerank_top_k: int
extract_facts: bool
auto_summarise: bool
summarise_after_turns: int
summarise_cooldown_seconds: int
strict_background_errors: bool
shutdown_grace_seconds: float
token_counter: Literal['heuristic', 'tiktoken']
budget_fraction_system: float
budget_fraction_episodic: float
budget_fraction_session: float
budget_fraction_current_turn: float
validate_runtime()[source]

Validate settings that require cross-field checks.

Call this before opening connections. Raises ConfigurationError with a clear message if any required setting is missing or inconsistent.

Return type:

None

class actrone_memory.MemoryEntry(*, id=<factory>, agent_id, session_id, content, content_type, embedding=None, importance_score=0.5, topic_tags=<factory>, token_count=0, timestamp=<factory>, source_turn_ids=<factory>, source='unknown', sensitivity='none')[source]

Bases: BaseModel

Parameters:
  • id (str)

  • agent_id (str)

  • session_id (str)

  • content (str)

  • content_type (Literal['turn', 'summary', 'tool_result', 'injected', 'fact'])

  • embedding (list[float] | None)

  • importance_score (float)

  • topic_tags (list[str])

  • token_count (int)

  • timestamp (datetime)

  • source_turn_ids (list[str])

  • source (str)

  • sensitivity (Literal['none', 'low', 'pii', 'sensitive'])

id: str
agent_id: str
session_id: str
content: str
content_type: ContentType
embedding: list[float] | None
importance_score: float
topic_tags: list[str]
token_count: int
timestamp: datetime
source_turn_ids: list[str]
source: str
sensitivity: Sensitivity
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class actrone_memory.RetrievedContext(*, recent_turns, episodic_memories, total_tokens_used, token_budget, retrieval_duration_ms)[source]

Bases: BaseModel

Output of MemoryManager.retrieve_context, ready to inject into an LLM prompt.

Parameters:
recent_turns: list[Turn]
episodic_memories: list[MemoryEntry]
total_tokens_used: int
token_budget: int
retrieval_duration_ms: float
property budget_utilisation: float
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class actrone_memory.SessionMetadata(*, agent_id, session_id, turn_count, created_at=None, last_active=None)[source]

Bases: BaseModel

Parameters:
agent_id: str
session_id: str
turn_count: int
created_at: datetime | None
last_active: datetime | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class actrone_memory.ToolResult(*, tool_name, params, result, success, duration_ms=None)[source]

Bases: BaseModel

Parameters:
tool_name: str
params: dict[str, object]
result: object
success: bool
duration_ms: int | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class actrone_memory.Turn(*, id=<factory>, session_id, user_message, assistant_message, tool_results=<factory>, timestamp=<factory>, token_count=0)[source]

Bases: BaseModel

Parameters:
id: str
session_id: str
user_message: str
assistant_message: str
tool_results: list[ToolResult]
timestamp: datetime
token_count: int
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

actrone_memory.create_memory_manager(config=None)[source]

Async context manager that creates and automatically closes a MemoryManager.

Usage:

async with create_memory_manager() as mm:
    await mm.store_turn(...)
Parameters:

config (MemoryConfig | None)

Return type:

AsyncIterator[MemoryManager]

class actrone_memory.InMemoryStore(max_turns=50, *, relevance_weight=0.7, recency_weight=0.3)[source]

Bases: object

Zero-dependency, in-process store implementing both memory tiers.

This is the local-first default: it needs no Redis and no Qdrant, so MemoryManager.create() runs with zero external services, parity with the TypeScript actrone-memory on-ramp. Data lives for the lifetime of the process; swap in RedisStore + QdrantStore for durability and horizontal scale.

Concurrency: every method is synchronous internally (no await points), so operations are atomic with respect to the asyncio event loop, concurrent background tasks (e.g. summarisation) cannot interleave a partial mutation.

Parameters:
  • max_turns (int)

  • relevance_weight (float)

  • recency_weight (float)

async append_turn(agent_id, session_id, turn)[source]
Parameters:
Return type:

None

async get_recent_turns(agent_id, session_id, n=None)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

  • n (int | None)

Return type:

list[Turn]

async turn_count(agent_id, session_id)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

int

async clear_session(agent_id, session_id)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

None

async get_session_metadata(agent_id, session_id)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

SessionMetadata | None

async try_acquire_summary_lock(agent_id, session_id, ttl_seconds)[source]

SET-NX-EX equivalent. Returns True for the first caller within a TTL window.

Deduplicates concurrent summarisations within this process and throttles re-summarisation, exactly like the Redis SET key NX EX ttl lock, but scoped to this process (in-memory backends are single-instance by design).

Parameters:
  • agent_id (str)

  • session_id (str)

  • ttl_seconds (int)

Return type:

bool

async upsert(entry)[source]
Parameters:

entry (MemoryEntry)

Return type:

None

async search(agent_id, query_embedding, threshold, limit=20, content_types=None, query_text=None)[source]

Hybrid relevance search, dense + lexical + recency fused with RRF.

Only memories with embedding cosine ≥ threshold are admitted; among those, the ranking fuses embedding cosine, BM25 over the content (when query_text is given), and recency via Reciprocal Rank Fusion. Without query_text (or with no shared terms) it degrades to the classic relevance × cosine + recency × recency blend, matching QdrantStore.

Time complexity: O(n) similarity scoring + O(n log n) rank over the agent’s memories, acceptable for the in-process on-ramp (bounded by max_episodic_memories).

Parameters:
  • agent_id (str)

  • query_embedding (list[float])

  • threshold (float)

  • limit (int)

  • content_types (list[Literal['turn', 'summary', 'tool_result', 'injected', 'fact']] | None)

  • query_text (str | None)

Return type:

list[MemoryEntry]

async delete(memory_id)[source]
Parameters:

memory_id (str)

Return type:

None

async delete_agent_memories(agent_id)[source]

Delete every memory for an agent. Irreversible (mirrors QdrantStore).

Parameters:

agent_id (str)

Return type:

None

async close()[source]

No-op, the in-memory store holds no external connections.

Return type:

None

actrone_memory.cosine_similarity(a, b)[source]

Cosine similarity of two vectors. Returns 0.0 when either is a zero vector.

Tolerates length mismatch by comparing over the shorter prefix, matching the TS cosineSimilarity helper so both OSS libs behave identically.

Parameters:
Return type:

float

class actrone_memory.ExtractedFact(*, content, sensitivity='none', topic_tags=<factory>, importance=0.6)[source]

Bases: BaseModel

One atomic fact extracted from conversation, conforming to the shared spec.

Parameters:
  • content (str)

  • sensitivity (Literal['none', 'low', 'pii', 'sensitive'])

  • topic_tags (list[str])

  • importance (float)

content: str
sensitivity: Sensitivity
topic_tags: list[str]
importance: float
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class actrone_memory.FactExtractor(*args, **kwargs)[source]

Bases: Protocol

Seam for turning conversation text into durable facts (turns → facts).

Implementations are LLM-backed; the library treats extraction as best-effort enrichment (a failure returns no facts and never breaks the write path).

async extract(text)[source]
Parameters:

text (str)

Return type:

list[ExtractedFact]

class actrone_memory.OpenAIFactExtractor(api_key, model='gpt-4o-mini')[source]

Bases: object

LLM fact extractor using OpenAI JSON mode, conforming to the shared spec.

Cost: one cheap completion (e.g. gpt-4o-mini) per extraction call. Extraction is opt-in (MemoryConfig.extract_facts) precisely because it costs tokens.

Parameters:
async extract(text)[source]
Parameters:

text (str)

Return type:

list[ExtractedFact]

actrone_memory.parse_facts(raw)[source]

Parse a model’s JSON response into validated facts, defensively.

Tolerates a bare list or a {"facts": [...]} envelope, skips malformed entries, clamps oversize content, and bounds the count. Never raises, a completely unparseable response yields [].

Parameters:

raw (str)

Return type:

list[ExtractedFact]

class actrone_memory.Embedder[source]

Bases: ABC

Abstract interface all embedding providers must implement.

abstractmethod async embed(text)[source]

Return the embedding vector for a single text string.

Parameters:

text (str)

Return type:

list[float]

abstractmethod async embed_batch(texts)[source]

Return embedding vectors for a batch of texts.

The returned list is always the same length as texts.

Parameters:

texts (list[str])

Return type:

list[list[float]]

abstract property dimensions: int

Dimensionality of the embedding vectors this provider produces.

property relevance_threshold: float | None

The cosine similarity at which this model’s results turn from unrelated to relevant.

Used as the admission threshold when MemoryConfig.relevance_threshold is not set. Override it in a custom embedder once you have measured it; the default None means the library default applies.

class actrone_memory.HashingEmbedder(dimensions=256)[source]

Bases: Embedder

Deterministic, dependency-free hashing embedder (a “hashing vectorizer”).

Hashes words into a fixed-dimension bag-of-words vector and L2-normalises it, so cosine similarity reflects word overlap. This is the zero-dependency, zero-API-key default, parity with the TypeScript LocalEmbedder, which makes the whole library run fully offline with no model download and no external service. It is not semantically rich (no synonymy); for production recall quality pass an OpenAIEmbedder or the sentence-transformers LocalEmbedder.

Deterministic: identical text always yields an identical vector, so no cache is needed.

Parameters:

dimensions (int)

property dimensions: int

Dimensionality of the embedding vectors this provider produces.

property relevance_threshold: float | None

The cosine similarity at which this model’s results turn from unrelated to relevant.

Used as the admission threshold when MemoryConfig.relevance_threshold is not set. Override it in a custom embedder once you have measured it; the default None means the library default applies.

async embed(text)[source]

Return the embedding vector for a single text string.

Parameters:

text (str)

Return type:

list[float]

async embed_batch(texts)[source]

Return embedding vectors for a batch of texts.

The returned list is always the same length as texts.

Parameters:

texts (list[str])

Return type:

list[list[float]]

class actrone_memory.LocalEmbedder[source]

Bases: Embedder

sentence-transformers/all-MiniLM-L6-v2 for offline / free usage (384-dim).

Requires: pip install actrone-memory[local] CPU-bound encoding is offloaded to a thread pool to avoid blocking the event loop.

property dimensions: int

Dimensionality of the embedding vectors this provider produces.

property relevance_threshold: float | None

The cosine similarity at which this model’s results turn from unrelated to relevant.

Used as the admission threshold when MemoryConfig.relevance_threshold is not set. Override it in a custom embedder once you have measured it; the default None means the library default applies.

async embed(text)[source]

Return the embedding vector for a single text string.

Parameters:

text (str)

Return type:

list[float]

async embed_batch(texts)[source]

Return embedding vectors for a batch of texts.

The returned list is always the same length as texts.

Parameters:

texts (list[str])

Return type:

list[list[float]]

class actrone_memory.OpenAIEmbedder(api_key, model='text-embedding-3-small', dimensions=1536)[source]

Bases: Embedder

OpenAI text-embedding-3-small (1536-dim) with automatic retry.

Retries up to 3 times on any exception using exponential backoff with jitter, starting at 1 second and capped at 10 seconds.

Parameters:
property dimensions: int

Dimensionality of the embedding vectors this provider produces.

async embed(text)[source]

Return the embedding vector for a single text string.

Parameters:

text (str)

Return type:

list[float]

async embed_batch(texts)[source]

Return embedding vectors for a batch of texts.

The returned list is always the same length as texts.

Parameters:

texts (list[str])

Return type:

list[list[float]]

class actrone_memory.L1Store(*args, **kwargs)[source]

Bases: Protocol

Hot session tier, recent conversation turns.

Both the Redis-backed RedisStore and the dependency-free InMemoryStore structurally satisfy this protocol, so MemoryManager depends on the seam, not a concrete backend.

async append_turn(agent_id, session_id, turn)[source]
Parameters:
Return type:

None

async get_recent_turns(agent_id, session_id, n=None)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

  • n (int | None)

Return type:

list[Turn]

async turn_count(agent_id, session_id)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

int

async clear_session(agent_id, session_id)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

None

async get_session_metadata(agent_id, session_id)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

Return type:

SessionMetadata | None

async try_acquire_summary_lock(agent_id, session_id, ttl_seconds)[source]
Parameters:
  • agent_id (str)

  • session_id (str)

  • ttl_seconds (int)

Return type:

bool

async close()[source]
Return type:

None

class actrone_memory.L2Store(*args, **kwargs)[source]

Bases: Protocol

Cold semantic tier, long-term episodic memories.

Implemented by QdrantStore and the dependency-free InMemoryStore.

async upsert(entry)[source]
Parameters:

entry (MemoryEntry)

Return type:

None

async search(agent_id, query_embedding, threshold, limit=20, content_types=None, query_text=None)[source]
Parameters:
  • agent_id (str)

  • query_embedding (list[float])

  • threshold (float)

  • limit (int)

  • content_types (list[Literal['turn', 'summary', 'tool_result', 'injected', 'fact']] | None)

  • query_text (str | None)

Return type:

list[MemoryEntry]

async delete(memory_id)[source]
Parameters:

memory_id (str)

Return type:

None

async delete_agent_memories(agent_id)[source]
Parameters:

agent_id (str)

Return type:

None

async close()[source]
Return type:

None

exception actrone_memory.ActroneMemoryError(message, *, code, details=None)[source]

Bases: Exception

Base error for all actrone-memory exceptions.

Every error carries:

code, machine-readable string for programmatic handling (e.g. in logs or alerts) message, human-readable description details, structured dict of context that helps locate the failure

Parameters:
Return type:

None

exception actrone_memory.ConfigurationError(message, details=None)[source]

Bases: ActroneMemoryError

Raised when required configuration is missing or invalid.

This always means something is wrong with how the library is set up, not a runtime failure. It should cause the application to exit.

Parameters:
Return type:

None

exception actrone_memory.EmbeddingError(message, details=None)[source]

Bases: ActroneMemoryError

Raised when an embedding provider returns an error or an unexpected response.

Parameters:
Return type:

None

exception actrone_memory.MemoryNotFoundError(memory_id)[source]

Bases: ActroneMemoryError

Raised when delete_memory() is called with an ID that does not exist.

Parameters:

memory_id (str)

Return type:

None

exception actrone_memory.StoreConnectionError(store, cause, details=None)[source]

Bases: ActroneMemoryError

Raised when a connection to Redis or Qdrant cannot be established or maintained.

Includes the name of the store that failed and the underlying exception.

Parameters:
Return type:

None

exception actrone_memory.TokenBudgetError(message, details=None)[source]

Bases: ActroneMemoryError

Raised when token_budget is zero or negative in retrieve_context().

Parameters:
Return type:

None

exception actrone_memory.ValidationError(field, message)[source]

Bases: ActroneMemoryError

Raised when a public method receives an invalid argument at the API boundary.

Parameters:
Return type:

None