CopilotChatMessageView
Angular standalone component that renders a list of chat messages, routing each message to assistant, user, reasoning, or activity rendering with slot customization.
Overview
CopilotChatMessageView renders an array of messages and routes each one to the correct renderer based on its role: assistant messages go to CopilotChatAssistantMessage, user messages to CopilotChatUserMessage, reasoning messages to the reasoning renderer, and activity messages to any registered activity renderer. It optionally renders a typing cursor at the end of the list while the agent is streaming.
This is the message-list layer used by CopilotChatView. Use it directly when you manage your own messages array and want the list without the surrounding scroll container and input.
The component is standalone and uses OnPush change detection. Reactive inputs are Angular signals.
Usage
Import the component class and use its copilot-chat-message-view selector in your template.
import { Component, signal } from "@angular/core";
import { CopilotChatMessageView } from "@copilotkit/angular";
import type { Message } from "@ag-ui/core";
@Component({
selector: "app-messages",
standalone: true,
imports: [CopilotChatMessageView],
template: `
<copilot-chat-message-view
[messages]="messages()"
[showCursor]="isLoading()"
[isLoading]="isLoading()"
/>
`,
})
export class MessagesComponent {
messages = signal<Message[]>([]);
isLoading = signal(false);
}Inputs
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Assistant message slot inputs
Prop
Type
Prop
Type
Prop
Type
User message slot inputs
Prop
Type
Reasoning message slot inputs
Prop
Type
Prop
Type
Prop
Type
Content after the message list
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Cursor slot inputs
Prop
Type
Prop
Type
Prop
Type
Outputs
Assistant actions bubble up from the assistant-message child component. Each payload is { message: Message }.
Prop
Type
Prop
Type
Prop
Type
Prop
Type
The current release declares userMessageCopy and userMessageEdit, but the default user-message child does not forward those events. Listen on a custom user-message component when you need them.
Custom layout
For full control over how the list is laid out, project a template named customLayout. It receives a context object with the current messages, the isLoading and showCursor flags, and messageElements (the messages filtered to the renderable roles). When this template is present, the default list rendering is replaced entirely.
<copilot-chat-message-view [messages]="messages()" [showCursor]="isLoading()">
<ng-template #customLayout let-messages="messages" let-showCursor="showCursor">
<div class="my-list">
@for (message of messages; track message.id) {
<div class="my-row">{{ message.content }}</div>
}
@if (showCursor) {
<span class="my-cursor">...</span>
}
</div>
</ng-template>
</copilot-chat-message-view>Customizing message rendering
To swap out how a whole role is rendered without rebuilding the layout, pass a slot input. The slot accepts either a component class or a template, with the template taking precedence.
import { Component, signal } from "@angular/core";
import { CopilotChatMessageView } from "@copilotkit/angular";
import { MyAssistantMessage } from "./my-assistant-message.component";
import type { Message } from "@ag-ui/core";
@Component({
selector: "app-messages",
standalone: true,
imports: [CopilotChatMessageView],
template: `
<copilot-chat-message-view
[messages]="messages()"
[assistantMessageComponent]="assistantMessage"
/>
`,
})
export class MessagesComponent {
messages = signal<Message[]>([]);
protected readonly assistantMessage = MyAssistantMessage;
}