Skip to content
SLICES / TECHNICAL FOLIO Nº 001FULL-STACK ASSEMBLIES — OPEN SOURCE

Headless / AI chat

Artifact workspace

Versioned React source written by the model through the createArtifact and updateArtifact tools, inspected beside the chat: a card in the transcript, a nonmodal panel that can be resized, version navigation with a diff, and a preview that runs only when somebody presses Run, in an isolated iframe. Nothing is stored beyond the conversation and nothing executes in the host page.

27 public parts · 2examples

@slices.sh/chat-artifacts/headlessView as Markdown ↗

Your design. Our behavior.

Explore the tree to see what each part controls. Gates reveal the relevant state; roots outline their scope.

Behavior / inputGateGenericRenderer · not headlessScope
COMPONENT ANATOMYHover · focus · tap
ONE POSSIBLE DESIGNStatic preview

Chat.Root · Scope

Chat.RootChat.Root publishes the SDK Chat itself, never a copy of its state, and provides a sink for Composer. submit(message) calls sendMessage with message.text and message.attachments as file parts. busy is true while a reply streams or a question or tool decision waits. whenBusy is "queue" unless queue={false}. accept.attachments follows the config's files capability: false for a config without files, so the attachment picker inside Composer renders nothing. A Chat.Root nested in another one with the same config and no chat shares the outer conversation.

Installation

Choose what your component needs. Run these commands in an initialized Next.js app.

0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the service registry

Adds services/index.ts, which import "@/services" loads. A provider setup writes the same file, so skip this if your app has one.

npx add services
2

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/chat-artifacts@^0.1.2 @slices.sh/ai-chat@^0.1.4

Import from @slices.sh/chat-artifacts/headless.

3

Install the service

Connect the parts to a provider. Skip this step if this service is already configured in your app.

Provider
npx add ai-chat.echo

Adds service configuration and API routes to your app, with the provider dependencies. For a headless composition, add import "@/services" after "use client".

The slices CLI installs the service and provisions its required resources in one command.

Provider setup notes
  • Echo needs nothing. When you want a model: npx shadcn@latest add @slices/ai-chat.vercel, then switch provider in services/ai-chat/default.config.ts.

Start small

Parts bring the behavior. Use their default elements, or supply your own with render.

example.tsx
"use client"// services/index.ts comes from https://slices.sh/r/services.json (or any provider setup)import "@/services"import { Chat } from "@slices.sh/ai-chat/headless"import { ChatArtifacts } from "@slices.sh/chat-artifacts/headless"export function Example() {  return (    <Chat.Root>      <ChatArtifacts.Root>        <Chat.Messages>          <Chat.Message>            <Chat.Parts>              <ChatArtifacts.PartCard>                {({ version }) => (                  <ChatArtifacts.Open artifactId={version.artifactId}>                    {version.title}                  </ChatArtifacts.Open>                )}              </ChatArtifacts.PartCard>            </Chat.Parts>          </Chat.Message>        </Chat.Messages>        <ChatArtifacts.Panel>          <ChatArtifacts.Close>Close</ChatArtifacts.Close>        </ChatArtifacts.Panel>      </ChatArtifacts.Root>    </Chat.Root>  )}

Requires a chat whose tools produce artifacts. The echo provider does not produce them.

API reference

Every public part used by this experience is listed below. Gates render children without adding an element. Element parts accept native element props and render; function children receive the state declared in their props. Scopes provide context rather than a visual element.

ChatArtifacts.Runtimescope

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.Runtime requires ChatArtifacts.Root.

Props

1 documented props

ChatArtifacts.Runtime props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/artifact-runtime.tsx

ChatArtifacts.Runaction · <button>

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.Run requires ChatArtifacts.Root.

ChatArtifacts.Run requires ChatArtifacts.Runtime.

Props

2 documented props · Native <button> attributes supported

ChatArtifacts.Run props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/run.tsx

ChatArtifacts.StopPreviewaction · <button>

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.StopPreview requires ChatArtifacts.Runtime.

Props

2 documented props · Native <button> attributes supported

ChatArtifacts.StopPreview props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/stop-preview.tsx

ChatArtifacts.PreviewFramecontent · <iframe>

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.PreviewFrame requires ChatArtifacts.Runtime.

Props

2 documented props · Native <iframe> attributes supported

ChatArtifacts.PreviewFrame props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/preview-frame.tsx

ChatArtifacts.PreviewIdlegate

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.PreviewIdle requires ChatArtifacts.Runtime.

Props

1 documented props

ChatArtifacts.PreviewIdle props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/preview-idle.tsx

ChatArtifacts.PreviewLoadinggate

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.PreviewLoading requires ChatArtifacts.Runtime.

Props

1 documented props

