chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
---
|
||||
title: CopilotChatAssistantMessage
|
||||
description: "AI response rendering component with toolbar actions"
|
||||
---
|
||||
|
||||
`CopilotChatAssistantMessage` is the default component used by [CopilotChatMessageView](/reference/copilot-chat-message-view) to render AI assistant responses. It handles markdown rendering, feedback collection, and tool call display.
|
||||
|
||||
## What is CopilotChatAssistantMessage?
|
||||
|
||||
The CopilotChatAssistantMessage component:
|
||||
|
||||
- Renders AI responses with full markdown support
|
||||
- Provides a toolbar with copy, feedback, and action buttons
|
||||
- Handles thumbs up/down feedback collection
|
||||
- Supports text-to-speech (read aloud) functionality
|
||||
- Displays tool call executions with visual feedback
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatAssistantMessage provides slots for customizing each part of the message:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
AM[CopilotChatAssistantMessage] --> markdownRenderer
|
||||
AM --> toolbar
|
||||
AM --> copyButton
|
||||
AM --> thumbsUpButton
|
||||
AM --> thumbsDownButton
|
||||
AM --> readAloudButton
|
||||
AM --> regenerateButton
|
||||
AM --> toolCallsView
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| ------------------ | ------------------------------------------------- |
|
||||
| `markdownRenderer` | Renders the message content with markdown support |
|
||||
| `toolbar` | Container for action buttons |
|
||||
| `copyButton` | Button to copy message content |
|
||||
| `thumbsUpButton` | Positive feedback button |
|
||||
| `thumbsDownButton` | Negative feedback button |
|
||||
| `readAloudButton` | Text-to-speech button |
|
||||
| `regenerateButton` | Button to regenerate the response |
|
||||
| `toolCallsView` | Renders tool call executions |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize assistant messages through the `messageView.assistantMessage` slot on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
className: "bg-slate-50 rounded-xl p-4",
|
||||
onThumbsUp: (message) => trackFeedback(message.id, "positive"),
|
||||
onThumbsDown: (message) => trackFeedback(message.id, "negative"),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Feedback Callbacks
|
||||
|
||||
CopilotChatAssistantMessage provides callbacks for user feedback:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (message) => {
|
||||
analytics.track("positive_feedback", {
|
||||
messageId: message.id,
|
||||
content: message.content,
|
||||
});
|
||||
},
|
||||
onThumbsDown: (message) => {
|
||||
analytics.track("negative_feedback", {
|
||||
messageId: message.id,
|
||||
content: message.content,
|
||||
});
|
||||
},
|
||||
onRegenerate: (message) => {
|
||||
console.log("Regenerating:", message.id);
|
||||
},
|
||||
onReadAloud: (message) => {
|
||||
speechSynthesis.speak(new SpeechSynthesisUtterance(message.content));
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Callback Props
|
||||
|
||||
| Callback | Signature | Description |
|
||||
| -------------- | ------------------------------------- | -------------------------------------- |
|
||||
| `onThumbsUp` | `(message: AssistantMessage) => void` | Called when user clicks thumbs up |
|
||||
| `onThumbsDown` | `(message: AssistantMessage) => void` | Called when user clicks thumbs down |
|
||||
| `onRegenerate` | `(message: AssistantMessage) => void` | Called when user requests regeneration |
|
||||
| `onReadAloud` | `(message: AssistantMessage) => void` | Called when user clicks read aloud |
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatAssistantMessage uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Toolbar Customization
|
||||
|
||||
Control visibility and styling of the toolbar:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
toolbar: "bg-gray-50 rounded-lg p-2",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
To hide the entire toolbar:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
toolbarVisible: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Individual Button Customization
|
||||
|
||||
Customize specific toolbar buttons:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
copyButton: "text-blue-500 hover:text-blue-700",
|
||||
thumbsUpButton: "text-green-500 hover:text-green-700",
|
||||
thumbsDownButton: "text-red-500 hover:text-red-700",
|
||||
readAloudButton: "text-purple-500 hover:text-purple-700",
|
||||
regenerateButton: "text-orange-500 hover:text-orange-700",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Hiding Specific Buttons
|
||||
|
||||
Hide buttons by returning null:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
readAloudButton: () => null,
|
||||
regenerateButton: () => null,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Note: `thumbsUpButton` and `thumbsDownButton` only show when their respective callbacks (`onThumbsUp`, `onThumbsDown`) are provided.
|
||||
|
||||
### Markdown Renderer Customization
|
||||
|
||||
Customize how message content is rendered:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
markdownRenderer: {
|
||||
className: "prose prose-lg dark:prose-invert",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Tool Calls View Customization
|
||||
|
||||
Customize how tool executions are displayed:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
toolCallsView: "bg-gray-100 rounded-lg p-3",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Replacing the Component
|
||||
|
||||
To completely replace the assistant message component:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatAssistantMessage } from "@copilotkit/react-core";
|
||||
|
||||
function CustomAssistantMessage({ message, isRunning, ...props }) {
|
||||
return (
|
||||
<div className="flex gap-3 items-start">
|
||||
<Avatar src="/ai-avatar.png" />
|
||||
<div className="flex-1">
|
||||
<CopilotChatAssistantMessage
|
||||
message={message}
|
||||
isRunning={isRunning}
|
||||
className="bg-white shadow-sm rounded-xl p-4"
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: CustomAssistantMessage,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Using the Render Function
|
||||
|
||||
For full layout control, use the children render function:
|
||||
|
||||
```tsx
|
||||
function CustomAssistantMessage(props) {
|
||||
return (
|
||||
<CopilotChatAssistantMessage {...props}>
|
||||
{({ markdownRenderer, toolbar, toolCallsView, message }) => (
|
||||
<div className="flex gap-4 p-4 bg-gradient-to-r from-blue-50 to-purple-50 rounded-xl">
|
||||
<img src="/ai-avatar.png" className="w-8 h-8 rounded-full" />
|
||||
<div className="flex-1">
|
||||
<div className="text-sm text-gray-500 mb-1">AI Assistant</div>
|
||||
{markdownRenderer}
|
||||
{toolCallsView}
|
||||
<div className="mt-2 border-t pt-2">{toolbar}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatAssistantMessage>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: CustomAssistantMessage,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
The render function receives:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------ | ------------------ | ----------------------------- |
|
||||
| `markdownRenderer` | `ReactElement` | The rendered markdown content |
|
||||
| `toolbar` | `ReactElement` | The action buttons toolbar |
|
||||
| `toolCallsView` | `ReactElement` | Tool call display |
|
||||
| `copyButton` | `ReactElement` | Copy button |
|
||||
| `thumbsUpButton` | `ReactElement` | Thumbs up button |
|
||||
| `thumbsDownButton` | `ReactElement` | Thumbs down button |
|
||||
| `readAloudButton` | `ReactElement` | Read aloud button |
|
||||
| `regenerateButton` | `ReactElement` | Regenerate button |
|
||||
| `message` | `AssistantMessage` | The message data |
|
||||
| `isRunning` | `boolean` | Whether AI is generating |
|
||||
| `toolbarVisible` | `boolean` | Whether toolbar should show |
|
||||
|
||||
## Examples
|
||||
|
||||
### Analytics Integration
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (message) => {
|
||||
analytics.track("ai_feedback", {
|
||||
type: "positive",
|
||||
messageId: message.id,
|
||||
messageLength: message.content?.length,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
},
|
||||
onThumbsDown: (message) => {
|
||||
analytics.track("ai_feedback", {
|
||||
type: "negative",
|
||||
messageId: message.id,
|
||||
messageLength: message.content?.length,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Minimal Toolbar
|
||||
|
||||
Show only the copy button:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
thumbsUpButton: () => null,
|
||||
thumbsDownButton: () => null,
|
||||
readAloudButton: () => null,
|
||||
regenerateButton: () => null,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Styling
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
className: "bg-white shadow-md rounded-2xl p-6 border border-gray-100",
|
||||
markdownRenderer: "prose prose-blue max-w-none",
|
||||
toolbar: "mt-4 pt-4 border-t border-gray-100",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component
|
||||
- [CopilotChatMessageView](/reference/copilot-chat-message-view) - Message list component that uses assistant messages
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,184 @@
|
||||
---
|
||||
title: CopilotChatConfigurationProvider
|
||||
description: "CopilotChatConfigurationProvider API Reference"
|
||||
---
|
||||
|
||||
`CopilotChatConfigurationProvider` is a React context provider that manages configuration for chat UI components,
|
||||
including labels, agent ID, and thread ID. It enables customization of all text labels in the chat interface and
|
||||
provides context for chat components to access configuration values.
|
||||
|
||||
## What is CopilotChatConfigurationProvider?
|
||||
|
||||
The CopilotChatConfigurationProvider:
|
||||
|
||||
- Manages UI labels for all chat components (placeholders, button labels, etc.), allowing for localization or
|
||||
customization of the chat interface.
|
||||
- Lets you to access the current `agentId` and `threadId`
|
||||
- Supports nested configuration with proper inheritance
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Wrap your chat components with the provider to customize configuration:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatConfigurationProvider } from "@copilotkit/react-core";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CopilotChatConfigurationProvider
|
||||
threadId="main-thread"
|
||||
agentId="assistant"
|
||||
labels={{
|
||||
chatInputPlaceholder: "Ask me anything...",
|
||||
assistantMessageToolbarCopyMessageLabel: "Copy response",
|
||||
}}
|
||||
>
|
||||
{/* Your chat components */}
|
||||
</CopilotChatConfigurationProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### threadId
|
||||
|
||||
`string` **(required)**
|
||||
|
||||
A unique identifier for the conversation thread. This is used to maintain conversation history and context.
|
||||
|
||||
```tsx
|
||||
<CopilotChatConfigurationProvider threadId="conversation-123">
|
||||
{children}
|
||||
</CopilotChatConfigurationProvider>
|
||||
```
|
||||
|
||||
### agentId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
The ID of the agent to use for this chat context. If not provided, defaults to `"default"`.
|
||||
|
||||
```tsx
|
||||
<CopilotChatConfigurationProvider
|
||||
threadId="thread-1"
|
||||
agentId="customer-support"
|
||||
>
|
||||
{children}
|
||||
</CopilotChatConfigurationProvider>
|
||||
```
|
||||
|
||||
### labels
|
||||
|
||||
`Partial<CopilotChatLabels>` **(optional)**
|
||||
|
||||
Custom labels for chat UI elements. Any labels not provided will use the default values.
|
||||
|
||||
```tsx
|
||||
<CopilotChatConfigurationProvider
|
||||
threadId="thread-1"
|
||||
labels={{
|
||||
chatInputPlaceholder: "Type your message here...",
|
||||
chatDisclaimerText: "AI responses may contain errors.",
|
||||
assistantMessageToolbarRegenerateLabel: "Try again",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CopilotChatConfigurationProvider>
|
||||
```
|
||||
|
||||
### children
|
||||
|
||||
`ReactNode` **(required)**
|
||||
|
||||
The React components that will have access to the chat configuration context.
|
||||
|
||||
## Using with CopilotChat
|
||||
|
||||
The `CopilotChat` component automatically creates its own `CopilotChatConfigurationProvider` internally. When using
|
||||
`CopilotChat`, you can pass configuration directly as props:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
threadId="main-thread"
|
||||
agentId="assistant"
|
||||
labels={{
|
||||
chatInputPlaceholder: "How can I help you today?",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Priority System
|
||||
|
||||
When `CopilotChat` is used within an existing `CopilotChatConfigurationProvider`, values are merged with the following
|
||||
priority (highest to lowest):
|
||||
|
||||
1. Props passed directly to `CopilotChat`
|
||||
2. Values from the outer `CopilotChatConfigurationProvider`
|
||||
3. Default values
|
||||
|
||||
Example:
|
||||
|
||||
```tsx
|
||||
<CopilotChatConfigurationProvider agentId="outer-agent">
|
||||
<CopilotChat
|
||||
threadId="inner-thread"
|
||||
// agentId inherits from outer: "outer-agent"
|
||||
/>
|
||||
</CopilotChatConfigurationProvider>
|
||||
```
|
||||
|
||||
## Accessing Configuration
|
||||
|
||||
Use the `useCopilotChatConfiguration` hook to access configuration values in your components:
|
||||
|
||||
```tsx
|
||||
import { useCopilotChatConfiguration } from "@copilotkit/react-core";
|
||||
|
||||
function MyComponent() {
|
||||
const config = useCopilotChatConfiguration();
|
||||
|
||||
if (!config) {
|
||||
// No provider found
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Agent: {config.agentId}</p>
|
||||
<p>Thread: {config.threadId}</p>
|
||||
<p>Labels: {JSON.stringify(config.labels)}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Note: The hook returns `null` if no provider is found in the component tree.
|
||||
|
||||
## Localization Example
|
||||
|
||||
The provider is ideal for implementing localization:
|
||||
|
||||
```tsx
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function LocalizedChat() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<CopilotChatConfigurationProvider
|
||||
threadId="chat-1"
|
||||
labels={{
|
||||
chatInputPlaceholder: t("chat.input.placeholder"),
|
||||
assistantMessageToolbarCopyMessageLabel: t("chat.assistant.copy"),
|
||||
assistantMessageToolbarThumbsUpLabel: t("chat.assistant.thumbsUp"),
|
||||
assistantMessageToolbarThumbsDownLabel: t("chat.assistant.thumbsDown"),
|
||||
userMessageToolbarEditMessageLabel: t("chat.user.edit"),
|
||||
chatDisclaimerText: t("chat.disclaimer"),
|
||||
}}
|
||||
>
|
||||
<CopilotChat />
|
||||
</CopilotChatConfigurationProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,302 @@
|
||||
---
|
||||
title: CopilotChatInput
|
||||
description: "Text input component with voice transcription and tools menu"
|
||||
---
|
||||
|
||||
`CopilotChatInput` is the default input component used by [CopilotChat](/reference/copilot-chat). It provides a full-featured text input with support for voice transcription, slash commands, and customizable toolbar buttons.
|
||||
|
||||
## What is CopilotChatInput?
|
||||
|
||||
The CopilotChatInput component:
|
||||
|
||||
- Provides a rich text input with auto-expanding height
|
||||
- Supports voice transcription via microphone button
|
||||
- Includes a slash command menu for quick actions
|
||||
- Shows a tools/add menu button for file uploads and custom actions
|
||||
- Handles send and stop functionality during streaming
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatInput provides slots for customizing each part of the input:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Input[CopilotChatInput] --> textArea
|
||||
Input --> sendButton
|
||||
Input --> startTranscribeButton
|
||||
Input --> cancelTranscribeButton
|
||||
Input --> finishTranscribeButton
|
||||
Input --> addMenuButton
|
||||
Input --> audioRecorder
|
||||
Input --> disclaimer
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| ------------------------ | ------------------------------------------- |
|
||||
| `textArea` | The main textarea input element |
|
||||
| `sendButton` | Send message or stop generation button |
|
||||
| `startTranscribeButton` | Button to start voice recording |
|
||||
| `cancelTranscribeButton` | Button to cancel voice recording |
|
||||
| `finishTranscribeButton` | Button to finish voice recording |
|
||||
| `addMenuButton` | Plus button for file uploads and tools menu |
|
||||
| `audioRecorder` | Voice recording visualization component |
|
||||
| `disclaimer` | Disclaimer text shown below the input |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize the input through the `input` prop on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
className: "border-2 border-blue-200 rounded-xl",
|
||||
sendButton: "bg-blue-500 hover:bg-blue-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Input Modes
|
||||
|
||||
CopilotChatInput operates in three modes:
|
||||
|
||||
| Mode | Description |
|
||||
| ------------ | ---------------------------------------- |
|
||||
| `input` | Normal text input mode (default) |
|
||||
| `transcribe` | Voice recording mode |
|
||||
| `processing` | Shows loading spinner while transcribing |
|
||||
|
||||
The component automatically switches between modes based on user interaction with the transcription buttons.
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatInput uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### TextArea Customization
|
||||
|
||||
The `textArea` slot controls the main text input:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
textArea: {
|
||||
className: "text-lg font-medium",
|
||||
placeholder: "What's on your mind?",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Send Button Customization
|
||||
|
||||
The `sendButton` slot controls the send/stop button:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
sendButton: "bg-green-500 hover:bg-green-600 text-white",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Or with a custom component:
|
||||
|
||||
```tsx
|
||||
function CustomSendButton({ onClick, disabled, children }) {
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
className="px-4 py-2 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-lg"
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
input={{
|
||||
sendButton: CustomSendButton,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Transcription Buttons
|
||||
|
||||
Customize the voice transcription buttons:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
startTranscribeButton: "text-blue-500",
|
||||
cancelTranscribeButton: "text-red-500",
|
||||
finishTranscribeButton: "text-green-500",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Add Menu Button
|
||||
|
||||
The add menu button shows a dropdown with file upload and custom tool options:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
addMenuButton: "text-gray-500 hover:text-gray-700",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Disclaimer Customization
|
||||
|
||||
The `disclaimer` slot shows helper text below the input:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
disclaimer: "text-xs text-gray-400 italic",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
To hide the disclaimer entirely:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
disclaimer: () => null,
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Replacing the Component
|
||||
|
||||
To completely replace the input with your own component:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatInput } from "@copilotkit/react-core";
|
||||
|
||||
function CustomInput({ onSubmitMessage, isRunning, onStop, ...props }) {
|
||||
return (
|
||||
<div className="custom-input-wrapper">
|
||||
<CopilotChatInput
|
||||
onSubmitMessage={onSubmitMessage}
|
||||
isRunning={isRunning}
|
||||
onStop={onStop}
|
||||
textArea="bg-gray-50"
|
||||
sendButton="bg-blue-600"
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat input={CustomInput} />;
|
||||
```
|
||||
|
||||
### Using the Render Function
|
||||
|
||||
For full control, use the children render function pattern:
|
||||
|
||||
```tsx
|
||||
function CustomInput(props) {
|
||||
return (
|
||||
<CopilotChatInput {...props}>
|
||||
{({ textArea, sendButton, addMenuButton }) => (
|
||||
<div className="flex items-center gap-2 p-4 bg-gray-100 rounded-xl">
|
||||
{addMenuButton}
|
||||
<div className="flex-1">{textArea}</div>
|
||||
{sendButton}
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatInput>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat input={CustomInput} />;
|
||||
```
|
||||
|
||||
The render function receives:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------------ | ----------------------------------------- | ----------------------------- |
|
||||
| `textArea` | `ReactElement` | The bound textarea component |
|
||||
| `sendButton` | `ReactElement` | The bound send/stop button |
|
||||
| `startTranscribeButton` | `ReactElement` | Start recording button |
|
||||
| `cancelTranscribeButton` | `ReactElement` | Cancel recording button |
|
||||
| `finishTranscribeButton` | `ReactElement` | Finish recording button |
|
||||
| `addMenuButton` | `ReactElement` | The tools menu button |
|
||||
| `audioRecorder` | `ReactElement` | Voice recording visualization |
|
||||
| `disclaimer` | `ReactElement` | The disclaimer text |
|
||||
| `mode` | `'input' \| 'transcribe' \| 'processing'` | Current input mode |
|
||||
| `isRunning` | `boolean` | Whether AI is generating |
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
| Shortcut | Action |
|
||||
| ------------- | ------------------------------------ |
|
||||
| `Enter` | Send message (or stop if generating) |
|
||||
| `Shift+Enter` | Insert newline |
|
||||
| `/` | Open slash command menu |
|
||||
| `Escape` | Close slash command menu |
|
||||
| `↑/↓` | Navigate slash menu items |
|
||||
|
||||
## Examples
|
||||
|
||||
### Custom Styled Input
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
className: "shadow-lg",
|
||||
textArea: "text-base placeholder:text-gray-400",
|
||||
sendButton: "bg-indigo-600 hover:bg-indigo-700",
|
||||
addMenuButton: "text-indigo-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Hiding the Disclaimer
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
disclaimer: () => null,
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Disclaimer Text
|
||||
|
||||
Use labels to customize the disclaimer text:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
labels={{
|
||||
chatDisclaimerText:
|
||||
"AI responses may contain errors. Always verify important information.",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Hide Transcription Button
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
startTranscribeButton: () => null,
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component that uses CopilotChatInput
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,286 @@
|
||||
---
|
||||
title: CopilotChatMessageView
|
||||
description: "Message list container component"
|
||||
---
|
||||
|
||||
`CopilotChatMessageView` is the default component used by [CopilotChat](/reference/copilot-chat) to render the message list. It handles rendering user messages, assistant messages, activity messages, and custom message renderers with optimized memoization for performance.
|
||||
|
||||
## What is CopilotChatMessageView?
|
||||
|
||||
The CopilotChatMessageView component:
|
||||
|
||||
- Renders the conversation message list
|
||||
- Handles user, assistant, and activity message types
|
||||
- Supports custom message renderers for extensibility
|
||||
- Optimizes re-renders with memoization
|
||||
- Shows a typing cursor during streaming responses
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatMessageView provides slots for customizing message rendering:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
MV[CopilotChatMessageView] --> assistantMessage
|
||||
MV --> userMessage
|
||||
MV --> cursor
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| ------------------ | ----------------------------------------------- |
|
||||
| `assistantMessage` | Component for rendering assistant (AI) messages |
|
||||
| `userMessage` | Component for rendering user messages |
|
||||
| `cursor` | Typing indicator shown during streaming |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize the message view through the `messageView` prop on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
className: "space-y-4 p-4",
|
||||
assistantMessage: "bg-blue-50 rounded-lg",
|
||||
userMessage: "bg-gray-100 rounded-lg",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatMessageView uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Assistant Message Customization
|
||||
|
||||
The `assistantMessage` slot controls how AI responses are rendered:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
className: "bg-slate-50 border border-slate-200 rounded-xl p-4",
|
||||
onThumbsUp: (message) => sendFeedback(message.id, "positive"),
|
||||
onThumbsDown: (message) => sendFeedback(message.id, "negative"),
|
||||
onRegenerate: (message) => regenerateResponse(message.id),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Assistant Message Sub-Slots
|
||||
|
||||
| Sub-Slot | Description |
|
||||
| ------------------ | ------------------------------------------------- |
|
||||
| `markdownRenderer` | Renders the message content with markdown support |
|
||||
| `toolbar` | Container for action buttons |
|
||||
| `copyButton` | Button to copy message content |
|
||||
| `thumbsUpButton` | Positive feedback button |
|
||||
| `thumbsDownButton` | Negative feedback button |
|
||||
| `readAloudButton` | Text-to-speech button |
|
||||
| `regenerateButton` | Button to regenerate the response |
|
||||
| `toolCallsView` | Renders tool call executions |
|
||||
|
||||
For full details, see [CopilotChatAssistantMessage](/reference/copilot-chat-assistant-message).
|
||||
|
||||
### User Message Customization
|
||||
|
||||
The `userMessage` slot controls how user messages are rendered:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
className: "bg-primary text-primary-foreground rounded-2xl px-4 py-2",
|
||||
onEditMessage: ({ message }) => editMessage(message),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
#### User Message Sub-Slots
|
||||
|
||||
| Sub-Slot | Description |
|
||||
| ------------------ | ------------------------------------ |
|
||||
| `messageRenderer` | Renders the message text content |
|
||||
| `toolbar` | Container for action buttons |
|
||||
| `copyButton` | Button to copy message content |
|
||||
| `editButton` | Button to edit the message |
|
||||
| `branchNavigation` | Navigation for conversation branches |
|
||||
|
||||
For full details, see [CopilotChatUserMessage](/reference/copilot-chat-user-message).
|
||||
|
||||
### Cursor Customization
|
||||
|
||||
The cursor appears while the AI is generating a response:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
cursor: "bg-blue-500 w-3 h-3",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Or with a custom component:
|
||||
|
||||
```tsx
|
||||
function CustomCursor() {
|
||||
return (
|
||||
<div className="flex gap-1">
|
||||
<span className="w-2 h-2 bg-blue-500 rounded-full animate-bounce" />
|
||||
<span className="w-2 h-2 bg-blue-500 rounded-full animate-bounce delay-100" />
|
||||
<span className="w-2 h-2 bg-blue-500 rounded-full animate-bounce delay-200" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
cursor: CustomCursor,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
## Replacing the Message View
|
||||
|
||||
To completely replace the message view with your own component, pass a custom component to the `messageView` prop:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatMessageView } from "@copilotkit/react-core";
|
||||
|
||||
function CustomMessageView({ messages, isRunning, ...props }) {
|
||||
return (
|
||||
<div className="custom-message-list">
|
||||
<div className="message-count text-sm text-muted-foreground mb-4">
|
||||
{messages.length} messages
|
||||
</div>
|
||||
|
||||
{/* Use the default implementation with customizations */}
|
||||
<CopilotChatMessageView
|
||||
messages={messages}
|
||||
isRunning={isRunning}
|
||||
className="space-y-6"
|
||||
assistantMessage="bg-white shadow-sm rounded-xl p-4"
|
||||
userMessage="bg-blue-500 text-white rounded-2xl"
|
||||
{...props}
|
||||
/>
|
||||
|
||||
{isRunning && (
|
||||
<div className="text-center text-muted-foreground mt-4">
|
||||
AI is thinking...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat messageView={CustomMessageView} />;
|
||||
```
|
||||
|
||||
### Using the Render Function
|
||||
|
||||
For even more control, use the children render function pattern:
|
||||
|
||||
```tsx
|
||||
function CustomMessageView({ messages, isRunning }) {
|
||||
return (
|
||||
<CopilotChatMessageView messages={messages} isRunning={isRunning}>
|
||||
{({ messageElements, messages, isRunning }) => (
|
||||
<div className="custom-layout">
|
||||
<header className="sticky top-0 bg-background p-2 border-b">
|
||||
{messages.length} messages
|
||||
</header>
|
||||
|
||||
<div className="messages p-4">{messageElements}</div>
|
||||
|
||||
{isRunning && (
|
||||
<footer className="sticky bottom-0 bg-background p-2">
|
||||
Generating response...
|
||||
</footer>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatMessageView>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat messageView={CustomMessageView} />;
|
||||
```
|
||||
|
||||
The render function receives:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ----------------- | ---------------- | ------------------------------- |
|
||||
| `messageElements` | `ReactElement[]` | Pre-rendered message components |
|
||||
| `messages` | `Message[]` | Raw message data |
|
||||
| `isRunning` | `boolean` | Whether AI is generating |
|
||||
|
||||
## Examples
|
||||
|
||||
### Styling All Messages
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
className: "space-y-6 p-4",
|
||||
assistantMessage: "bg-white shadow-sm rounded-xl p-4",
|
||||
userMessage: "bg-blue-500 text-white rounded-2xl px-4 py-2",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Adding Feedback Handlers
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (message) => {
|
||||
analytics.track("positive_feedback", { messageId: message.id });
|
||||
},
|
||||
onThumbsDown: (message) => {
|
||||
analytics.track("negative_feedback", { messageId: message.id });
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Assistant Message Component
|
||||
|
||||
Replace the assistant message component entirely:
|
||||
|
||||
```tsx
|
||||
function CustomAssistantMessage({ message, isRunning }) {
|
||||
return (
|
||||
<div className="flex gap-3">
|
||||
<Avatar src="/bot-avatar.png" />
|
||||
<div className="flex-1">
|
||||
<Markdown>{message.content}</Markdown>
|
||||
{isRunning && <TypingIndicator />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: CustomAssistantMessage,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component that uses CopilotChatMessageView
|
||||
- [CopilotChatAssistantMessage](/reference/copilot-chat-assistant-message) - Assistant message customization
|
||||
- [CopilotChatUserMessage](/reference/copilot-chat-user-message) - User message customization
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,205 @@
|
||||
---
|
||||
title: CopilotChatScrollView
|
||||
description: "Scrollable message container with auto-scroll behavior"
|
||||
---
|
||||
|
||||
`CopilotChatScrollView` is the default scroll container used by [CopilotChat](/reference/copilot-chat). It handles auto-scrolling during message streaming, provides a scroll-to-bottom button, and displays a gradient fade (feather) overlay.
|
||||
|
||||
## What is CopilotChatScrollView?
|
||||
|
||||
The CopilotChatScrollView component:
|
||||
|
||||
- Provides a scrollable container for the message list
|
||||
- Auto-scrolls to bottom during AI response streaming
|
||||
- Shows a scroll-to-bottom button when scrolled up
|
||||
- Includes a gradient "feather" overlay for visual polish
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatScrollView provides slots for customizing its visual elements:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
SV[CopilotChatScrollView] --> scrollToBottomButton
|
||||
SV --> feather
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| ---------------------- | ------------------------------------------------------ |
|
||||
| `scrollToBottomButton` | Button that appears when scrolled up from bottom |
|
||||
| `feather` | Gradient fade overlay at the bottom of the scroll area |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize the scroll view through the `scrollView` prop on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
scrollToBottomButton: "bg-blue-500 hover:bg-blue-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Auto-Scroll Behavior
|
||||
|
||||
By default, CopilotChatScrollView automatically scrolls to the bottom when:
|
||||
|
||||
- New messages are added to the conversation
|
||||
- The AI is streaming a response
|
||||
- The user is already near the bottom of the scroll area
|
||||
|
||||
To disable auto-scroll:
|
||||
|
||||
```tsx
|
||||
<CopilotChat autoScroll={false} />
|
||||
```
|
||||
|
||||
When auto-scroll is disabled, users must manually scroll to see new messages. The scroll-to-bottom button will appear when new content is available below the viewport.
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatScrollView uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Scroll-to-Bottom Button Customization
|
||||
|
||||
Style the scroll-to-bottom button:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
scrollToBottomButton: "bg-blue-500 shadow-xl rounded-full",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Or with a custom component:
|
||||
|
||||
```tsx
|
||||
function CustomScrollButton({ onClick }) {
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className="px-4 py-2 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-lg shadow-lg"
|
||||
>
|
||||
Jump to latest
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
scrollToBottomButton: CustomScrollButton,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Feather (Gradient Overlay) Customization
|
||||
|
||||
The feather provides a gradient fade at the bottom of the scroll area:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
feather: "from-blue-50 via-blue-50 to-transparent",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
To remove the feather entirely:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
feather: () => null,
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Replacing the Scroll View
|
||||
|
||||
To completely replace the scroll view with your own component:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatView } from "@copilotkit/react-core";
|
||||
|
||||
function CustomScrollView({ children, autoScroll, ...props }) {
|
||||
return (
|
||||
<CopilotChatView.ScrollView
|
||||
autoScroll={autoScroll}
|
||||
scrollToBottomButton="bg-indigo-600"
|
||||
feather="from-gray-50 via-gray-50 to-transparent"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</CopilotChatView.ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat scrollView={CustomScrollView} />;
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Custom Scroll Button
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
scrollToBottomButton: {
|
||||
className:
|
||||
"bg-gradient-to-r from-pink-500 to-orange-500 text-white shadow-xl",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Dark Mode Feather
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
feather: "from-gray-900 via-gray-900 to-transparent",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Removing Visual Elements
|
||||
|
||||
Remove both the scroll button and feather for a minimal look:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
scrollView={{
|
||||
scrollToBottomButton: () => null,
|
||||
feather: () => null,
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Themed Scroll View
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
className="bg-slate-50"
|
||||
scrollView={{
|
||||
className: "bg-slate-50",
|
||||
scrollToBottomButton: "bg-slate-700 hover:bg-slate-800 text-white",
|
||||
feather: "from-slate-50 via-slate-50 to-transparent",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component that uses CopilotChatScrollView
|
||||
- [CopilotChatMessageView](/reference/copilot-chat-message-view) - Message list rendered inside the scroll view
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,244 @@
|
||||
---
|
||||
title: CopilotChatSuggestionView
|
||||
description: "Clickable suggestion chips component"
|
||||
---
|
||||
|
||||
`CopilotChatSuggestionView` is the default component used by [CopilotChat](/reference/copilot-chat) to render clickable suggestion chips. These chips provide quick actions that users can click to send predefined messages.
|
||||
|
||||
## What is CopilotChatSuggestionView?
|
||||
|
||||
The CopilotChatSuggestionView component:
|
||||
|
||||
- Renders a list of clickable suggestion chips
|
||||
- Supports loading states for individual suggestions
|
||||
- Handles click events to trigger message sending
|
||||
- Displays suggestions in a flexible wrapped layout
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatSuggestionView provides slots for customizing the container and individual chips:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
SV[CopilotChatSuggestionView] --> container
|
||||
SV --> suggestion
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| ------------ | --------------------------------------------------- |
|
||||
| `container` | The outer container that holds all suggestion chips |
|
||||
| `suggestion` | Individual suggestion chip (pill button) |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize suggestions through the `suggestionView` prop on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
container: "gap-4",
|
||||
suggestion: "bg-blue-100 hover:bg-blue-200 text-blue-800",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## How Suggestions Work
|
||||
|
||||
Suggestions are managed through the `useSuggestions` hook, which:
|
||||
|
||||
1. Receives suggestions from the AI agent
|
||||
2. Displays them as clickable chips
|
||||
3. Triggers message sending when clicked
|
||||
4. Shows loading states during processing
|
||||
|
||||
You don't need to manage suggestions manually - CopilotChat handles this automatically.
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatSuggestionView uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Container Customization
|
||||
|
||||
Style the suggestions container:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
container: "flex-wrap gap-2 justify-center",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Suggestion Chip Customization
|
||||
|
||||
Style individual suggestion chips:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
suggestion:
|
||||
"bg-gradient-to-r from-blue-500 to-purple-500 text-white px-4 py-2 rounded-full",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Or with a props object:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
suggestion: {
|
||||
className: "bg-indigo-100 text-indigo-800 font-medium",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Replacing the Component
|
||||
|
||||
To completely replace the suggestion view with your own component:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatSuggestionView } from "@copilotkit/react-core";
|
||||
|
||||
function CustomSuggestionView({ suggestions, onSelectSuggestion, ...props }) {
|
||||
return (
|
||||
<div className="custom-suggestions-wrapper">
|
||||
<CopilotChatSuggestionView
|
||||
suggestions={suggestions}
|
||||
onSelectSuggestion={onSelectSuggestion}
|
||||
container="gap-3"
|
||||
suggestion="bg-white shadow-md hover:shadow-lg rounded-xl px-4 py-2"
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat suggestionView={CustomSuggestionView} />;
|
||||
```
|
||||
|
||||
### Using the Render Function
|
||||
|
||||
For full layout control, use the children render function:
|
||||
|
||||
```tsx
|
||||
function CustomSuggestionView(props) {
|
||||
return (
|
||||
<CopilotChatSuggestionView {...props}>
|
||||
{({ suggestions, onSelectSuggestion }) => (
|
||||
<div className="grid grid-cols-2 gap-2 p-4">
|
||||
{suggestions.map((suggestion, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => onSelectSuggestion(suggestion, index)}
|
||||
className="p-3 bg-white border rounded-lg hover:bg-gray-50 text-left"
|
||||
>
|
||||
{suggestion.title}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatSuggestionView>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat suggestionView={CustomSuggestionView} />;
|
||||
```
|
||||
|
||||
The render function receives:
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------------------- | ----------------------------- | ---------------------------------------- |
|
||||
| `container` | `ReactElement` | The bound container element |
|
||||
| `suggestion` | `ReactElement` | A sample bound suggestion chip |
|
||||
| `suggestions` | `Suggestion[]` | Array of suggestion objects |
|
||||
| `onSelectSuggestion` | `(suggestion, index) => void` | Callback when suggestion is clicked |
|
||||
| `loadingIndexes` | `ReadonlyArray<number>` | Indexes of suggestions currently loading |
|
||||
|
||||
## Loading States
|
||||
|
||||
Individual suggestions can show loading states when clicked:
|
||||
|
||||
```tsx
|
||||
// Suggestions automatically show loading states when:
|
||||
// 1. The suggestion is clicked and processing
|
||||
// 2. The suggestion has isLoading: true in its data
|
||||
```
|
||||
|
||||
The loading state is indicated by a spinner or visual feedback on the chip.
|
||||
|
||||
## Examples
|
||||
|
||||
### Pill-Style Suggestions
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
container: "flex flex-wrap gap-2",
|
||||
suggestion:
|
||||
"rounded-full bg-gray-100 hover:bg-gray-200 px-4 py-1.5 text-sm",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Card-Style Suggestions
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
container: "grid grid-cols-2 gap-3",
|
||||
suggestion:
|
||||
"bg-white shadow-sm border rounded-xl p-3 hover:shadow-md text-left",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Colorful Gradient Chips
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
suggestion:
|
||||
"bg-gradient-to-r from-pink-500 to-orange-500 text-white hover:from-pink-600 hover:to-orange-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Minimal Style
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
container: "gap-1",
|
||||
suggestion:
|
||||
"text-blue-600 hover:text-blue-800 underline underline-offset-2 bg-transparent",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Centered Suggestions
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
container: "flex justify-center flex-wrap gap-2",
|
||||
suggestion:
|
||||
"bg-blue-50 text-blue-700 hover:bg-blue-100 rounded-lg px-3 py-1.5",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component that uses CopilotChatSuggestionView
|
||||
- [CopilotChatWelcomeScreen](/reference/copilot-chat-welcome-screen) - Welcome screen that displays suggestions
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,376 @@
|
||||
---
|
||||
title: CopilotChatUserMessage
|
||||
description: "User message rendering component with edit and branch navigation"
|
||||
---
|
||||
|
||||
`CopilotChatUserMessage` is the default component used by [CopilotChatMessageView](/reference/copilot-chat-message-view) to render user messages. It handles message display, editing functionality, and branch navigation for conversation history.
|
||||
|
||||
## What is CopilotChatUserMessage?
|
||||
|
||||
The CopilotChatUserMessage component:
|
||||
|
||||
- Renders user messages in a styled bubble
|
||||
- Provides a toolbar with copy and edit buttons
|
||||
- Supports message editing functionality
|
||||
- Handles branch navigation for conversation forks
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatUserMessage provides slots for customizing each part of the message:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
UM[CopilotChatUserMessage] --> messageRenderer
|
||||
UM --> toolbar
|
||||
UM --> copyButton
|
||||
UM --> editButton
|
||||
UM --> branchNavigation
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| ------------------ | ----------------------------------------------- |
|
||||
| `messageRenderer` | Renders the message text content |
|
||||
| `toolbar` | Container for action buttons (appears on hover) |
|
||||
| `copyButton` | Button to copy message content |
|
||||
| `editButton` | Button to edit the message |
|
||||
| `branchNavigation` | Navigation controls for conversation branches |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize user messages through the `messageView.userMessage` slot on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
className: "bg-blue-500 text-white rounded-2xl",
|
||||
onEditMessage: ({ message }) => handleEdit(message),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Callbacks
|
||||
|
||||
CopilotChatUserMessage provides callbacks for user interactions:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
onEditMessage: ({ message }) => {
|
||||
// Open edit modal or inline editor
|
||||
setEditingMessage(message);
|
||||
},
|
||||
onSwitchToBranch: ({ message, branchIndex, numberOfBranches }) => {
|
||||
// Switch to a different conversation branch
|
||||
switchToBranch(message.id, branchIndex);
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Callback Props
|
||||
|
||||
| Callback | Signature | Description |
|
||||
| ------------------ | ------------------------------------------------------ | ------------------------------------------- |
|
||||
| `onEditMessage` | `({ message }) => void` | Called when user clicks the edit button |
|
||||
| `onSwitchToBranch` | `({ message, branchIndex, numberOfBranches }) => void` | Called when user navigates between branches |
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatUserMessage uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Message Renderer Customization
|
||||
|
||||
Style the message bubble:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
messageRenderer:
|
||||
"bg-gradient-to-r from-blue-500 to-purple-500 text-white",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Toolbar Customization
|
||||
|
||||
The toolbar appears on hover and contains action buttons:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
toolbar: "bg-gray-50 rounded-lg p-1",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Individual Button Customization
|
||||
|
||||
Customize specific toolbar buttons:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
copyButton: "text-gray-500 hover:text-gray-700",
|
||||
editButton: "text-blue-500 hover:text-blue-700",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Hiding Buttons
|
||||
|
||||
Hide buttons by returning null:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
editButton: () => null,
|
||||
branchNavigation: () => null,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Note: The `editButton` only shows when `onEditMessage` callback is provided.
|
||||
|
||||
### Branch Navigation Customization
|
||||
|
||||
Customize the branch navigation controls:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
branchNavigation: "bg-gray-100 rounded-lg px-2",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Branch navigation only appears when there are multiple branches (conversation forks) available.
|
||||
|
||||
## Replacing the Component
|
||||
|
||||
To completely replace the user message component:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatUserMessage } from "@copilotkit/react-core";
|
||||
|
||||
function CustomUserMessage({ message, ...props }) {
|
||||
return (
|
||||
<div className="flex gap-3 items-start justify-end">
|
||||
<div className="flex-1">
|
||||
<CopilotChatUserMessage
|
||||
message={message}
|
||||
className="bg-blue-600 text-white"
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
<Avatar src="/user-avatar.png" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: CustomUserMessage,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Using the Render Function
|
||||
|
||||
For full layout control, use the children render function:
|
||||
|
||||
```tsx
|
||||
function CustomUserMessage(props) {
|
||||
return (
|
||||
<CopilotChatUserMessage {...props}>
|
||||
{({ messageRenderer, toolbar, message }) => (
|
||||
<div className="flex flex-col items-end gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs text-gray-400">You</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
{new Date(message.createdAt).toLocaleTimeString()}
|
||||
</span>
|
||||
</div>
|
||||
{messageRenderer}
|
||||
{toolbar}
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatUserMessage>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: CustomUserMessage,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
The render function receives:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------ | -------------- | ---------------------------- |
|
||||
| `messageRenderer` | `ReactElement` | The rendered message content |
|
||||
| `toolbar` | `ReactElement` | The action buttons toolbar |
|
||||
| `copyButton` | `ReactElement` | Copy button |
|
||||
| `editButton` | `ReactElement` | Edit button |
|
||||
| `branchNavigation` | `ReactElement` | Branch navigation controls |
|
||||
| `message` | `UserMessage` | The message data |
|
||||
| `branchIndex` | `number` | Current branch index |
|
||||
| `numberOfBranches` | `number` | Total number of branches |
|
||||
|
||||
## Branch Navigation
|
||||
|
||||
When users edit messages and regenerate responses, CopilotKit creates conversation branches. The branch navigation allows users to switch between these alternative conversation paths:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
onSwitchToBranch: ({ message, branchIndex, numberOfBranches }) => {
|
||||
console.log(
|
||||
`Switching to branch ${branchIndex + 1} of ${numberOfBranches}`,
|
||||
);
|
||||
// Your branch switching logic
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
The branch navigation shows:
|
||||
|
||||
- Previous/Next arrows to navigate between branches
|
||||
- Current branch indicator (e.g., "2/3")
|
||||
|
||||
## Examples
|
||||
|
||||
### Chat Bubble Style
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
className: "items-end",
|
||||
messageRenderer:
|
||||
"bg-blue-600 text-white rounded-2xl px-4 py-2 max-w-[75%]",
|
||||
toolbar: "opacity-0 group-hover:opacity-100 transition-opacity",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### With Edit Functionality
|
||||
|
||||
```tsx
|
||||
function ChatWithEdit() {
|
||||
const [editingMessage, setEditingMessage] = useState(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
onEditMessage: ({ message }) => setEditingMessage(message),
|
||||
editButton: "text-blue-500 hover:text-blue-700",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
{editingMessage && (
|
||||
<EditMessageModal
|
||||
message={editingMessage}
|
||||
onClose={() => setEditingMessage(null)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Minimal Style
|
||||
|
||||
Hide all toolbar elements for a clean look:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
toolbar: () => null,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Message with Avatar
|
||||
|
||||
```tsx
|
||||
function UserMessageWithAvatar(props) {
|
||||
return (
|
||||
<CopilotChatUserMessage {...props}>
|
||||
{({ messageRenderer, toolbar }) => (
|
||||
<div className="flex items-start gap-3 justify-end">
|
||||
<div className="flex flex-col items-end">
|
||||
{messageRenderer}
|
||||
{toolbar}
|
||||
</div>
|
||||
<img
|
||||
src="/user-avatar.png"
|
||||
alt="You"
|
||||
className="w-8 h-8 rounded-full"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatUserMessage>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: UserMessageWithAvatar,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Styled for Dark Mode
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
messageRenderer: "bg-blue-600 text-white dark:bg-blue-500",
|
||||
toolbar: "text-gray-400 dark:text-gray-500",
|
||||
copyButton: "hover:text-white dark:hover:text-gray-300",
|
||||
editButton: "hover:text-white dark:hover:text-gray-300",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component
|
||||
- [CopilotChatMessageView](/reference/copilot-chat-message-view) - Message list component that uses user messages
|
||||
- [CopilotChatAssistantMessage](/reference/copilot-chat-assistant-message) - Counterpart for AI messages
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,292 @@
|
||||
---
|
||||
title: CopilotChatWelcomeScreen
|
||||
description: "Initial empty state and welcome message component"
|
||||
---
|
||||
|
||||
`CopilotChatWelcomeScreen` is the default component displayed by [CopilotChat](/reference/copilot-chat) when there are no messages. It provides a welcoming introduction with an input field and optional suggestion chips.
|
||||
|
||||
## What is CopilotChatWelcomeScreen?
|
||||
|
||||
The CopilotChatWelcomeScreen component:
|
||||
|
||||
- Displays when the conversation is empty (no messages)
|
||||
- Shows a customizable welcome message
|
||||
- Includes the chat input for starting conversations
|
||||
- Displays suggestion chips for quick actions
|
||||
- Built on the [slot system](/reference/slot-system) for deep customization
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChatWelcomeScreen provides a slot for the welcome message and receives input and suggestions as props:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
WS[CopilotChatWelcomeScreen] --> welcomeMessage
|
||||
WS --> input[input prop]
|
||||
WS --> suggestionView[suggestionView prop]
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot/Prop | Description |
|
||||
| ---------------- | --------------------------------------------------- |
|
||||
| `welcomeMessage` | The greeting text or component displayed at the top |
|
||||
| `input` | The chat input component (passed as a prop) |
|
||||
| `suggestionView` | Suggestion chips component (passed as a prop) |
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Customize the welcome screen through the `welcomeScreen` prop on [CopilotChat](/reference/copilot-chat):
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
welcomeScreen={{
|
||||
className: "bg-gradient-to-b from-blue-50 to-white",
|
||||
welcomeMessage: "text-2xl font-bold text-blue-900",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Customizing the Welcome Message
|
||||
|
||||
The simplest way to customize the welcome message is through labels:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
labels={{
|
||||
welcomeMessage: "Hello! I'm your AI assistant. How can I help you today?",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Or style the welcome message component:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
welcomeScreen={{
|
||||
welcomeMessage: {
|
||||
className:
|
||||
"text-3xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Disabling the Welcome Screen
|
||||
|
||||
To skip the welcome screen and show an empty chat directly:
|
||||
|
||||
```tsx
|
||||
<CopilotChat welcomeScreen={false} />
|
||||
```
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChatWelcomeScreen uses the [slot system](/reference/slot-system). Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Welcome Message Customization
|
||||
|
||||
Style the welcome message:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
welcomeScreen={{
|
||||
welcomeMessage: "text-4xl font-extrabold tracking-tight",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Or with a custom component:
|
||||
|
||||
```tsx
|
||||
function CustomWelcomeMessage() {
|
||||
return (
|
||||
<div className="text-center">
|
||||
<img src="/logo.svg" alt="Logo" className="w-16 h-16 mx-auto mb-4" />
|
||||
<h1 className="text-2xl font-bold">Welcome to AI Assistant</h1>
|
||||
<p className="text-gray-500 mt-2">Ask me anything about your project</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat
|
||||
welcomeScreen={{
|
||||
welcomeMessage: CustomWelcomeMessage,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
## Replacing the Welcome Screen
|
||||
|
||||
To completely replace the welcome screen with your own component:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatView } from "@copilotkit/react-core";
|
||||
|
||||
function CustomWelcomeScreen({ input, suggestionView }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full bg-gradient-to-b from-indigo-50 to-white p-8">
|
||||
<img src="/mascot.svg" alt="AI Mascot" className="w-32 h-32 mb-6" />
|
||||
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-2">Hi there!</h1>
|
||||
|
||||
<p className="text-gray-600 text-center max-w-md mb-8">
|
||||
I'm your AI assistant. I can help you with coding, research, writing,
|
||||
and much more. What would you like to explore?
|
||||
</p>
|
||||
|
||||
<div className="w-full max-w-2xl">{input}</div>
|
||||
|
||||
<div className="mt-6">{suggestionView}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat welcomeScreen={CustomWelcomeScreen} />;
|
||||
```
|
||||
|
||||
### Using the Render Function
|
||||
|
||||
For full layout control while keeping the default components:
|
||||
|
||||
```tsx
|
||||
function CustomWelcomeScreen(props) {
|
||||
return (
|
||||
<CopilotChatView.WelcomeScreen {...props}>
|
||||
{({ welcomeMessage, input, suggestionView }) => (
|
||||
<div className="flex flex-col lg:flex-row h-full">
|
||||
<div className="lg:w-1/2 bg-indigo-600 text-white p-12 flex items-center justify-center">
|
||||
<div className="max-w-md">
|
||||
<h1 className="text-4xl font-bold mb-4">AI Assistant</h1>
|
||||
<p className="text-indigo-200">
|
||||
Your intelligent companion for coding, writing, and
|
||||
problem-solving.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:w-1/2 p-12 flex flex-col items-center justify-center">
|
||||
<div className="w-full max-w-md">
|
||||
{welcomeMessage}
|
||||
<div className="mt-8">{input}</div>
|
||||
<div className="mt-6">{suggestionView}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatView.WelcomeScreen>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat welcomeScreen={CustomWelcomeScreen} />;
|
||||
```
|
||||
|
||||
The render function receives:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------- | -------------- | ------------------------------- |
|
||||
| `welcomeMessage` | `ReactElement` | The rendered welcome message |
|
||||
| `input` | `ReactElement` | The chat input component |
|
||||
| `suggestionView` | `ReactElement` | The suggestions chips component |
|
||||
|
||||
## Examples
|
||||
|
||||
### Branded Welcome Screen
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
labels={{
|
||||
welcomeMessage: "Welcome to Acme AI Assistant",
|
||||
}}
|
||||
welcomeScreen={{
|
||||
className: "bg-brand-50",
|
||||
welcomeMessage: "text-brand-900 text-3xl font-display",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Minimal Welcome
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
labels={{
|
||||
welcomeMessage: "How can I help?",
|
||||
}}
|
||||
welcomeScreen={{
|
||||
welcomeMessage: "text-lg text-gray-500 font-normal",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Welcome with Custom Layout
|
||||
|
||||
```tsx
|
||||
function CenteredWelcome({ input, suggestionView }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full p-8">
|
||||
<div className="animate-pulse mb-8">
|
||||
<div className="w-20 h-20 bg-gradient-to-br from-blue-400 to-purple-500 rounded-full" />
|
||||
</div>
|
||||
|
||||
<h1 className="text-2xl font-semibold text-gray-900 mb-1">
|
||||
Ready to help
|
||||
</h1>
|
||||
|
||||
<p className="text-gray-500 mb-8">Start a conversation below</p>
|
||||
|
||||
<div className="w-full max-w-xl">{input}</div>
|
||||
|
||||
<div className="mt-4 flex flex-wrap justify-center gap-2">
|
||||
{suggestionView}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat welcomeScreen={CenteredWelcome} />;
|
||||
```
|
||||
|
||||
### Welcome Screen with Feature List
|
||||
|
||||
```tsx
|
||||
function FeatureWelcome({ input, suggestionView }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full p-8">
|
||||
<h1 className="text-3xl font-bold mb-8">AI Assistant</h1>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4 mb-8 max-w-2xl">
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl mb-2">💻</div>
|
||||
<div className="font-medium">Code Help</div>
|
||||
</div>
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl mb-2">📝</div>
|
||||
<div className="font-medium">Writing</div>
|
||||
</div>
|
||||
<div className="text-center p-4">
|
||||
<div className="text-2xl mb-2">🔍</div>
|
||||
<div className="font-medium">Research</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-xl">{input}</div>
|
||||
|
||||
<div className="mt-4">{suggestionView}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat welcomeScreen={FeatureWelcome} />;
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Parent component that uses CopilotChatWelcomeScreen
|
||||
- [CopilotChatInput](/reference/copilot-chat-input) - Input component displayed in welcome screen
|
||||
- [CopilotChatSuggestionView](/reference/copilot-chat-suggestion-view) - Suggestions displayed in welcome screen
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
@@ -0,0 +1,444 @@
|
||||
---
|
||||
title: CopilotChat
|
||||
description: "CopilotChat Component API Reference"
|
||||
---
|
||||
|
||||
`CopilotChat` is a React component that provides a complete chat interface for interacting with AI agents. It handles
|
||||
message display, user input, tool execution rendering, and agent communication automatically.
|
||||
|
||||
## What is CopilotChat?
|
||||
|
||||
The CopilotChat component:
|
||||
|
||||
- Provides a complete chat UI out of the box
|
||||
- Manages conversation threads and message history
|
||||
- Automatically connects to agents and handles message routing
|
||||
- Renders tool executions with visual feedback
|
||||
- Supports deep customization through the [slot system](/reference/slot-system)
|
||||
- Handles auto-scrolling and responsive layouts
|
||||
- Supports voice transcription for hands-free input
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotChat is built on a composable component hierarchy. Understanding this structure helps you customize exactly what you need.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
CC[CopilotChat] --> messageView
|
||||
CC --> scrollView
|
||||
CC --> input
|
||||
CC --> suggestionView
|
||||
CC --> welcomeScreen
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description | Reference |
|
||||
| ---------------- | -------------------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| `messageView` | Container for the message list (user and assistant messages) | [CopilotChatMessageView](/reference/copilot-chat-message-view) |
|
||||
| `scrollView` | Scrollable container with auto-scroll behavior | [CopilotChatScrollView](/reference/copilot-chat-scroll-view) |
|
||||
| `input` | Text input with toolbar, transcription support, and disclaimer | [CopilotChatInput](/reference/copilot-chat-input) |
|
||||
| `suggestionView` | Clickable suggestion chips | [CopilotChatSuggestionView](/reference/copilot-chat-suggestion-view) |
|
||||
| `welcomeScreen` | Initial screen before any messages | [CopilotChatWelcomeScreen](/reference/copilot-chat-welcome-screen) |
|
||||
|
||||
See [Slot Customization](#slot-customization) for details on how to customize these slots.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { CopilotChat, CopilotKitProvider } from "@copilotkit/react-core";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CopilotKitProvider runtimeUrl="/api/copilotkit">
|
||||
<CopilotChat />
|
||||
</CopilotKitProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### agentId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
The ID of the agent to connect to. Defaults to `"default"`.
|
||||
|
||||
```tsx
|
||||
<CopilotChat agentId="assistant" />
|
||||
```
|
||||
|
||||
### threadId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
The conversation thread ID. If not provided, a new thread ID is automatically generated.
|
||||
|
||||
When you provide a `threadId`, CopilotChat automatically loads the conversation history for that thread, including any messages that are currently streaming. This enables seamless continuation of conversations across page reloads or component remounts.
|
||||
|
||||
```tsx
|
||||
<CopilotChat threadId="thread-123" />
|
||||
```
|
||||
|
||||
### labels
|
||||
|
||||
`Partial<CopilotChatLabels>` **(optional)**
|
||||
|
||||
Customize the text labels used throughout the chat interface.
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
labels={{
|
||||
chatInputPlaceholder: "Ask me anything...",
|
||||
chatDisclaimerText: "AI assistant - verify important info",
|
||||
welcomeMessage: "Hello! How can I help you today?",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### autoScroll
|
||||
|
||||
`boolean` **(optional, default: true)**
|
||||
|
||||
Automatically scroll to the bottom when new messages appear.
|
||||
|
||||
```tsx
|
||||
<CopilotChat autoScroll={false} />
|
||||
```
|
||||
|
||||
### className
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
CSS class name for the root container.
|
||||
|
||||
```tsx
|
||||
<CopilotChat className="h-screen bg-white" />
|
||||
```
|
||||
|
||||
### isModalDefaultOpen
|
||||
|
||||
`boolean` **(optional)**
|
||||
|
||||
When using CopilotChat in modal mode, controls whether the modal is open by default.
|
||||
|
||||
```tsx
|
||||
<CopilotChat isModalDefaultOpen={true} />
|
||||
```
|
||||
|
||||
### chatView
|
||||
|
||||
`SlotValue<typeof CopilotChatView>` **(optional)**
|
||||
|
||||
Customize the main chat view component. See [Slot Customization](#slot-customization) for details.
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotChat uses a powerful [slot system](/reference/slot-system) that allows you to customize any part of the UI. Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Customizing Appearance with Tailwind Classes
|
||||
|
||||
The simplest way to customize appearance is with Tailwind class strings:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
className="bg-gradient-to-b from-white to-gray-50 rounded-xl shadow-2xl"
|
||||
messageView="space-y-4"
|
||||
input="border-2 border-gray-200"
|
||||
/>
|
||||
```
|
||||
|
||||
### Customizing with Props
|
||||
|
||||
Pass a props object to modify component behavior while keeping the default implementation:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{ className: "custom-message-view" }}
|
||||
input={{ placeholder: "Ask a question..." }}
|
||||
scrollView="custom-scroll-view"
|
||||
/>
|
||||
```
|
||||
|
||||
### Nested Slot Customization
|
||||
|
||||
You can drill down into nested components through props objects:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: () => console.log("thumbsUp"),
|
||||
onThumbsDown: () => console.log("thumbsDown"),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Components
|
||||
|
||||
For full control, replace components entirely:
|
||||
|
||||
```tsx
|
||||
import { CopilotChatView } from "@copilotkit/react-core";
|
||||
|
||||
function CustomChatView(props) {
|
||||
return (
|
||||
<div className="custom-chat-layout">
|
||||
<CopilotChatView
|
||||
{...props}
|
||||
messageView="custom-message-from-wrapper"
|
||||
input="custom-input-from-wrapper"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat chatView={CustomChatView} />;
|
||||
```
|
||||
|
||||
## Message View Customization
|
||||
|
||||
The `messageView` slot controls how messages are rendered:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
// Style the message container
|
||||
className: "space-y-4 p-4",
|
||||
|
||||
// Customize assistant messages
|
||||
assistantMessage: {
|
||||
className: "bg-blue-50 rounded-lg",
|
||||
onThumbsUp: (message) => trackFeedback(message.id, "positive"),
|
||||
onThumbsDown: (message) => trackFeedback(message.id, "negative"),
|
||||
},
|
||||
|
||||
// Customize user messages
|
||||
userMessage: "bg-gray-100 rounded-lg",
|
||||
|
||||
// Customize the typing cursor
|
||||
cursor: "bg-blue-500",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Assistant Message Customization
|
||||
|
||||
Customize how assistant messages appear and behave:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
className: "bg-slate-50 border border-slate-200 rounded-xl p-4",
|
||||
onThumbsUp: (message) => sendFeedback(message.id, "positive"),
|
||||
onThumbsDown: (message) => sendFeedback(message.id, "negative"),
|
||||
onRegenerate: (message) => regenerateResponse(message.id),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
For full details on assistant message slots and customization options, see [CopilotChatAssistantMessage](/reference/copilot-chat-assistant-message).
|
||||
|
||||
### User Message Customization
|
||||
|
||||
Customize how user messages appear:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: "bg-blue-500 text-white rounded-2xl px-4 py-2",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
You can also pass a props object or a custom component:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
userMessage: {
|
||||
className: "bg-primary text-primary-foreground",
|
||||
"data-testid": "user-message",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Input Customization
|
||||
|
||||
The `input` slot controls the text input and its toolbar:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
className: "border-2 border-primary rounded-xl",
|
||||
placeholder: "Type your message...",
|
||||
|
||||
// Customize individual buttons
|
||||
sendButton: "bg-blue-500 hover:bg-blue-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
For full details on input slots and customization options, see [CopilotChatInput](/reference/copilot-chat-input).
|
||||
|
||||
## Suggestions
|
||||
|
||||
CopilotChat automatically manages suggestion chips through the `useSuggestions` hook. Suggestions are generated by the agent and displayed as clickable chips that users can select to quickly send messages.
|
||||
|
||||
You can customize suggestions through the `suggestionView` slot, which has two sub-slots:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
suggestionView={{
|
||||
// Customize the container that holds all chips
|
||||
container: "gap-4",
|
||||
// Customize individual suggestion chips
|
||||
suggestion: "bg-blue-100 hover:bg-blue-200 rounded-full",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Voice Transcription
|
||||
|
||||
CopilotChat supports voice input through transcription. To enable it, configure your CopilotKitProvider with transcription settings:
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider
|
||||
runtimeUrl="/api/copilotkit"
|
||||
transcribeAudioUrl="/api/transcribe"
|
||||
>
|
||||
<CopilotChat />
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
|
||||
Once enabled, a microphone button appears in the input toolbar. Users can record audio which is transcribed and inserted into the message input.
|
||||
|
||||
## Welcome Screen Customization
|
||||
|
||||
The welcome screen is displayed before any messages are sent. You can customize it in several ways:
|
||||
|
||||
### Custom Welcome Message
|
||||
|
||||
The simplest customization is changing the welcome message text:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
labels={{
|
||||
welcomeMessage: "Hello! I'm your AI assistant. How can I help you today?",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Custom Welcome Screen Component
|
||||
|
||||
For full control, replace the entire welcome screen:
|
||||
|
||||
```tsx
|
||||
function CustomWelcomeScreen() {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full p-8">
|
||||
<img src="/logo.svg" alt="Logo" className="w-16 h-16 mb-4" />
|
||||
<h2 className="text-2xl font-bold mb-2">Welcome to AI Assistant</h2>
|
||||
<p className="text-muted-foreground text-center">
|
||||
Ask me anything about your data, documents, or tasks.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat welcomeScreen={CustomWelcomeScreen} />;
|
||||
```
|
||||
|
||||
## Auto-scrolling Behavior
|
||||
|
||||
CopilotChat automatically scrolls to the bottom when:
|
||||
|
||||
- New messages are added
|
||||
- The user is already near the bottom
|
||||
- `autoScroll` prop is true (default)
|
||||
|
||||
The scroll-to-bottom button appears when the user scrolls up and new content is available.
|
||||
|
||||
```tsx
|
||||
// Disable auto-scroll
|
||||
<CopilotChat autoScroll={false} />
|
||||
|
||||
// Customize the scroll button
|
||||
<CopilotChat scrollView={{ scrollToBottomButton: "bg-blue-500 rounded-full shadow-lg" }} />
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
Here's a fully customized CopilotChat implementation:
|
||||
|
||||
```tsx
|
||||
import { CopilotChat, CopilotKitProvider } from "@copilotkit/react-core";
|
||||
|
||||
function App() {
|
||||
const handleFeedback = (messageId: string, type: "positive" | "negative") => {
|
||||
analytics.track("message_feedback", { messageId, type });
|
||||
};
|
||||
|
||||
return (
|
||||
<CopilotKitProvider runtimeUrl="/api/copilotkit">
|
||||
<div className="h-screen">
|
||||
<CopilotChat
|
||||
agentId="my-assistant"
|
||||
className="h-full"
|
||||
labels={{
|
||||
chatInputPlaceholder: "Ask me anything...",
|
||||
chatDisclaimerText: "AI responses may not be accurate.",
|
||||
welcomeMessage: "Hello! I'm here to help.",
|
||||
}}
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (msg) => handleFeedback(msg.id, "positive"),
|
||||
onThumbsDown: (msg) => handleFeedback(msg.id, "negative"),
|
||||
},
|
||||
}}
|
||||
input={{
|
||||
className: "border-2 border-gray-200 rounded-xl",
|
||||
disclaimer: "text-xs text-gray-400",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</CopilotKitProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
### Slot Components
|
||||
|
||||
- [CopilotChatMessageView](/reference/copilot-chat-message-view) - Message list customization
|
||||
- [CopilotChatScrollView](/reference/copilot-chat-scroll-view) - Scroll container customization
|
||||
- [CopilotChatInput](/reference/copilot-chat-input) - Input component customization
|
||||
- [CopilotChatSuggestionView](/reference/copilot-chat-suggestion-view) - Suggestion chips customization
|
||||
- [CopilotChatWelcomeScreen](/reference/copilot-chat-welcome-screen) - Welcome screen customization
|
||||
- [CopilotChatAssistantMessage](/reference/copilot-chat-assistant-message) - Assistant message customization
|
||||
|
||||
### Other Components
|
||||
|
||||
- [CopilotSidebar](/reference/copilot-sidebar) - Slide-in sidebar chat interface
|
||||
- [CopilotPopup](/reference/copilot-popup) - Floating popup chat dialog
|
||||
|
||||
### Guides & Concepts
|
||||
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
|
||||
### Providers & Hooks
|
||||
|
||||
- [CopilotKitProvider](/reference/copilotkit-provider) - Provider configuration
|
||||
- [useAgent](/reference/use-agent) - Hook for programmatic agent control
|
||||
- [useFrontendTool](/reference/use-frontend-tool) - Adding custom tools to the chat
|
||||
@@ -0,0 +1,216 @@
|
||||
---
|
||||
title: CopilotPopup
|
||||
description: "Floating popup chat dialog"
|
||||
---
|
||||
|
||||
`CopilotPopup` is a React component that provides a floating popup chat interface. It wraps [CopilotChat](/reference/copilot-chat) with additional popup-specific behavior including a toggle button, fade/scale animation, and optional click-outside-to-close functionality.
|
||||
|
||||
## What is CopilotPopup?
|
||||
|
||||
The CopilotPopup component:
|
||||
|
||||
- Provides a floating dialog with smooth fade/scale animation
|
||||
- Includes a toggle button for open/close
|
||||
- Supports click-outside-to-close behavior
|
||||
- Responsive design (fullscreen on mobile, fixed size on desktop)
|
||||
- Built on [CopilotChat](/reference/copilot-chat) - inherits all its features and customization options
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotPopup extends [CopilotChat](/reference/copilot-chat#component-architecture) with additional slots:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
CP[CopilotPopup] --> header
|
||||
CP --> toggleButton
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| -------------- | --------------------------------------- |
|
||||
| `header` | Header bar with title and close button |
|
||||
| `toggleButton` | Floating button to open/close the popup |
|
||||
|
||||
CopilotPopup also inherits all slots from CopilotChat: `messageView`, `scrollView`, `input`, `suggestionView`, and `welcomeScreen`.
|
||||
|
||||
See [Slot Customization](#slot-customization) for details on how to customize these slots.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { CopilotPopup, CopilotKitProvider } from "@copilotkit/react-core";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CopilotKitProvider runtimeUrl="/api/copilotkit">
|
||||
<CopilotPopup />
|
||||
</CopilotKitProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### Popup-Specific Props
|
||||
|
||||
These props are unique to CopilotPopup:
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| --------------------- | ------------------ | ------- | --------------------------------------------------- |
|
||||
| `defaultOpen` | `boolean` | `true` | Whether the popup is open initially |
|
||||
| `width` | `number \| string` | `420` | Popup width in pixels or CSS unit |
|
||||
| `height` | `number \| string` | `560` | Popup height in pixels or CSS unit |
|
||||
| `clickOutsideToClose` | `boolean` | `false` | Close the popup when clicking outside |
|
||||
| `header` | `SlotValue` | - | Custom header component with title and close button |
|
||||
| `toggleButton` | `SlotValue` | - | Custom toggle button to open/close the popup |
|
||||
|
||||
### Shared Props
|
||||
|
||||
CopilotPopup inherits all props from [CopilotChat](/reference/copilot-chat), including:
|
||||
|
||||
- `agentId` - The agent to connect to
|
||||
- `threadId` - The conversation thread ID
|
||||
- `labels` - Customize text labels
|
||||
- `autoScroll` - Auto-scroll behavior
|
||||
- `className` - CSS class for the root container
|
||||
|
||||
See [CopilotChat Props](/reference/copilot-chat#props) for the complete list.
|
||||
|
||||
## Header Customization
|
||||
|
||||
The popup includes a header with a title and close button. Customize it through the `header` prop:
|
||||
|
||||
```tsx
|
||||
<CopilotPopup
|
||||
header={{
|
||||
titleContent: "My Assistant",
|
||||
closeButton: "hidden",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Header Sub-Slots
|
||||
|
||||
| Sub-Slot | Description |
|
||||
| -------------- | -------------------------------- |
|
||||
| `titleContent` | The title text or component |
|
||||
| `closeButton` | The close button (can be hidden) |
|
||||
|
||||
### Custom Header Component
|
||||
|
||||
Replace the entire header with your own component:
|
||||
|
||||
```tsx
|
||||
function CustomHeader() {
|
||||
return (
|
||||
<div className="flex items-center justify-between p-4 border-b">
|
||||
<div className="flex items-center gap-2">
|
||||
<BotIcon className="w-5 h-5" />
|
||||
<span className="font-semibold">My AI Assistant</span>
|
||||
</div>
|
||||
<button onClick={() => /* close popup */}>
|
||||
<XIcon className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotPopup header={CustomHeader} />
|
||||
```
|
||||
|
||||
## Toggle Button Customization
|
||||
|
||||
The popup includes a floating toggle button to open and close it. Customize it through the `toggleButton` prop:
|
||||
|
||||
```tsx
|
||||
<CopilotPopup
|
||||
toggleButton={{
|
||||
className: "bg-purple-500 hover:bg-purple-600",
|
||||
openIcon: "text-white",
|
||||
closeIcon: "text-white",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Toggle Button Sub-Slots
|
||||
|
||||
| Sub-Slot | Description |
|
||||
| ----------- | ----------------------------------------------- |
|
||||
| `openIcon` | Icon shown when popup is closed (click to open) |
|
||||
| `closeIcon` | Icon shown when popup is open (click to close) |
|
||||
|
||||
### Custom Toggle Button Component
|
||||
|
||||
Replace the toggle button entirely:
|
||||
|
||||
```tsx
|
||||
function CustomToggleButton() {
|
||||
return (
|
||||
<button className="fixed bottom-4 right-4 p-3 bg-blue-500 rounded-full">
|
||||
<ChatIcon className="w-6 h-6 text-white" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotPopup toggleButton={CustomToggleButton} />;
|
||||
```
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotPopup uses the same [slot system](/reference/slot-system) as CopilotChat. Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Custom Dimensions
|
||||
|
||||
```tsx
|
||||
<CopilotPopup width={500} height={700} />
|
||||
|
||||
// Or with CSS units
|
||||
<CopilotPopup width="30vw" height="80vh" />
|
||||
```
|
||||
|
||||
### Click Outside to Close
|
||||
|
||||
```tsx
|
||||
<CopilotPopup clickOutsideToClose={true} />
|
||||
```
|
||||
|
||||
### Custom Header Styling
|
||||
|
||||
```tsx
|
||||
<CopilotPopup
|
||||
header={{
|
||||
className: "bg-gradient-to-r from-blue-500 to-purple-500 text-white",
|
||||
titleContent: "AI Assistant",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Nested Slot Customization
|
||||
|
||||
```tsx
|
||||
<CopilotPopup
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (msg) => console.log("Liked:", msg.id),
|
||||
onThumbsDown: (msg) => console.log("Disliked:", msg.id),
|
||||
},
|
||||
}}
|
||||
input={{
|
||||
className: "border-2 border-gray-200",
|
||||
sendButton: "bg-blue-500 hover:bg-blue-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Base chat component with full customization options
|
||||
- [CopilotSidebar](/reference/copilot-sidebar) - Slide-in sidebar chat interface
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
- [CopilotKitProvider](/reference/copilotkit-provider) - Provider configuration
|
||||
@@ -0,0 +1,341 @@
|
||||
---
|
||||
title: CopilotRuntime
|
||||
description: "Server-side runtime for hosting CopilotKit agents"
|
||||
---
|
||||
|
||||
The `CopilotRuntime` package gives you everything you need to host CopilotKit agents on your own infrastructure. It owns the agent registry, wires an `AgentRunner`, exposes HTTP endpoints (Express or Hono), and optionally coordinates middleware and transcription services.
|
||||
|
||||
## Basic Setup
|
||||
|
||||
```ts
|
||||
import { CopilotRuntime, InMemoryAgentRunner } from "@copilotkit/runtime";
|
||||
import { BasicAgent } from "@copilotkit/runtime/v2";
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: {
|
||||
default: new BasicAgent({
|
||||
model: "openai/gpt-4o",
|
||||
prompt: "You are a helpful assistant.",
|
||||
}),
|
||||
},
|
||||
runner: new InMemoryAgentRunner(),
|
||||
});
|
||||
```
|
||||
|
||||
Once you create a runtime instance you can mount one of the provided HTTP endpoints (Express or Hono) described below.
|
||||
|
||||
## `CopilotRuntime` Constructor
|
||||
|
||||
```ts
|
||||
new CopilotRuntime(options: CopilotRuntimeOptions)
|
||||
```
|
||||
|
||||
### `CopilotRuntimeOptions`
|
||||
|
||||
| Option | Type | Description |
|
||||
| ------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `agents` | `Promise<Record<string, AbstractAgent>> \| Record<string, AbstractAgent>` | Required. A map from agent identifier to an `AbstractAgent`. You can return the map synchronously or asynchronously. |
|
||||
| `runner` | `AgentRunner` | Optional. Defaults to `new InMemoryAgentRunner()`. Controls how agent runs are scheduled and streamed. |
|
||||
| `transcriptionService` | `TranscriptionService` | Optional. Enables `/transcribe` and reports `audioFileTranscriptionEnabled: true` from `/info`. |
|
||||
| `beforeRequestMiddleware` | `BeforeRequestMiddleware` | Optional. Runs before every request. Can mutate the incoming `Request` or return `void`. |
|
||||
| `afterRequestMiddleware` | `AfterRequestMiddleware` | Optional. Runs after every handler resolves. Receives the response along with parsed messages, thread ID, and run ID extracted from the SSE stream. Use this for logging, metrics, telemetry, etc. |
|
||||
|
||||
### Passing Agents
|
||||
|
||||
- Provide a plain object mapping agent ids to instances. The helper `BasicAgent` covers common OpenAI/Anthropic/Gemini setups, but you can supply any `AbstractAgent`.
|
||||
- Because `agents` may be an async function, you can lazily load credentials or fetch configuration before returning the record.
|
||||
- Each request clones the selected agent instance so per-request state (messages, headers, tool registration) does not leak between threads.
|
||||
- `Authorization` and `x-*` headers on the incoming request are forwarded to the cloned agent automatically. Override or strip them inside `beforeRequestMiddleware` if needed.
|
||||
|
||||
```ts
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: async () => ({
|
||||
default: buildDefaultAgent(),
|
||||
support: buildSupportAgent(),
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
### Choosing an `AgentRunner`
|
||||
|
||||
`InMemoryAgentRunner` is the default and streams events directly from your Node.js process. Swap it with a custom `AgentRunner` if you need to enqueue work or forward to another service:
|
||||
|
||||
```ts
|
||||
class QueueBackedRunner implements AgentRunner {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents,
|
||||
runner: new QueueBackedRunner(),
|
||||
});
|
||||
```
|
||||
|
||||
### Middleware Hooks
|
||||
|
||||
```ts
|
||||
const runtime = new CopilotRuntime({
|
||||
agents,
|
||||
beforeRequestMiddleware: async ({ request, path }) => {
|
||||
const auth = request.headers.get("authorization");
|
||||
if (!auth) {
|
||||
throw new Response("Unauthorized", { status: 401 });
|
||||
}
|
||||
},
|
||||
afterRequestMiddleware: async ({
|
||||
response,
|
||||
path,
|
||||
messages,
|
||||
threadId,
|
||||
runId,
|
||||
}) => {
|
||||
console.info("Handled", path, response.status);
|
||||
console.info("Thread:", threadId, "Run:", runId);
|
||||
console.info("Messages:", messages);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Throwing a `Response` from `beforeRequestMiddleware` short-circuits the request. `afterRequestMiddleware` runs in the background and should swallow its own errors.
|
||||
|
||||
#### `AfterRequestMiddlewareParameters`
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| ---------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `runtime` | `CopilotRuntime` | The runtime instance. |
|
||||
| `response` | `Response` | A clone of the response sent to the client. The body is still readable. |
|
||||
| `path` | `string` | The matched route path (e.g. `/agent/default/run`). |
|
||||
| `messages` | `Message[]` | Reconstructed messages from the SSE stream. Empty for non-SSE responses. Each message has `id`, `role`, and optionally `content`, `toolCalls`, or `toolCallId`. |
|
||||
| `threadId` | `string \| undefined` | Thread ID from the `RUN_STARTED` event. |
|
||||
| `runId` | `string \| undefined` | Run ID from the `RUN_STARTED` event. |
|
||||
|
||||
This makes `afterRequestMiddleware` suitable for telemetry, audit logging, and post-run analytics without needing to manually parse the streamed response.
|
||||
|
||||
### Audio Transcription
|
||||
|
||||
Enable audio transcription by providing a `transcriptionService`. The `@copilotkit/voice` package includes providers:
|
||||
|
||||
```ts
|
||||
import { CopilotRuntime } from "@copilotkit/runtime";
|
||||
import { TranscriptionServiceOpenAI } from "@copilotkit/voice";
|
||||
import OpenAI from "openai";
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: { default: yourAgent },
|
||||
transcriptionService: new TranscriptionServiceOpenAI({
|
||||
openai: new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
This enables the `/transcribe` endpoint and shows a microphone button in the chat UI. The `/info` endpoint will report `audioFileTranscriptionEnabled: true`.
|
||||
|
||||
For custom providers, extend `TranscriptionService` from runtime:
|
||||
|
||||
```ts
|
||||
import {
|
||||
TranscriptionService,
|
||||
TranscribeFileOptions,
|
||||
} from "@copilotkit/runtime";
|
||||
|
||||
class MyTranscriptionService extends TranscriptionService {
|
||||
async transcribeFile(options: TranscribeFileOptions): Promise<string> {
|
||||
// options.audioFile, options.mimeType, options.size
|
||||
return "transcribed text";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## HTTP Endpoints
|
||||
|
||||
Import the helper that matches your server framework and the transport style you want to expose.
|
||||
|
||||
### Hono (REST-style)
|
||||
|
||||
```ts
|
||||
import { createCopilotEndpoint } from "@copilotkit/runtime";
|
||||
|
||||
const copilot = createCopilotEndpoint({ runtime, basePath: "/api/copilotkit" });
|
||||
|
||||
const app = new Hono();
|
||||
app.route("/", copilot);
|
||||
```
|
||||
|
||||
This mounts five routes under the base path:
|
||||
|
||||
| Method | Path | Purpose |
|
||||
| ------ | -------------------------------- | -------------------------------------------------------------- |
|
||||
| `POST` | `/agent/:agentId/run` | Streams agent events (SSE). |
|
||||
| `POST` | `/agent/:agentId/connect` | Creates a live WebSocket/stream connection. |
|
||||
| `POST` | `/agent/:agentId/stop/:threadId` | Cancels an in-flight thread. |
|
||||
| `GET` | `/info` | Returns runtime metadata and agent list. |
|
||||
| `POST` | `/transcribe` | Proxies audio transcription (requires `transcriptionService`). |
|
||||
|
||||
### Hono (Single-route)
|
||||
|
||||
```ts
|
||||
import { createCopilotEndpointSingleRoute } from "@copilotkit/runtime";
|
||||
|
||||
const copilot = createCopilotEndpointSingleRoute({
|
||||
runtime,
|
||||
basePath: "/api/copilotkit",
|
||||
});
|
||||
|
||||
const app = new Hono();
|
||||
app.route("/", copilot);
|
||||
```
|
||||
|
||||
All interactions happen through a single `POST /api/copilotkit` endpoint. The client sends a JSON envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "agent/run",
|
||||
"params": { "agentId": "default" },
|
||||
"body": { "messages": [...], "threadId": "thread-123" }
|
||||
}
|
||||
```
|
||||
|
||||
Allowed `method` values are:
|
||||
|
||||
- `agent/run`
|
||||
- `agent/connect`
|
||||
- `agent/stop`
|
||||
- `info`
|
||||
- `transcribe`
|
||||
|
||||
Pair this server endpoint with the React provider flag `<CopilotKitProvider useSingleEndpoint />`.
|
||||
|
||||
### Next.js (App Router) with Hono
|
||||
|
||||
When you're inside a Next.js `app/` route, export the Hono handlers directly:
|
||||
|
||||
```ts
|
||||
// app/api/copilotkit/[[...slug]]/route.ts
|
||||
import { CopilotRuntime, createCopilotEndpoint } from "@copilotkit/runtime";
|
||||
import { handle } from "hono/vercel";
|
||||
|
||||
const runtime = new CopilotRuntime({ agents, runner });
|
||||
const app = createCopilotEndpoint({ runtime, basePath: "/api/copilotkit" });
|
||||
|
||||
export const GET = handle(app);
|
||||
export const POST = handle(app);
|
||||
```
|
||||
|
||||
Swap `createCopilotEndpoint` for `createCopilotEndpointSingleRoute` if you configure the client with `useSingleEndpoint`.
|
||||
|
||||
### Express (REST-style)
|
||||
|
||||
```ts
|
||||
import express from "express";
|
||||
import { createCopilotEndpointExpress } from "@copilotkit/runtime/express";
|
||||
|
||||
const app = express();
|
||||
app.use(
|
||||
"/api/copilotkit",
|
||||
createCopilotEndpointExpress({ runtime, basePath: "/" }),
|
||||
);
|
||||
```
|
||||
|
||||
The router mirrors the Hono REST routes and automatically enables permissive CORS (allowing all origins, headers, and methods). Adjust headers upstream if you need tighter controls.
|
||||
|
||||
### Express (Single-route)
|
||||
|
||||
```ts
|
||||
import express from "express";
|
||||
import { createCopilotEndpointSingleRouteExpress } from "@copilotkit/runtime/express";
|
||||
|
||||
const app = express();
|
||||
app.use(
|
||||
"/api/copilotkit",
|
||||
createCopilotEndpointSingleRouteExpress({ runtime, basePath: "/" }),
|
||||
);
|
||||
```
|
||||
|
||||
Single-route Express works identically to the Hono version: send the JSON envelope described earlier, and set `useSingleEndpoint` on the client.
|
||||
|
||||
### NestJS (Express backend)
|
||||
|
||||
NestJS uses Express by default. Mount the Express router in `main.ts`:
|
||||
|
||||
```ts
|
||||
// main.ts
|
||||
import { NestFactory } from "@nestjs/core";
|
||||
import { AppModule } from "./app.module";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { CopilotRuntime } from "@copilotkit/runtime";
|
||||
import { createCopilotEndpointExpress } from "@copilotkit/runtime/express";
|
||||
import { BasicAgent } from "@copilotkit/runtime/v2";
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: {
|
||||
default: new BasicAgent({
|
||||
model: "openai/gpt-4o",
|
||||
prompt: "You are helpful.",
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
// Mount under /api/copilotkit (REST-style routes)
|
||||
app.use(
|
||||
"/api/copilotkit",
|
||||
createCopilotEndpointExpress({ runtime, basePath: "/" }),
|
||||
);
|
||||
|
||||
await app.listen(3000);
|
||||
}
|
||||
bootstrap();
|
||||
```
|
||||
|
||||
Available routes (no global prefix):
|
||||
|
||||
- `POST /api/copilotkit/agent/:agentId/run`
|
||||
- `POST /api/copilotkit/agent/:agentId/connect`
|
||||
- `POST /api/copilotkit/agent/:agentId/stop/:threadId`
|
||||
- `GET /api/copilotkit/info`
|
||||
- `POST /api/copilotkit/transcribe`
|
||||
|
||||
If you prefer the single-route transport, mount the single-route helper instead and set `useSingleEndpoint` on the client:
|
||||
|
||||
```ts
|
||||
import { createCopilotEndpointSingleRouteExpress } from "@copilotkit/runtime/express";
|
||||
|
||||
app.use(
|
||||
"/api/copilotkit",
|
||||
createCopilotEndpointSingleRouteExpress({ runtime, basePath: "/" }),
|
||||
);
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- If you call `app.setGlobalPrefix('api')`, the effective paths become `/api/copilotkit/...` (or `/api/copilotkit` for single-route).
|
||||
- Endpoints stream Server‑Sent Events; ensure your proxy honors `text/event-stream` and keep‑alive.
|
||||
- The router enables permissive CORS; tighten via Nest’s `enableCors` if needed.
|
||||
|
||||
## Runtime Metadata
|
||||
|
||||
Calling `GET /info` (or the `info` single-route method) returns:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.0.20",
|
||||
"agents": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"className": "BasicAgent",
|
||||
"description": "You are a helpful assistant."
|
||||
}
|
||||
},
|
||||
"audioFileTranscriptionEnabled": false
|
||||
}
|
||||
```
|
||||
|
||||
Use this to verify deployments and surface diagnostics in your UI.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Configure the React client with `runtimeUrl` (and `useSingleEndpoint` if you chose the single endpoint helper).
|
||||
- Register frontend tools with `CopilotKitProvider` so agents can trigger UI actions.
|
||||
- Extend the runtime runner or middleware hooks to integrate logging, rate limiting, or background queues.
|
||||
@@ -0,0 +1,208 @@
|
||||
---
|
||||
title: CopilotSidebar
|
||||
description: "Sidebar chat interface with slide-in animation"
|
||||
---
|
||||
|
||||
`CopilotSidebar` is a React component that provides a slide-in sidebar chat interface. It wraps [CopilotChat](/reference/copilot-chat) with additional sidebar-specific behavior including a toggle button, slide-in animation, and automatic body margin adjustment.
|
||||
|
||||
## What is CopilotSidebar?
|
||||
|
||||
The CopilotSidebar component:
|
||||
|
||||
- Provides a fixed right-side panel with smooth slide-in animation
|
||||
- Includes a toggle button for open/close
|
||||
- Automatically adjusts body margin when open to prevent content overlap
|
||||
- Responsive design (full width on mobile, custom width on desktop)
|
||||
- Built on [CopilotChat](/reference/copilot-chat) - inherits all its features and customization options
|
||||
|
||||
## Component Architecture
|
||||
|
||||
CopilotSidebar extends [CopilotChat](/reference/copilot-chat#component-architecture) with additional slots:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
CS[CopilotSidebar] --> header
|
||||
CS --> toggleButton
|
||||
```
|
||||
|
||||
### Slot Descriptions
|
||||
|
||||
| Slot | Description |
|
||||
| -------------- | ----------------------------------------- |
|
||||
| `header` | Header bar with title and close button |
|
||||
| `toggleButton` | Floating button to open/close the sidebar |
|
||||
|
||||
CopilotSidebar also inherits all slots from CopilotChat: `messageView`, `scrollView`, `input`, `suggestionView`, and `welcomeScreen`.
|
||||
|
||||
See [Slot Customization](#slot-customization) for details on how to customize these slots.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { CopilotSidebar, CopilotKitProvider } from "@copilotkit/react-core";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CopilotKitProvider runtimeUrl="/api/copilotkit">
|
||||
<CopilotSidebar />
|
||||
</CopilotKitProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### Sidebar-Specific Props
|
||||
|
||||
These props are unique to CopilotSidebar:
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| -------------- | ------------------ | ------- | --------------------------------------------------- |
|
||||
| `defaultOpen` | `boolean` | `true` | Whether the sidebar is open initially |
|
||||
| `width` | `number \| string` | `480` | Sidebar width in pixels or CSS unit |
|
||||
| `header` | `SlotValue` | - | Custom header component with title and close button |
|
||||
| `toggleButton` | `SlotValue` | - | Custom toggle button to open/close the sidebar |
|
||||
|
||||
### Shared Props
|
||||
|
||||
CopilotSidebar inherits all props from [CopilotChat](/reference/copilot-chat), including:
|
||||
|
||||
- `agentId` - The agent to connect to
|
||||
- `threadId` - The conversation thread ID
|
||||
- `labels` - Customize text labels
|
||||
- `autoScroll` - Auto-scroll behavior
|
||||
- `className` - CSS class for the root container
|
||||
|
||||
See [CopilotChat Props](/reference/copilot-chat#props) for the complete list.
|
||||
|
||||
## Header Customization
|
||||
|
||||
The sidebar includes a header with a title and close button. Customize it through the `header` prop:
|
||||
|
||||
```tsx
|
||||
<CopilotSidebar
|
||||
header={{
|
||||
titleContent: "My Assistant",
|
||||
closeButton: "hidden",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Header Sub-Slots
|
||||
|
||||
| Sub-Slot | Description |
|
||||
| -------------- | -------------------------------- |
|
||||
| `titleContent` | The title text or component |
|
||||
| `closeButton` | The close button (can be hidden) |
|
||||
|
||||
### Custom Header Component
|
||||
|
||||
Replace the entire header with your own component:
|
||||
|
||||
```tsx
|
||||
function CustomHeader() {
|
||||
return (
|
||||
<div className="flex items-center justify-between p-4 border-b">
|
||||
<div className="flex items-center gap-2">
|
||||
<BotIcon className="w-5 h-5" />
|
||||
<span className="font-semibold">My AI Assistant</span>
|
||||
</div>
|
||||
<button onClick={() => /* close sidebar */}>
|
||||
<XIcon className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotSidebar header={CustomHeader} />
|
||||
```
|
||||
|
||||
## Toggle Button Customization
|
||||
|
||||
The sidebar includes a floating toggle button to open and close it. Customize it through the `toggleButton` prop:
|
||||
|
||||
```tsx
|
||||
<CopilotSidebar
|
||||
toggleButton={{
|
||||
className: "bg-purple-500 hover:bg-purple-600",
|
||||
openIcon: "text-white",
|
||||
closeIcon: "text-white",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Toggle Button Sub-Slots
|
||||
|
||||
| Sub-Slot | Description |
|
||||
| ----------- | ------------------------------------------------- |
|
||||
| `openIcon` | Icon shown when sidebar is closed (click to open) |
|
||||
| `closeIcon` | Icon shown when sidebar is open (click to close) |
|
||||
|
||||
### Custom Toggle Button Component
|
||||
|
||||
Replace the toggle button entirely:
|
||||
|
||||
```tsx
|
||||
function CustomToggleButton() {
|
||||
return (
|
||||
<button className="fixed bottom-4 right-4 p-3 bg-blue-500 rounded-full">
|
||||
<ChatIcon className="w-6 h-6 text-white" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotSidebar toggleButton={CustomToggleButton} />;
|
||||
```
|
||||
|
||||
## Slot Customization
|
||||
|
||||
CopilotSidebar uses the same [slot system](/reference/slot-system) as CopilotChat. Each slot accepts four types of values:
|
||||
|
||||
1. **Tailwind class string** - Add or override CSS classes
|
||||
2. **Props object** - Pass additional props to the default component
|
||||
3. **Custom component** - Replace the component entirely
|
||||
4. **Nested sub-slots** - Drill down to customize child components
|
||||
|
||||
### Custom Width
|
||||
|
||||
```tsx
|
||||
<CopilotSidebar width={600} />
|
||||
|
||||
// Or with CSS units
|
||||
<CopilotSidebar width="50vw" />
|
||||
```
|
||||
|
||||
### Custom Header Styling
|
||||
|
||||
```tsx
|
||||
<CopilotSidebar
|
||||
header={{
|
||||
className: "bg-gradient-to-r from-blue-500 to-purple-500 text-white",
|
||||
titleContent: "AI Assistant",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Nested Slot Customization
|
||||
|
||||
```tsx
|
||||
<CopilotSidebar
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (msg) => console.log("Liked:", msg.id),
|
||||
onThumbsDown: (msg) => console.log("Disliked:", msg.id),
|
||||
},
|
||||
}}
|
||||
input={{
|
||||
className: "border-2 border-gray-200",
|
||||
sendButton: "bg-blue-500 hover:bg-blue-600",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Base chat component with full customization options
|
||||
- [CopilotPopup](/reference/copilot-popup) - Floating popup chat dialog
|
||||
- [Slot System](/reference/slot-system) - Deep dive into slot customization
|
||||
- [CopilotKitProvider](/reference/copilotkit-provider) - Provider configuration
|
||||
@@ -0,0 +1,550 @@
|
||||
---
|
||||
title: CopilotKitCore
|
||||
description: "CopilotKitCore API Reference"
|
||||
---
|
||||
|
||||
`CopilotKitCore` is the client-side cross-framework orchestration layer that coordinates communication between your
|
||||
application's UI, agents abd the remote Copilot runtime.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Framework["Framework Layer"]
|
||||
React["**CopilotKit React**<br/>Components & Hooks"]
|
||||
Angular["**CopilotKit Angular**<br/>Directives & Services"]
|
||||
Vue["**CopilotKit ...**<br/>Future frameworks"]
|
||||
end
|
||||
|
||||
subgraph CoreLayer["Core Layer"]
|
||||
Core["**CopilotKitCore**<br/>Cross-framework Orchestration<br/>State Management & Agent Coordination"]
|
||||
end
|
||||
|
||||
subgraph RuntimeLayer["Runtime Layer"]
|
||||
Runtime["**CopilotRuntime**<br/>AI Agent Execution<br/>Backend Services"]
|
||||
end
|
||||
|
||||
React --> Core
|
||||
Angular --> Core
|
||||
Vue -.-> Core
|
||||
Core <--> Runtime
|
||||
```
|
||||
|
||||
## What does CopilotKitCore do?
|
||||
|
||||
CopilotKitCore solves several complex challenges in building AI-powered applications:
|
||||
|
||||
1. **Agent Orchestration**: Handles the entire lifecycle of running AI agents, from starting the agent and executing
|
||||
tools, to providing tool results, handling follow-ups and handling streaming updates to the UI.
|
||||
2. **Runtime Connection**: Manages connecting to and synchronizing with the remote `CopilotRuntime`.
|
||||
3. **State Synchronization**: Maintains consistent state across your application, ensuring all components have access to
|
||||
the latest agents, tools, and context
|
||||
4. **Framework Independence**: Works with any frontend framework, providing a consistent API whether you're using React,
|
||||
Angular, Vue, or vanilla JavaScript
|
||||
|
||||
At its heart, CopilotKitCore maintains the authoritative state for these critical elements:
|
||||
|
||||
- **Agents**: Both local and remote AI agents that power your application's intelligence
|
||||
- **Context**: Additional information that agents can use to make more informed decisions
|
||||
- **Frontend Tools**: Functions that agents can call to interact with your UI
|
||||
- **Properties and Headers**: Application-specific data forwarded to agents as additional properties or HTTP headers
|
||||
- **Runtime Metadata**: Connection status, versioning, and configuration details
|
||||
|
||||
## Creating a CopilotKitCore Instance
|
||||
|
||||
<Info>
|
||||
In most applications, you don’t need to create a `CopilotKitCore` instance
|
||||
yourself—CopilotKit initializes and manages it behind the scenes.
|
||||
</Info>
|
||||
|
||||
Instantiate `CopilotKitCore` to initialize the client that manages runtime connections, agents, and tools.
|
||||
|
||||
```typescript
|
||||
new CopilotKitCore(config?: CopilotKitCoreConfig)
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
```typescript
|
||||
interface CopilotKitCoreConfig {
|
||||
runtimeUrl?: string; // The endpoint where your CopilotRuntime server is hosted
|
||||
headers?: Record<string, string>; // Custom HTTP headers to include with every request
|
||||
properties?: Record<string, unknown>; // Application-specific data forwarded to agents as context
|
||||
agents__unsafe_dev_only?: Record<string, AbstractAgent>; // Local agents for development only - production requires CopilotRuntime
|
||||
tools?: FrontendTool<any>[]; // Frontend functions that agents can invoke
|
||||
}
|
||||
```
|
||||
|
||||
Configuration details:
|
||||
|
||||
- `runtimeUrl`: When provided, CopilotKitCore will automatically connect and discover available remote agents.
|
||||
- `headers`: Headers to include with every request.
|
||||
- `properties`: Properties forwarded to agents as `forwardedProps`.
|
||||
- `tools`: Frontend tools that agents can invoke.
|
||||
- `agents__unsafe_dev_only`: **Development only** - This property is intended solely for rapid prototyping during
|
||||
development. Production deployments require the security, reliability, and performance guarantees that only the
|
||||
CopilotRuntime can provide. The key becomes the agent's identifier.
|
||||
|
||||
## Core Properties
|
||||
|
||||
Once initialized, CopilotKitCore exposes several properties that provide insight into its current state:
|
||||
|
||||
### Runtime Configuration
|
||||
|
||||
- `runtimeUrl`: `string | undefined` The current runtime endpoint. Changing this property triggers a connection attempt
|
||||
to the new runtime. Setting it to `undefined` gracefully disconnects from the current runtime.
|
||||
|
||||
- `runtimeVersion`: `string | undefined` The version of the connected runtime, helpful for compatibility checks and
|
||||
debugging.
|
||||
|
||||
- `runtimeConnectionStatus`: `CopilotKitCoreRuntimeConnectionStatus` Tracks the current connection state, allowing you
|
||||
to respond to connection changes in your UI.
|
||||
|
||||
### State Management
|
||||
|
||||
- `headers`: `Readonly<Record<string, string>>` The current request headers sent with every request.
|
||||
|
||||
- `properties`: `Readonly<Record<string, unknown>>` The application properties being forwarded to agents.
|
||||
|
||||
- `agents`: `Readonly<Record<string, AbstractAgent>>` A combined view of all available agents, merging local development
|
||||
agents with those discovered from the runtime.
|
||||
|
||||
- `tools`: `Readonly<FrontendTool<any>[]>` The list of registered frontend tools available to agents.
|
||||
|
||||
- `context`: `Readonly<Record<string, Context>>` Contextual information that agents can use to make more informed
|
||||
decisions.
|
||||
|
||||
## Understanding Runtime Connections
|
||||
|
||||
When you provide a `runtimeUrl`, CopilotKitCore initiates a connection to your CopilotRuntime server. Here's what
|
||||
happens behind the scenes:
|
||||
|
||||
1. CopilotKitCore sends a GET request to `{runtimeUrl}/info`
|
||||
2. The runtime responds with available agents and metadata
|
||||
3. For each remote agent, `CopilotKitCore` creates a `ProxiedCopilotRuntimeAgent` instance
|
||||
4. These remote agents are merged with your local agents
|
||||
5. Subscribers are notified of the connection status and agent availability
|
||||
|
||||
### Runtime Connection States
|
||||
|
||||
The connection to your runtime can be in one of four states:
|
||||
|
||||
- `Disconnected`: No runtime URL is configured, or the connection was intentionally closed
|
||||
- `Connecting`: Actively attempting to establish a connection with the runtime
|
||||
- `Connected`: Successfully connected and remote agents are available
|
||||
- `Error`: The connection attempt failed, but CopilotKitCore will continue with local agents only
|
||||
|
||||
## Event Subscription System
|
||||
|
||||
CopilotKitCore implements a robust event system that allows you to react to state changes and agent activities:
|
||||
|
||||
### subscribe()
|
||||
|
||||
Registers a subscriber to receive events. Returns a subscription object with an `unsubscribe()` method, keeping
|
||||
unsubscription localized to the subscription object.
|
||||
|
||||
```typescript
|
||||
subscribe(subscriber: CopilotKitCoreSubscriber): { unsubscribe(): void }
|
||||
```
|
||||
|
||||
## Subscribing to Events
|
||||
|
||||
The event subscription system allows you to build reactive UIs that respond to CopilotKitCore's state changes. Each
|
||||
event provides both the CopilotKitCore instance and relevant data:
|
||||
|
||||
### onRuntimeConnectionStatusChanged()
|
||||
|
||||
Notified whenever the connection to the runtime changes state. Use this to show connection indicators in your UI.
|
||||
|
||||
```typescript
|
||||
onRuntimeConnectionStatusChanged?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
status: CopilotKitCoreRuntimeConnectionStatus;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onToolExecutionStart()
|
||||
|
||||
Fired when an agent begins executing a tool. Useful for showing loading states or activity indicators.
|
||||
|
||||
```typescript
|
||||
onToolExecutionStart?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
toolCallId: string;
|
||||
agentId: string;
|
||||
toolName: string;
|
||||
args: unknown;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onToolExecutionEnd()
|
||||
|
||||
Fired when tool execution completes, whether successfully or with an error. Use this to update your UI based on the
|
||||
results.
|
||||
|
||||
```typescript
|
||||
onToolExecutionEnd?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
toolCallId: string;
|
||||
agentId: string;
|
||||
toolName: string;
|
||||
result: string;
|
||||
error?: string;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onAgentsChanged()
|
||||
|
||||
Notified when agents are added, removed, or updated. This includes both local changes and runtime discovery.
|
||||
|
||||
```typescript
|
||||
onAgentsChanged?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
agents: Readonly<Record<string, AbstractAgent>>;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onContextChanged()
|
||||
|
||||
Fired when context items are added or removed. Use this to keep UI elements in sync with available context.
|
||||
|
||||
```typescript
|
||||
onContextChanged?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
context: Readonly<Record<string, Context>>;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onPropertiesChanged()
|
||||
|
||||
Notified when application properties are updated. Useful for debugging or showing current configuration.
|
||||
|
||||
```typescript
|
||||
onPropertiesChanged?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
properties: Readonly<Record<string, unknown>>;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onHeadersChanged()
|
||||
|
||||
Fired when HTTP headers are modified. Important for tracking authentication state changes.
|
||||
|
||||
```typescript
|
||||
onHeadersChanged?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
headers: Readonly<Record<string, string>>;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
### onError()
|
||||
|
||||
The central error handler for all CopilotKitCore operations. Every error includes a code and contextual information to
|
||||
help with debugging.
|
||||
|
||||
```typescript
|
||||
onError?: (event: {
|
||||
copilotkit: CopilotKitCore;
|
||||
error: Error;
|
||||
code: CopilotKitCoreErrorCode;
|
||||
context: Record<string, any>;
|
||||
}) => void | Promise<void>
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
CopilotKitCore provides detailed error information through typed error codes, making it easier to handle different
|
||||
failure scenarios appropriately:
|
||||
|
||||
### Understanding Error Codes
|
||||
|
||||
Each error is categorized with a specific code that indicates what went wrong:
|
||||
|
||||
- `RUNTIME_INFO_FETCH_FAILED`: The attempt to fetch runtime information failed. This might indicate network issues or an
|
||||
incorrect runtime URL.
|
||||
|
||||
- `AGENT_CONNECT_FAILED`: Failed to establish a connection with an agent. Check that the agent is properly configured.
|
||||
|
||||
- `AGENT_RUN_FAILED`: The agent execution failed. This could be due to invalid messages or agent-side errors.
|
||||
|
||||
- `AGENT_RUN_FAILED_EVENT`: The agent reported a failure through its event stream.
|
||||
|
||||
- `AGENT_RUN_ERROR_EVENT`: The agent emitted an error event during execution.
|
||||
|
||||
- `TOOL_ARGUMENT_PARSE_FAILED`: The arguments provided to a tool couldn't be parsed. This usually indicates a mismatch
|
||||
between expected and actual parameters.
|
||||
|
||||
- `TOOL_HANDLER_FAILED`: A tool's handler function threw an error during execution.
|
||||
|
||||
## Running Agents
|
||||
|
||||
CopilotKitCore provides two primary methods for executing agents: `runAgent` for immediate execution with message
|
||||
handling, and `connectAgent` for establishing live connections to existing agent sessions.
|
||||
|
||||
### runAgent()
|
||||
|
||||
Executes an agent and intelligently handles the complete request-response cycle, including automatic tool execution and
|
||||
follow-up runs.
|
||||
|
||||
The execution flow:
|
||||
|
||||
1. Sends initial messages (if provided) to the agent
|
||||
2. Agent processes the request and may request tool calls
|
||||
3. CopilotKitCore automatically executes any requested frontend tools
|
||||
4. Tool results are added back to the message history
|
||||
5. If tools were executed and have `followUp` enabled (default), the agent is automatically re-run with the tool results
|
||||
6. This cycle continues until the agent completes without requesting more tools
|
||||
|
||||
Key behaviors:
|
||||
|
||||
- **Automatic Tool Execution**: When an agent requests a tool call, CopilotKitCore finds the matching tool, executes it,
|
||||
and adds the result to the conversation
|
||||
- **Smart Follow-ups**: After executing tools, it automatically re-runs the agent so it can process the tool results and
|
||||
continue its work
|
||||
- **Error Recovery**: Tool execution errors are captured and returned to the agent, allowing it to handle failures
|
||||
gracefully
|
||||
- **Wildcard Tools**: Supports a special "\*" tool that can handle any undefined tool request
|
||||
|
||||
```typescript
|
||||
runAgent(params: CopilotKitCoreRunAgentParams): Promise<RunAgentResult>
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
```typescript
|
||||
interface CopilotKitCoreRunAgentParams {
|
||||
agent: AbstractAgent; // The agent to execute
|
||||
}
|
||||
```
|
||||
|
||||
### connectAgent()
|
||||
|
||||
Establishes a live connection with an agent, restoring any existing conversation history and subscribing to real-time
|
||||
events. This method is particularly useful when:
|
||||
|
||||
- Reconnecting to an agent that's already running (displays new events as they occur)
|
||||
- Restoring conversation history after a page refresh
|
||||
- Setting up an agent that will receive updates from background processes
|
||||
|
||||
The connection process:
|
||||
|
||||
1. Provides the agent with current properties and available tools
|
||||
2. Sets up error event subscribers for proper error handling
|
||||
3. Restores any existing message history
|
||||
4. Returns immediately without triggering a new agent run
|
||||
|
||||
```typescript
|
||||
connectAgent(params: CopilotKitCoreConnectAgentParams): Promise<RunAgentResult>
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
```typescript
|
||||
interface CopilotKitCoreConnectAgentParams {
|
||||
agent: AbstractAgent; // The agent to connect
|
||||
agentId?: string; // Override the agent's default identifier
|
||||
}
|
||||
```
|
||||
|
||||
### getAgent()
|
||||
|
||||
Retrieves an agent by its identifier. Returns `undefined` if the agent doesn't exist or if the runtime is still
|
||||
connecting.
|
||||
|
||||
```typescript
|
||||
getAgent(id: string): AbstractAgent | undefined
|
||||
```
|
||||
|
||||
## Managing Context
|
||||
|
||||
Context provides agents with additional information about the current state of your application:
|
||||
|
||||
### addContext()
|
||||
|
||||
Adds contextual information that agents can reference. Returns a unique identifier for later removal.
|
||||
|
||||
```typescript
|
||||
addContext(context: Context): string
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
```typescript
|
||||
interface Context {
|
||||
description: string; // A human-readable description of what this context represents
|
||||
value: any; // The actual context data
|
||||
}
|
||||
```
|
||||
|
||||
### removeContext()
|
||||
|
||||
Removes previously added context using its identifier.
|
||||
|
||||
```typescript
|
||||
removeContext(id: string): void
|
||||
```
|
||||
|
||||
## Managing Tools
|
||||
|
||||
Tools are functions that agents can call to interact with your application:
|
||||
|
||||
### addTool()
|
||||
|
||||
Registers a new frontend tool. If a tool with the same name and agent scope already exists, the registration is skipped
|
||||
to prevent duplicates.
|
||||
|
||||
```typescript
|
||||
addTool<T>(tool: FrontendTool<T>): void
|
||||
```
|
||||
|
||||
### removeTool()
|
||||
|
||||
Removes a tool from the registry. You can remove tools globally or for specific agents:
|
||||
|
||||
- When `agentId` is provided, removes the tool only for that agent
|
||||
- When `agentId` is omitted, removes only global tools with the matching name
|
||||
|
||||
```typescript
|
||||
removeTool(id: string, agentId?: string): void
|
||||
```
|
||||
|
||||
### getTool()
|
||||
|
||||
Retrieves a tool by name, with intelligent fallback behavior:
|
||||
|
||||
- If an agent-specific tool isn't found, it falls back to global tools
|
||||
|
||||
```typescript
|
||||
getTool(params: CopilotKitCoreGetToolParams): FrontendTool<any> | undefined
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
```typescript
|
||||
interface CopilotKitCoreGetToolParams {
|
||||
toolName: string; // The tool's name
|
||||
agentId?: string; // Look for agent-specific tools first
|
||||
}
|
||||
```
|
||||
|
||||
### setTools()
|
||||
|
||||
Replaces all tools at once. Useful for completely reconfiguring available tools.
|
||||
|
||||
```typescript
|
||||
setTools(tools: FrontendTool<any>[]): void
|
||||
```
|
||||
|
||||
## Tool Execution Lifecycle
|
||||
|
||||
Understanding how CopilotKitCore handles tool execution is crucial for building responsive AI applications. Here's the
|
||||
complete lifecycle:
|
||||
|
||||
### 1. Tool Request
|
||||
|
||||
When an agent needs to interact with your application, it returns a tool call request with:
|
||||
|
||||
- Tool name
|
||||
- Structured arguments (JSON)
|
||||
- Unique call ID for tracking
|
||||
|
||||
### 2. Tool Resolution
|
||||
|
||||
CopilotKitCore uses a two-tier resolution strategy:
|
||||
|
||||
- First checks for agent-specific tools (scoped to that particular agent)
|
||||
- Falls back to global tools available to all agents
|
||||
- Special wildcard tool (`*`) can handle any unmatched tool requests
|
||||
|
||||
### 3. Execution & Error Handling
|
||||
|
||||
The tool handler is invoked with parsed arguments:
|
||||
|
||||
- Successful results are stringified and added to the conversation
|
||||
- Errors are caught and returned to the agent for graceful handling
|
||||
- Subscribers are notified of start and completion events
|
||||
|
||||
### 4. Automatic Follow-up
|
||||
|
||||
By default, after tool execution completes:
|
||||
|
||||
- The tool result is inserted into the message history
|
||||
- The agent is automatically re-run to process the results
|
||||
- This continues until no more tools are requested
|
||||
- You can disable follow-up by setting `followUp: false` on specific tools
|
||||
|
||||
## Working with Configuration
|
||||
|
||||
These methods allow you to dynamically update CopilotKitCore's configuration after initialization:
|
||||
|
||||
### setRuntimeUrl()
|
||||
|
||||
Changes the runtime endpoint and manages the connection lifecycle. This is useful when switching between different
|
||||
environments or disconnecting from the runtime entirely.
|
||||
|
||||
```typescript
|
||||
setRuntimeUrl(runtimeUrl: string | undefined): void
|
||||
```
|
||||
|
||||
### setHeaders()
|
||||
|
||||
Replaces all HTTP headers. Subscribers are notified so they can react to authentication changes or other header updates.
|
||||
|
||||
```typescript
|
||||
setHeaders(headers: Record<string, string>): void
|
||||
```
|
||||
|
||||
### setProperties()
|
||||
|
||||
Updates the properties forwarded to agents. Use this when your application state changes in ways that might affect agent
|
||||
behavior.
|
||||
|
||||
```typescript
|
||||
setProperties(properties: Record<string, unknown>): void
|
||||
```
|
||||
|
||||
## Managing Local Agents
|
||||
|
||||
<Warning>
|
||||
In production applications, agents must be managed through the CopilotRuntime,
|
||||
which provides proper isolation, monitoring, and scalability. The local agent
|
||||
methods below are marked `__unsafe_dev_only` as they're intended solely for
|
||||
rapid prototyping during development. Production deployments require the
|
||||
security and performance guarantees that only the CopilotRuntime can provide.
|
||||
</Warning>
|
||||
|
||||
Agents are the AI-powered components that process requests and generate responses. CopilotKitCore provides several
|
||||
methods to manage them locally during development:
|
||||
|
||||
### setAgents\_\_unsafe_dev_only()
|
||||
|
||||
Replaces all local development agents while preserving remote agents from the runtime.
|
||||
|
||||
```typescript
|
||||
setAgents__unsafe_dev_only(agents: Record<string, AbstractAgent>): void
|
||||
```
|
||||
|
||||
### addAgent\_\_unsafe_dev_only()
|
||||
|
||||
Adds a single agent for development testing.
|
||||
|
||||
```typescript
|
||||
addAgent__unsafe_dev_only(params: CopilotKitCoreAddAgentParams): void
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
```typescript
|
||||
interface CopilotKitCoreAddAgentParams {
|
||||
id: string; // A unique identifier for the agent
|
||||
agent: AbstractAgent; // The agent instance to add
|
||||
}
|
||||
```
|
||||
|
||||
### removeAgent\_\_unsafe_dev_only()
|
||||
|
||||
Removes a local development agent by its identifier. Remote agents from the runtime cannot be removed this way.
|
||||
|
||||
```typescript
|
||||
removeAgent__unsafe_dev_only(id: string): void
|
||||
```
|
||||
@@ -0,0 +1,298 @@
|
||||
---
|
||||
title: CopilotKitProvider
|
||||
description: "CopilotKitProvider API Reference"
|
||||
---
|
||||
|
||||
`CopilotKitProvider` is the React context provider that initializes and manages `CopilotKitCore` for your React
|
||||
application. It provides all child components with access to agents, tools, and copilot functionality through React's
|
||||
context API.
|
||||
|
||||
## What is CopilotKitProvider?
|
||||
|
||||
The CopilotKitProvider is the root component that:
|
||||
|
||||
- Creates and manages a `CopilotKitCore` instance
|
||||
- Provides React-specific features like hooks and render components
|
||||
- Manages tool rendering and human-in-the-loop interactions
|
||||
- Handles state synchronization between your React app and AI agents
|
||||
|
||||
## Basic Usage
|
||||
|
||||
Typically you would wrap your application with `CopilotKitProvider` at the root level:
|
||||
|
||||
```tsx
|
||||
import { CopilotKitProvider } from "@copilotkit/react-core";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CopilotKitProvider runtimeUrl="http://localhost:3000/api/copilotkit">
|
||||
{/* Your app components */}
|
||||
</CopilotKitProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### runtimeUrl
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
The URL of your CopilotRuntime server. The provider will automatically connect to the runtime and discover available
|
||||
agents.
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider runtimeUrl="https://api.example.com/copilot">
|
||||
{children}
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
|
||||
### headers
|
||||
|
||||
`Record<string, string>` **(optional)**
|
||||
|
||||
Custom HTTP headers to include with every request to the runtime. Useful for authentication and custom metadata.
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider
|
||||
runtimeUrl="https://api.example.com"
|
||||
headers={{
|
||||
Authorization: "Bearer your-token",
|
||||
"X-Custom-Header": "value",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
|
||||
### properties
|
||||
|
||||
`Record<string, unknown>` **(optional)**
|
||||
|
||||
Application-specific data that gets forwarded to agents as additional context. Agents receive these as `forwardedProps`.
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider
|
||||
properties={{
|
||||
userId: "user-123",
|
||||
theme: "dark",
|
||||
locale: "en-US",
|
||||
featureFlags: {
|
||||
betaFeatures: true,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
|
||||
### agents\_\_unsafe_dev_only
|
||||
|
||||
`Record<string, AbstractAgent>` **(optional, development only)**
|
||||
|
||||
<Warning>
|
||||
This property is intended solely for rapid prototyping during development.
|
||||
Production deployments require the security, reliability, and performance
|
||||
guarantees that only the CopilotRuntime can provide.
|
||||
</Warning>
|
||||
|
||||
Local agents for development testing. The key becomes the agent's identifier.
|
||||
|
||||
```tsx
|
||||
import { HttpAgent } from "@ag-ui/client";
|
||||
|
||||
const devAgent = new HttpAgent({
|
||||
url: "http://localhost:8000",
|
||||
});
|
||||
|
||||
<CopilotKitProvider
|
||||
agents__unsafe_dev_only={{
|
||||
devAgent,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CopilotKitProvider>;
|
||||
```
|
||||
|
||||
### useSingleEndpoint
|
||||
|
||||
`boolean` **(optional, default: `false`)**
|
||||
|
||||
When set to `true`, the provider connects to runtimes that expose the **single-route** transport (a single POST endpoint that multiplexes all runtime actions). Leave this `false` for the default REST-style transport.
|
||||
|
||||
Pair this flag with the matching server endpoint helper:
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider runtimeUrl="/api/copilotkit" useSingleEndpoint>
|
||||
{children}
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
|
||||
On the server, mount one of the single-route runtimes (`createCopilotEndpointSingleRoute` for Hono or `createCopilotEndpointSingleRouteExpress` for Express).
|
||||
|
||||
### renderToolCalls
|
||||
|
||||
`ReactToolCallRenderer[]` **(optional)**
|
||||
|
||||
A static list of components to render when specific tools are called. Enables visual feedback for tool execution.
|
||||
|
||||
```tsx
|
||||
const renderToolCalls = [
|
||||
{
|
||||
name: "searchProducts",
|
||||
args: z.object({
|
||||
query: z.string(),
|
||||
}),
|
||||
render: ({ args }) => <div>Searching for: {args.query}</div>,
|
||||
},
|
||||
];
|
||||
|
||||
<CopilotKitProvider renderToolCalls={renderToolCalls}>
|
||||
{children}
|
||||
</CopilotKitProvider>;
|
||||
```
|
||||
|
||||
<Note>
|
||||
The `renderToolCalls` array must be stable across renders. Define it outside
|
||||
your component or use `useMemo`. For dynamic tool rendering, use the
|
||||
`useRenderToolCall` hook instead.
|
||||
</Note>
|
||||
|
||||
### frontendTools
|
||||
|
||||
`ReactFrontendTool[]` **(optional)**
|
||||
|
||||
A static list of frontend tools that agents can invoke. These are React-specific wrappers around the base `FrontendTool`
|
||||
type with additional rendering capabilities.
|
||||
|
||||
```tsx
|
||||
const tools = [
|
||||
{
|
||||
name: "showNotification",
|
||||
description: "Display a notification to the user",
|
||||
parameters: z.object({
|
||||
message: z.string(),
|
||||
type: z.enum(["info", "success", "warning", "error"]),
|
||||
}),
|
||||
handler: async ({ message, type }) => {
|
||||
toast[type](message);
|
||||
return "Notification displayed";
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
<CopilotKitProvider frontendTools={tools}>{children}</CopilotKitProvider>;
|
||||
```
|
||||
|
||||
<Note>
|
||||
The `frontendTools` array must be stable across renders. For dynamically
|
||||
adding/removing tools, use the `useFrontendTool` hook.
|
||||
</Note>
|
||||
|
||||
### humanInTheLoop
|
||||
|
||||
`ReactHumanInTheLoop[]` **(optional)**
|
||||
|
||||
Tools that require human interaction or approval before execution. These tools pause agent execution until the user
|
||||
responds.
|
||||
|
||||
```tsx
|
||||
const humanInTheLoop = [
|
||||
{
|
||||
name: "confirmAction",
|
||||
description: "Request user confirmation for an action",
|
||||
parameters: z.object({
|
||||
action: z.string(),
|
||||
details: z.string(),
|
||||
}),
|
||||
render: ({ args, resolve }) => (
|
||||
<ConfirmDialog
|
||||
action={args.action}
|
||||
details={args.details}
|
||||
onConfirm={() => resolve({ confirmed: true })}
|
||||
onCancel={() => resolve({ confirmed: false })}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
<CopilotKitProvider humanInTheLoop={humanInTheLoop}>
|
||||
{children}
|
||||
</CopilotKitProvider>;
|
||||
```
|
||||
|
||||
### a2ui
|
||||
|
||||
`{ theme?: Theme; catalog?: any; loadingComponent?: React.ComponentType; includeSchema?: boolean }` **(optional)**
|
||||
|
||||
Configuration for the A2UI (Agent-to-UI) renderer. The built-in renderer activates automatically when the runtime reports that `a2ui` is configured in `CopilotRuntime`. This prop is only needed to override defaults.
|
||||
|
||||
| Option | Type | Description |
|
||||
| ------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `theme` | `Theme` | Override the default A2UI viewer theme. |
|
||||
| `catalog` | `any` | Custom component catalog. Defaults to `basicCatalog`. |
|
||||
| `loadingComponent` | `React.ComponentType` | Custom loading component shown while a surface is generating. |
|
||||
| `includeSchema` | `boolean` | When `true` (default), full component schemas are sent as agent context so the agent knows what's available. |
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider
|
||||
runtimeUrl="/api/copilotkit"
|
||||
a2ui={{
|
||||
theme: myCustomTheme,
|
||||
catalog: myCustomCatalog,
|
||||
loadingComponent: MySpinner,
|
||||
includeSchema: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
|
||||
### children
|
||||
|
||||
`ReactNode` **(required)**
|
||||
|
||||
The React components that will have access to the CopilotKit context.
|
||||
|
||||
## Context Value
|
||||
|
||||
The provider makes a `CopilotKitContextValue` available to child components through React context:
|
||||
|
||||
```typescript
|
||||
interface CopilotKitContextValue {
|
||||
copilotkit: CopilotKitCore;
|
||||
renderToolCalls: ReactToolCallRenderer<any>[];
|
||||
currentRenderToolCalls: ReactToolCallRenderer<unknown>[];
|
||||
setCurrentRenderToolCalls: React.Dispatch<
|
||||
React.SetStateAction<ReactToolCallRenderer<unknown>[]>
|
||||
>;
|
||||
}
|
||||
```
|
||||
|
||||
Access this context using the `useCopilotKit` hook:
|
||||
|
||||
```tsx
|
||||
import { useCopilotKit } from "@copilotkit/react-core";
|
||||
|
||||
function MyComponent() {
|
||||
const { copilotkit } = useCopilotKit();
|
||||
|
||||
// Access CopilotKitCore instance
|
||||
const agent = copilotkit.getAgent("assistant");
|
||||
}
|
||||
```
|
||||
|
||||
## Considerations
|
||||
|
||||
### Server-Side Rendering (SSR)
|
||||
|
||||
The provider is compatible with SSR but won't fetch runtime information during server-side rendering. The runtime
|
||||
connection is established only on the client side to prevent blocking SSR.
|
||||
|
||||
### Dynamic Updates
|
||||
|
||||
You can dynamically update the following props:
|
||||
|
||||
- `runtimeUrl`: Changing this will disconnect from the current runtime and connect to the new one
|
||||
- `headers`: Updates are applied to all future requests
|
||||
- `properties`: Changes are immediately available to agents
|
||||
@@ -0,0 +1,159 @@
|
||||
---
|
||||
title: FrontendTool
|
||||
description: "FrontendTool API Reference"
|
||||
---
|
||||
|
||||
`FrontendTool` is a cross-platform type that defines tools (functions) that AI agents can invoke in your frontend
|
||||
application. These tools enable agents to interact the user, retrieve data, perform actions, and integrate with your
|
||||
application's functionality.
|
||||
|
||||
## What is a FrontendTool?
|
||||
|
||||
A FrontendTool represents a capability you expose to AI agents, allowing them to:
|
||||
|
||||
- Interact with the user
|
||||
- Fetch or manipulate application data
|
||||
- Trigger application workflows
|
||||
|
||||
Frontend tools are framework-agnostic and work consistently across all frameworks through `CopilotKitCore`.
|
||||
|
||||
## Type Definition
|
||||
|
||||
```typescript
|
||||
type FrontendToolHandlerContext = {
|
||||
toolCall: ToolCall;
|
||||
agent: AbstractAgent;
|
||||
};
|
||||
|
||||
type FrontendTool<T extends Record<string, unknown> = Record<string, unknown>> =
|
||||
{
|
||||
name: string;
|
||||
description?: string;
|
||||
parameters?: z.ZodType<T>;
|
||||
handler?: (
|
||||
args: T,
|
||||
context: FrontendToolHandlerContext,
|
||||
) => Promise<unknown>;
|
||||
followUp?: boolean;
|
||||
agentId?: string;
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### name
|
||||
|
||||
`string` **(required)**
|
||||
|
||||
A unique identifier for the tool. This is the name agents will use to request this tool's execution. Avoid spaces and
|
||||
special characters.
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "searchProducts";
|
||||
}
|
||||
```
|
||||
|
||||
A special wildcard tool is available with the name `*`. This tool will handle any unmatched tool requests.
|
||||
|
||||
### description
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
A human-readable description that helps agents understand when and how to use this tool. This description is sent to the
|
||||
LLM to guide its decision-making.
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "searchProducts",
|
||||
description: "Search for products in the catalog by name, category, or price range"
|
||||
}
|
||||
```
|
||||
|
||||
### parameters
|
||||
|
||||
`z.ZodType<T>` **(optional)**
|
||||
|
||||
A Zod schema that defines and validates the tool's input parameters. This ensures type safety and provides automatic
|
||||
validation of agent-provided arguments.
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
{
|
||||
name: "updateUserProfile",
|
||||
parameters: z.object({
|
||||
firstName: z.string().optional(),
|
||||
lastName: z.string().optional(),
|
||||
email: z.string().email().optional(),
|
||||
preferences: z.object({
|
||||
theme: z.enum(["light", "dark"]).optional(),
|
||||
notifications: z.boolean().optional()
|
||||
}).optional()
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### handler
|
||||
|
||||
`(args: T, context: FrontendToolHandlerContext) => Promise<unknown>` **(optional)**
|
||||
|
||||
The async function that executes when the agent invokes this tool. It receives the validated arguments and a context
|
||||
object containing the `toolCall` with metadata about the invocation.
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "addToCart",
|
||||
parameters: z.object({
|
||||
productId: z.string(),
|
||||
quantity: z.number().min(1)
|
||||
}),
|
||||
handler: async ({productId, quantity}) => {
|
||||
// Add product to cart
|
||||
const result = await cartService.addItem(productId, quantity);
|
||||
|
||||
// Return a string or serializable object
|
||||
return {
|
||||
success: true,
|
||||
cartTotal: result.total,
|
||||
itemCount: result.itemCount
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### followUp
|
||||
|
||||
`boolean` **(optional, default: true)**
|
||||
|
||||
Controls whether the agent should be automatically re-run after this tool completes. When `true`, the tool's result is
|
||||
added to the conversation and the agent continues processing. Disable follow-up for final actions that complete a
|
||||
workflow.
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "saveDocument",
|
||||
handler: async (args) => {
|
||||
await documentService.save(args);
|
||||
return "Document saved successfully";
|
||||
},
|
||||
followUp: false // Don't re-run agent after saving
|
||||
}
|
||||
```
|
||||
|
||||
### agentId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
Restricts this tool to a specific agent. When set, only the specified agent can invoke this tool.
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "adminAction",
|
||||
agentId: "admin-assistant",
|
||||
handler: async (args) => {
|
||||
// Only the admin-assistant agent can call this
|
||||
return await performAdminAction(args);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: ProxiedCopilotRuntimeAgent
|
||||
description: "ProxiedCopilotRuntimeAgent API Reference"
|
||||
---
|
||||
|
||||
`ProxiedCopilotRuntimeAgent` is a specialized HTTP agent that acts as a proxy between your client application and remote
|
||||
agents hosted on the `CopilotRuntime` server. It extends the base `HttpAgent` class to provide seamless communication
|
||||
with runtime-hosted agents.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Client["Client Application"]
|
||||
Core[CopilotKitCore]
|
||||
PRA1[ProxiedCopilotRuntimeAgent<br/>customer-support]
|
||||
PRA2[ProxiedCopilotRuntimeAgent<br/>code-assistant]
|
||||
PRA3[ProxiedCopilotRuntimeAgent<br/>data-analyst]
|
||||
|
||||
Core --> PRA1
|
||||
Core --> PRA2
|
||||
Core --> PRA3
|
||||
end
|
||||
|
||||
subgraph Server["CopilotRuntime Server"]
|
||||
Runtime[Runtime API]
|
||||
Agent1[Agent: customer-support]
|
||||
Agent2[Agent: code-assistant]
|
||||
Agent3[Agent: data-analyst]
|
||||
|
||||
Runtime --> Agent1
|
||||
Runtime --> Agent2
|
||||
Runtime --> Agent3
|
||||
end
|
||||
|
||||
PRA1 -.-> Runtime
|
||||
PRA2 -.-> Runtime
|
||||
PRA3 -.-> Runtime
|
||||
```
|
||||
|
||||
## What is ProxiedCopilotRuntimeAgent?
|
||||
|
||||
When `CopilotKitCore` connects to a `CopilotRuntime` server, it discovers available remote agents. For each remote
|
||||
agent, it creates a `ProxiedCopilotRuntimeAgent` instance that handles all communication with that specific agent
|
||||
through the runtime's API endpoints.
|
||||
|
||||
Key characteristics:
|
||||
|
||||
- **Remote Agent Communication**: Handles communication with the remote agent through the runtime's API endpoints
|
||||
- **Header and Property Forwarding**: Inherits and forwards authentication headers and properties from `CopilotKitCore`
|
||||
- **Connection and History Management**: Handles loading history and reconnecting to existing live agent sessions
|
||||
|
||||
## How does it work?
|
||||
|
||||
`CopilotKitCore` automatically creates `ProxiedCopilotRuntimeAgent` instances during runtime discovery:
|
||||
|
||||
1. `CopilotKitCore` fetches `/info` from the runtime
|
||||
2. The runtime responds with available agents
|
||||
3. For each agent, `CopilotKitCore` creates a `ProxiedCopilotRuntimeAgent`
|
||||
4. These agents are merged with any local agents
|
||||
5. The agents become available through `copilotKit.getAgent()`
|
||||
|
||||
## Creating a ProxiedCopilotRuntimeAgent
|
||||
|
||||
<Note>
|
||||
In typical usage, you don't create `ProxiedCopilotRuntimeAgent` instances
|
||||
directly. `CopilotKitCore` automatically creates them when discovering agents
|
||||
from the runtime.
|
||||
</Note>
|
||||
|
||||
```typescript
|
||||
import { ProxiedCopilotRuntimeAgent } from "@copilotkit/core";
|
||||
|
||||
const agent = new ProxiedCopilotRuntimeAgent({
|
||||
runtimeUrl: "https://your-runtime.example.com",
|
||||
agentId: "my-agent",
|
||||
headers: {
|
||||
Authorization: "Bearer your-token",
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,394 @@
|
||||
---
|
||||
title: Slot System
|
||||
description: "Deep customization system for CopilotKit components"
|
||||
---
|
||||
|
||||
The Slot System is CopilotKit's approach to component customization. It allows you to customize any part of the UI - from simple styling changes to complete component replacement - all through a consistent, composable API.
|
||||
|
||||
## What is the Slot System?
|
||||
|
||||
The Slot System:
|
||||
|
||||
- Provides four levels of customization depth
|
||||
- Maintains type safety throughout the customization process
|
||||
- Supports nested slots for drilling into child components
|
||||
- Uses automatic memoization for optimal performance
|
||||
- Works consistently across all CopilotKit components
|
||||
|
||||
## Four Customization Levels
|
||||
|
||||
Every slot accepts one of four value types, from simplest to most flexible:
|
||||
|
||||
### 1. Tailwind Class String
|
||||
|
||||
Pass a string of Tailwind classes to add or override styles:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input="border-2 border-blue-500 rounded-xl"
|
||||
messageView="space-y-4 p-4"
|
||||
/>
|
||||
```
|
||||
|
||||
Classes are merged with the component's existing classes using `tailwind-merge`, so conflicting classes are resolved intelligently.
|
||||
|
||||
### 2. Props Object
|
||||
|
||||
Pass an object of props to customize behavior while keeping the default component:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
className: "custom-input",
|
||||
autoFocus: false,
|
||||
}}
|
||||
messageView={{
|
||||
className: "custom-messages",
|
||||
assistantMessage: {
|
||||
onThumbsUp: (msg) => trackFeedback(msg.id, "positive"),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
Props are merged with defaults, and you can include nested slots to drill down to child components.
|
||||
|
||||
### 3. Custom Component
|
||||
|
||||
Replace the component entirely with your own implementation:
|
||||
|
||||
```tsx
|
||||
function CustomInput({ onSubmitMessage, isRunning, ...props }) {
|
||||
return (
|
||||
<div className="my-custom-wrapper">
|
||||
<CopilotChatInput
|
||||
onSubmitMessage={onSubmitMessage}
|
||||
isRunning={isRunning}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat input={CustomInput} />;
|
||||
```
|
||||
|
||||
Custom components receive all the props that would have been passed to the default component.
|
||||
|
||||
### 4. Render Function (Children)
|
||||
|
||||
For full layout control, use the children render function pattern:
|
||||
|
||||
```tsx
|
||||
function CustomInput(props) {
|
||||
return (
|
||||
<CopilotChatInput {...props}>
|
||||
{({ textArea, sendButton, addMenuButton }) => (
|
||||
<div className="flex gap-2">
|
||||
{addMenuButton}
|
||||
<div className="flex-1">{textArea}</div>
|
||||
{sendButton}
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatInput>
|
||||
);
|
||||
}
|
||||
|
||||
<CopilotChat input={CustomInput} />;
|
||||
```
|
||||
|
||||
The render function receives pre-built slot elements that you can arrange however you like.
|
||||
|
||||
## Nested Slot Customization
|
||||
|
||||
Slots can be nested to customize deeply nested components:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
// Top-level slot
|
||||
messageView={{
|
||||
// First level nesting
|
||||
assistantMessage: {
|
||||
// Second level nesting
|
||||
toolbar: "bg-gray-50 rounded-lg",
|
||||
copyButton: "text-blue-500",
|
||||
thumbsUpButton: () => null, // Hide the button
|
||||
},
|
||||
userMessage: "bg-blue-100 rounded-xl",
|
||||
}}
|
||||
input={{
|
||||
textArea: "text-lg",
|
||||
sendButton: "bg-green-500",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Hiding Components
|
||||
|
||||
To hide a slot entirely, return `null` from a component function:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
input={{
|
||||
disclaimer: () => null, // Hide disclaimer
|
||||
startTranscribeButton: () => null, // Hide voice button
|
||||
}}
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
regenerateButton: () => null, // Hide regenerate
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Complete Slot Hierarchy
|
||||
|
||||
Here's the full hierarchy of all customizable slots in CopilotChat:
|
||||
|
||||
```
|
||||
CopilotChat
|
||||
├── chatView
|
||||
│ ├── messageView
|
||||
│ │ ├── assistantMessage
|
||||
│ │ │ ├── markdownRenderer
|
||||
│ │ │ ├── toolbar
|
||||
│ │ │ ├── copyButton
|
||||
│ │ │ ├── thumbsUpButton
|
||||
│ │ │ ├── thumbsDownButton
|
||||
│ │ │ ├── readAloudButton
|
||||
│ │ │ ├── regenerateButton
|
||||
│ │ │ └── toolCallsView
|
||||
│ │ ├── userMessage (see CopilotChatUserMessage)
|
||||
│ │ │ ├── messageRenderer
|
||||
│ │ │ ├── toolbar
|
||||
│ │ │ ├── copyButton
|
||||
│ │ │ ├── editButton
|
||||
│ │ │ └── branchNavigation
|
||||
│ │ └── cursor
|
||||
│ ├── scrollView
|
||||
│ │ ├── scrollToBottomButton
|
||||
│ │ └── feather
|
||||
│ ├── input
|
||||
│ │ ├── textArea
|
||||
│ │ ├── sendButton
|
||||
│ │ ├── startTranscribeButton
|
||||
│ │ ├── cancelTranscribeButton
|
||||
│ │ ├── finishTranscribeButton
|
||||
│ │ ├── addMenuButton
|
||||
│ │ ├── audioRecorder
|
||||
│ │ └── disclaimer
|
||||
│ ├── suggestionView
|
||||
│ │ ├── container
|
||||
│ │ └── suggestion
|
||||
│ └── welcomeScreen
|
||||
│ └── welcomeMessage
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
Under the hood, the slot system uses three key concepts:
|
||||
|
||||
### SlotValue Type
|
||||
|
||||
Every slot accepts one of three value types:
|
||||
|
||||
```typescript
|
||||
type SlotValue<C extends React.ComponentType<any>> =
|
||||
| C // Custom component
|
||||
| string // Tailwind class string
|
||||
| Partial<React.ComponentProps<C>>; // Props object
|
||||
```
|
||||
|
||||
### renderSlot Function
|
||||
|
||||
The `renderSlot` function resolves a slot value into a React element:
|
||||
|
||||
```typescript
|
||||
// Internal implementation (simplified)
|
||||
function renderSlot(slot, DefaultComponent, props) {
|
||||
if (typeof slot === "string") {
|
||||
// Merge className with existing
|
||||
return <DefaultComponent {...props} className={twMerge(props.className, slot)} />;
|
||||
}
|
||||
|
||||
if (isReactComponent(slot)) {
|
||||
// Use custom component
|
||||
return <slot {...props} />;
|
||||
}
|
||||
|
||||
if (isPropsObject(slot)) {
|
||||
// Merge props
|
||||
return <DefaultComponent {...props} {...slot} />;
|
||||
}
|
||||
|
||||
// Use default
|
||||
return <DefaultComponent {...props} />;
|
||||
}
|
||||
```
|
||||
|
||||
### WithSlots Type
|
||||
|
||||
Components use the `WithSlots` type to define their slot interface:
|
||||
|
||||
```typescript
|
||||
type MyComponentProps = WithSlots<
|
||||
{
|
||||
button: typeof MyButton;
|
||||
input: typeof MyInput;
|
||||
},
|
||||
{
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
}
|
||||
>;
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Start Simple, Escalate as Needed
|
||||
|
||||
Begin with Tailwind classes, then move to props objects, and only use custom components when necessary:
|
||||
|
||||
```tsx
|
||||
// Start here
|
||||
<CopilotChat input="border-blue-500" />
|
||||
|
||||
// Then this
|
||||
<CopilotChat input={{ className: "border-blue-500", autoFocus: false }} />
|
||||
|
||||
// Only if needed
|
||||
<CopilotChat input={CustomInputComponent} />
|
||||
```
|
||||
|
||||
### 2. Use Props Objects for Nested Customization
|
||||
|
||||
When customizing nested slots, use props objects to drill down:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
className: "bg-blue-50",
|
||||
toolbar: "border-t mt-2",
|
||||
copyButton: "text-blue-600",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### 3. Preserve Default Behavior
|
||||
|
||||
When creating custom components, spread the remaining props to preserve default functionality:
|
||||
|
||||
```tsx
|
||||
function CustomButton({ onClick, disabled, className, ...props }) {
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
className={twMerge("my-custom-classes", className)}
|
||||
{...props} // Preserve other props
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Use Render Functions for Complex Layouts
|
||||
|
||||
When you need to completely rearrange elements, use the render function pattern:
|
||||
|
||||
```tsx
|
||||
function CustomLayout(props) {
|
||||
return (
|
||||
<CopilotChatInput {...props}>
|
||||
{({ textArea, sendButton, addMenuButton }) => (
|
||||
<div className="grid grid-cols-[auto_1fr_auto] gap-2">
|
||||
{addMenuButton}
|
||||
{textArea}
|
||||
{sendButton}
|
||||
</div>
|
||||
)}
|
||||
</CopilotChatInput>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Themed Chat Interface
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
className="bg-gray-900 text-white"
|
||||
messageView={{
|
||||
className: "p-4",
|
||||
assistantMessage: {
|
||||
className: "bg-gray-800 rounded-xl p-4",
|
||||
toolbar: "border-gray-700",
|
||||
},
|
||||
userMessage: "bg-blue-600 text-white rounded-2xl px-4 py-2",
|
||||
}}
|
||||
input={{
|
||||
className: "bg-gray-800 border-gray-700",
|
||||
sendButton: "bg-blue-600 hover:bg-blue-700",
|
||||
}}
|
||||
scrollView={{
|
||||
feather: "from-gray-900 via-gray-900 to-transparent",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Minimal Interface
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
welcomeScreen={false}
|
||||
input={{
|
||||
disclaimer: () => null,
|
||||
startTranscribeButton: () => null,
|
||||
addMenuButton: () => null,
|
||||
}}
|
||||
scrollView={{
|
||||
scrollToBottomButton: () => null,
|
||||
feather: () => null,
|
||||
}}
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
toolbar: () => null,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Feedback-Focused Interface
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
messageView={{
|
||||
assistantMessage: {
|
||||
onThumbsUp: (msg) => {
|
||||
analytics.track("positive_feedback", { messageId: msg.id });
|
||||
toast.success("Thanks for your feedback!");
|
||||
},
|
||||
onThumbsDown: (msg) => {
|
||||
analytics.track("negative_feedback", { messageId: msg.id });
|
||||
showFeedbackModal(msg);
|
||||
},
|
||||
toolbar: "bg-yellow-50 border border-yellow-200 rounded-lg p-2",
|
||||
thumbsUpButton: "text-green-600 hover:text-green-800",
|
||||
thumbsDownButton: "text-red-600 hover:text-red-800",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [CopilotChat](/reference/copilot-chat) - Main chat component
|
||||
- [CopilotChatInput](/reference/copilot-chat-input) - Input component slots
|
||||
- [CopilotChatAssistantMessage](/reference/copilot-chat-assistant-message) - Assistant message slots
|
||||
- [CopilotChatUserMessage](/reference/copilot-chat-user-message) - User message slots
|
||||
- [CopilotChatScrollView](/reference/copilot-chat-scroll-view) - Scroll container slots
|
||||
- [CopilotChatSuggestionView](/reference/copilot-chat-suggestion-view) - Suggestion chips slots
|
||||
- [CopilotChatWelcomeScreen](/reference/copilot-chat-welcome-screen) - Welcome screen slots
|
||||
- [CopilotChatMessageView](/reference/copilot-chat-message-view) - Message list slots
|
||||
@@ -0,0 +1,391 @@
|
||||
---
|
||||
title: useAgentContext
|
||||
description: "useAgentContext Hook API Reference"
|
||||
---
|
||||
|
||||
`useAgentContext` is a React hook that provides contextual information to AI agents during their execution. It allows
|
||||
you to dynamically add relevant data that agents can use to make more informed decisions and provide better responses.
|
||||
|
||||
## What is useAgentContext?
|
||||
|
||||
The useAgentContext hook:
|
||||
|
||||
- Provides contextual information to agents
|
||||
- Automatically manages context lifecycle (add on mount, remove on unmount)
|
||||
- Updates context when values change
|
||||
- Helps agents understand application state and user data
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core";
|
||||
|
||||
function UserPreferences() {
|
||||
const userSettings = {
|
||||
theme: "dark",
|
||||
language: "en",
|
||||
timezone: "UTC-5",
|
||||
};
|
||||
|
||||
useAgentContext({
|
||||
description: "User preferences and settings",
|
||||
value: userSettings,
|
||||
});
|
||||
|
||||
return <div>User preferences loaded</div>;
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
The hook accepts a single `Context` object with the following properties:
|
||||
|
||||
### description
|
||||
|
||||
`string` **(required)**
|
||||
|
||||
A clear description of what this context represents. This helps agents understand how to use the provided information.
|
||||
|
||||
```tsx
|
||||
useAgentContext({
|
||||
description: "Current shopping cart contents",
|
||||
value: cartItems,
|
||||
});
|
||||
```
|
||||
|
||||
### value
|
||||
|
||||
`any` **(required)**
|
||||
|
||||
The actual data to provide as context. Can be any serializable value including objects, arrays, strings, or numbers.
|
||||
|
||||
```tsx
|
||||
useAgentContext({
|
||||
description: "Current form validation state",
|
||||
value: {
|
||||
hasErrors: false,
|
||||
touchedFields: ["email", "name"],
|
||||
dirtyFields: ["email"],
|
||||
isSubmitting: false,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### User Preferences Context
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core";
|
||||
import { useUserPreferences } from "./hooks/useUserPreferences";
|
||||
|
||||
function UserPreferencesContext() {
|
||||
const { preferences, isLoading } = useUserPreferences();
|
||||
|
||||
useAgentContext({
|
||||
description: "User display preferences and settings",
|
||||
value: {
|
||||
theme: preferences?.theme || "light",
|
||||
language: preferences?.language || "en",
|
||||
timezone: preferences?.timezone || "UTC",
|
||||
displayDensity: preferences?.displayDensity || "comfortable",
|
||||
isLoading,
|
||||
},
|
||||
});
|
||||
|
||||
return null; // Context-only component
|
||||
}
|
||||
```
|
||||
|
||||
### Form State Context
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core";
|
||||
import { useState } from "react";
|
||||
|
||||
function ContactForm() {
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
subject: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
// Provide form state to agent for assistance
|
||||
useAgentContext({
|
||||
description: "Contact form current state",
|
||||
value: {
|
||||
formData,
|
||||
hasUnsavedChanges: Object.values(formData).some((v) => v !== ""),
|
||||
isValid: formData.email.includes("@") && formData.name.length > 0,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form>
|
||||
<input
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
placeholder="Name"
|
||||
/>
|
||||
{/* Rest of form fields */}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Application State Context
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
function AppStateContext() {
|
||||
const location = useLocation();
|
||||
const currentTime = new Date().toISOString();
|
||||
|
||||
useAgentContext({
|
||||
description: "Current application state and navigation",
|
||||
value: {
|
||||
currentPath: location.pathname,
|
||||
queryParams: Object.fromEntries(new URLSearchParams(location.search)),
|
||||
timestamp: currentTime,
|
||||
},
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### Dynamic Data Context
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function DynamicDataContext() {
|
||||
const [data, setData] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const response = await fetch("/api/context-data");
|
||||
setData(await response.json());
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
// Context updates automatically when data changes
|
||||
useAgentContext({
|
||||
description: "Dynamic application data",
|
||||
value: data || { loading: true },
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple Contexts
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core";
|
||||
|
||||
function MultipleContexts() {
|
||||
const userContext = { id: "123", name: "John" };
|
||||
const appContext = { version: "1.0.0", features: ["chat", "search"] };
|
||||
|
||||
// Use multiple hooks for different contexts
|
||||
useAgentContext({
|
||||
description: "User information",
|
||||
value: userContext,
|
||||
});
|
||||
|
||||
useAgentContext({
|
||||
description: "Application configuration",
|
||||
value: appContext,
|
||||
});
|
||||
|
||||
return <div>Multiple contexts provided</div>;
|
||||
}
|
||||
```
|
||||
|
||||
## Context Lifecycle
|
||||
|
||||
### Automatic Management
|
||||
|
||||
Context is automatically managed throughout the component lifecycle:
|
||||
|
||||
```tsx
|
||||
function ManagedContext() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
useAgentContext({
|
||||
description: "Counter state",
|
||||
value: { count, lastUpdated: Date.now() },
|
||||
});
|
||||
|
||||
// Context is:
|
||||
// 1. Added when component mounts
|
||||
// 2. Updated when count changes
|
||||
// 3. Removed when component unmounts
|
||||
|
||||
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
|
||||
}
|
||||
```
|
||||
|
||||
### Updates on Change
|
||||
|
||||
Context automatically updates when values change:
|
||||
|
||||
```tsx
|
||||
function ReactiveContext() {
|
||||
const [filters, setFilters] = useState({
|
||||
category: "all",
|
||||
priceRange: [0, 100],
|
||||
});
|
||||
|
||||
// Context updates whenever filters change
|
||||
useAgentContext({
|
||||
description: "Active search filters",
|
||||
value: filters,
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<select
|
||||
value={filters.category}
|
||||
onChange={(e) => setFilters({ ...filters, category: e.target.value })}
|
||||
>
|
||||
<option value="all">All</option>
|
||||
<option value="electronics">Electronics</option>
|
||||
<option value="clothing">Clothing</option>
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Descriptive Context Names
|
||||
|
||||
Provide clear, descriptive names for your context:
|
||||
|
||||
```tsx
|
||||
// ✅ Good - Clear and specific
|
||||
useAgentContext({
|
||||
description: "E-commerce shopping cart with items and totals",
|
||||
value: cartData,
|
||||
});
|
||||
|
||||
// ❌ Avoid - Too vague
|
||||
useAgentContext({
|
||||
description: "Data",
|
||||
value: cartData,
|
||||
});
|
||||
```
|
||||
|
||||
### Structured Data
|
||||
|
||||
Organize context data in a structured format:
|
||||
|
||||
```tsx
|
||||
// ✅ Good - Well-structured data
|
||||
useAgentContext({
|
||||
description: "Order processing state",
|
||||
value: {
|
||||
orderId: "ORD-123",
|
||||
status: "processing",
|
||||
items: [{ id: "1", name: "Product", quantity: 2, price: 29.99 }],
|
||||
customer: {
|
||||
id: "CUST-456",
|
||||
email: "user@example.com",
|
||||
},
|
||||
timestamps: {
|
||||
created: "2024-01-01T10:00:00Z",
|
||||
updated: "2024-01-01T10:30:00Z",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// ❌ Avoid - Unstructured data
|
||||
useAgentContext({
|
||||
description: "Order info",
|
||||
value: "Order ORD-123 for user@example.com with 2 items",
|
||||
});
|
||||
```
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
Memoize complex computed values:
|
||||
|
||||
```tsx
|
||||
import { useMemo } from "react";
|
||||
|
||||
function OptimizedContext({ items }) {
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
itemCount: items.length,
|
||||
totalValue: items.reduce((sum, item) => sum + item.price, 0),
|
||||
categories: [...new Set(items.map((item) => item.category))],
|
||||
}),
|
||||
[items],
|
||||
);
|
||||
|
||||
useAgentContext({
|
||||
description: "Computed inventory statistics",
|
||||
value: contextValue,
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Agents
|
||||
|
||||
Context provided through this hook is available to agents during execution:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
useAgentContext,
|
||||
useAgent,
|
||||
useCopilotKit,
|
||||
} from "@copilotkit/react-core";
|
||||
|
||||
function IntegratedExample() {
|
||||
const { agent } = useAgent();
|
||||
const { copilotkit } = useCopilotKit();
|
||||
const [productSearch, setProductSearch] = useState("");
|
||||
|
||||
// Provide search context
|
||||
useAgentContext({
|
||||
description: "Current product search parameters",
|
||||
value: {
|
||||
searchQuery: productSearch,
|
||||
resultsPerPage: 20,
|
||||
sortBy: "relevance",
|
||||
},
|
||||
});
|
||||
|
||||
const handleSearch = async () => {
|
||||
// Agent has access to the context when running
|
||||
agent.addMessage({
|
||||
id: crypto.randomUUID(),
|
||||
role: "user",
|
||||
content: `Help me refine my search for: ${productSearch}`,
|
||||
});
|
||||
|
||||
await copilotkit.runAgent({ agent });
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
value={productSearch}
|
||||
onChange={(e) => setProductSearch(e.target.value)}
|
||||
placeholder="Search products..."
|
||||
/>
|
||||
<button onClick={handleSearch}>Get AI Help</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,491 @@
|
||||
---
|
||||
title: useAgent
|
||||
description: "useAgent Hook API Reference"
|
||||
---
|
||||
|
||||
`useAgent` is a React hook that provides access to [AG-UI](https://ag-ui.com) agents and subscribes to their state
|
||||
changes. It enables components to interact with agents, access their messages, and respond to updates in real-time.
|
||||
The hook always returns an agent instance. While the runtime is syncing, it returns a provisional runtime agent; once
|
||||
the runtime has synced, if the agent id does not exist the hook throws an error.
|
||||
|
||||
## What is useAgent?
|
||||
|
||||
The useAgent hook:
|
||||
|
||||
- Retrieves an agent by ID from the CopilotKit context
|
||||
- Subscribes to agent state changes (messages, state, run status)
|
||||
- Automatically triggers component re-renders when the agent updates
|
||||
- Handles cleanup of subscriptions when the component unmounts
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { useAgent } from "@copilotkit/react-core";
|
||||
|
||||
function ChatComponent() {
|
||||
const { agent } = useAgent({ agentId: "assistant" });
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Agent: {agent.id}</h2>
|
||||
<div>Messages: {agent.messages.length}</div>
|
||||
<div>Running: {agent.isRunning ? "Yes" : "No"}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
### agentId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
The ID of the agent to retrieve. If not provided, defaults to `"default"`.
|
||||
|
||||
```tsx
|
||||
const { agent } = useAgent({ agentId: "customer-support" });
|
||||
```
|
||||
|
||||
### updates
|
||||
|
||||
`UseAgentUpdate[]` **(optional)**
|
||||
|
||||
An array of update types to subscribe to. This allows you to optimize re-renders by only subscribing to specific
|
||||
changes.
|
||||
|
||||
```tsx
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core";
|
||||
|
||||
const { agent } = useAgent({
|
||||
agentId: "assistant",
|
||||
updates: [UseAgentUpdate.OnMessagesChanged],
|
||||
});
|
||||
```
|
||||
|
||||
Available update types:
|
||||
|
||||
- `UseAgentUpdate.OnMessagesChanged` - Updates when messages are added or modified
|
||||
- `UseAgentUpdate.OnStateChanged` - Updates when agent state changes
|
||||
- `UseAgentUpdate.OnRunStatusChanged` - Updates when agent starts or stops running
|
||||
|
||||
If `updates` is not provided, the hook subscribes to all update types by default.
|
||||
|
||||
## Return Value
|
||||
|
||||
The hook returns an object with a single property:
|
||||
|
||||
### agent
|
||||
|
||||
`AbstractAgent`
|
||||
|
||||
The agent instance. During runtime synchronization, the hook returns a provisional runtime agent so you can bind UI
|
||||
immediately. After the runtime has synced (Connected or Error), if the agent id does not exist the hook throws an
|
||||
error.
|
||||
|
||||
## Accessing Agent Messages
|
||||
|
||||
The agent's message history is available through the `messages` property. You can read messages and add new ones to
|
||||
create interactive conversations.
|
||||
|
||||
### Reading Messages
|
||||
|
||||
```tsx
|
||||
function SimpleChat() {
|
||||
const { agent } = useAgent();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{agent.messages.map((message) => (
|
||||
<div key={message.id}>
|
||||
<strong>{message.role}:</strong> {message.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Sending Messages
|
||||
|
||||
To send a message, add it to the agent and then run the agent:
|
||||
|
||||
```tsx
|
||||
import { useAgent } from "@copilotkit/react-core";
|
||||
import { useCopilotKit } from "@copilotkit/react-core";
|
||||
|
||||
function MessageSender() {
|
||||
const { agent } = useAgent({ agentId: "assistant" });
|
||||
const { copilotkit } = useCopilotKit();
|
||||
|
||||
const sendMessage = async (content: string) => {
|
||||
// Add message to agent
|
||||
agent.addMessage({
|
||||
id: crypto.randomUUID(),
|
||||
role: "user",
|
||||
content,
|
||||
});
|
||||
|
||||
// Run the agent to get a response
|
||||
await copilotkit.runAgent({
|
||||
agent,
|
||||
agentId: "assistant",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => sendMessage("Hello!")} disabled={agent.isRunning}>
|
||||
Send Hello
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Accessing and Updating Shared State
|
||||
|
||||
Shared state enables real-time collaboration between users and agents. Both can read and modify the state, creating a
|
||||
synchronized workspace for interactive features.
|
||||
|
||||
### Understanding Shared State
|
||||
|
||||
The agent's state is a shared data structure that:
|
||||
|
||||
- Can be read by both your application and the agent
|
||||
- Can be modified by both parties
|
||||
- Automatically triggers re-renders when changed
|
||||
- Persists throughout the conversation
|
||||
|
||||
State updates cause re-renders when:
|
||||
|
||||
- You call `agent.setState()` from your application
|
||||
- The agent modifies the state during execution
|
||||
- Any state change occurs, regardless of source
|
||||
|
||||
### Reading State
|
||||
|
||||
```tsx
|
||||
function StateDisplay() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnStateChanged], // Subscribe to state changes
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Current State</h3>
|
||||
<pre>{JSON.stringify(agent.state, null, 2)}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Updating State
|
||||
|
||||
```tsx
|
||||
function StateController() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnStateChanged],
|
||||
});
|
||||
|
||||
const updateState = (key: string, value: any) => {
|
||||
// Update the shared state
|
||||
agent.setState({
|
||||
...agent.state,
|
||||
[key]: value,
|
||||
});
|
||||
|
||||
// This will trigger re-renders for all components
|
||||
// subscribed to OnStateChanged
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={() => updateState("counter", (agent.state.counter || 0) + 1)}
|
||||
>
|
||||
Increment Counter: {agent.state.counter || 0}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Collaborative Features
|
||||
|
||||
Shared state enables collaborative features where users and agents work together:
|
||||
|
||||
```tsx
|
||||
function CollaborativeTodo() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnStateChanged],
|
||||
});
|
||||
const { copilotkit } = useCopilotKit();
|
||||
|
||||
const todos = agent.state.todos || [];
|
||||
|
||||
const addTodo = (text: string) => {
|
||||
agent.setState({
|
||||
...agent.state,
|
||||
todos: [...todos, { id: crypto.randomUUID(), text, done: false }],
|
||||
});
|
||||
};
|
||||
|
||||
const toggleTodo = (id: string) => {
|
||||
agent.setState({
|
||||
...agent.state,
|
||||
todos: todos.map((todo) =>
|
||||
todo.id === id ? { ...todo, done: !todo.done } : todo,
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
const askAgentToOrganize = async () => {
|
||||
// Add a message asking the agent to organize todos
|
||||
agent.addMessage({
|
||||
id: crypto.randomUUID(),
|
||||
role: "user",
|
||||
content: "Please organize my todos by priority",
|
||||
});
|
||||
|
||||
// The agent can read and modify the todos in agent.state
|
||||
await copilotkit.runAgent({ agent });
|
||||
|
||||
// After the agent runs, the state will be updated
|
||||
// and the component will re-render automatically
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Shared Todo List</h3>
|
||||
<ul>
|
||||
{todos.map((todo) => (
|
||||
<li key={todo.id}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={todo.done}
|
||||
onChange={() => toggleTodo(todo.id)}
|
||||
/>
|
||||
<span className={todo.done ? "done" : ""}>{todo.text}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<button onClick={() => addTodo(prompt("New todo:") || "")}>
|
||||
Add Todo
|
||||
</button>
|
||||
|
||||
<button onClick={askAgentToOrganize}>Ask Agent to Organize</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Optimized Updates
|
||||
|
||||
Subscribe only to message changes to avoid unnecessary re-renders:
|
||||
|
||||
```tsx
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core";
|
||||
|
||||
function MessageList() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnMessagesChanged],
|
||||
});
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{agent.messages.map((msg) => (
|
||||
<li key={msg.id}>{msg.content}</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Run Status Indicator
|
||||
|
||||
Show a loading indicator when the agent is processing:
|
||||
|
||||
```tsx
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core";
|
||||
|
||||
function RunStatus() {
|
||||
const { agent } = useAgent({
|
||||
agentId: "assistant",
|
||||
updates: [UseAgentUpdate.OnRunStatusChanged],
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={`status ${agent.isRunning ? "running" : "idle"}`}>
|
||||
{agent.isRunning ? "🔄 Processing..." : "✅ Ready"}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple Agents
|
||||
|
||||
Access different agents in different components:
|
||||
|
||||
```tsx
|
||||
function DualAgentView() {
|
||||
const { agent: primaryAgent } = useAgent({
|
||||
agentId: "primary-assistant",
|
||||
});
|
||||
|
||||
const { agent: supportAgent } = useAgent({
|
||||
agentId: "support-assistant",
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="dual-view">
|
||||
<div className="primary">
|
||||
<h3>Primary Assistant</h3>
|
||||
<div>Messages: {primaryAgent.messages.length}</div>
|
||||
</div>
|
||||
|
||||
<div className="support">
|
||||
<h3>Support Assistant</h3>
|
||||
<div>Messages: {supportAgent.messages.length}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### No Updates Subscription
|
||||
|
||||
For static access without subscribing to updates:
|
||||
|
||||
```tsx
|
||||
const { agent } = useAgent({
|
||||
agentId: "assistant",
|
||||
updates: [], // No subscriptions
|
||||
});
|
||||
|
||||
// Component won't re-render on agent changes
|
||||
```
|
||||
|
||||
### Custom Message Rendering with Optimized Updates
|
||||
|
||||
```tsx
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core";
|
||||
import { Message } from "@ag-ui/core";
|
||||
|
||||
function MessageRenderer() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnMessagesChanged], // Only re-render on message changes
|
||||
});
|
||||
|
||||
if (agent.messages.length === 0) {
|
||||
return <div>No messages yet</div>;
|
||||
}
|
||||
|
||||
const renderMessage = (message: Message) => {
|
||||
switch (message.role) {
|
||||
case "user":
|
||||
return (
|
||||
<div className="user-message">
|
||||
<span className="avatar">👤</span>
|
||||
<span className="content">{message.content}</span>
|
||||
</div>
|
||||
);
|
||||
case "assistant":
|
||||
return (
|
||||
<div className="assistant-message">
|
||||
<span className="avatar">🤖</span>
|
||||
<span className="content">{message.content}</span>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="message-list">
|
||||
{agent.messages.map((msg) => (
|
||||
<div key={msg.id}>{renderMessage(msg)}</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Selective Updates
|
||||
|
||||
By default, `useAgent` subscribes to all update types, which can cause frequent re-renders. Use the `updates` parameter
|
||||
to subscribe only to the changes you need:
|
||||
|
||||
```tsx
|
||||
// ❌ Subscribes to all updates (may cause unnecessary re-renders)
|
||||
const { agent } = useAgent({ agentId: "assistant" });
|
||||
|
||||
// ✅ Only subscribes to message changes
|
||||
const { agent } = useAgent({
|
||||
agentId: "assistant",
|
||||
updates: [UseAgentUpdate.OnMessagesChanged],
|
||||
});
|
||||
|
||||
// ✅ Only subscribes to run status changes
|
||||
const { agent } = useAgent({
|
||||
agentId: "assistant",
|
||||
updates: [UseAgentUpdate.OnRunStatusChanged],
|
||||
});
|
||||
```
|
||||
|
||||
### Component Splitting
|
||||
|
||||
Split components by update type to optimize rendering:
|
||||
|
||||
```tsx
|
||||
// Message display component - only updates on message changes
|
||||
function Messages() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnMessagesChanged],
|
||||
});
|
||||
|
||||
// Render messages...
|
||||
}
|
||||
|
||||
// Status indicator - only updates on run status changes
|
||||
function StatusIndicator() {
|
||||
const { agent } = useAgent({
|
||||
updates: [UseAgentUpdate.OnRunStatusChanged],
|
||||
});
|
||||
|
||||
// Render status...
|
||||
}
|
||||
|
||||
// Parent component doesn't need to subscribe
|
||||
function ChatView() {
|
||||
return (
|
||||
<>
|
||||
<StatusIndicator />
|
||||
<Messages />
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
After the runtime has synced (Connected or Error), `useAgent` throws if the requested agent id does not exist. During
|
||||
runtime syncing, a provisional agent is returned. To avoid runtime errors:
|
||||
|
||||
- Ensure the agent id you request is registered (via `agents__unsafe_dev_only` or exposed by your runtime).
|
||||
- Optionally wrap the component that calls `useAgent` in an error boundary to render a fallback UI if the agent is
|
||||
missing due to misconfiguration in development.
|
||||
|
||||
Example configuration with a local agent for development:
|
||||
|
||||
```tsx
|
||||
<CopilotKitProvider agents__unsafe_dev_only={{ myAgent: new MyAgent() }}>
|
||||
<App />
|
||||
</CopilotKitProvider>
|
||||
```
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: useCopilotKit
|
||||
description: "useCopilotKit Hook API Reference"
|
||||
---
|
||||
|
||||
`useCopilotKit` is a React hook that provides access to the CopilotKit context, including the core instance, tool
|
||||
rendering capabilities, and runtime connection status. It's the primary way to interact with CopilotKit's core
|
||||
functionality from React components.
|
||||
|
||||
## What is useCopilotKit?
|
||||
|
||||
The useCopilotKit hook:
|
||||
|
||||
- Provides access to the `CopilotKitCore` instance for agent and tool management
|
||||
- Exposes render tool calls for visual tool execution feedback
|
||||
- Subscribes to runtime connection status changes
|
||||
- Enables programmatic control over agents, tools, and context
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { useCopilotKit } from "@copilotkit/react-core";
|
||||
|
||||
function MyComponent() {
|
||||
const { copilotkit } = useCopilotKit();
|
||||
|
||||
// Access runtime status
|
||||
console.log("Runtime status:", copilotkit.runtimeConnectionStatus);
|
||||
|
||||
// Get an agent
|
||||
const agent = copilotkit.getAgent("assistant");
|
||||
|
||||
return (
|
||||
<div>Connected: {copilotkit.runtimeConnectionStatus === "Connected"}</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Return Value
|
||||
|
||||
The hook returns a `CopilotKitContextValue` object with the following properties:
|
||||
|
||||
### copilotkit
|
||||
|
||||
`CopilotKitCore`
|
||||
|
||||
The core CopilotKit instance that manages agents, tools, context, and runtime connections. This is the main interface
|
||||
for interacting with CopilotKit programmatically.
|
||||
|
||||
### renderToolCalls
|
||||
|
||||
`ReactToolCallRenderer<any>[]`
|
||||
|
||||
An array of tool call render configurations defined at the provider level. These are used to render visual feedback when
|
||||
tools are executed.
|
||||
|
||||
### currentRenderToolCalls
|
||||
|
||||
`ReactToolCallRenderer<unknown>[]`
|
||||
|
||||
The current list of render tool calls, including both static configurations and dynamically registered ones.
|
||||
|
||||
### setCurrentRenderToolCalls
|
||||
|
||||
`React.Dispatch<React.SetStateAction<ReactToolCallRenderer<unknown>[]>>`
|
||||
|
||||
A setter function to update the current render tool calls. Useful for dynamically adding or removing tool renderers.
|
||||
|
||||
## Examples
|
||||
|
||||
### Running an Agent
|
||||
|
||||
```tsx
|
||||
import { useCopilotKit } from "@copilotkit/react-core";
|
||||
import { useAgent } from "@copilotkit/react-core";
|
||||
|
||||
function AgentRunner() {
|
||||
const { copilotkit } = useCopilotKit();
|
||||
const { agent } = useAgent({ agentId: "assistant" });
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!message) return;
|
||||
|
||||
// Add user message
|
||||
agent.addMessage({
|
||||
id: crypto.randomUUID(),
|
||||
role: "user",
|
||||
content: message,
|
||||
});
|
||||
|
||||
// Run the agent
|
||||
await copilotkit.runAgent({ agent, agentId: "assistant" });
|
||||
|
||||
setMessage("");
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="Type a message..."
|
||||
/>
|
||||
<button onClick={handleSubmit}>Send</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Monitoring Runtime Connection
|
||||
|
||||
```tsx
|
||||
import { useCopilotKit } from "@copilotkit/react-core";
|
||||
|
||||
function ConnectionStatus() {
|
||||
const { copilotkit } = useCopilotKit();
|
||||
|
||||
const getStatusColor = () => {
|
||||
switch (copilotkit.runtimeConnectionStatus) {
|
||||
case "Connected":
|
||||
return "green";
|
||||
case "Connecting":
|
||||
return "yellow";
|
||||
case "Error":
|
||||
return "red";
|
||||
default:
|
||||
return "gray";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="connection-status">
|
||||
<div className={`indicator ${getStatusColor()}`} />
|
||||
<span>Runtime: {copilotkit.runtimeConnectionStatus}</span>
|
||||
{copilotkit.runtimeVersion && <span>v{copilotkit.runtimeVersion}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Automatic Re-renders
|
||||
|
||||
The hook automatically subscribes to runtime connection status changes and triggers re-renders when:
|
||||
|
||||
- The runtime connects or disconnects
|
||||
- The connection status changes
|
||||
- Connection errors occur
|
||||
|
||||
This ensures your components always display the current connection state without manual subscriptions.
|
||||
@@ -0,0 +1,281 @@
|
||||
---
|
||||
title: useFrontendTool
|
||||
description: "useFrontendTool Hook API Reference"
|
||||
---
|
||||
|
||||
`useFrontendTool` is a React hook that dynamically registers tools (functions) that AI agents can invoke in your
|
||||
application. It enables components to expose interactive capabilities to agents, with optional visual rendering of tool
|
||||
execution.
|
||||
|
||||
## What is useFrontendTool?
|
||||
|
||||
The useFrontendTool hook:
|
||||
|
||||
- Registers tools dynamically when components mount
|
||||
- Automatically cleans up tools when components unmount
|
||||
- Optionally registers visual renderers for tool execution feedback in the chat interface
|
||||
- Supports agent-specific tool registration
|
||||
- Handles tool lifecycle management automatically
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { useFrontendTool } from "@copilotkit/react-core";
|
||||
import { z } from "zod";
|
||||
|
||||
function SearchComponent() {
|
||||
useFrontendTool({
|
||||
name: "searchProducts",
|
||||
description: "Search for products in the catalog",
|
||||
parameters: z.object({
|
||||
query: z.string(),
|
||||
category: z.string().optional(),
|
||||
}),
|
||||
handler: async ({ query, category }) => {
|
||||
const results = await searchAPI(query, category);
|
||||
return results;
|
||||
},
|
||||
});
|
||||
|
||||
return <div>Rest of your component...</div>;
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
The hook accepts:
|
||||
|
||||
- A required `ReactFrontendTool` object describing the tool
|
||||
- An optional dependency array to control when the tool is re-registered
|
||||
|
||||
### name
|
||||
|
||||
`string` **(required)**
|
||||
|
||||
A unique identifier for the tool. This is the name agents will use to request this tool's execution.
|
||||
|
||||
```tsx
|
||||
useFrontendTool({
|
||||
name: "calculateTotal",
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### description
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
A description that helps agents understand when and how to use this tool. This is sent to the LLM to guide its
|
||||
decision-making.
|
||||
|
||||
```tsx
|
||||
useFrontendTool({
|
||||
name: "fetchUserData",
|
||||
description:
|
||||
"Retrieve detailed user profile information including preferences and history",
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### parameters
|
||||
|
||||
`z.ZodType<T>` **(optional)**
|
||||
|
||||
A Zod schema defining the tool's input parameters. Provides type safety and automatic validation.
|
||||
|
||||
```tsx
|
||||
import { z } from "zod";
|
||||
|
||||
useFrontendTool({
|
||||
name: "updateSettings",
|
||||
parameters: z.object({
|
||||
theme: z.enum(["light", "dark", "auto"]),
|
||||
language: z.string(),
|
||||
notifications: z.boolean(),
|
||||
}),
|
||||
handler: async ({ theme, language, notifications }) => {
|
||||
// settings is fully typed based on the schema
|
||||
await updateUserSettings({ theme, language, notifications });
|
||||
return "Settings updated successfully";
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### handler
|
||||
|
||||
`(args: T, toolCall: ToolCall) => Promise<unknown>` **(optional)**
|
||||
|
||||
The async function executed when the agent invokes this tool. Receives validated arguments and metadata about the
|
||||
invocation.
|
||||
|
||||
```tsx
|
||||
useFrontendTool({
|
||||
name: "addToCart",
|
||||
parameters: z.object({
|
||||
productId: z.string(),
|
||||
quantity: z.number().min(1),
|
||||
}),
|
||||
handler: async ({ productId, quantity }, toolCall) => {
|
||||
console.log(`Tool called by agent at ${toolCall.id}`);
|
||||
const result = await cartService.addItem(productId, quantity);
|
||||
return {
|
||||
success: true,
|
||||
cartTotal: result.total,
|
||||
};
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### render
|
||||
|
||||
`(props: { name: string; args: T; result?: unknown; status: ToolCallStatus }) => React.ReactNode` **(optional)**
|
||||
|
||||
A React component that renders visual feedback when the tool is executed. This appears in the chat interface to show
|
||||
tool execution progress and results.
|
||||
|
||||
```tsx
|
||||
import { ToolCallStatus } from "@copilotkit/core";
|
||||
|
||||
useFrontendTool({
|
||||
name: "generateChart",
|
||||
parameters: z.object({
|
||||
data: z.array(z.number()),
|
||||
type: z.enum(["bar", "line", "pie"]),
|
||||
}),
|
||||
handler: async ({ data, type }) => {
|
||||
return generateChartData(data, type);
|
||||
},
|
||||
render: ({ name, args, result, status }) => (
|
||||
<div className="tool-execution">
|
||||
<h3>Generating {args.type} chart...</h3>
|
||||
{status === ToolCallStatus.InProgress && <Spinner />}
|
||||
{status === ToolCallStatus.Complete && result && (
|
||||
<ChartDisplay data={result} />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
});
|
||||
```
|
||||
|
||||
### followUp
|
||||
|
||||
`boolean` **(optional, default: true)**
|
||||
|
||||
Controls whether the agent should automatically continue after this tool completes. Set to `false` for final actions.
|
||||
|
||||
```tsx
|
||||
useFrontendTool({
|
||||
name: "submitForm",
|
||||
handler: async (formData) => {
|
||||
await submitToServer(formData);
|
||||
return "Form submitted successfully";
|
||||
},
|
||||
followUp: false, // Don't continue after submission
|
||||
});
|
||||
```
|
||||
|
||||
### agentId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
Restricts this tool to a specific agent. Only the specified agent can invoke this tool.
|
||||
|
||||
```tsx
|
||||
useFrontendTool({
|
||||
name: "adminAction",
|
||||
agentId: "admin-assistant",
|
||||
handler: async (args) => {
|
||||
return await performAdminAction(args);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### deps (second argument)
|
||||
|
||||
`ReadonlyArray<unknown>` **(optional)**
|
||||
|
||||
Additional dependencies that should trigger re-registration of the tool. By default, the hook only depends on the tool
|
||||
name and CopilotKit instance to avoid re-register loops from object identity changes. Pass a dependency array as the
|
||||
second argument when the tool's configuration is derived from changing props or state:
|
||||
|
||||
```tsx
|
||||
function PriceTool({ currency }: { currency: string }) {
|
||||
useFrontendTool(
|
||||
{
|
||||
name: "convertPrice",
|
||||
handler: async (args) => convertPrice(args.amount, currency),
|
||||
},
|
||||
[currency],
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
## Lifecycle Management
|
||||
|
||||
### Automatic Registration
|
||||
|
||||
Tools are automatically registered when the component mounts:
|
||||
|
||||
```tsx
|
||||
function DynamicTool() {
|
||||
// Tool is registered when this component mounts
|
||||
useFrontendTool({
|
||||
name: "dynamicAction",
|
||||
handler: async () => "Action performed",
|
||||
});
|
||||
|
||||
return <div>Tool available</div>;
|
||||
}
|
||||
|
||||
// Usage
|
||||
function App() {
|
||||
const [showTool, setShowTool] = useState(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => setShowTool(!showTool)}>Toggle Tool</button>
|
||||
{showTool && <DynamicTool />} {/* Tool only available when mounted */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Cleanup on Unmount
|
||||
|
||||
Tools are automatically removed when components unmount, but their renderers persist to maintain chat history:
|
||||
|
||||
```tsx
|
||||
function TemporaryTool() {
|
||||
useFrontendTool({
|
||||
name: "tempAction",
|
||||
handler: async () => "Temporary action",
|
||||
render: ({ status }) => <div>Temp tool: {status}</div>,
|
||||
});
|
||||
|
||||
// When this component unmounts:
|
||||
// - The tool handler is removed (agent can't call it anymore)
|
||||
// - The renderer persists (previous executions still visible in chat)
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### Tool Override Warning
|
||||
|
||||
If a tool with the same name already exists, it will be overridden with a console warning:
|
||||
|
||||
```tsx
|
||||
// First registration
|
||||
useFrontendTool({
|
||||
name: "search",
|
||||
handler: async () => "Search v1",
|
||||
});
|
||||
|
||||
// Second registration (overrides first)
|
||||
useFrontendTool({
|
||||
name: "search", // Same name - will override with warning
|
||||
handler: async () => "Search v2",
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,223 @@
|
||||
---
|
||||
title: useHumanInTheLoop
|
||||
description: "useHumanInTheLoop Hook API Reference"
|
||||
---
|
||||
|
||||
`useHumanInTheLoop` is a React hook that creates interactive tools requiring human approval or input before the agent
|
||||
can proceed. It enables you to build approval workflows, confirmation dialogs, and interactive decision points where
|
||||
human oversight is needed.
|
||||
|
||||
## What is useHumanInTheLoop?
|
||||
|
||||
The useHumanInTheLoop hook:
|
||||
|
||||
- Creates tools that pause execution until human input is received
|
||||
- Manages status transitions (InProgress → Executing → Complete)
|
||||
- Provides a `respond` callback for user interactions
|
||||
- Automatically handles promise resolution for agent continuation
|
||||
- Renders interactive UI components in the chat interface
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { useHumanInTheLoop } from "@copilotkit/react-core";
|
||||
import { ToolCallStatus } from "@copilotkit/core";
|
||||
import { z } from "zod";
|
||||
|
||||
function ApprovalComponent() {
|
||||
useHumanInTheLoop({
|
||||
name: "requireApproval",
|
||||
description: "Requires human approval before proceeding",
|
||||
parameters: z.object({
|
||||
action: z.string(),
|
||||
reason: z.string(),
|
||||
}),
|
||||
render: ({ status, args, respond }) => {
|
||||
if (status === ToolCallStatus.Executing && respond) {
|
||||
return (
|
||||
<div className="approval-request">
|
||||
<p>Approve action: {args.action}</p>
|
||||
<p>Reason: {args.reason}</p>
|
||||
<button onClick={() => respond({ approved: true })}>Approve</button>
|
||||
<button onClick={() => respond({ approved: false })}>Deny</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>Status: {status}</div>;
|
||||
},
|
||||
});
|
||||
|
||||
return <div>Approval system active</div>;
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
The hook accepts:
|
||||
|
||||
- A required `ReactHumanInTheLoop` object describing the tool
|
||||
- An optional `options` object for controlling dependency behavior
|
||||
|
||||
### name
|
||||
|
||||
`string` **(required)**
|
||||
|
||||
A unique identifier for the human-in-the-loop tool.
|
||||
|
||||
```tsx
|
||||
useHumanInTheLoop({
|
||||
name: "confirmDeletion",
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### description
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
Describes the tool's purpose to help agents understand when human approval is needed.
|
||||
|
||||
```tsx
|
||||
useHumanInTheLoop({
|
||||
name: "sensitiveAction",
|
||||
description: "Requires human confirmation for sensitive operations",
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### parameters
|
||||
|
||||
`z.ZodType<T>` **(optional)**
|
||||
|
||||
A Zod schema defining the parameters the agent will provide when requesting human input.
|
||||
|
||||
```tsx
|
||||
import { z } from "zod";
|
||||
|
||||
useHumanInTheLoop({
|
||||
name: "reviewChanges",
|
||||
parameters: z.object({
|
||||
changes: z.array(z.string()),
|
||||
impact: z.enum(["low", "medium", "high"]),
|
||||
estimatedTime: z.number(),
|
||||
}),
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### render
|
||||
|
||||
`React.ComponentType` **(required)**
|
||||
|
||||
A React component that renders the interactive UI. It receives different props based on the current status:
|
||||
|
||||
#### Status: InProgress
|
||||
|
||||
Initial state when the tool is called but not yet executing:
|
||||
|
||||
```tsx
|
||||
{
|
||||
name: string;
|
||||
description: string;
|
||||
args: Partial<T>; // Partial arguments as they're being streamed
|
||||
status: ToolCallStatus.InProgress;
|
||||
result: undefined;
|
||||
respond: undefined;
|
||||
}
|
||||
```
|
||||
|
||||
#### Status: Executing
|
||||
|
||||
Active state where user interaction is required:
|
||||
|
||||
```tsx
|
||||
{
|
||||
name: string;
|
||||
description: string;
|
||||
args: T; // Complete arguments
|
||||
status: ToolCallStatus.Executing;
|
||||
result: undefined;
|
||||
respond: (result: unknown) => Promise<void>; // Callback to provide response
|
||||
}
|
||||
```
|
||||
|
||||
#### Status: Complete
|
||||
|
||||
Final state after user has responded:
|
||||
|
||||
```tsx
|
||||
{
|
||||
name: string;
|
||||
description: string;
|
||||
args: T; // Complete arguments
|
||||
status: ToolCallStatus.Complete;
|
||||
result: string; // The response provided via respond()
|
||||
respond: undefined;
|
||||
}
|
||||
```
|
||||
|
||||
### followUp
|
||||
|
||||
`boolean` **(optional, default: true)**
|
||||
|
||||
Controls whether the agent continues after receiving the human response. Provided for completeness, but typically you
|
||||
would want the agent to continue (default behavior).
|
||||
|
||||
```tsx
|
||||
useHumanInTheLoop({
|
||||
name: "finalConfirmation",
|
||||
followUp: false, // Don't continue after confirmation
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### agentId
|
||||
|
||||
`string` **(optional)**
|
||||
|
||||
Restricts this tool to a specific agent.
|
||||
|
||||
```tsx
|
||||
useHumanInTheLoop({
|
||||
name: "adminApproval",
|
||||
agentId: "admin-assistant",
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### deps (second argument)
|
||||
|
||||
`ReadonlyArray<unknown>` **(optional)**
|
||||
|
||||
Additional dependencies that should trigger re-registration of the human-in-the-loop tool. By default, the hook only
|
||||
depends on stable keys like the tool name and CopilotKit instance to avoid re-register loops from object identity
|
||||
changes. Pass a dependency array as the second argument when the tool configuration is derived from changing props or
|
||||
state:
|
||||
|
||||
```tsx
|
||||
function VersionedApproval({ version }: { version: number }) {
|
||||
useHumanInTheLoop(
|
||||
{
|
||||
name: "versionedApproval",
|
||||
description: `Approve deployment v${version}`,
|
||||
// ...
|
||||
},
|
||||
[version],
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
## Differences from useFrontendTool
|
||||
|
||||
While `useFrontendTool` executes immediately and returns results, `useHumanInTheLoop`:
|
||||
|
||||
- Pauses execution until human input is received
|
||||
- Provides a `respond` callback during the Executing state
|
||||
- Manages status transitions automatically
|
||||
- Is designed specifically for approval workflows and interactive decisions
|
||||
|
||||
Choose `useHumanInTheLoop` when you need human oversight, and `useFrontendTool` for automated tool execution.
|
||||
@@ -0,0 +1,277 @@
|
||||
---
|
||||
title: useRenderToolCall
|
||||
description: "useRenderToolCall Hook API Reference"
|
||||
---
|
||||
|
||||
<Warning>
|
||||
You would use this hook if you use the headless functionality of CopilotKit,
|
||||
rendering your own chat UI instead of the default `CopilotChat`. If you are
|
||||
using `CopilotChat`, you don't need to use this hook.
|
||||
</Warning>
|
||||
|
||||
`useRenderToolCall` is a React hook that provides a function to render visual representations of tool calls in the chat
|
||||
interface. It manages the rendering of tool execution states (InProgress, Executing, Complete) based on configured
|
||||
render functions.
|
||||
|
||||
## What is useRenderToolCall?
|
||||
|
||||
The useRenderToolCall hook:
|
||||
|
||||
- Returns a render function for tool calls
|
||||
- Automatically determines the appropriate status (InProgress, Executing, or Complete)
|
||||
- Manages tool execution state transitions
|
||||
- Supports agent-specific and wildcard renderers
|
||||
- Integrates with CopilotKit's tool rendering system
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```tsx
|
||||
import { useRenderToolCall } from "@copilotkit/react-core";
|
||||
import { ToolCall } from "@ag-ui/core";
|
||||
|
||||
function ToolCallDisplay({ toolCall, toolMessage }) {
|
||||
const renderToolCall = useRenderToolCall();
|
||||
|
||||
return (
|
||||
<div className="tool-call-container">
|
||||
{renderToolCall({ toolCall, toolMessage })}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Return Value
|
||||
|
||||
The hook returns a function with the following signature:
|
||||
|
||||
```tsx
|
||||
(props: UseRenderToolCallProps) => React.ReactElement | null;
|
||||
```
|
||||
|
||||
### UseRenderToolCallProps
|
||||
|
||||
```tsx
|
||||
interface UseRenderToolCallProps {
|
||||
toolCall: ToolCall; // The tool call to render
|
||||
toolMessage?: ToolMessage; // Optional result message
|
||||
}
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### Status Determination
|
||||
|
||||
The render function automatically determines the tool's status:
|
||||
|
||||
1. **Complete**: When a `toolMessage` is provided
|
||||
2. **Executing**: When the tool is currently running (tracked internally)
|
||||
3. **InProgress**: Default state when neither complete nor executing
|
||||
|
||||
### Renderer Selection
|
||||
|
||||
The function selects renderers based on priority:
|
||||
|
||||
1. **Exact match** with matching agentId
|
||||
2. **Exact match** without agentId (global)
|
||||
3. **Exact match** (any agentId)
|
||||
4. **Wildcard** renderer (`*`)
|
||||
5. **No render** (returns null)
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Tool Call Rendering
|
||||
|
||||
```tsx
|
||||
import { useRenderToolCall } from "@copilotkit/react-core";
|
||||
import { AssistantMessage } from "@ag-ui/core";
|
||||
|
||||
function ChatMessage({ message }: { message: AssistantMessage }) {
|
||||
const renderToolCall = useRenderToolCall();
|
||||
|
||||
if (!message.toolCalls) {
|
||||
return <div>{message.content}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{message.content}
|
||||
{message.toolCalls.map((toolCall) => (
|
||||
<div key={toolCall.id} className="tool-call">
|
||||
{renderToolCall({ toolCall })}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### With Tool Results
|
||||
|
||||
```tsx
|
||||
import { useRenderToolCall } from "@copilotkit/react-core";
|
||||
import { Message, ToolMessage } from "@ag-ui/core";
|
||||
|
||||
function ChatWithResults({
|
||||
message,
|
||||
allMessages,
|
||||
}: {
|
||||
message: AssistantMessage;
|
||||
allMessages: Message[];
|
||||
}) {
|
||||
const renderToolCall = useRenderToolCall();
|
||||
|
||||
return (
|
||||
<>
|
||||
{message.toolCalls?.map((toolCall) => {
|
||||
// Find the corresponding result message
|
||||
const toolMessage = allMessages.find(
|
||||
(m): m is ToolMessage =>
|
||||
m.role === "tool" && m.toolCallId === toolCall.id,
|
||||
);
|
||||
|
||||
return (
|
||||
<div key={toolCall.id}>
|
||||
{renderToolCall({
|
||||
toolCall,
|
||||
toolMessage, // Pass result if available
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Tool Renderers
|
||||
|
||||
The hook works with tool renderers defined at various levels:
|
||||
|
||||
### Provider-Level Renderers
|
||||
|
||||
Renderers defined in `CopilotKitProvider`:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
CopilotKitProvider,
|
||||
defineToolCallRenderer,
|
||||
} from "@copilotkit/react-core";
|
||||
|
||||
const searchRenderer = defineToolCallRenderer({
|
||||
name: "search",
|
||||
render: ({ args, status }) => <SearchDisplay {...args} status={status} />,
|
||||
});
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CopilotKitProvider renderToolCalls={[searchRenderer]}>
|
||||
{/* Components using useRenderToolCall will use this renderer */}
|
||||
</CopilotKitProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Dynamic Tool Renderers
|
||||
|
||||
Renderers registered via `useFrontendTool`:
|
||||
|
||||
```tsx
|
||||
function DynamicTool() {
|
||||
useFrontendTool({
|
||||
name: "dynamicAction",
|
||||
handler: async (args) => {
|
||||
/* ... */
|
||||
},
|
||||
render: ({ args, status }) => <div>Dynamic tool: {status}</div>,
|
||||
});
|
||||
|
||||
// This renderer is automatically available to useRenderToolCall
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
### Wildcard Renderer
|
||||
|
||||
A fallback renderer for unmatched tools:
|
||||
|
||||
```tsx
|
||||
const wildcardRenderer = defineToolCallRenderer({
|
||||
name: "*",
|
||||
render: ({ name, args, status }) => (
|
||||
<div className="unknown-tool">
|
||||
<span>Unknown tool: {name}</span>
|
||||
<span>Status: {status}</span>
|
||||
</div>
|
||||
),
|
||||
});
|
||||
```
|
||||
|
||||
## Status Lifecycle
|
||||
|
||||
The hook manages three status states automatically:
|
||||
|
||||
### InProgress
|
||||
|
||||
Initial state when tool is called but not executing:
|
||||
|
||||
```tsx
|
||||
// Renderer receives:
|
||||
{
|
||||
name: string;
|
||||
args: Partial<T>; // May be incomplete during streaming
|
||||
status: ToolCallStatus.InProgress;
|
||||
result: undefined;
|
||||
}
|
||||
```
|
||||
|
||||
### Executing
|
||||
|
||||
Active execution state:
|
||||
|
||||
```tsx
|
||||
// Renderer receives:
|
||||
{
|
||||
name: string;
|
||||
args: T; // Complete arguments
|
||||
status: ToolCallStatus.Executing;
|
||||
result: undefined;
|
||||
}
|
||||
```
|
||||
|
||||
### Complete
|
||||
|
||||
Final state with results:
|
||||
|
||||
```tsx
|
||||
// Renderer receives:
|
||||
{
|
||||
name: string;
|
||||
args: T; // Complete arguments
|
||||
status: ToolCallStatus.Complete;
|
||||
result: string; // Tool execution result
|
||||
}
|
||||
```
|
||||
|
||||
## Agent-Specific Rendering
|
||||
|
||||
The hook supports agent-specific renderers:
|
||||
|
||||
```tsx
|
||||
import { useCopilotChatConfiguration } from "@copilotkit/react-core";
|
||||
|
||||
function AgentAwareRendering() {
|
||||
const renderToolCall = useRenderToolCall();
|
||||
const config = useCopilotChatConfiguration();
|
||||
|
||||
// The hook automatically selects renderers based on the current agent
|
||||
// Priority: agent-specific > global > wildcard
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Agent: {config?.agentId || "default"}</h3>
|
||||
{/* Renders will use agent-appropriate renderers */}
|
||||
{toolCalls.map((tc) => renderToolCall({ toolCall: tc }))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user