The user session is designed to persist data in memory through the life cycle of a chat session. Each user session is unique to a user and a given chat session.

Why use the user session?

Let’s say you want to keep track of each chat session message count.

A naive implementation might look like this:

This example is for illustrative purposes only. It is not recommended to use this code in production.

Naive Example
import chainlit as cl

counter = 0

async def on_message(message: cl.Message):
    global counter
    counter += 1

    await cl.Message(content=f"You sent {counter} message(s)!").send()

At first glance, this code seems to work. However, it has a major flaw. If two users are chatting with the bot at the same time, both users will increment the same counter.

This is where the user session comes in. Let’s rewrite the above example using the user session:

Correct example
import chainlit as cl

def on_chat_start():
    cl.user_session.set("counter", 0)

async def on_message(message: cl.Message):
    counter = cl.user_session.get("counter")
    counter += 1
    cl.user_session.set("counter", counter)

    await cl.Message(content=f"You sent {counter} message(s)!").send()

User Session Default Values

By default, Chainlit stores chat session related data in the user session.

The following keys are reserved for chat session related data:


The session id.


Only set if you are enabled Authentication. Contains the user object of the user that started this chat session.


Only relevant if you are using the Chat Profiles feature. Contains the chat profile selected by this user.


Only relevant if you are using the Chat Settings feature. Contains the chat settings given by this user.

default: "{}"

Only relevant if you are using the user_env config. Contains the environment variables given by this user.


The most recent Message (not Step) in this chat session.