Skip to main content
The session store owns committed multi-turn conversation history and JSON-safe application state. It does not own an active framework run; checkpoints handle that separately. Every application resolves exactly one session factory across its root and Harnest Extension extensions. This example assumes the shared PostgresStore from lib/state.py in the storage overview:
lifecycle/sessions.py
Committed session state survives an ADK ↔ LangGraph switch when both compiled applications use compatible session storage. Active framework checkpoints do not move with it.

Store session-scoped data

Use context.session for values that should persist with a session without entering prompts or model-visible history:
lib/exports.py
Session writes are scoped to the authenticated user and session. They emit payload-free OTEL audit events.

Isolate long-lived PostgreSQL leases

Each active invocation holds one PostgreSQL connection for its session advisory lock. By default, PostgresStore draws that connection from the primary pool for compatibility. Use lease_pool_options= to give long-lived execution leases a dedicated pool and protect short database operations from pool starvation:
lib/state.py
Both pools connect to the same DSN and are owned by the store. Size the lease pool for the number of simultaneous session executions you want to admit. Size the primary pool for short-operation concurrency. Omitting lease_pool_options preserves one shared pool. Harnest serializes framework-state and application-data writes within each lease because asyncpg allows only one active command per connection. Pool isolation separates workloads; it does not permit concurrent commands on one leased connection.

Register a domain repository

Custom storage is for business data that needs a typed repository. It is not a session store or framework checkpointer.
lifecycle/users.py
lib/user_profiles.py
A custom store must provide async start() and close() methods. Prefer domain methods over exposing a raw connection to agent code. Sessions and checkpoints never appear in context.storage.

Register asset stores

Declare one or more named stores for session-owned media:
lifecycle/assets.py
context.assets selects default; context.assets("generated") selects a named store. An AssetRef retains its store and optional domain label, so later reads cannot silently switch backends. See Store and retrieve media.

Configure checkpoints separately

Add active-run persistence and recovery without exposing checkpoint state to agent code.