Concepts: Sessions & Hydration
A Session (sessionId) in Invariant is an optional durable continuity boundary that groups identity, hydrated application context, channels, and related workflow executions.
"Executions preserve progress within one Workflow run. Sessions preserve continuity across application activity."
1. What is a Session?
A Session is not a chat history transcript.
A Session is the durable container that allows multiple user interactions, channels, and workflow executions to belong to the same ongoing entity or business process.
A Session does not execute a Workflow and is not itself an Execution. It provides continuity around application activity that may span multiple executions.
Session
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
Identity Session Context Channels
sessionId / userId hydrated business web / voice / MCP
│ │ │
└──────────────────────┼──────────────────────┘
│
┌────────────┴────────────┐
▼ ▼
Workflow Executions Agent TurnsPublic Session API vs. Runtime Relationships
| Dimension | Element | Description |
|---|---|---|
| Public Session API | session.id | Unique durable session identifier (sess_101) |
session.userId | User or tenant identity associated with the session (usr_441) | |
session.context | Typed business context hydrated from external systems (TSessionContext) | |
| Runtime Relationships | Identity Boundary | Ties workflows and agent turns to a specific user or tenant |
| Attached Transports | Delivery channels (Web Chat, Gemini Live WebSocket, MCP) | |
| Workflow Executions | Active and historical workflow runs associated with the session |
2. Session ≠ Conversation
Sessions are not limited to conversational chat interactions. A Session can span multiple communication channels or run fully programmatic non-conversational automation:
Cross-Channel Customer Support
Web Chat (Session: sess_44) ──► Customer requests refund
│
▼
Voice Call (Session: sess_44) ──► Customer calls support line; speaks to Live Voice Agent
│
▼
Web Portal (Session: sess_44) ──► Customer reviews completed refund status onlineAccount Lifecycle Automation (Non-Conversational)
Webhook (Stripe Event)
│
▼
Session(account_123) ──► Starts Subscription Renewal Workflow
│
later...
│
Cron (Nightly Job)
│
▼
Session(account_123) ──► Starts Billing Reconciliation WorkflowBoth workflows share the same durable Session(account_123) context without any conversation or chat interface.
3. Hydration — Importing Authoritative Context
"Sessions do not ask the model to remember application truth. They hydrate it from authoritative systems."
When a new Session is created, Invariant invokes your application's hydrate() hook to fetch fresh, authoritative data from your CRM, database, or identity service—rather than forcing an LLM to reconstruct user identity from past message history. Existing Sessions load their durable context from storage without re-running hydration unless explicitly rehydrated (await session.rehydrate()).
// src/runtime.ts
import { z } from "zod";
import { invariant } from "@invariant/sdk";
export const app = invariant({
session: {
contextSchema: z.object({
customerId: z.string(),
accountTier: z.enum(["FREE", "PRO", "ENTERPRISE"]),
preferredLanguage: z.string(),
}),
hydrate: async ({ userId }) => {
// Hydration is application-defined; it can compose data from multiple sources:
const customer = await crm.getCustomer(userId);
const billing = await stripe.customers.retrieve(customer.stripeId);
return {
customerId: customer.id,
accountTier: billing.plan,
preferredLanguage: customer.language,
};
},
},
});Hydration vs. Capabilities: Hydration is a Session lifecycle boundary, not a Workflow execution node. External reads performed during hydration establish Session Context; external I/O performed as part of Workflow execution belongs behind
.capability()boundaries.
When you retrieve or create a session:
const session = await app.sessions.getOrCreate("sess_101", "usr_441");If no Session with that ID exists, Invariant creates it and runs the initial hydrate() pipeline. Existing Sessions are loaded from durable storage without invoking the hydrator again.
Identity (usr_441)
│
▼
hydrate() ──► Composes CRM / Billing / Identity
│
▼
Session Context
{
customerId: "cust_91",
accountTier: "PRO",
preferredLanguage: "es"
}
│
├── Available to Workflows (({ session }) => ...)
└── Projected to Agents (Agent Context Projection)4. Rehydration — Refreshing Context
rehydrate() refreshes Session Context from its authoritative external sources when underlying business facts change.
For example, if a customer upgrades their subscription plan while a session remains active:
// Customer upgrades plan in external billing portal...
await session.rehydrate();Before rehydrate():
session.context.accountTier ──► "FREE"
CRM / Stripe updated:
customer.tier ──────────────► "PRO"
After session.rehydrate():
session.context.accountTier ──► "PRO"Context Refresh Responsibility: Session Context remains durable until explicitly updated or rehydrated. Applications decide when external facts require a refresh.
5. Context Operations Summary
Invariant provides three distinct mechanisms for context management:
| Operation | Trigger | Source | Purpose |
|---|---|---|---|
hydrate() | New session creation | External systems (CRM / DB) | Bootstraps initial Session Context |
updateContext() | Application code | Developer code mutation | Applies explicit, validated context changes |
rehydrate() | Explicit refresh call | External systems (CRM / DB) | Refreshes context when external facts change |
"
updateContext()declares a context change.rehydrate()discovers one from authoritative sources."
// Explicit application code mutation:
await session.updateContext({
preferredLanguage: "en",
});6. What Belongs in Session Context vs. Execution State?
It is essential to distinguish between Session Context and Workflow Execution State:
Session Context (sess_101)
customerId, accountTier, tenantId, permissions
│ available across executions
▼
Execution run_1 Execution run_2
refund cancellation
──────── ────────────
orderId subscriptionId
refundAmount effectiveDate| Dimension | Session Context (session.context) | Workflow Execution State (state) |
|---|---|---|
| Scope | Long-lived, independent from any individual execution | Finite run of one specific workflow (runId) |
| Example Data | customerId, accountTier, tenantId, permissions | orderId, refundEligibility, refundAmount, approvalStatus |
| Nature | Hydrated typed domain context | Event-sourced accumulated state |
| Lifecycle | Survives across multiple workflow runs & channels | Resets for each new workflow execution |
"Put information in Session Context when it should survive across related application activity. Put information in Execution State when it belongs to the progress of one Workflow run."
"Session Context represents durable continuity. Execution State represents durable progress."
7. Using Sessions with Agents & Workflows
With Agents
When an Agent turn executes (agent.run({ session, message })), Invariant combines session.context with the current RuntimeProjection to construct the model-facing payload:
export const supportAgent = app.agent("support", {
workflows: [refundWorkflow],
context: ({ session }) => ({
customerId: session.context.customerId,
tier: session.context.accountTier,
}),
});With Programmatic Workflows
Programmatic workflows can access session context directly without involving an Agent or LLM:
const run = await refundWorkflow.start({
session,
input: { orderId: "ord_99" },
});8. Exact Session API Reference
// Create or retrieve a durable session:
const session = await app.sessions.getOrCreate("sess_101", "usr_441");
// Read current context:
console.log(session.context.customerId);
console.log(session.context.accountTier);
// Update context explicitly:
await session.updateContext({ preferredLanguage: "es" });
// Rehydrate from external CRM/Stripe:
await session.rehydrate();Go Deeper
- Mental Model — Understand how Sessions fit into the 6 common execution paths.
- Agents & Actions — Learn how
AgentContextProjectioncombines Session Context with Runtime Projections. - Durable State & Events — Inspect event log persistence and state materialization.