# Reasoning

> A collapsible block that shows how an agent reached its answer, with the reasoning streamed in as markdown.

## Facts

- **Product**: Crew OS
- **Family**: AI
- **Global**: `window.DigitalCrew.Reasoning`
- **Source**: `digitalcrew-orchestrator: components/ui/reasoning.tsx`
- **Import in the app**: `import { Reasoning } from "@/components/ui/reasoning";`
- **Live preview**: /design/components/reasoning/preview.html
- **Page**: /design/components/reasoning

## Guidelines

**Use it for** the "thinking" part of an agent reply: which signals it weighed before proposing a meeting time or a next step. Keep the answer itself outside the block.

**What you provide**: `Reasoning` (`open`/`onOpenChange` to control it; uncontrolled it starts open), `ReasoningTrigger` (its children are the label), `ReasoningContent` (the collapsing region, `className` for the rule or spacing), and inside it `ReasoningResponse` with `text` (a string or `AsyncIterable<string>`) and the [`ResponseStream`](/design/components/response-stream.md) options: `speed` (default 20), `mode` (default `typewriter`), `onComplete`, `fadeDuration`, `segmentDelay`, `characterChunkSize`.

**Anatomy**: the trigger is a button with an 8px gap, the label in `text-primary` and a 16px chevron that turns 180° when open. The response renders [`Markdown`](/design/components/markdown.md) in `text-sm text-muted-foreground`; its `prose` classes have no effect in Crew OS (no typography plugin), so style lists and emphasis through `className`.

**Behaviour**: the content animates `max-height` over 300ms ease-out between 0 and its measured height (a ResizeObserver follows the growing text). The response fades between opacity 0 and 1 over 300ms with the open state.

**Don't** put the final answer or actions inside the block, or open several reasoning blocks at once in one reply.

## API

```ts
export type ReasoningProps = {
    children: React.ReactNode;
    className?: string;
    open?: boolean;
    onOpenChange?: (open: boolean) => void;
};
declare function Reasoning({ children, className, open, onOpenChange, }: ReasoningProps): any;
export type ReasoningTriggerProps = {
    children: React.ReactNode;
    className?: string;
} & React.HTMLAttributes<HTMLButtonElement>;
declare function ReasoningTrigger({ children, className, ...props }: ReasoningTriggerProps): any;
export type ReasoningContentProps = {
    children: React.ReactNode;
    className?: string;
} & React.HTMLAttributes<HTMLDivElement>;
declare function ReasoningContent({ children, className, ...props }: ReasoningContentProps): any;
export type ReasoningResponseProps = {
    text: string | AsyncIterable<string>;
    className?: string;
    speed?: number;
    mode?: Mode;
    onComplete?: () => void;
    fadeDuration?: number;
    segmentDelay?: number;
    characterChunkSize?: number;
};
declare function ReasoningResponse({ text, className, speed, mode, onComplete, fadeDuration, segmentDelay, characterChunkSize, }: ReasoningResponseProps): any;
export { Reasoning, ReasoningTrigger, ReasoningContent, ReasoningResponse };
```

## Example

```html
<div id="root" class="p-6"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
  var thinking = "Claire opened the last two emails but has not replied. Her calendar shows the Northwind budget review on **14 October**.\n\n- Tuesday 14:30 has the best acceptance rate for CFOs in her region\n- Wednesday clashes with her board prep\n\nSo I will propose Tuesday 14:30, Paris time.";
  function App() {
    return h("div", { className: "grid max-w-xl gap-4" },
      h("div", { className: "ml-auto max-w-sm rounded-2xl bg-secondary px-4 py-2.5 text-sm text-secondary-foreground" }, "When should we follow up with Claire Dubois?"),
      h("div", { className: "grid gap-3 rounded-xl border bg-card p-4" },
        h(DC.Reasoning, null,
          h(DC.ReasoningTrigger, { className: "text-sm" }, "Show reasoning"),
          h(DC.ReasoningContent, { className: "mt-2 border-l-2 pl-3" },
            h(DC.ReasoningResponse, { text: thinking, speed: 60, className: "space-y-2 [&_strong]:font-semibold [&_ul]:list-disc [&_ul]:pl-5" }))),
        h("p", { className: "text-sm" }, "Propose Tuesday 14:30 (Paris). I have drafted the email in your outbox.")));
  }
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>
```

## More in AI

- [Markdown](/design/components/markdown.md): Renders a markdown string (GitHub-flavoured: tables, task lists, strikethrough) and stays cheap while an AI reply streams in.
- [ResponseStream](/design/components/response-stream.md): Reveals text progressively, either typed out character by character or faded in word by word, from a string or an async stream of chunks.
