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
Use SessionContext to read, replace, update, delete, or namespace session values. See the session operation reference for return values and lease behavior. 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 a PostgreSQL connection for its session lock. Use lease_pool_options= to keep long-lived leases from exhausting the primary pool:
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.