Skip to main content

When do you need sessions?

Sessions add a lifecycle and persistence layer on top of any Agent-protocol brain - the default PlaybookAgent and the legacy DialogMachine alike. A bare agent holds its conversation state in memory for the lifetime of the instance. This works perfectly for:
  • Voice calls (one machine per call, ephemeral)
  • CLI testing (single conversation, short-lived)
  • Simple single-user demos
You need SessionWorker when:
  • Multi-user: multiple concurrent conversations hit the same process
  • Multi-worker: requests are load-balanced across FastAPI workers or pods
  • Long-lived chat: conversations span hours or days and must survive restarts

The Agent Protocol

SessionWorker works with any brain that implements this Protocol:
The Playbook engine’s PlaybookAgent, the legacy DialogMachine, LLMAgent, and LangChainAgent all implement this.

SessionWorker

The agent_factory returns a fresh agent per session. Point DialogMachine at a playbook and you get the default engine; the factory is identical whatever the artifact:
Use it with an async context manager:
What acquire does:
  1. Loads or creates the session for session_id
  2. Acquires a per-session lock (serialises concurrent requests for the same id)
  3. Yields a SessionHandle
  4. On exit: persists state to the store and releases the lock
Requests for different session_ids run fully in parallel.

FastAPI multi-user example

Session stores

Switch stores by changing one line - the rest of the code stays the same:

Lock backends

Other agent brains

When you want sessions and persistence but no checkpoint or flow opinion at all - a raw chat brain:
Or with LangChain (requires pip install superdialog[langchain]):

Conversation state

Internally, each session stores a ChatContext - LiveKit-aligned message history:
Beyond the transcript, each engine carries its own runtime state:
  • Playbook engine - the source of truth is the event-sourced log (agent.event_log); ConversationState.fold(log, playbook) derives the checkpoint, slots, and outcome. Persist event_log.to_jsonl() and restore via load_event_log for full fidelity.
  • Legacy DialogMachine - FlowState (current node, slot values). Present only when the brain is a DialogMachine; None otherwise.
SessionWorker’s built-in SessionRecord persists chat_ctx / flow_state only. For durable or multi-worker resume on the Playbook engine, persist agent.event_log.to_jsonl() yourself and restore with load_event_log - otherwise playbook state fidelity (provisional vs confirmed slots, tool results) is lost.

Voice (ephemeral) pattern

For voice calls where each call is a fresh conversation and no persistence is needed:
NullSessionStore keeps the single-call lifecycle of a bare agent while still giving you the multiplexing and locking of SessionWorker.