ChatArtifacts.PreviewLoading props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/preview-loading.tsx

ChatArtifacts.PreviewErrorgate

Runtime scopes the compilation, frame and console of the selected version (artifact-runtime). Run compiles in a worker and shows the preview; StopPreview cancels and removes the frame. PreviewFrame locks its srcdoc, sandbox and permissions. PreviewIdle, PreviewLoading and PreviewError gate its states. Changing version or closing the panel discards the previous run.

Capability: artifact-runtime

Required scope

ChatArtifacts.PreviewError requires ChatArtifacts.Runtime.

Props

1 documented props

ChatArtifacts.PreviewError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { error: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/preview-error.tsx

ChatArtifacts.Consolecontent · <ol>

Console gives { entries }, bounded text-only output from the frame. ConsoleEmpty renders before anything is logged, and ClearConsole empties it.

Required scope

ChatArtifacts.Console requires ChatArtifacts.Runtime.

Props

2 documented props · Native <ol> attributes supported

ChatArtifacts.Console props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { entries: ArtifactLog[] }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/console.tsx

ChatArtifacts.ConsoleEmptygate

Console gives { entries }, bounded text-only output from the frame. ConsoleEmpty renders before anything is logged, and ClearConsole empties it.

Required scope

ChatArtifacts.ConsoleEmpty requires ChatArtifacts.Runtime.

Props

1 documented props

ChatArtifacts.ConsoleEmpty props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/console-empty.tsx

ChatArtifacts.ClearConsoleaction · <button>

Console gives { entries }, bounded text-only output from the frame. ConsoleEmpty renders before anything is logged, and ClearConsole empties it.

Required scope

ChatArtifacts.ClearConsole requires ChatArtifacts.Runtime.

Props

2 documented props · Native <button> attributes supported

ChatArtifacts.ClearConsole props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/clear-console.tsx

ChatArtifacts.Rootscope · <div>

Root reads artifacts from the Chat inside Chat.Root and owns the selection and split. PartCard gates a valid streamed or completed artifact call inside Chat.Parts and hands { version }. OtherTool renders its children for every tool call that is not an artifact, so the chat's own tool UI handles approvals, refusals and malformed calls. Open artifact={id} version={n} opens the panel on that version.

Required scope

ChatArtifacts.Root requires Chat.Root.

Props

2 documented props · Native <div> attributes supported

ChatArtifacts.Root props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/root.tsx

ChatArtifacts.PartCardgate

Root reads artifacts from the Chat inside Chat.Root and owns the selection and split. PartCard gates a valid streamed or completed artifact call inside Chat.Parts and hands { version }. OtherTool renders its children for every tool call that is not an artifact, so the chat's own tool UI handles approvals, refusals and malformed calls. Open artifact={id} version={n} opens the panel on that version.

Required scope

ChatArtifacts.PartCard requires Chat.Parts.

ChatArtifacts.PartCard requires ChatArtifacts.Root.

Props

1 documented props

ChatArtifacts.PartCard props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { version: ArtifactVersion }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/part-card.tsx

ChatArtifacts.OtherToolgate

Root reads artifacts from the Chat inside Chat.Root and owns the selection and split. PartCard gates a valid streamed or completed artifact call inside Chat.Parts and hands { version }. OtherTool renders its children for every tool call that is not an artifact, so the chat's own tool UI handles approvals, refusals and malformed calls. Open artifact={id} version={n} opens the panel on that version.

Required scope

ChatArtifacts.OtherTool requires Chat.Parts.

ChatArtifacts.OtherTool requires ChatArtifacts.Root.

Props

1 documented props

ChatArtifacts.OtherTool props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/other-tool.tsx

ChatArtifacts.Openaction · <button>

Root reads artifacts from the Chat inside Chat.Root and owns the selection and split. PartCard gates a valid streamed or completed artifact call inside Chat.Parts and hands { version }. OtherTool renders its children for every tool call that is not an artifact, so the chat's own tool UI handles approvals, refusals and malformed calls. Open artifact={id} version={n} opens the panel on that version.

Required scope

ChatArtifacts.Open requires ChatArtifacts.Root.

Props

4 documented props · Native <button> attributes supported

ChatArtifacts.Open props
PropTypeDefault
artifactIdRequired
string—
callId
string—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/open.tsx

ChatArtifacts.Panelcontent · <div>

Panel is an inline nonmodal dialog on wide screens and a full-viewport modal on narrow ones; the chat stays usable beside it and Escape returns focus. Title, Description and Close label and dismiss it. Resize is a pointer and keyboard separator between the chat and the panel, 58% to the artifact at first, within 30% to 75%.

Required scope

ChatArtifacts.Panel requires ChatArtifacts.Root.

Props

2 documented props · Native <div> attributes supported

ChatArtifacts.Panel props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/panel.tsx

ChatArtifacts.Closeaction · <button>

Panel is an inline nonmodal dialog on wide screens and a full-viewport modal on narrow ones; the chat stays usable beside it and Escape returns focus. Title, Description and Close label and dismiss it. Resize is a pointer and keyboard separator between the chat and the panel, 58% to the artifact at first, within 30% to 75%.

Props

2 documented props · Native <button> attributes supported

ChatArtifacts.Close props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/close.tsx

ChatArtifacts.Selectedgate

Selected hands the selected artifact, its version, the preceding version and its index. Previous and Next move between versions in the transcript without asking the model anything. Diff gives a bounded source diff against the preceding version, with a coarse fallback when it is too large.

Required scope

ChatArtifacts.Selected requires ChatArtifacts.Root.

Props

1 documented props

ChatArtifacts.Selected props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: NonNullable<ArtifactSelection["current"]>) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/selected.tsx

