# MessagePrimitive
URL: /docs/api-reference/primitives/message
Components for rendering message content, parts, and attachments.
A single message in a conversation. Messages may consist of multiple parts.
Anatomy \[#anatomy]
```tsx
import { MessagePrimitive } from "@assistant-ui/react";
const UserMessage = () => (
User:
);
const AssistantMessage = () => (
Assistant:
);
```
API Reference \[#api-reference]
Root \[#root]
Contains all parts of the message.
This primitive renders a `
` element unless `asChild` is set.
Parts \[#parts]
The content of the message. This renders a separate component for each message part.
Quote \[#quote]
Renders a quote block if the message has quote metadata (`message.metadata.custom.quote`). Place this above `MessagePrimitive.Parts`.
```tsx
{({ text, messageId }) => }
```
PartByIndex \[#partbyindex]
Renders a single message part at the specified index.
```tsx
```
Attachments \[#attachments]
Renders all attachments of the message.
AttachmentByIndex \[#attachmentbyindex]
Renders a single attachment at the specified index within the message.
```tsx
```
useMessageQuote() \[#usemessagequote]
A hook that returns the quote info attached to the current message, if any. Reads from `message.metadata.custom.quote`.
```tsx
import { useMessageQuote } from "@assistant-ui/react";
const QuoteBlock = () => {
const quote = useMessageQuote();
if (!quote) return null;
return (
{quote.text}
);
};
```
**Returns:** `QuoteInfo | undefined`
```typescript
type QuoteInfo = {
readonly text: string; // the quoted plain text
readonly messageId: string; // the source message ID
};
```
See the [Quoting guide](/docs/guides/quoting) for a complete walkthrough.
Unstable\_PartsGrouped \[#unstable\_partsgrouped]
Renders the parts of a message grouped by a custom grouping function. Use this component when you need to visually group related message parts together — for example, grouping parts that share a common parent ID, or collecting consecutive tool calls under a single header.
The `groupingFunction` prop controls how parts are grouped. It receives the full array of message parts and must return an array of group descriptors, each with a `groupKey` (or `undefined` for ungrouped parts) and an array of `indices` into the message parts array. The optional `components.Group` component is then rendered once per group and receives the `groupKey`, `indices`, and the rendered part children.
This API is unstable and may change in a future release.
```tsx
{
const groups = new Map();
parts.forEach((part, i) => {
const key = part.parentId ?? `__ungrouped_${i}`;
const indices = groups.get(key) ?? [];
indices.push(i);
groups.set(key, indices);
});
return Array.from(groups.entries()).map(([key, indices]) => ({
groupKey: key.startsWith("__ungrouped_") ? undefined : key,
indices,
}));
}}
components={{
Text: ({ text }) => {text}
,
Group: ({ groupKey, indices, children }) => {
if (!groupKey) return <>{children}>;
return (
Parent: {groupKey}
{children}
);
},
}}
/>
```
Unstable\_PartsGroupedByParentId \[#unstable\_partsgroupedbyparentid]
A convenience wrapper around `MessagePrimitive.Unstable_PartsGrouped` that groups message parts by their `parentId` field. Parts without a `parentId` appear individually at their chronological position; parts sharing the same `parentId` are collected into a single group at the position of their first occurrence.
This API is unstable and may change in a future release.
```tsx
{
if (!groupKey) return <>{children}>;
return (
Parent ID: {groupKey}
{children}
);
},
}}
/>
```
Accepts the same `components` prop as [`MessagePrimitive.Unstable_PartsGrouped`](#unstable_partsgrouped), but without a `groupingFunction` prop (the parent-ID grouping function is applied automatically).
Error \[#error]
Renders children only if the message has an error status.
```tsx
{/* rendered if the message has an error status */}
```