# 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(); ```