ChatArtifacts.Previousaction · <button>

Selected hands the selected artifact, its version, the preceding version and its index. Previous and Next move between versions in the transcript without asking the model anything. Diff gives a bounded source diff against the preceding version, with a coarse fallback when it is too large.

Required scope

ChatArtifacts.Previous requires ChatArtifacts.Root.

Props

2 documented props · Native <button> attributes supported

ChatArtifacts.Previous props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/previous.tsx

ChatArtifacts.Nextaction · <button>

Selected hands the selected artifact, its version, the preceding version and its index. Previous and Next move between versions in the transcript without asking the model anything. Diff gives a bounded source diff against the preceding version, with a coarse fallback when it is too large.

Required scope

ChatArtifacts.Next requires ChatArtifacts.Root.

Props

2 documented props · Native <button> attributes supported

ChatArtifacts.Next props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/next.tsx

ChatArtifacts.Diffgate

Selected hands the selected artifact, its version, the preceding version and its index. Previous and Next move between versions in the transcript without asking the model anything. Diff gives a bounded source diff against the preceding version, with a coarse fallback when it is too large.

Required scope

ChatArtifacts.Diff requires ChatArtifacts.Root.

Props

1 documented props

ChatArtifacts.Diff props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: ArtifactDiff) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/diff.tsx

ChatArtifacts.Resizecontent · <div>

Panel is an inline nonmodal dialog on wide screens and a full-viewport modal on narrow ones; the chat stays usable beside it and Escape returns focus. Title, Description and Close label and dismiss it. Resize is a pointer and keyboard separator between the chat and the panel, 58% to the artifact at first, within 30% to 75%.

Required scope

ChatArtifacts.Resize requires ChatArtifacts.Root.

Props

2 documented props · Native <div> attributes supported

ChatArtifacts.Resize props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/resize.tsx

ChatArtifacts.Titlecontent

Panel is an inline nonmodal dialog on wide screens and a full-viewport modal on narrow ones; the chat stays usable beside it and Escape returns focus. Title, Description and Close label and dismiss it. Resize is a pointer and keyboard separator between the chat and the panel, 58% to the artifact at first, within 30% to 75%.

Props

0 documented props

No additional named props are declared here. See TypeScript for the inherited contract.

Required props are marked. A dash means no explicit default is declared in this component.

Also inherits React.ComponentProps<typeof Dialog.Title>. See TypeScript for the complete declaration.

Source: @slices.sh/chat-artifacts/src/headless/index.ts

ChatArtifacts.Descriptioncontent

Panel is an inline nonmodal dialog on wide screens and a full-viewport modal on narrow ones; the chat stays usable beside it and Escape returns focus. Title, Description and Close label and dismiss it. Resize is a pointer and keyboard separator between the chat and the panel, 58% to the artifact at first, within 30% to 75%.

Props

0 documented props

No additional named props are declared here. See TypeScript for the inherited contract.

Required props are marked. A dash means no explicit default is declared in this component.

Also inherits React.ComponentProps<typeof Dialog.Description>. See TypeScript for the complete declaration.

Source: @slices.sh/chat-artifacts/src/headless/index.ts

ChatArtifacts.Tabscontent · <div>

Tabs, TabList, Tab and TabPanel switch between source, diff, preview and console with native tab keyboard behaviour.

Required scope

ChatArtifacts.Tabs requires ChatArtifacts.Runtime.

Props

2 documented props · Native <div> attributes supported

ChatArtifacts.Tabs props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/chat-artifacts/src/headless/view-tabs.tsx

ChatArtifacts.TabListcontent

Tabs, TabList, Tab and TabPanel switch between source, diff, preview and console with native tab keyboard behaviour.

Props

0 documented props

