4.2 KiB
Chats
Overview
A chat is a conversation container owned by a user. Agents become chat members, receive messages, and can reply in threads. Every message a user sees belongs to a chat.
Chats are either persistent (stored in the database) or temporary (in-memory only, useful for quick, unsaved conversations). Both kinds share the same features and appear together in listings.
Structure
A chat contains:
- Messages — the conversation content.
- Threads — messages can be grouped into named threads; messages without a thread go to the chat's default thread.
- Memberships — which agents are in the chat. Every agent is created with a main chat it belongs to.
Messages
Each message carries:
sender—'user'or an agent id.kind— the message class:message(normal content),log(agent internals like reasoning),note(annotations), orresource(declarations such as remotes; not shown to agents).subkind— a refinement of the kind (e.g.reasoning,remote).format— content format hint.threadId— the thread the message belongs to.
Message content may be a stream rather than a final value: the message is stored immediately with a stream reference and updated in place when the stream finishes. This is how agent replies appear progressively.
Delivery
When a message is sent to a chat:
- The chat's owner is notified over their websocket connections (as an update when a streamed message settles).
- Every member agent is notified, except the sender itself. The agent then builds a run from the message's thread and can stream a reply into the same thread.
resourcemessages are not delivered to agents — they are declarations, not conversation.
Threads
Threads are lightweight sub-conversations inside a chat:
- Messages with no thread id belong to the chat's implicit default thread.
- Named threads can be created on demand; new messages open new threads implicitly.
noteandresourcemessages are attached to their thread separately from the main message list, so notes and remote declarations travel with a thread without polluting the conversation.
Reading Chats
The ChatView is the read-side view of a chat in the backend, used both by agents (to build their message history) and by tooling:
- Loads the chat's basic data plus the most recent page of messages (
MESSAGE_PAGE_SIZE), paging further back on demand — messages are ordered by id, which is more robust than timestamps. - Groups messages into threads, keeping messages, notes, and resources separate per thread.
- Tracks the current thread (the most recently active one) and provides a debug dump of the full structure.
Lifecycle
- Chats are created with a name, description, picture, and an optional list of member agents.
- Agents can be added to existing chats at any time.
- Deleting a chat removes its memberships.
Frontend: the chat view
The chat page is the live surface of these concepts:
- Messages render with sender names resolved from the agent registry; new messages arrive over websockets, streamed content updates in place, and the user's own messages appear optimistically until the broadcast confirms them.
- Threads are UI-first: "New Thread" is a local state, and the thread is only created upstream once a message is actually sent into it. Exactly one thread is open at a time — the active one — while all others collapse into preview headers; opening a preview makes that thread active. The last thread is only continued automatically while it is fresh (ten minutes), otherwise the chat starts in "New Thread" state.
- Composing supports note mode, editing an existing message, and attaching a connected remote to the current thread as a resource.
- Runs are tracked per message, so an in-flight agent reply can be cancelled from the chat.
Backend and frontend
On the backend, chats are storage and routing: the App owns chat, thread and message persistence, membership, and the notification fan-out to users and agents. On the frontend, chats are presentation and composing: thread UX, live updates, optimistic sending, notes and edits.