# Headless Chat Primitives
URL: /docs/primitives

Unstyled, accessible Radix-style building blocks for React AI chat interfaces — Thread, Composer, Message, and more, ready to compose with assistant-ui.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

Primitives are the foundation of assistant-ui. They are unstyled, accessible React components that handle all the wiring for AI chat, including state management, keyboard shortcuts, auto-scrolling, streaming, and tool calls, so you can focus entirely on your UI.

## Why Primitives?

Every assistant-ui [Component](/docs/ui/thread) is built from primitives. When you install a component like `Thread`, you get a pre-styled composition of primitives with default styling and behavior included.

But when you need a UI that doesn't fit the defaults, such as a floating composer, a custom message layout, or an inline editing experience, you reach for the primitives directly.

```
import { ComposerPrimitive } from "@assistant-ui/react";

<ComposerPrimitive.Root>
  <ComposerPrimitive.Input placeholder="Ask anything..." />
  <ComposerPrimitive.Send>Send</ComposerPrimitive.Send>
</ComposerPrimitive.Root>
```

This renders an unstyled `<form>` with a `<textarea>` and a `<button>`. No styles, no opinions, but it already handles submit-on-enter, focus management, empty-state disabling, and streaming state.

## How They Work

Every primitive follows the same pattern inspired by [Radix UI](https://www.radix-ui.com/):

- **`Primitive.Root`**: container that provides context to child parts
- **`Primitive.PartName`**: individual elements (input, button, text, etc.)
- **`asChild`**: merge primitive behavior onto your own element instead of rendering a wrapper
- **`AuiIf`**: conditional rendering based on state

Primitives read from the nearest runtime context. Place them inside an `AssistantRuntimeProvider` and they work without prop drilling or manual state wiring.

## Available Primitives

- [Composer](/docs/primitives/composer) —

  Text input, send button, attachments, and dictation. The interface for composing new messages or editing existing ones.

- [Thread](/docs/primitives/thread) —

  The scrollable message container with auto-scroll, empty states, and message rendering.

- [Message](/docs/primitives/message) —

  Individual message rendering with role-based content, parts, and metadata.

- [ActionBar](/docs/primitives/action-bar) —

  Copy, reload, edit, and other message actions.

- [BranchPicker](/docs/primitives/branch-picker) —

  Navigate between message branches (alternative responses).

- [ThreadList](/docs/primitives/thread-list) —

  Multi-thread management: list, create, switch, and archive threads.

- [AssistantModal](/docs/primitives/assistant-modal) —

  Floating chat popover built on Radix UI Popover.

- [Attachment](/docs/primitives/attachment) —

  File and image attachment rendering.

- [Suggestion](/docs/primitives/suggestion) —

  Suggested prompts and quick actions.

- [SelectionToolbar](/docs/primitives/selection-toolbar) —

  Floating toolbar for text selection actions like quoting.

- [Error](/docs/primitives/error) —

  Error display with accessible alert role and automatic error text.

- [ChainOfThought](/docs/primitives/chain-of-thought) —

  Collapsible reasoning accordion for thinking steps and tool calls.

`MessagePartPrimitive` (for rendering individual text, image, and streaming parts) is documented within the [Message](/docs/primitives/message#messagepartprimitive) primitive page.

## Related Primitive References

Additional primitive references:

- [MessagePartPrimitive](/docs/api-reference/primitives/message-part)
- [ThreadListItemPrimitive](/docs/api-reference/primitives/thread-list-item)
- [ThreadListItemMorePrimitive](/docs/api-reference/primitives/thread-list-item-more)
- [ActionBarMorePrimitive](/docs/api-reference/primitives/action-bar-more)
- [AuiIf](/docs/api-reference/primitives/assistant-if)

## Common Mistakes

- Forgetting to wrap primitives with runtime context (`AssistantRuntimeProvider` + runtime hook)
- Mixing deprecated props with current APIs (`submitOnEnter`, `autoSend`, legacy `Suggestion`)
- Mounting primitives in the wrong context (`ActionBarPrimitive` / `BranchPickerPrimitive` outside `MessagePrimitive.Root`)
- Using unstable props unintentionally (`unstable_*` APIs)

## Next Steps

Start with the [Composer](/docs/primitives/composer) primitive to see how primitives work in practice, or jump to the [API Reference](/docs/api-reference/primitives/composer) for full prop details.