No additional named props are declared here. See TypeScript for the inherited contract.

Required props are marked. A dash means no explicit default is declared in this component.

Also inherits React.ComponentProps<typeof Tabs.List>. See TypeScript for the complete declaration.

Source: @slices.sh/chat-artifacts/src/headless/index.ts

ChatArtifacts.Tabcontent

Tabs, TabList, Tab and TabPanel switch between source, diff, preview and console with native tab keyboard behaviour.

Props

0 documented props

No additional named props are declared here. See TypeScript for the inherited contract.

Required props are marked. A dash means no explicit default is declared in this component.

Also inherits React.ComponentProps<typeof Tabs.Tab>. See TypeScript for the complete declaration.

Source: @slices.sh/chat-artifacts/src/headless/index.ts

ChatArtifacts.TabPanelcontent

Tabs, TabList, Tab and TabPanel switch between source, diff, preview and console with native tab keyboard behaviour.

Props

0 documented props

No additional named props are declared here. See TypeScript for the inherited contract.

Required props are marked. A dash means no explicit default is declared in this component.

Also inherits React.ComponentProps<typeof Tabs.Panel>. See TypeScript for the complete declaration.

Source: @slices.sh/chat-artifacts/src/headless/index.ts

Chat.Rootscope

Chat.Root publishes the SDK Chat itself, never a copy of its state, and provides a sink for Composer. submit(message) calls sendMessage with message.text and message.attachments as file parts. busy is true while a reply streams or a question or tool decision waits. whenBusy is "queue" unless queue={false}. accept.attachments follows the config's files capability: false for a config without files, so the attachment picker inside Composer renders nothing. A Chat.Root nested in another one with the same config and no chat shares the outer conversation.

Props

9 documented props

Chat.Root props
PropTypeDefault
onFeedback
(feedback: ChatFeedback) => void | Promise<void>—
name

The key in services/ai-chat/config.ts: the route the chat talks to when it is handed none. Left out, the config's slug.

string—
config

The config to talk to, "default" when left out.

string—
enabled

Left out or true: required, and a missing service or config throws. "optional": renders its children, and a Composer under it renders nothing. false: off. A capability name requires the service and that capability.

Enabled—
chat

An AI SDK Chat the app made — its id, the messages it opens on, a transport with your headers — which every part reads with useChat({ chat }). Without one, a chat over the installed backend's route.

AiChat—
settings

From chatSession(client, name), bound to the supplied Chat transport.

ChatSettings | null—
queue

The sink's whenBusy: on, a message sent mid-answer is accepted and queued; off, Composer holds it until the chat is free.

booleantrue
rememberApprovals

Enable explicit per-tool consent remembered only for this Chat instance.

booleantrue
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/root.tsx

Chat.Messagesscope

The transcript's messages, each in its own scope, exactly as the AI SDK holds them. The repeat is a part rather than a `map` in the pattern, because a message is where the looks change most and the iteration never does: a skin decides what a row is, and this decides what the rows are.

Required scope

Chat.Messages must be inside <Chat.Root>.

Props

1 documented props

Chat.Messages props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/messages.tsx

Chat.Messagecontent · <div>

Messages repeats once per UIMessage and Message is its element: data-state user or assistant, aria-busy while it is the answer being written, data-invalid when it was cut off. Speaker says who spoke, for screen readers. Parts repeats once per SDK part in the order the model produced them, and each kind has its own gate: PartText is one run of prose, StepBoundary marks a new model step. Stopped renders only for a reply that was cut off, and Continue sends a follow-up prompt that resumes it.

Required scope

Chat.Message must be inside <Chat.Messages>.

Chat.Message must be inside <Chat.Root>.

Props

3 documented props · Native <div> attributes supported

Chat.Message props
PropTypeDefault
optimizeHistory
booleantrue
children

Content rendered inside this part.

ReactNode | ((state: MessageState) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/message.tsx

Chat.Partsscope

A message's parts, in the order the model produced them, exactly as the AI SDK holds them. The order is the content. Reasoning before an answer, a tool call between two halves of one, a citation after both — a transcript that grouped by kind would say the model did things in an order it did not. Each kind gates itself inside here, and a kind no gate draws — a step boundary, an app's own `data-*` part — draws nothing. → docs/rules/states-gate-themselves.md

Required scope

Chat.Parts must be inside <Chat.Messages>.

Props

1 documented props

Chat.Parts props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/ai-chat/src/headless/parts.tsx

When something is missing

No service configuration
Install the chat-artifacts setup below and import "@/services". Required service roots report missing setup; gates do not replace that configuration.
Missing capability or parent scope
Follow each part’s context requirements and the example composition. Capability-aware controls hide when the provider cannot perform their action.
Read the setup guide →