# 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 = () => (
  <MessagePrimitive.Root>
    User: <MessagePrimitive.Parts />
    <BranchPicker />
    <ActionBar />
  </MessagePrimitive.Root>
);

const AssistantMessage = () => (
  <MessagePrimitive.Root>
    Assistant: <MessagePrimitive.Parts />
    <BranchPicker />
    <ActionBar />
  </MessagePrimitive.Root>
);
```

API Reference \[#api-reference]

Root \[#root]

Containts all parts of the message.

This primitive renders a `<div>` element unless `asChild` is set.

<ParametersTable
  type="MessagePrimitiveRootProps"
  parameters={[
{
  name: "asChild",
},
]}
/>

Parts \[#parts]

The content of the message. This renders a separate component for each content part of the message.

<ParametersTable
  type="MessagePrimitiveContentProps"
  parameters={[
{
  name: "components",
  required: false,
  type: "ContentPartComponents",
  description: "The components to render for each content part.",
  children: [
    {
      type: "ContentPartComponents",
      parameters: [
        {
          name: "Text",
          type: "TextContentPartComponent",
          description:
            "The component to render for each text content part.",
        },
        {
          name: "Image",
          type: "ImageContentPartComponent",
          description:
            "The component to render for each image content part.",
        },
        {
          name: "Source",
          type: "SourceContentPartComponent",
          description:
            "The component to render for each source content part.",
        },
        {
          name: "File",
          type: "FileContentPartComponent",
          description:
            "The component to render for each file content part.",
        },
        {
          name: "Unstable_Audio",
          type: "Unstable_AudioContentPartComponent",
          description:
            "The component to render for each audio content part.",
        },
        {
          name: "tools",
          type: "object",
          description:
            "The component to render for each tool call content part.",
          children: [
            {
              parameters: [
                {
                  name: "by_name",
                  type: "Record<string, ToolCallContentPartComponent>",
                  description:
                    "The components to render for each tool call content part.",
                },
                {
                  name: "Fallback",
                  type: "ToolCallContentPartComponent",
                  description:
                    "The fallback component to render for tool call content parts.",
                },
              ],
            },
          ],
        },
        {
          name: "ToolGroup",
          type: "ComponentType<PropsWithChildren<{ startIndex: number; endIndex: number }>>",
          description:
            "Component for rendering grouped consecutive tool calls. When provided, consecutive tool-call content parts will be automatically grouped and wrapped with this component.",
          children: [
            {
              type: "ToolGroupProps",
              parameters: [
                {
                  name: "startIndex",
                  type: "number",
                  description: "Index of the first tool call in the group.",
                  required: true,
                },
                {
                  name: "endIndex",
                  type: "number",
                  description: "Index of the last tool call in the group.",
                  required: true,
                },
                {
                  name: "children",
                  type: "ReactNode",
                  description:
                    "The rendered tool call components within the group.",
                  required: true,
                },
              ],
            },
          ],
        },
      ],
    },
  ],
},
]}
/>

PartByIndex \[#partbyindex]

Renders a single message part at the specified index.

```tsx
<MessagePrimitive.PartByIndex
  index={0}
  components={{
    Text: MyTextComponent,
    Image: MyImageComponent
  }}
/>
```

<ParametersTable
  type="MessagePrimitive.PartByIndex.Props"
  parameters={[
{
  name: "index",
  type: "number",
  required: true,
  description: "The index of the message part to render.",
},
{
  name: "components",
  required: false,
  type: "ContentPartComponents",
  description: "The components to render for the message part.",
},
]}
/>

Attachments \[#attachments]

Renders all attachments of the message.

<ParametersTable
  type="MessagePrimitive.Attachments.Props"
  parameters={[
{
  name: "components",
  type: "AttachmentComponents",
  description: "The components to render for each attachment.",
  children: [
    {
      type: "AttachmentComponents",
      parameters: [
        {
          name: "Image",
          type: "ComponentType",
          description: "The component to render for image attachments.",
        },
        {
          name: "Document",
          type: "ComponentType",
          description: "The component to render for document attachments.",
        },
        {
          name: "File",
          type: "ComponentType",
          description: "The component to render for file attachments.",
        },
        {
          name: "Attachment",
          type: "ComponentType",
          description: "The fallback component to render for any attachment type.",
        },
      ],
    },
  ],
},
]}
/>

AttachmentByIndex \[#attachmentbyindex]

Renders a single attachment at the specified index within the message.

```tsx
<MessagePrimitive.AttachmentByIndex
  index={0}
  components={{
    Image: MyImageAttachment,
    Document: MyDocumentAttachment
  }}
/>
```

<ParametersTable
  type="MessagePrimitive.AttachmentByIndex.Props"
  parameters={[
{
  name: "index",
  type: "number",
  required: true,
  description: "The index of the attachment to render.",
},
{
  name: "components",
  type: "AttachmentComponents",
  description: "The components to render for the attachment.",
},
]}
/>

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 (
    <div className="mb-2 flex items-start gap-1.5 text-sm italic text-muted-foreground">
      {quote.text}
    </div>
  );
};
```

**Returns:** `QuoteInfo | undefined`

```typescript
type QuoteInfo = {
  readonly text: string;       // the quoted plain text
  readonly messageId: string;  // the source message ID
};
```

<Callout type="info">
  See the [Quoting guide](/docs/guides/quoting) for a complete walkthrough.
</Callout>

Error \[#error]

Renders children only if the message has an error status.

```tsx
<MessagePrimitive.Error>
  {/* rendered if the message has an error status */}
  <ErrorPrimitive.Root>
    <ErrorPrimitive.Message />
  </ErrorPrimitive.Root>
</MessagePrimitive.Error>
```
