Session Management
Sessions in AgentDock provide the foundation for stateful, continuous interactions between users and AI agents. This document covers the core concepts, architecture, implementation details, and optimization strategies for the session management system.
Core Concepts
- Session: Represents a single conversation, identified by a unique
SessionId
. It maintains state across multiple interactions (messages, tool calls) to preserve context. - Session Isolation: Ensures that concurrent conversations do not interfere with each other. Critical for multi-user environments.
- Single Source of Truth: Session IDs are generated centrally (typically by the entry point, like an API route handler), and state is managed through a single
SessionManager
instance for a given state type, ensuring consistency.
Architecture & Implementation
The session system revolves around the generic SessionManager
class found in agentdock-core/src/session/index.ts
.
SessionManager<T extends SessionState>
- Generic: Can manage different types of session state (e.g., base state, orchestration state, tool state) by extending the base
SessionState
interface. - Storage-Backed: Uses the Storage Abstraction Layer for persistence. It defaults to an in-memory provider but can be configured (via constructor options) to use Redis, Vercel KV, or other providers.
- Namespace: Uses a storage namespace (e.g.,
sessions
,orchestration-state
) to keep different types of session data separate in the storage backend. - State Factory: Requires a
defaultStateGenerator
function during instantiation to define how the initial state (T
) for a new session should be created.
Key Operations
-
createSession(options)
: Creates a new session (if one doesn't exist for the given or generatedSessionId
) using thedefaultStateGenerator
and stores it. Returns aSessionResult<T>
. -
getSession(sessionId)
: Retrieves the current state for a session ID from storage. ReturnsSessionResult<T>
. -
updateSession(sessionId, updateFn)
: Updates session state immutably. It retrieves the current state, applies theupdateFn
to generate a new state object, and stores the new state atomically. ReturnsSessionResult<T>
. -
deleteSession(sessionId)
: Removes a session from storage.
Session ID Generation
Session IDs are typically generated by the application entry point (e.g., API route handler) to maintain the single source of truth. While the core library can generate a UUID (generateSessionId
), passing a predetermined ID is preferred. Format often includes prefixes for traceability.
Session Lifecycle & Cleanup
- Creation: Handled by
createSession
, often triggered by the first interaction if noSessionId
is provided. - Access & Update:
getSession
andupdateSession
are used throughout the agent's processing logic. - Expiration (TTL): Each session state includes
lastAccessed
(timestamp) andttl
(milliseconds) properties. The TTL is configurable (default: 30 minutes).- Default: The default TTL is 24 hours of inactivity, defined in
agentdock-core
. - Configuration: This default can be overridden globally for the application by setting the
SESSION_TTL_SECONDS
environment variable (value in seconds). This configured TTL is used when creating or updating session keys in the storage provider.
- Default: The default TTL is 24 hours of inactivity, defined in
- Automatic Cleanup: The
SessionManager
includes an optional, periodic cleanup mechanism (setupCleanupInterval
,cleanupExpiredSessions
) that checkslastAccessed + ttl
against the current time and automatically callsdeleteSession
for expired entries. This timer usesunref()
in Node.js to avoid blocking process exit.
Persistence & Long-Lived Sessions
For sessions needing longer persistence than typical web interactions (e.g., persistent personal assistants):
- Configure Long TTL: Set
SESSION_TTL_SECONDS
in the application's environment to a large value (e.g.,31536000
for one year). - Ensure Activity: As long as the session is accessed (via
getSession
orupdateSession
), thelastAccessed
timestamp is updated, resetting the TTL timer for the storage key. - No TTL: Setting
SESSION_TTL_SECONDS
to0
or a negative value will likely result in the storage provider not setting an expiration time, making the session persist indefinitely until explicitly deleted. Use this cautiously to avoid accumulating orphaned data.
Optimization Techniques
- Conditional State Creation: Components or managers (like
OrchestrationStateManager
) should check if session state is truly needed before callingcreateSession
orgetSession
. For example, an agent without orchestration configured doesn't need orchestration state. - Minimalist State Design: Session state interfaces (
T extends SessionState
) should only include essential data, avoiding large objects or duplication. - Lazy Loading: Components retrieve session state only when required for an operation.
- Efficient Updates: The immutable update pattern (
updateSession
) with partial updates ({ ...state, ...updates }
) is efficient and prevents race conditions. - Last Accessed Tracking: Updating
lastAccessed
ongetSession
orupdateSession
keeps active sessions alive while allowing inactive ones to expire naturally via TTL. - Storage Provider Choice: Selecting an appropriate storage provider (Memory for development, Redis/Vercel KV for production) significantly impacts performance and scalability.
- Leverage Configurable TTL: Set
SESSION_TTL_SECONDS
appropriately for your application's needs (e.g., shorter for web sessions, longer for persistent agents) for automatic cleanup.
Integration
- LLM: Session state (especially message history) provides context for LLM calls.
- Tools: Tools can access session state (via specific managers if needed) to maintain context or share data across invocations.
- Orchestration: The
OrchestrationStateManager
uses theSessionManager
to store its specificOrchestrationState
per session, enabling step tracking, sequence management, etc. - Next.js: See Next.js Integration for details on managing session IDs in API routes and client components.
Best Practices
- Single Source of Truth: Generate/manage session IDs at the entry point (API route).
- Pass, Don't Create: Components receive session IDs; they don't generate them.
- Configure Storage: Choose the appropriate storage provider for your environment.
- Minimize State: Only store necessary data in session state objects.
- Leverage TTL: Use TTL effectively for automatic cleanup.
- Handle Errors: Check
SessionResult.success
and handle potential errors (e.g., session not found).