# MessagePartPrimitive
URL: /docs/api-reference/primitives/message-part
Primitives for text, images, tool calls, and other message content.
Each message can have any number of message parts.
Message parts are usually one of text, reasoning, audio, tool-call, or data.
Message part Types \[#message-part-types]
Text \[#text]
Standard text content, used for both user and assistant messages.
Reasoning \[#reasoning]
Exposes the assistant's reasoning process, showing how it arrived at its responses. This is typically used only in assistant messages.
Audio \[#audio]
Audio content that can be played back.
Tool Call \[#tool-call]
Interactive elements that represent tool operations.
Data \[#data]
Custom data events that can be rendered as UI at their position in the message stream. Each data part has a `name` and a `data` payload.
You can use either the explicit format `{ type: "data", name: "workflow", data: {...} }` or the shorthand `data-*` prefixed format `{ type: "data-workflow", data: {...} }`. The prefixed format is automatically converted to a `DataMessagePart` (stripping the `data-` prefix as the `name`). Unknown message part types that don't match any built-in type are silently skipped with a console warning.
Streaming Data Parts \[#streaming-data-parts]
Data parts can be sent from the server using `appendData()` on the stream controller:
```ts
controller.appendData({
type: "data",
name: "chart",
data: { labels: ["Q1", "Q2"], values: [10, 20] },
});
```
Register a renderer with `makeAssistantDataUI` to display data parts:
```tsx
import { makeAssistantDataUI } from "@assistant-ui/react";
const ChartUI = makeAssistantDataUI({
name: "chart",
render: ({ data }) => ,
});
```
Anatomy \[#anatomy]
```tsx
import { MessagePartPrimitive } from "@assistant-ui/react";
const TextMessagePart = () => {
return ;
};
```
Primitives \[#primitives]
Plain Text \[#plain-text]
```tsx
import { MessagePartPrimitive } from "@assistant-ui/react";
;
```
Markdown Text \[#markdown-text]
Renders the message's text as Markdown.
```tsx
import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
;
```
Audio \[#audio-1]
Coming soon.
InProgress \[#inprogress]
Renders children only if the message part is in progress.
```tsx
import { MessagePartPrimitive } from "@assistant-ui/react";
;
```
Tool UI \[#tool-ui]
You can map tool calls to UI components. We provide a few utility functions to make this easier, such as `makeAssistantToolUI`.
```tsx
const MyWeatherToolUI = makeAssistantToolUI({
toolName: "get_weather",
render: function MyWeatherToolUI({ args, result }) {
return (
get_weather({JSON.stringify(args)})
{result !== undefined && (
{JSON.stringify(result)}
)}
);
},
});
```
Data UI \[#data-ui]
You can map data events to UI components, similar to tool UIs. There are two approaches:
Inline configuration \[#inline-configuration]
Pass a `data` config to `MessagePrimitive.Parts`:
```tsx
{({ part }) => {
if (part.type === "data" && part.name === "my_chart") return ;
if (part.type === "data") return {JSON.stringify(part.data, null, 2)};
return null;
}}
```
Global registration \[#global-registration]
Use `makeAssistantDataUI` or `useAssistantDataUI` to register data UIs globally. Global registrations take priority over inline configuration.
```tsx
import { makeAssistantDataUI } from "@assistant-ui/react";
const MyChartUI = makeAssistantDataUI({
name: "my_chart",
render: ({ name, data }) => ,
});
// Place inside AssistantRuntimeProvider
function App() {
return (
);
}
```
The hook variant allows access to component state:
```tsx
import { useAssistantDataUI } from "@assistant-ui/react";
function MyComponent() {
useAssistantDataUI({
name: "my_chart",
render: ({ name, data }) => ,
});
return null;
}
```
Each data component receives the full data part as props: `{ type: "data", name: string, data: T, status: MessagePartStatus }`.
For a catch-all renderer (e.g. LangSmith's [`LoadExternalComponent`](/docs/runtimes/langgraph#dynamic-loading-with-fallback) loaded at runtime), pass `Fallback` via the inline `data` config on `MessagePrimitive.Parts`, or use the LangGraph adapter's [`uiComponents.fallback`](/docs/runtimes/langgraph#dynamic-loading-with-fallback) option.
Messages (Sub-Agent) \[#messages-sub-agent]
Renders nested messages from a tool call part's `messages` field. This is used in multi-agent setups where a sub-agent's conversation is embedded inside a tool call.
```tsx
import { MessagePartPrimitive } from "@assistant-ui/react";
{({ message }) => {
if (message.role === "user") return ;
return ;
}}
;
```
This primitive must be used inside a tool call part context (e.g. inside a `makeAssistantToolUI` render function). It reads the `messages` field from the current `ToolCallMessagePart` and renders them in a readonly thread context.
Parent tool UI registrations are inherited — tools registered via `makeAssistantToolUI` at the parent level are available inside sub-agent messages.
See the [Multi-Agent Guide](/docs/guides/multi-agent) for detailed usage.
Context Provider \[#context-provider]
Message part context is provided by `MessagePrimitive.Parts` or `TextMessagePartProvider`
MessagePrimitive.Parts \[#messageprimitiveparts]
```tsx
import { MessagePrimitive } from "@assistant-ui/react";
{({ part }) => {
if (part.type === "text") return ;
if (part.type === "reasoning") return ;
if (part.type === "audio") return ;
if (part.type === "tool-call" && part.toolName === "get_weather") return ;
if (part.type === "tool-call") return ;
if (part.type === "data" && part.name === "my_chart") return ;
if (part.type === "data") return ;
return null;
}}
;
```
TextMessagePartProvider \[#textmessagepartprovider]
This is a helper context provider to allow you to reuse the message part components outside a message part.
```tsx
import { TextMessagePartProvider } from "@assistant-ui/react";
;
```
Runtime API \[#runtime-api]
`useAui` (Message Part Actions) \[#useaui-message-part-actions]
```tsx
import { useAui } from "@assistant-ui/react";
const aui = useAui();
aui.part().addToolResult(result);
const partState = aui.part().getState();
```
`useAuiState` (Message Part State) \[#useauistate-message-part-state]
```tsx
import { useAuiState } from "@assistant-ui/react";
const type = useAuiState((s) => s.part.type);
const status = useAuiState((s) => s.part.status);
```
`useMessagePartText` \[#usemessageparttext]
```tsx
import { useMessagePartText } from "@assistant-ui/react";
const { text, status } = useMessagePartText();
```