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.

src/app/messages.component.ts
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.

src/app/messages.component.html
<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.

src/app/messages.component.ts
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;
}

Related