# CopilotKit Chat Components (React)

This skill builds on `copilotkit/provider-setup`. Read it first — every
chat component must be inside the `CopilotKit` provider (from
`@copilotkit/react-core/v2`).

All chat components live on `@copilotkit/react-core/v2`. The legacy
`@copilotkit/react-ui` package is v1-only; its `/v2` subpath is a CSS-only
import.

## Setup

```tsx
"use client";
import { CopilotChat } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";

export function ChatPanel() {
  return <CopilotChat agentId="default" />;
}
```

`<CopilotChat>` manages messages, input, streaming, attachments, and
suggestions internally via `useAgent`. You do not pass `messages` or
`isRunning` — they are managed for you.

## Core Patterns

### Floating popup

```tsx
import { CopilotPopup } from "@copilotkit/react-core/v2";

<CopilotPopup agentId="default" defaultOpen={false} />;
```

### Persistent sidebar

```tsx
import { CopilotSidebar } from "@copilotkit/react-core/v2";

<CopilotSidebar agentId="default">
  <MainAppContent />
</CopilotSidebar>;
```

### Headless composition with slot primitives

Use `CopilotChatView` plus the individual slot components when you need
full control over messages, input, or layout. This is the path when you
want to manage `messages`/`isRunning` yourself.

```tsx
import {
  CopilotChatView,
  useAgent,
  useCopilotKit,
} from "@copilotkit/react-core/v2";

export function HeadlessChat() {
  const { agent } = useAgent({ agentId: "default" });
  const { copilotkit } = useCopilotKit();

  return (
    <CopilotChatView
      messages={agent.messages}
      isRunning={agent.isRunning}
      onSubmitMessage={async (text) => {
        agent.addMessage({
          id: crypto.randomUUID(),
          role: "user",
          content: text,
        });
        await copilotkit.runAgent({ agent });
      }}
    >
      {({ messageView, input }) => (
        <>
          {messageView}
          {input}
        </>
      )}
    </CopilotChatView>
  );
}
```

### Custom labels

```tsx
<CopilotChat
  agentId="default"
  labels={{
    chatInputPlaceholder: "Ask about the data…",
    welcomeMessageText: "What would you like to analyze?",
  }}
/>
```

## Common Mistakes

### CRITICAL — Importing `CopilotPanel`

Wrong:

```tsx
import { CopilotPanel } from "@copilotkit/react-core/v2";
```

Correct:

```tsx
import {
  CopilotChat,
  CopilotPopup,
  CopilotSidebar,
  CopilotChatView,
} from "@copilotkit/react-core/v2";
```

`CopilotPanel` does not exist in v2 (or v1). This is a common hallucination.
The four chat surfaces are `CopilotChat`, `CopilotPopup`, `CopilotSidebar`,
and the headless `CopilotChatView`.

Source: `packages/react-core/src/v2/components/chat/index.ts` (no `CopilotPanel` export)

### CRITICAL — Importing chat components from `@copilotkit/react-ui` in v2

Wrong:

```tsx
import { CopilotPopup } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
```

Correct:

```tsx
import { CopilotPopup } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";
```

`@copilotkit/react-ui` is v1 only. The v2 subpath of `react-ui` is a
CSS-only import — the components are not there. All v2 chat components ship
from `@copilotkit/react-core/v2`.

Source: `packages/react-ui/src/v2/index.ts` (CSS-only); v2 migration guide

### HIGH — Passing `messages` or `isRunning` to `<CopilotChat>`

Wrong:

```tsx
<CopilotChat agentId="default" messages={myMessages} isRunning={busy} />
```

Correct:

```tsx
// CopilotChat manages messages and isRunning internally.
<CopilotChat agentId="default" />

// For manual control, drop down to headless CopilotChatView. Its `children`
// is a render prop that receives the bound slot elements:
<CopilotChatView
  messages={myMessages}
  isRunning={busy}
  onSubmitMessage={handleSubmit}
>
  {({ messageView, input }) => (
    <>
      {messageView}
      {input}
    </>
  )}
</CopilotChatView>
```

`CopilotChatProps` explicitly `Omit`s `messages` and `isRunning` — passing
them is a TypeScript error, and `<CopilotChat>` always reads from its
internal `useAgent` call.

Source: `packages/react-core/src/v2/components/chat/CopilotChat.tsx:37-52`

### MEDIUM — Two `<CopilotChat>` with the same `agentId` + `threadId`

Wrong:

```tsx
<CopilotChat agentId="research" threadId="t1" />
<CopilotChat agentId="research" threadId="t1" />
```

Correct:

```tsx
// Either use distinct threadIds...
<CopilotChat agentId="research" threadId="panel-a" />
<CopilotChat agentId="research" threadId="panel-b" />

// ...or mount only one <CopilotChat> instance per agent/thread.
```

Both components resolve to the same per-thread clone (cached in a
module-level WeakMap) and submit duplicate messages. See `agent-access` for
the clone semantics.

Source: `packages/react-core/src/v2/hooks/use-agent.tsx:78-119`

### MEDIUM — Missing the v2 CSS import

Wrong:

```tsx
import { CopilotChat } from "@copilotkit/react-core/v2";
// …no styles imported
```

Correct:

```tsx
import { CopilotChat } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";
```

The chat components ship unstyled without the v2 stylesheet. Import it once
at the root of the app or in the same file that sets up the provider.

Source: `packages/react-core/src/v2/index.ts:3` (imports `./index.css`)
