CopilotChatAssistantMessage

Vue 3 component for displaying assistant messages with Markdown, tool calls, and an action toolbar


Overview

CopilotChatAssistantMessage is a Vue 3 component that displays assistant messages with Markdown support, tool call rendering, and an action toolbar. Markdown is rendered with streamdown-vue (StreamMarkdown), which supports GitHub Flavored Markdown tables, math expressions (KaTeX styles are loaded automatically), and syntax-highlighted code blocks via Shiki (github-light / github-dark themes). Tables and code blocks include built-in copy and download actions, and images get a hover download button.

The toolbar provides copy, thumbs up, thumbs down, read aloud, and regenerate buttons. Tooltip and aria labels are sourced from the nearest CopilotChatConfigurationProvider (see useCopilotChatConfiguration). The thumbs up, thumbs down, read aloud, and regenerate buttons are only rendered when a listener for the corresponding event is attached; the copy button is always shown when the toolbar is visible.

The toolbar is hidden while the latest assistant message is still streaming (when isRunning is true for the last message) and when the message has no text content. It also respects the toolbarVisible prop.

Import

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
</script>

Example

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

const message: AssistantMessage = {
  id: "1",
  role: "assistant",
  content: "Here is **Markdown** with a `code` sample.",
};
</script>

<template>
  <CopilotChatAssistantMessage
    :message="message"
    @thumbs-up="(msg) => console.log('Thumbs up:', msg.id)"
    @thumbs-down="(msg) => console.log('Thumbs down:', msg.id)"
  />
</template>

Props

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Events

Each event emits the current message as its payload. Attaching a listener for thumbs-up, thumbs-down, read-aloud, or regenerate also causes the matching toolbar button to render; without a listener the button is omitted.

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Copying the message to the clipboard is handled internally by the copy button. There is no copy event; the copy button is always present when the toolbar is visible.

Slots

The component exposes named slots so you can override individual pieces of the default layout. Each slot receives scoped props (shown below) that wire its behavior to the message and toolbar handlers.

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Usage

Basic assistant message

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

defineProps<{ message: AssistantMessage }>();
</script>

<template>
  <CopilotChatAssistantMessage
    :message="message"
    @thumbs-up="(msg) => console.log('Thumbs up:', msg.id)"
    @thumbs-down="(msg) => console.log('Thumbs down:', msg.id)"
  />
</template>

Adding regenerate and read aloud

Attaching the listeners makes the corresponding buttons appear automatically.

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

defineProps<{ message: AssistantMessage }>();

function handleRegenerate(msg: AssistantMessage) {
  // re-run the agent for this message
}

function handleReadAloud(msg: AssistantMessage) {
  // speak msg.content
}
</script>

<template>
  <CopilotChatAssistantMessage
    :message="message"
    @regenerate="handleRegenerate"
    @read-aloud="handleReadAloud"
  />
</template>

Adding custom toolbar items

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

defineProps<{ message: AssistantMessage }>();
</script>

<template>
  <CopilotChatAssistantMessage :message="message">
    <template #toolbar-items>
      <button type="button" @click="shareMessage(message)">Share</button>
    </template>
  </CopilotChatAssistantMessage>
</template>

Hiding the toolbar

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

defineProps<{ message: AssistantMessage }>();
</script>

<template>
  <CopilotChatAssistantMessage :message="message" :toolbar-visible="false" />
</template>

Custom Markdown renderer

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

defineProps<{ message: AssistantMessage }>();
</script>

<template>
  <CopilotChatAssistantMessage :message="message">
    <template #message-renderer="{ content }">
      <div class="custom-markdown">{{ content }}</div>
    </template>
  </CopilotChatAssistantMessage>
</template>

Customizing a toolbar button

<script setup lang="ts">
import { CopilotChatAssistantMessage } from "@copilotkit/vue/v2";
import type { AssistantMessage } from "@ag-ui/core";

defineProps<{ message: AssistantMessage }>();
</script>

<template>
  <CopilotChatAssistantMessage
    :message="message"
    @regenerate="(msg) => regenerate(msg)"
  >
    <template #regenerate-button="{ onRegenerate, label }">
      <button type="button" :title="label" @click="onRegenerate">
        Regenerate
      </button>
    </template>
  </CopilotChatAssistantMessage>
</template>

Related