Chat - Core
Runtime, adapter contract, hooks, selectors, and stream processing for building fully custom chat UIs.
@mui/x-chat/headless is the runtime-focused layer in the chat package family.
It gives you chat state, streaming, adapters, selectors, and composer logic without imposing any rendered UI.
Where core fits
Use the core layer when you want chat behavior but you want to own the markup, layout, styling, and interaction model yourself.
Core owns:
- the normalized chat store
- controlled and uncontrolled state models
- adapter-driven message sending and history loading
- stream processing and runtime callbacks
- realtime subscriptions and presence/read updates
- selector-friendly hooks for render-sensitive trees
- composer state, attachments, and submit behavior
- typed message-part and stream contracts
Core does not own:
- semantic DOM structure
- default rendering for message parts
- visual slots or compound components
- Material UI theming or styling
Those concerns belong to Headless.
Mental model
The following demo shows the core runtime with a minimal custom UI:
Minimal headless chat
Send the first message to start the thread.
The runtime is easiest to understand as a pipeline:
ChatProvidercreates the store and runtime actions.- Your
ChatAdaptertalks to the backend and returns streams. processStreamturns chunks into normalized message updates.- Hooks and selectors read the store at the granularity your UI needs.
- Your components render plain React, headless primitives, or your own design system.
<ChatProvider adapter={adapter}>
<YourCustomChatUI />
</ChatProvider>
The main public surface is:
import {
ChatProvider,
chatSelectors,
useChat,
useChatComposer,
useChatPartRenderer,
useChatStatus,
useChatStore,
useConversation,
useConversations,
useMessage,
useMessageIds,
} from '@mui/x-chat/headless';
State and store
ChatProvider supports both controlled and uncontrolled state for messages, conversations, active conversation ID, and composer value.
Internally the store normalizes data into ID arrays and record maps, making streaming updates efficient and selector subscriptions granular.
See State and store for the full ChatProvider props reference, the controlled/uncontrolled model, error model, callbacks, and store internals.
Hooks
Nine public hooks cover the full spectrum from all-in-one orchestration (useChat()) to row-level subscriptions (useMessageIds() + useMessage(id)).
Narrower hooks like useChatComposer(), useChatStatus(), and useChatPartRenderer() handle specific concerns without subscribing to unrelated state.
See Hooks for signatures, return types, and when-to-use guidance for every hook.
Selectors
chatSelectors provides memoized selectors for the normalized store.
Use them directly with useChatStore() for custom derived values and advanced subscriptions.
See Selectors for the full selector table and usage patterns.
Adapter contract
ChatAdapter is the transport boundary between the runtime and your backend.
Only sendMessage() is required — everything else is optional and incrementally adopted.
The adapter works with HTTP, SSE, WebSocket, or AI SDK-style streaming backends.
See Adapters for the full interface reference, a step-by-step writing guide, and backend pattern guidance.
Streaming
The adapter returns a ReadableStream of typed chunks.
The runtime processes text, reasoning, tool, source, file, data, step, and metadata chunks into normalized message parts.
streamFlushInterval batches rapid deltas for efficient store updates.
See Streaming for the chunk protocol reference, envelope format, and stream construction patterns.
Realtime
The adapter's subscribe() method enables push-based updates for messages, conversations, typing indicators, presence, and read state.
The runtime manages the subscription lifecycle on mount and unmount.
See Realtime for event types, store effects, and consumption patterns.
Type augmentation
Module augmentation lets you add app-specific metadata, typed tool definitions, typed data-* payloads, and custom message parts.
Types flow through the entire stack at compile time — no provider props needed.
See Type augmentation for the six registry interfaces, a step-by-step guide, and an end-to-end example.
Core examples
The core examples are organized as demos. Move from the smallest setup to the more specialized runtime patterns:
- Core examples overview
- Minimal core chat
- Controlled state
- Selector-driven thread
- Conversation history
- Composer
- Message parts
- Streaming lifecycle
- Realtime
- Realtime thread sync
- Tool call events
- Type augmentation
- Tool approval and renderers
- Advanced store access
Scope boundary
- Stay on core when you want runtime primitives and complete control over UI.
- Move to Headless when you want structure and composition primitives.