jeevesagent.memory.lazy¶
Lazy-construction wrapper for async-connect Memory backends.
The framework’s resolver lets users write:
Agent("...", model="...", memory="postgres://prod-db/agent")
But PostgresMemory.connect(...) and RedisMemory.connect(...)
are async — they open a pool / client on the wire. The
Agent constructor is synchronous, so we need a way to defer
the connection until the agent loop is actually running.
LazyMemory is that bridge. It:
takes an async builder coroutine that returns the real backend (e.g.
lambda: PostgresMemory.connect(dsn))holds it un-called until the first protocol method is invoked
connects exactly once, caches the instance, then proxies every subsequent call straight through
So users see a regular Memory from the constructor onward; the
network round-trip happens on the first agent.run (where any
connection error surfaces as MemoryStoreError, not a sync
exception in user-side construction code).
Construction is also safe under structured concurrency: the first-
use path is wrapped in an anyio.Lock so concurrent agent.run
calls don’t open the pool twice.
Classes¶
Defer construction of an async-built |
Module Contents¶
- class jeevesagent.memory.lazy.LazyMemory(builder: collections.abc.Callable[[], collections.abc.Awaitable[Any]], *, description: str = 'memory')[source]¶
Defer construction of an async-built
Memoryuntil first use.Users rarely instantiate this directly — it’s what the
_resolve_memory()resolver returns when given apostgres://orredis://URL. Pass a zero-arg async callable that builds the real backend; everything else (working / remember / recall / facts / session_messages / consolidate) is forwarded once that callable resolves.- async aclose() None[source]¶
Close the inner backend if it was constructed.
Safe to call when the backend was never resolved (no-op).
- async export(*, user_id: str | None = None) jeevesagent.core.types.MemoryExport[source]¶
- async forget(*, user_id: str | None = None, session_id: str | None = None, before: datetime.datetime | None = None) int[source]¶
- async profile(*, user_id: str | None = None) jeevesagent.core.types.MemoryProfile[source]¶
- async recall(query: str, *, kind: str = 'episodic', limit: int = 5, time_range: tuple[datetime.datetime, datetime.datetime] | None = None, user_id: str | None = None) list[jeevesagent.core.types.Episode][source]¶
- async recall_facts(query: str, *, limit: int = 5, valid_at: datetime.datetime | None = None, user_id: str | None = None) list[jeevesagent.core.types.Fact][source]¶
- async remember(episode: jeevesagent.core.types.Episode) str[source]¶
- async session_messages(session_id: str, *, user_id: str | None = None, limit: int = 20) list[jeevesagent.core.types.Message][source]¶
- property description: str¶
Human-readable label (e.g.
"postgres://prod-db/agent") — used in error messages so users can tell which Memory failed to connect.
- property facts: Any | None¶
Direct access to the inner backend’s fact store (if any).
Reading this BEFORE the backend has connected returns
None— the connection deliberately hasn’t happened yet. Once the backend is resolved (after the firstagent.runor an explicitawait mem._resolve()), this returns the liveFactStore. Power-user escape hatch; most callers go throughrecall_facts().