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
The ID of the agent to use for this chat. Defaults to "default".
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)
CSS class name for the chat container.
Slot Customization
CopilotChat supports extensive customization through slots:
Customize message rendering. Can be a custom component or configuration object with className.
Customize suggestion pill rendering.
Customize the input component. Can pass additional props like disclaimer.
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.
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
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)