Skip to content

Commit a3891bb

Browse files
docs: add CrewAI UI components documentation (CopilotKit#1513)
1 parent d152e11 commit a3891bb

9 files changed

Lines changed: 1143 additions & 13 deletions

File tree

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
---
2+
title: UI Components
3+
description: UI components for building CrewAI applications with CopilotKit
4+
icon: "lucide/LayoutTemplate"
5+
---
6+
7+
import { Card, Cards } from "fumadocs-ui/components/card";
8+
import { Callout } from "fumadocs-ui/components/callout";
9+
import { SiCrewai } from "@icons-pack/react-simple-icons";
10+
import { LayoutTemplate, Eye, Type } from "lucide-react";
11+
12+
# UI Components for CrewAI Crews
13+
14+
<Callout type="info">
15+
CopilotKit provides a set of pure UI components designed specifically for
16+
building human-in-the-loop applications with CrewAI Crews.
17+
</Callout>
18+
19+
The CopilotKit UI components help you build beautiful, interactive CrewAI applications that engage users throughout the agent's workflow. These components make it easy to visualize agent activity, collect user feedback, and provide a seamless user experience.
20+
21+
## Key Benefits
22+
23+
- **Visibility into Agent Activity**: Show users what your agents are doing in real-time
24+
- **Human-in-the-Loop Workflows**: Easily implement approval flows and user feedback
25+
- **Customizable Styling**: Adapt the components to match your application's design
26+
- **TypeScript Support**: Strong typing for all components and interfaces
27+
- **Composition-Friendly**: Build complex UIs by combining simple components
28+
29+
## Available Components
30+
31+
<Cards>
32+
<Card
33+
title="State Renderer"
34+
description="Display agent state and progress in a collapsible UI component"
35+
href="/crewai-crews/components/state-renderer"
36+
icon={<LayoutTemplate />}
37+
/>
38+
<Card
39+
title="Response Renderer"
40+
description="Display agent responses and collect user feedback"
41+
href="/crewai-crews/components/response-renderer"
42+
icon={<Eye />}
43+
/>
44+
<Card
45+
title="Component Types"
46+
description="Type definitions for CrewAI UI components"
47+
href="/crewai-crews/components/types"
48+
icon={<Type />}
49+
/>
50+
</Cards>
51+
52+
## Installation
53+
54+
All components are part of the `@copilotkit/react-ui` package:
55+
56+
```bash
57+
npm install @copilotkit/react-ui
58+
```
59+
60+
Don't forget to import the styles:
61+
62+
```tsx
63+
import "@copilotkit/react-ui/styles.css";
64+
```
65+
66+
## Basic Usage Example
67+
68+
Here's a simple example showing how to use the components together:
69+
70+
```tsx
71+
import {
72+
useCoAgentStateRender,
73+
useCopilotAction,
74+
} from "@copilotkit/react-core";
75+
import {
76+
DefaultStateRenderer,
77+
DefaultResponseRenderer,
78+
AgentState,
79+
ResponseStatus,
80+
} from "@copilotkit/react-ui";
81+
import "@copilotkit/react-ui/styles.css";
82+
83+
export function YourCrewAIApp() {
84+
// Render agent state (progress, tool calls, etc.)
85+
useCoAgentStateRender({
86+
name: "restaurant_finder_agent",
87+
render: ({ state, status }) => (
88+
<DefaultStateRenderer
89+
state={state}
90+
status={status}
91+
defaultCollapsed={false}
92+
/>
93+
),
94+
});
95+
96+
// Handle human-in-the-loop requests
97+
useCopilotAction({
98+
name: "ask_for_feedback",
99+
renderAndWaitForResponse({ status, args, respond }) {
100+
return (
101+
<DefaultResponseRenderer
102+
response={{
103+
id: args.id || "feedback-1",
104+
content: args.question || "What do you think?",
105+
metadata: args,
106+
}}
107+
onRespond={(input) => respond?.(input)}
108+
status={status as ResponseStatus}
109+
/>
110+
);
111+
},
112+
});
113+
114+
return <div className="your-app-container">{/* Your app UI */}</div>;
115+
}
116+
```
117+
118+
## Integration with CrewAI Enterprise
119+
120+
These components work seamlessly with CrewAI Enterprise. Follow our [CrewAI Quickstart](/crewai-crews/quickstart/crewai) guide to learn how to connect your crews to CopilotKit.
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
---
2+
title: Response Renderer
3+
description: Display agent responses and collect user feedback
4+
icon: "lucide/Eye"
5+
---
6+
7+
import { Callout } from "fumadocs-ui/components/callout";
8+
9+
# Response Renderer
10+
11+
The Response Renderer displays responses from an agent that may require user feedback, such as approving or rejecting a suggestion. It's especially useful for implementing human-in-the-loop workflows with CrewAI crews.
12+
13+
<Callout type="info">
14+
The Response Renderer is perfect for CrewAI crews that require user approval
15+
for critical decisions or need to collect user feedback.
16+
</Callout>
17+
18+
## Installation
19+
20+
This component is part of the `@copilotkit/react-ui` package:
21+
22+
```bash
23+
npm install @copilotkit/react-ui
24+
```
25+
26+
Don't forget to import the styles:
27+
28+
```tsx
29+
import "@copilotkit/react-ui/styles.css";
30+
```
31+
32+
## Basic Usage
33+
34+
Here's a simple example of how to use the DefaultResponseRenderer:
35+
36+
```tsx
37+
import { DefaultResponseRenderer } from "@copilotkit/react-ui";
38+
import "@copilotkit/react-ui/styles.css";
39+
40+
export function YourComponent() {
41+
return (
42+
<DefaultResponseRenderer
43+
response={{
44+
id: "response-1",
45+
content: "I've analyzed your data and found these insights...",
46+
}}
47+
status="inProgress"
48+
onRespond={(input) => console.log(`User responded: ${input}`)}
49+
/>
50+
);
51+
}
52+
```
53+
54+
## Integration with CoAgents
55+
56+
The DefaultResponseRenderer works seamlessly with the useCopilotAction hook to gather user feedback:
57+
58+
```tsx
59+
import { useCopilotAction } from "@copilotkit/react-core";
60+
import { DefaultResponseRenderer, ResponseStatus } from "@copilotkit/react-ui";
61+
62+
export function YourApp() {
63+
// Example: Crew is asking for user feedback on recommendations
64+
useCopilotAction({
65+
name: "crew_requesting_feedback",
66+
renderAndWaitForResponse({ status, args, respond }) {
67+
const feedback = args as { id: string; task_output: string };
68+
return (
69+
<DefaultResponseRenderer
70+
response={{
71+
id: feedback.id,
72+
content: feedback.task_output,
73+
metadata: feedback,
74+
}}
75+
onRespond={(input: string) => {
76+
respond?.(input);
77+
}}
78+
status={status as ResponseStatus}
79+
/>
80+
);
81+
},
82+
});
83+
84+
return (
85+
// Your app content
86+
);
87+
}
88+
```
89+
90+
## Customization
91+
92+
You can customize the appearance and behavior of the component:
93+
94+
```tsx
95+
<DefaultResponseRenderer
96+
response={{
97+
id: "task-123",
98+
content: "Would you like to proceed with this recommendation?",
99+
}}
100+
status="inProgress"
101+
onRespond={handleResponse}
102+
labels={{
103+
responseLabel: "AI Recommendation",
104+
approveLabel: "Yes, proceed",
105+
rejectLabel: "No, cancel",
106+
approvedMessage: "Proceeding with recommendation",
107+
rejectedMessage: "Recommendation cancelled",
108+
}}
109+
className="my-custom-response"
110+
contentClassName="my-custom-content"
111+
buttonClassName="my-custom-button"
112+
/>
113+
```
114+
115+
### Custom Content Renderer
116+
117+
You can provide a custom content renderer to format the response content:
118+
119+
```tsx
120+
import ReactMarkdown from "react-markdown";
121+
122+
<DefaultResponseRenderer
123+
response={{
124+
id: "task-456",
125+
content: "# Important Decision\nThis requires your approval",
126+
}}
127+
status="inProgress"
128+
onRespond={handleResponse}
129+
ContentRenderer={({ content, className }) => (
130+
<div className={className}>
131+
<ReactMarkdown>{content}</ReactMarkdown>
132+
</div>
133+
)}
134+
/>;
135+
```
136+
137+
### Custom Feedback Buttons
138+
139+
You can provide custom button components:
140+
141+
```tsx
142+
<DefaultResponseRenderer
143+
response={{
144+
id: "task-789",
145+
content: "Please review these findings",
146+
}}
147+
status="inProgress"
148+
onRespond={handleResponse}
149+
FeedbackButton={({ label, onClick, className }) => (
150+
<button
151+
onClick={onClick}
152+
className={`${className} ${
153+
label === "Approve" ? "bg-green-500" : "bg-red-500"
154+
}`}
155+
>
156+
{label}
157+
</button>
158+
)}
159+
/>
160+
```
161+
162+
## Props Reference
163+
164+
### `ResponseRendererProps`
165+
166+
| Prop | Type | Description | Default |
167+
| ---------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------ |
168+
| `response` | `Response` | The response data to render | - |
169+
| `status` | `ResponseStatus` | Current status: "inProgress", "complete", or "executing" | - |
170+
| `onRespond` | `(input: string) => void` | Function to call when a response is given | `undefined` |
171+
| `icons` | `{ expand?: React.ComponentType; collapse?: React.ComponentType }` | Custom icons for the component | Default icons |
172+
| `labels` | `ResponseRendererLabels` | Custom labels for the component | Default labels |
173+
| `ContentRenderer` | `React.ComponentType<ContentRendererProps>` | Custom component for rendering content | `DefaultContentRenderer` |
174+
| `FeedbackButton` | `React.ComponentType<FeedbackButtonProps>` | Custom component for rendering feedback buttons | `DefaultFeedbackButton` |
175+
| `CompletedFeedback` | `React.ComponentType<CompletedFeedbackProps>` | Custom component for rendering completed feedback | `DefaultCompletedFeedback` |
176+
| `className` | `string` | CSS class for the root element | `"copilotkit-response"` |
177+
| `contentClassName` | `string` | CSS class for the content element | `"copilotkit-response-content"` |
178+
| `actionsClassName` | `string` | CSS class for the actions container | `"copilotkit-response-actions"` |
179+
| `buttonClassName` | `string` | CSS class for feedback buttons | `"copilotkit-response-button"` |
180+
| `completedFeedbackClassName` | `string` | CSS class for completed feedback | `"copilotkit-response-completed-feedback"` |
181+
182+
### `Response` Interface
183+
184+
```typescript
185+
interface Response {
186+
id: string;
187+
content: string;
188+
metadata?: Record<string, any>;
189+
}
190+
```
191+
192+
### `ResponseRendererLabels` Interface
193+
194+
```typescript
195+
interface ResponseRendererLabels {
196+
responseLabel?: string;
197+
approveLabel?: string;
198+
rejectLabel?: string;
199+
approvedMessage?: string;
200+
rejectedMessage?: string;
201+
feedbackSubmittedMessage?: string;
202+
}
203+
```
204+
205+
## Styling
206+
207+
By default, CopilotKit components use minimal styling. You can customize the look and feel by either:
208+
209+
1. Overriding the default CSS classes
210+
2. Providing your own class names via props
211+
3. Using the built-in CSS variables
212+
213+
The component uses classes like `copilotkit-response`, `copilotkit-response-content`, and `copilotkit-response-button` that you can target for styling.
214+
215+
## Examples
216+
217+
### Human Approval Flow
218+
219+
```tsx
220+
// Example: Crew is asking for user approval before taking an important action
221+
useCopilotAction({
222+
name: "approve_restaurant_reservation",
223+
renderAndWaitForResponse({ status, args, respond }) {
224+
const reservation = args as {
225+
id: string;
226+
restaurant: string;
227+
time: string;
228+
guests: number;
229+
};
230+
231+
return (
232+
<DefaultResponseRenderer
233+
response={{
234+
id: reservation.id,
235+
content: `Would you like to make a reservation at ${reservation.restaurant}
236+
for ${reservation.guests} people at ${reservation.time}?`,
237+
metadata: reservation,
238+
}}
239+
onRespond={(input: string) => {
240+
if (input === "Approve") {
241+
// User approved the reservation
242+
respond?.("confirmed");
243+
} else {
244+
// User rejected the reservation
245+
respond?.("cancelled");
246+
}
247+
}}
248+
status={status as ResponseStatus}
249+
labels={{
250+
approveLabel: "Confirm Reservation",
251+
rejectLabel: "Cancel Reservation",
252+
}}
253+
/>
254+
);
255+
},
256+
});
257+
```

0 commit comments

Comments
 (0)