# 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 */} ```