Skip to content

Memory

zeroth.integrations.memory

Memory subsystem for Zeroth agents.

This package provides the building blocks for giving agents persistent memory. It includes governed-protocol connector implementations, models (data shapes), and a registry/resolver (looking up and wrapping connectors by name).

KeyValueMemoryConnector

KeyValueMemoryConnector()

Simple key-value memory connector.

A general-purpose connector for storing and retrieving data by key.

search async

search(
    query: dict,
    scope: MemoryScope,
    *,
    target: str | None = None,
) -> list[MemoryEntry]

Rank entries by token overlap with the query text.

Whole-phrase substring matches outrank token overlap; an empty query returns everything. Honors query["limit"] (the retrieval node's top_k). Sentence queries — the shape a RetrievalNode produces — therefore work against this connector without a vector backend.

RunEphemeralMemoryConnector

RunEphemeralMemoryConnector()

Memory that only lasts for a single run and is thrown away afterward.

Use this when an agent needs scratch space during one execution but the data doesn't need to survive after the run finishes.

ThreadMemoryConnector

ThreadMemoryConnector()

Memory scoped to a conversation thread.

Use this when data should persist across multiple runs within the same thread (like a conversation) but stay separate between threads.

ConnectorManifest

Bases: BaseModel

Describes how a memory connector is configured.

This is the "ID card" for a connector -- it tells the system what type of connector to use, what scope it operates at, and any extra config.

ResolvedMemoryBinding

Bases: BaseModel

A fully resolved, ready-to-use memory binding.

Combines the connector instance and its manifest (configuration). The connector is already wrapped with ScopedMemoryConnector and (optionally) AuditingMemoryConnector, so callers just call read/write/delete/search directly.

InMemoryConnectorRegistry

InMemoryConnectorRegistry()

A simple lookup table that maps memory ref names to connectors.

You register connectors by name, then look them up later when you need to read or write memory. Raises KeyError if a name isn't found.

register

register(
    memory_ref: str,
    manifest: ConnectorManifest,
    connector: Any,
) -> None

Add a connector to the registry under the given name.

unregister

unregister(memory_ref: str) -> None

Remove a connector from the registry. Missing refs are a no-op.

resolve

resolve(memory_ref: str) -> tuple[ConnectorManifest, Any]

Look up a connector by name. Raises KeyError if not registered.

list

list() -> dict[str, tuple[ConnectorManifest, Any]]

All registered entries by ref (shallow copy; used by /v1/connectors).

MemoryConnectorResolver

MemoryConnectorResolver(
    *,
    registry: InMemoryConnectorRegistry | None = None,
    thread_repository: ThreadRepository | None = None,
    audit_emitter: AuditEmitter | None = None,
    workflow_name: str = "",
)

Turns memory ref names into fully resolved, ready-to-use bindings.

Given a list of memory reference names, this resolver looks each one up in the registry, wraps the raw connector with AuditingMemoryConnector (if an emitter is provided) and ScopedMemoryConnector, and returns ResolvedMemoryBinding instances.

set_embedding_call_hooks

set_embedding_call_hooks(
    hooks: EmbeddingCallHooks | None,
) -> None

Wire the shared control plane used by per-resolve campaign wrappers.

consume_embedding_call_costs async

consume_embedding_call_costs(
    *,
    tenant_id: str,
    run_id: str,
    node_id: str,
    campaign_id: str,
    operation: EmbeddingOperation,
) -> tuple[dict[str, Any], ...]

Consume settled embedding costs once for the owning runtime node.

resolve async

resolve(
    memory_refs: list[str],
    *,
    thread_id: str | None = None,
    runtime_context: Mapping[str, Any] | None = None,
    node_id: str | None = None,
    effective_capabilities: set[Capability] | None = None,
) -> list[ResolvedMemoryBinding]

Resolve a list of memory ref names into ready-to-use bindings.

For each ref, looks up the connector and builds the wrapper stack Scoped(TenantScoped(Auditing(raw))): Auditing (innermost, optional) emits events, TenantScoped rewrites the resolved target into a tenant-namespaced form, and Scoped (outermost) resolves scope -> target before either sees it. TenantScoped sits below Scoped on purpose: Scoped first produces "__shared__" / run_id / thread_id, then TenantScoped namespaces it — that is what stops SHARED memory from being cross-tenant readable on a shared backend.

Tenant is read per-call from runtime_context["tenant_id"] and is fail-closed: an empty/missing tenant raises TenantScopeError (an explicit "default" sentinel is permitted). The resolver stays a shared singleton, so tenant must never be stored on __init__.

effective_capabilities (WS-C) is the node's granted capability set. When it is not None the connector is wrapped with CapabilityEnforcingMemoryConnector as the OUTERMOST layer, so MEMORY_READ / MEMORY_WRITE are enforced (fail-closed: an empty granted set denies) before scope/tenant/audit/raw see the call. When it is None enforcement is inactive (the policy guard is not wired) and the stack is left unchanged — the caller, not this method, decides whether enforcement applies, so None never silently bypasses an active gate.

register_memory_connectors

register_memory_connectors(
    registry: InMemoryConnectorRegistry,
    settings: Any,
    *,
    redis_client: Any | None = None,
    pg_conninfo: str | None = None,
    secret_provider: Any | None = None,
    tenant_id: str | None = None,
    allow_env_fallback: bool = True,
) -> None

Create and register all configured memory connectors.

Always registers the three in-memory connectors (ephemeral, key_value, thread) for dev/test. Conditionally registers external backend connectors based on settings and available clients.

Parameters:

Name Type Description Default
registry InMemoryConnectorRegistry

The connector registry to populate.

required
settings Any

Application settings with memory/pgvector/chroma/elasticsearch config.

required
redis_client Any | None

An async Redis client instance (if Redis is available).

None
pg_conninfo str | None

Postgres connection string (if Postgres is available).

None
secret_provider Any | None

Optional tenant-aware provider for resolving logical credential references.

None
tenant_id str | None

Tenant scope used for secret-provider resolution.

None
allow_env_fallback bool

Whether logical references may fall back to the process environment when no secret-provider value is available.

True