Skip to main content
The CopilotChat component provides a complete chat interface for interacting with AI agents. It handles message display, user input, suggestions, voice transcription, and agent execution automatically.

Basic Usage

import { CopilotChat } from "@copilotkit/react-core";

function App() {
  return (
    <div style={{ height: "100vh" }}>
      <CopilotChat />
    </div>
  );
}

Props

agentId
string
The ID of the agent to use for this chat. Defaults to "default".
threadId
string
The conversation thread ID. If not provided, a new unique thread is created automatically.
labels
Partial<CopilotChatLabels>
Custom labels for UI text elements. Override default text for placeholders, buttons, and messages.Available labels:
  • inputPlaceholder - Placeholder text for the input field
  • stopGenerating - Text for the stop button
  • microphoneButtonLabel - Accessibility label for microphone button
  • And more…
welcomeScreen
React.ReactElement | boolean
Custom welcome screen component shown before the first message. Set to false to disable.
onError
(event) => void | Promise<void>
Error handler scoped to this chat’s agent. Fires in addition to the provider-level onError.Receives:
  • error - The error object
  • code - CopilotKit error code
  • context - Additional context (including agentId)
className
string
CSS class name for the chat container.

Slot Customization

CopilotChat supports extensive customization through slots:
messageView
React.Component | object
Customize message rendering. Can be a custom component or configuration object with className.
suggestionView
React.Component | object
Customize suggestion pill rendering.
input
React.Component | object
Customize the input component. Can pass additional props like disclaimer.
chatView
React.Component
Replace the entire chat view component with a custom implementation.

Examples

Basic Chat

import { CopilotChat } from "@copilotkit/react-core";

function BasicChat() {
  return (
    <div style={{ height: "600px" }}>
      <CopilotChat 
        labels={{
          inputPlaceholder: "Ask me anything...",
        }}
      />
    </div>
  );
}

Multi-Agent Chat

import { CopilotChat } from "@copilotkit/react-core";
import { useState } from "react";

function MultiAgentChat() {
  const [activeAgent, setActiveAgent] = useState("default");
  
  return (
    <div>
      <div className="agent-selector">
        <button onClick={() => setActiveAgent("default")}>
          General Assistant
        </button>
        <button onClick={() => setActiveAgent("research-agent")}>
          Research Agent
        </button>
        <button onClick={() => setActiveAgent("code-agent")}>
          Code Assistant
        </button>
      </div>
      
      <div style={{ height: "600px" }}>
        <CopilotChat agentId={activeAgent} />
      </div>
    </div>
  );
}

Custom Welcome Screen

import { CopilotChat } from "@copilotkit/react-core";

function CustomWelcome({ input, suggestionView, ...props }) {
  return (
    <div {...props}>
      <div style={{ textAlign: "center", padding: "40px" }}>
        <h1>Welcome to AI Assistant</h1>
        <p>I can help you with:</p>
        <ul>
          <li>Answering questions</li>
          <li>Searching documentation</li>
          <li>Writing code</li>
        </ul>
      </div>
      {suggestionView}
      {input}
    </div>
  );
}

function ChatWithCustomWelcome() {
  return (
    <div style={{ height: "600px" }}>
      <CopilotChat welcomeScreen={CustomWelcome} />
    </div>
  );
}

Error Handling

import { CopilotChat } from "@copilotkit/react-core";
import { useState } from "react";

function ChatWithErrorHandling() {
  const [error, setError] = useState<string | null>(null);
  
  return (
    <div>
      {error && (
        <div className="error-banner">
          Error: {error}
          <button onClick={() => setError(null)}>Dismiss</button>
        </div>
      )}
      
      <div style={{ height: "600px" }}>
        <CopilotChat
          onError={({ error, code }) => {
            console.error(`Error ${code}:`, error);
            setError(error.message);
          }}
        />
      </div>
    </div>
  );
}

Persistent Thread

import { CopilotChat } from "@copilotkit/react-core";
import { useState, useEffect } from "react";

function PersistentChat() {
  const [threadId, setThreadId] = useState<string | null>(null);
  
  // Load thread ID from localStorage
  useEffect(() => {
    const saved = localStorage.getItem("chat-thread-id");
    if (saved) {
      setThreadId(saved);
    } else {
      const newId = crypto.randomUUID();
      localStorage.setItem("chat-thread-id", newId);
      setThreadId(newId);
    }
  }, []);
  
  if (!threadId) return <div>Loading...</div>;
  
  return (
    <div style={{ height: "600px" }}>
      <CopilotChat threadId={threadId} />
    </div>
  );
}

