5.2 KiB
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
"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
import { CopilotPopup } from "@copilotkit/react-core/v2";
<CopilotPopup agentId="default" defaultOpen={false} />;
Persistent sidebar
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.
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
<CopilotChat
agentId="default"
labels={{
chatInputPlaceholder: "Ask about the data…",
welcomeMessageText: "What would you like to analyze?",
}}
/>
Common Mistakes
CRITICAL — Importing CopilotPanel
Wrong:
import { CopilotPanel } from "@copilotkit/react-core/v2";
Correct:
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:
import { CopilotPopup } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
Correct:
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:
<CopilotChat agentId="default" messages={myMessages} isRunning={busy} />
Correct:
// 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 Omits 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:
<CopilotChat agentId="research" threadId="t1" />
<CopilotChat agentId="research" threadId="t1" />
Correct:
// 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:
import { CopilotChat } from "@copilotkit/react-core/v2";
// …no styles imported
Correct:
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)