CopilotChatMessageView
Component for rendering a list of chat messages
Open your coding agent in your project's folder, or in an empty folder for a new app.This runs in a coding agent on your computer.
Overview
CopilotChatMessageView renders a list of chat messages and, optionally, a typing cursor while the agent is running. It delegates rendering of individual messages to slot components (assistantMessage and userMessage) and supports a render-prop children function for full control over layout.
Import
import { CopilotChatMessageView } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";Props
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Slots
All slot props follow the CopilotKit slot system: each accepts a replacement React component, a className string that is merged into the default component's classes, or a partial props object that extends the default component.
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Usage
Basic Message List
function MessageList() {
const { agent } = useAgent();
return (
<CopilotChatMessageView
messages={agent.messages}
isRunning={agent.isRunning}
/>
);
}Customizing Message Slots
function CustomMessages() {
const { agent } = useAgent();
return (
<CopilotChatMessageView
messages={agent.messages}
isRunning={agent.isRunning}
assistantMessage="bg-blue-50 p-4 rounded-xl"
userMessage="bg-gray-100 p-4 rounded-xl"
cursor={() => (
<div className="animate-pulse text-gray-400">Thinking...</div>
)}
/>
);
}Render-Prop Children for Custom Layout
function CustomLayout() {
const { agent } = useAgent();
return (
<CopilotChatMessageView
messages={agent.messages}
isRunning={agent.isRunning}
>
{({ isRunning, messages, messageElements }) => (
<div className="flex flex-col gap-4 p-6">
<div className="text-sm text-gray-500">
{messages.length} message{messages.length !== 1 ? "s" : ""}
</div>
{messageElements}
{isRunning && (
<div className="text-sm text-blue-500 animate-pulse">
Agent is responding...
</div>
)}
</div>
)}
</CopilotChatMessageView>
);
}Choosing How Tool Calls Show
function AgentChat() {
const { agent } = useAgent();
return (
<CopilotChatMessageView
messages={agent.messages}
isRunning={agent.isRunning}
toolCallDisplay="turn"
/>
);
}From CopilotChat, CopilotSidebar or CopilotPopup, set it through the
messageView slot:
<CopilotChat messageView={{ toolCallDisplay: "line" }} />To give every call its own card again:
<CopilotChat messageView={{ toolCallDisplay: "separate" }} />Hiding the Toolbar on Assistant Messages
function MinimalChat() {
const { agent } = useAgent();
return (
<CopilotChatMessageView
messages={agent.messages}
isRunning={agent.isRunning}
assistantMessage={{ toolbarVisible: false }}
/>
);
}Behavior
- Message Rendering: Each message in the
messagesarray is rendered using the corresponding slot component based on itsrole. Assistant messages use theassistantMessageslot; user messages use theuserMessageslot. - Cursor Display: The
cursorslot is only rendered whenisRunningistrue. It appears after the last message in the list, and is hidden when the last rendered message is a reasoning message, which shows its own indicator. - Virtualization: Inside a chat scroll container, once more than 50 messages render, only the rows on screen are mounted. The count is of the messages that render: the ones
transformMessagesreturns or, withgroupMessages, the ones in the rows it returns. The window itself moves by rows, and each group is one row. Providingchildrenturns virtualization off; in development the component warns once when that is what keeps a long thread mounted in full. - Latest Message: The last rendered message is passed to its slot as
isLatest. WhileisRunningistrue, the latest assistant message hides its toolbar and a latest reasoning message shows as streaming. - Tool-Call Groups: Groups can span messages, since agents often send each call as its own assistant message. The group belongs to the message where it starts, and the later messages whose calls joined it render no tool calls of their own. While the agent is running and nothing follows a group, its summary names the call in progress.
- Work Summary: In the
"turn"display, the summary replaces the cursor while the reply is in progress. "Worked for 9s" adds up the agent's runs on the reply, so waiting between them (for an approval, say) doesn't count. It needs a reply this component watched start, so a restored thread shows the tool count ("Used 7 tools") instead. Text that ends the reply stays visible after the fold, even when its message also calls a tool. Opening or closing a reply's work sticks, even when later runs update it. - Render-Prop Override: When
childrenis provided as a function, the component delegates all layout to that function. ThemessageElementsarray is pre-built from the slot components, so custom layouts still benefit from slot customization. - Slot System: Each slot prop accepts three forms -- a replacement component, a className string merged into the default, or a partial props object that extends the default component's props.
Related
CopilotChatAssistantMessage-- Default assistant message slot componentCopilotChatUserMessage-- Default user message slot componentCopilotChatToolCallGroup-- Default group for tool calls made in a rowCopilotChatView-- Higher-level chat view that composes this component