Open a chat view for real-time messaging. Supports human-human chat (via matchmaking) and human-AI chat (via agents).
Props
| Prop | Type | Default | Description |
|---|---|---|---|
agents |
string[] | [] |
List of agent ids to join the chat (see Agents) |
groupId |
string | - | Explicit chat group identifier for shared contexts |
placeholder |
string | "Type a message..." |
Placeholder text in the message input |
avatars |
object | - | Optional chat avatar overrides for self, participant, agent, or specific agents.{id} |
Group Resolution
Chat rooms are identified by groupId. The resolution order is:
- Matchmaking: If participant was matched, uses
session_state.chat_group_id(shared with matched participants) - Explicit prop: If
groupIdprop is set, uses{sessionId}:{groupId}(session-scoped) - Default: Uses
{sessionId}:{pageId}(isolated to this session and page)
Shared Chat (via Matchmaking)
When participants are matched, they share a chat_group_id and see each other's messages:
pages:
- id: matchmaking
components:
- type: matchmaking
props:
num_users: 2
- id: discussion
components:
- type: chat # Uses session_state.chat_group_id from matchmaking
Isolated Chat (AI Only)
Without matchmaking, each participant has their own chat context:
pages:
- id: ai_chat
components:
- type: chat
props:
agents: [assistant]
placeholder: "Ask me anything..."
Avatars
Chat supports optional avatar overrides for:
- self
- participant
- agent
- agents.{agentId} for specific agents
Each avatar can use either:
- icon: a Lucide icon name
- image: an image URL or public path
If both are provided, image wins.
pages:
- id: ai_chat
components:
- type: chat
props:
agents: [assistant, tutor]
avatars:
self:
icon: user-round
participant:
icon: leaf
agent:
icon: bot
agents:
tutor:
image: /images/tutor.png
agents:
- id: assistant
model: gpt-4o
avatar:
icon: sparkles
system: You are a helpful assistant.
- id: tutor
model: gpt-4o
avatar:
icon: graduation-cap
system: You are a tutor.
Precedence:
1. Specific agent override: props.avatars.agents.{agentId}
2. Agent default: props.avatars.agent
3. Built-in default icon
For icons, use Lucide icon names in kebab-case, like bot, sparkles, or graduation-cap.
Agent-level avatars are configured in agents[].avatar and act as the natural default for that agent when no chat-level override is present.
Explicit Group Sharing
Use groupId to share context across pages within a session:
pages:
- id: chat_1
components:
- type: chat
props:
groupId: main_conversation
- id: chat_2
components:
- type: chat
props:
groupId: main_conversation # Same conversation continues
Events
- onMessageSend: emitted when user sends a message
- onMessageReceive: emitted when user receives a message
- onTypingStart: emitted when user begins typing
- onTypingStop: emitted when user stops typing
Event Data
- chat_group_id: identifier of the chat room/group
- message_id: unique identifier for the message (send/receive events)
- sender_type: "participant", "agent", or "system" (receive events)
- message_length: character count of the message (send events)
- agent_id: which agent sent the message (agent messages only)
- Custom data can be added via events.{eventName}.data
Session state
Chat now maintains a server-side per-session counter at session_state.chat.messages_sent for participant-authored messages. You can use it in conditional UI and text interpolation:
session_state:
chat:
type: object
properties:
messages_sent:
type: integer
default: 0
pages:
- id: discussion
components:
- type: chat
- type: text
when: "session_state.chat.messages_sent >= 3"
props:
text: "Thanks — you've sent {{session_state.chat.messages_sent}} messages."
Example
pages:
- id: chat_control
components:
- type: chat
id: group_chat_control
events:
onMessageSend:
type: "chat_message_sent"
data:
condition: "control"
onMessageReceive:
type: "chat_message_received"
data:
condition: "control"
buttons:
- id: finish
text: "Finish"
action: { type: go_to, target: outro }
- id: chat_treated
components:
- type: chat
id: group_chat_treated
props:
agents: [default_agent]
events:
onMessageSend:
type: "chat_message_sent"
data:
condition: "treated"
has_agent: true
onMessageReceive:
type: "chat_message_received"
data:
condition: "treated"
has_agent: true
buttons:
- id: finish
text: "Finish"
action: { type: go_to, target: outro }
Agents