Documents
reasoning
reasoning
Type
External
Status
Published
Created
Mar 17, 2026
Updated
Mar 17, 2026

import { ReasoningSample, ReasoningGroupSample } from "@/components/docs/samples/reasoning";

Getting Started#

Add reasoning#

<InstallCommand shadcn={["reasoning"]} />

This adds a /components/assistant-ui/reasoning.tsx file to your project.

Use in your application#

Pass the Reasoning and ReasoningGroup components to the MessagePrimitive.Parts component:

import { MessagePrimitive } from "@assistant-ui/react";
import { Reasoning } from "@/components/assistant-ui/reasoning";

const AssistantMessage: FC = () => {
  return (
    <MessagePrimitive.Root className="...">
      <div className="...">
        <MessagePrimitive.Parts>
          {({ part }) => {
            if (part.type === "reasoning") return <Reasoning {...part} />;
            return null;
          }}
        </MessagePrimitive.Parts>
      </div>
      <AssistantActionBar />
      <BranchPicker className="..." />
    </MessagePrimitive.Root>
  );
};

How It Works#

The component consists of two parts:

  1. Reasoning: Renders individual reasoning message part content (with markdown support)
  2. ReasoningGroup: Wraps consecutive reasoning parts in a collapsible container

Consecutive reasoning parts are automatically grouped together by the ReasoningGroup component.

When using the composable API, Reasoning.Text is a plain container. Add <MarkdownText /> for markdown rendering.

Variants#

Use the variant prop on Reasoning.Root to change the visual style:

<Reasoning.Root variant="outline">...</Reasoning.Root>
<Reasoning.Root variant="ghost">...</Reasoning.Root>
<Reasoning.Root variant="muted">...</Reasoning.Root>
VariantDescription
outlineRounded border (default)
ghostNo additional styling
mutedMuted background

ReasoningGroup#

ReasoningGroup wraps consecutive reasoning parts in a collapsible container. It auto-expands during streaming.

import { ReasoningGroup } from "@/components/assistant-ui/reasoning";

const ReasoningGroupImpl: ReasoningGroupComponent = ({
  children,
  startIndex,
  endIndex,
}) => {
  const isReasoningStreaming = useAuiState((s) => {
    if (s.message.status?.type !== "running") return false;
    const lastIndex = s.message.parts.length - 1;
    if (lastIndex < 0) return false;
    const lastType = s.message.parts[lastIndex]?.type;
    if (lastType !== "reasoning") return false;
    return lastIndex >= startIndex && lastIndex <= endIndex;
  });

  return (
    <ReasoningRoot defaultOpen={isReasoningStreaming}>
      <ReasoningTrigger active={isReasoningStreaming} />
      <ReasoningContent aria-busy={isReasoningStreaming}>
        <ReasoningText>{children}</ReasoningText>
      </ReasoningContent>
    </ReasoningRoot>
  );
};

API Reference#

Composable API#

All sub-components are exported for custom layouts:

ComponentDescription
Reasoning.RootCollapsible container with scroll lock
Reasoning.TriggerButton with icon, label, and shimmer
Reasoning.ContentAnimated collapsible content wrapper
Reasoning.TextText wrapper with slide/fade animation
Reasoning.FadeGradient fade overlay at bottom
import {
  Reasoning,
  ReasoningRoot,
  ReasoningTrigger,
  ReasoningContent,
  ReasoningText,
  ReasoningFade,
} from "@/components/assistant-ui/reasoning";

// Compound component syntax
<Reasoning.Root variant="muted">
  <Reasoning.Trigger active={isStreaming} />
  <Reasoning.Content>
    <Reasoning.Text>{children}</Reasoning.Text>
  </Reasoning.Content>
</Reasoning.Root>
  • ToolGroup - Similar grouping pattern for tool calls
  • PartGrouping - Experimental API for grouping message parts