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 internally by CopilotChatView. It mirrors React's CopilotChatMessageView. Use it directly when you manage your own messages array and want only the list rendering 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
Assistant message slot inputs
Prop
Type
Prop
Type
Prop
Type
User message slot inputs
Prop
Type
Prop
Type
Prop
Type
Cursor slot inputs
Prop
Type
Prop
Type
Prop
Type
Outputs
These bubble up from the per-message child components so you can observe toolbar interactions from the list level. Each payload is { message: Message }.
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
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;
}