Custom Message Styling

import { CopilotChat } from "@copilotkit/react-core";

function StyledChat() {
  return (
    <div style={{ height: "600px" }}>
      <CopilotChat
        messageView={{
          className: "custom-message"
        }}
        className="custom-chat"
      />
    </div>
  );
}

// In your CSS:
// .custom-chat { background: #f5f5f5; }
// .custom-message { border-radius: 12px; padding: 16px; }

Disable Welcome Screen

import { CopilotChat } from "@copilotkit/react-core";

function NoWelcomeChat() {
  return (
    <div style={{ height: "600px" }}>
      <CopilotChat welcomeScreen={false} />
    </div>
  );
}

Custom Labels

import { CopilotChat } from "@copilotkit/react-core";

function LocalizedChat() {
  return (
    <div style={{ height: "600px" }}>
      <CopilotChat
        labels={{
          inputPlaceholder: "Escribe un mensaje...",
          stopGenerating: "Detener",
          microphoneButtonLabel: "Grabar audio"
        }}
      />
    </div>
  );
}

Voice Transcription

CopilotChat includes built-in voice transcription support when configured:
import { CopilotKitProvider, CopilotChat } from "@copilotkit/react-core";

function App() {
  return (
    <CopilotKitProvider
      runtimeUrl="/api/copilotkit"
      transcriptionUrl="/api/transcribe" // Enable transcription
    >
      <CopilotChat />
    </CopilotKitProvider>
  );
}
Users can click the microphone button to record audio, which is automatically transcribed and inserted into the input field.

Auto-scroll Behavior

CopilotChat automatically scrolls to show new messages. The scroll behavior adapts to user interaction:
  • Automatically scrolls when new messages arrive
  • Preserves scroll position when user scrolls up
  • Shows a “scroll to bottom” button when not at bottom
  • Smooth animations during transitions

Tool Rendering

CopilotChat automatically renders tool calls registered with:
  • useFrontendTool
  • useHumanInTheLoop
  • useRenderTool
Tool calls appear inline in the conversation with their custom UI.

Suggestions

Display suggestions to users before or after messages:
import { useFrontendTool, CopilotChat } from "@copilotkit/react-core";

function ChatWithSuggestions() {
  return (
    <CopilotKitProvider
      runtimeUrl="/api/copilotkit"
      suggestions={{
        suggestions: [
          { title: "Hello", message: "Say hello" },
          { title: "Help", message: "Show help information" }
        ],
        available: "before-first-message"
      }}
    >
      <div style={{ height: "600px" }}>
        <CopilotChat />
      </div>
    </CopilotKitProvider>
  );
}

Best Practices

Set Container Height

Always set a height on the CopilotChat container. The component uses height: 100% internally and needs a sized parent.

One Chat Per Agent

Each CopilotChat manages one agent conversation. Use multiple CopilotChat components for multi-agent UIs.

Handle Errors

Implement onError to handle runtime errors gracefully and provide feedback to users.

Persistent Threads

Use consistent thread IDs to maintain conversation history across sessions.

Accessibility

CopilotChat includes built-in accessibility features:
  • ARIA labels for interactive elements
  • Keyboard navigation support
  • Screen reader announcements for new messages
  • Focus management for modal interactions

Styling

CopilotChat uses Tailwind CSS internally. You can:
  • Override styles with custom CSS classes
  • Use the className prop for container styling
  • Customize slot components for deeper control
  • Apply your own Tailwind theme

TypeScript

interface CopilotChatProps {
  agentId?: string;
  threadId?: string;
  labels?: Partial<CopilotChatLabels>;
  welcomeScreen?: React.ReactElement | boolean;
  onError?: (event: {
    error: Error;
    code: CopilotKitCoreErrorCode;
    context: Record<string, any>;
  }) => void | Promise<void>;
  className?: string;
  messageView?: React.Component | { className?: string };
  suggestionView?: React.Component | { className?: string };
  input?: React.Component | { disclaimer?: React.Component };
  chatView?: React.Component;
}

interface CopilotChatLabels {
  inputPlaceholder: string;
  stopGenerating: string;
  microphoneButtonLabel: string;
  // ... more labels
}

Component Hierarchy

CopilotChat
├── CopilotChatView
│   ├── WelcomeScreen (optional)
│   ├── ScrollView
│   │   └── MessageView (for each message)
│   │       └── ToolCallsView (for tool calls)
│   ├── SuggestionView
│   └── Input
│       ├── Textarea
│       ├── Send Button
│       └── Microphone Button (if enabled)