Built-in chat¶
uproot provides a built-in chat system for experiments where participants need to communicate. The chat handles message display, pseudonyms, and real-time updates automatically.
Creating a chat¶
Create a chat at the session or group level, typically in the new_session callback:
The chat.create() function returns a chat identifier that you store on the session for later use.
Adding players to a chat¶
Add participants to the chat using chat.add_player(). This is typically done when they reach the chat page:
class ChatPage(Page):
@classmethod
async def before_once(page, player):
chat.add_player(player.session.chat, player)
The before_once method ensures each player is added exactly once, even if they refresh the page.
Assigning pseudonyms¶
You can assign pseudonyms to protect participant identity:
If no pseudonym is provided, an anonymous identifier is generated automatically.
Displaying the chat¶
Use the chat() template function to render the chat interface:
The chat widget provides:
- A message display area showing all messages
- An input field for typing messages
- A send button
- Real-time updates when others send messages
- Visual distinction between your messages and others'
Session-level chat¶
The simplest chat setup is session-wide, where all participants can see all messages:
def new_session(session):
session.chat = chat.create(session)
class ChatPage(Page):
@classmethod
async def before_once(page, player):
chat.add_player(
player.session.chat,
player,
pseudonym=f"Player {player.id}",
)
page_order = [
ChatPage,
]
Group-level chat¶
For private communication within groups, create a chat per group in the after_grouping callback:
class GroupPlease(GroupCreatingWait):
group_size = 2
@classmethod
def after_grouping(page, group):
group.chat = chat.create(group.session)
for player in group.players:
chat.add_player(group.chat, player)
Then display the group's chat:
Multiple chats¶
You can create multiple chat channels for different purposes:
def new_session(session):
session.general_chat = chat.create(session)
session.announcements = chat.create(session) # Admin-only channel
Display them on the same page or different pages:
<h3>General discussion</h3>
{{ chat(session.general_chat) }}
<h3>Announcements</h3>
{{ chat(session.announcements) }}
Reacting to new messages¶
Use chat.on_message() to register a callback that runs whenever a message is sent to a chat. This is useful for bots, automated responses, or recording-keeping logic.
async def on_chat_message(chat, player, message):
if player is None:
return # Message was sent programmatically, not by a participant
# React to the message here
def new_player(player):
player.my_chat = chat.create(player.session)
chat.add_player(player.my_chat, player)
chat.on_message(player.my_chat, on_chat_message)
The callback receives:
- chat โ the ModelIdentifier of the chat
- player โ the player who sent the message, or None if sent programmatically
- message โ the message text
The callback is persistent: it is automatically restored when the server restarts.
See the chat example with callback ยท chat_with_claude example
Chat API reference¶
chat.create(session)¶
Creates a new chat channel.
Returns a ModelIdentifier that you store on the session or group.
chat.add_player(chat, player, pseudonym=None)¶
Adds a participant to the chat.
chat.messages(chat)¶
Returns all messages in the chat.
chat.players(chat)¶
Returns the list of players in the chat.
chat.exists(chat)¶
Checks if a chat exists.
Styling the chat¶
The chat uses Bootstrap classes and can be customized with CSS. The main elements are:
.uproot-chat- Container for the entire chat widget.messages-container- The scrollable message area.list-unstyled- The message list
Example custom styling:
Complete example¶
Here's a complete session-level chat:
def new_session(session):
session.chat = chat.create(session)
class ChatHere(Page):
@classmethod
async def before_once(page, player):
chat.add_player(
player.session.chat,
player,
pseudonym=f"Player {player.id}",
)
page_order = [
ChatHere,
]
Template (ChatHere.html):
{% extends "Base.html" %}
{% block title %}
Chat
{% endblock title %}
{% block main %}
{{ chat(session.chat) }}
{% endblock main %}
Summary¶
| Function | Purpose |
|---|---|
chat.create(session) |
Create a new chat channel |
chat.add_player(chat, player, pseudonym=...) |
Add a participant to the chat |
chat.on_message(chat, callback) |
Register a callback for new messages |
chat(chat_id) |
Template function to render the chat |
chat.messages(chat) |
Get all messages |
chat.players(chat) |
Get all participants |