Skip to main content
Transform your data visualization experience with an AI-powered dashboard assistant. This example demonstrates how to build a conversational interface that allows users to ask questions about their data, get insights, and interact with metrics through natural language. Chat with your data demo

Overview

The Chat with Your Data example showcases a sales dashboard where users can:
  • Ask questions about sales trends, product performance, and customer metrics
  • Get AI-generated insights and analysis
  • Search the internet for additional context using Tavily
  • View custom generative UI components for search results
  • Customize the chat interface to match the dashboard design
Live Demo: https://copilotkit.ai/examples/chat-with-your-data Source Code: GitHub

What You’ll Learn

This example teaches you how to:
  • Make dashboard data available to AI using useAgentContext
  • Implement backend actions for secure server-side processing
  • Create custom generative UI components for tool results
  • Customize the CopilotKit sidebar appearance
  • Style assistant messages to match your design system
  • Use CSS variables for theming

Prerequisites

Installation

1

Clone the Repository

git clone https://github.com/CopilotKit/CopilotKit.git
cd CopilotKit/examples/v1/chat-with-your-data
2

Install Dependencies

pnpm install
# Using yarn
yarn install

# Using npm
npm install
3

Configure Environment Variables

Create a .env file in the project root:
OPENAI_API_KEY=your_openai_api_key
TAVILY_API_KEY=your_tavily_api_key
4

Start the Development Server

pnpm dev
# Using yarn
yarn dev

# Using npm
npm run dev
5

Open the Application

Navigate to http://localhost:3000 in your browser.
Add ?openCopilot=true to the URL to automatically open the sidebar

Key Implementation Details

1. CopilotKit Provider Setup

The provider wraps the entire application to enable CopilotKit features: File: app/layout.tsx
import { CopilotKit } from "@copilotkit/react";

export default function RootLayout({
  children,
}: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
        <CopilotKit runtimeUrl="/api/copilotkit">
          {children}
        </CopilotKit>
      </body>
    </html>
  );
}

2. Making Data Readable to AI

Use useAgentContext to provide dashboard data to the AI assistant: File: components/Dashboard.tsx
import { useAgentContext } from "@copilotkit/react";

export function Dashboard() {
  const salesData = useSalesData();
  const productData = useProductData();
  // ... other data hooks

  useAgentContext({
    description: "Dashboard data including sales trends, product performance, and category distribution",
    value: {
      salesData,
      productData,
      categoryData,
      regionalData,
      demographicsData,
      metrics: {
        totalRevenue,
        totalProfit,
        totalCustomers,
        conversionRate,
        averageOrderValue,
        profitMargin,
      },
    },
  });

  return (
    <div className="dashboard">
      {/* Dashboard UI */}
    </div>
  );
}
The AI can now access all this data when answering questions, providing context-aware insights.

3. Backend Actions for Secure Operations

Backend actions allow you to perform server-side operations securely while still letting the AI use them: File: app/api/copilotkit/route.ts
import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/runtime";
import { tavily } from "@tavily/core";

export async function POST(req: Request) {
  const runtime = new CopilotRuntime({
    actions: () => {
      return [
        {
          name: "searchInternet",
          description: "Searches the internet for information.",
          parameters: [
            {
              name: "query",
              type: "string",
              description: "The query to search the internet for.",
              required: true,
            },
          ],
          handler: async ({ query }: { query: string }) => {
            // Safely access environment variables on the server
            const tvly = tavily({ apiKey: process.env.TAVILY_API_KEY });
            return await tvly.search(query, { max_results: 5 });
          },
        },
      ];
    },
  });

  const { handleRequest } = runtime;
  return handleRequest(req);
}

4. Frontend Rendering of Backend Actions

You can render backend actions in the frontend using generative UI: File: components/Dashboard.tsx
import { useRenderToolCall } from "@copilotkit/react";
import { SearchResults } from "./generative-ui/SearchResults";

useRenderToolCall({
  name: "searchInternet",
  agentId: undefined, // Available for all agents
  render: ({ args, status }) => {
    return (
      <SearchResults
        query={args.query || "No query provided"}
        status={status}
      />
    );
  },
});

5. Custom Generative UI Component

Create custom components that render based on agent actions: File: components/generative-ui/SearchResults.tsx
import React from "react";
import { Search, Loader, CheckCircle, AlertCircle } from "lucide-react";

type SearchResultsProps = {
  query: string;
  status: "executing" | "inProgress" | "complete" | "error";
};

export function SearchResults({ query, status }: SearchResultsProps) {
  return (
    <div className="bg-white dark:bg-gray-800 p-3 rounded-lg border">
      <div className="flex items-center gap-2 mb-2">
        <Search className="h-4 w-4 text-blue-500" />
        <h3 className="text-sm font-medium">Search Results</h3>
      </div>

      <p className="text-xs text-gray-500 dark:text-gray-400 mb-2">
        Query: {query}
      </p>

      {status === "executing" && (
        <div className="flex items-center gap-2 text-xs text-blue-500">
          <Loader className="h-3 w-3 animate-spin" />
          <span>Searching...</span>
        </div>
      )}

      {status === "complete" && (
        <div className="flex items-center gap-2 text-xs text-green-500">
          <CheckCircle className="h-3 w-3" />
          <span>Complete</span>
        </div>
      )}
    </div>
  );
}

6. Customizing the Sidebar

Customize the CopilotKit sidebar with labels and custom message components: File: app/page.tsx
import { CopilotSidebar } from "@copilotkit/react";
import { CustomAssistantMessage } from "@/components/AssistantMessage";

const prompt = `You are a data analysis assistant helping users understand their sales dashboard...`;

export default function Home() {
  return (
    <div className="app">
      <Dashboard />
      <CopilotSidebar
        instructions={prompt}
        AssistantMessage={CustomAssistantMessage}
        labels={{
          title: "Data Assistant",
          initial: "Hello, I'm here to help you understand your data. How can I help?",
          placeholder: "Ask about sales, trends, or metrics...",
        }}
      />
    </div>
  );
}

7. Custom Assistant Message Component

Create a custom message component to match your design: File: components/AssistantMessage.tsx
import { AssistantMessageProps } from "@copilotkit/react";
import { Markdown } from "./Markdown";
import { Loader } from "lucide-react";

export const CustomAssistantMessage = (props: AssistantMessageProps) => {
  const { message, isLoading, subComponent } = props;

  return (
    <div className="pb-4">
      {(message || isLoading) && (
        <div className="bg-white dark:bg-gray-800 p-4 rounded-lg border shadow-sm">
          <div className="text-sm text-gray-700 dark:text-gray-300">
            {message && <Markdown content={message} />}
            {isLoading && (
              <div className="flex items-center gap-2 text-xs text-blue-500">
                <Loader className="h-3 w-3 animate-spin" />
                <span>Thinking...</span>
              </div>
            )}
          </div>
        </div>
      )}

      {subComponent && <div className="mt-2">{subComponent}</div>}
    </div>
  );
};

8. CSS Customization

Customize CopilotKit’s appearance using CSS variables: File: app/globals.css
:root {
  --copilot-kit-primary-color: #3b82f6;
  --copilot-kit-contrast-color: white;
  --copilot-kit-secondary-contrast-color: #1e293b;
  --copilot-kit-background-color: white;
  --copilot-kit-muted-color: #64748b;
  --copilot-kit-separator-color: rgba(0, 0, 0, 0.08);
  --copilot-kit-scrollbar-color: rgba(0, 0, 0, 0.2);
}

.dark {
  --copilot-kit-primary-color: #3b82f6;
  --copilot-kit-contrast-color: #1e293b;
  --copilot-kit-background-color: #1e293b;
  --copilot-kit-muted-color: #94a3b8;
}

/* Custom styling for CopilotKit components */
.copilotKitSidebar .copilotKitWindow {
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}

.copilotKitButton {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

Expected Behavior

When you run the application, you should be able to:
  1. View the dashboard with various sales metrics and charts
  2. Click the copilot button to open the chat sidebar
  3. Ask questions like:
    • “What were the top selling products last month?”
    • “Show me the revenue trend for the last quarter”
    • “What’s the average order value?”
    • “Search for market trends in e-commerce”
  4. See generative UI when the AI performs internet searches
  5. Get contextual answers based on the dashboard data

Try It Yourself

Here are some example queries to try:
  • “What’s the total revenue and how does it compare to last month?”
  • “Which product category has the highest profit margin?”
  • “Can you search for recent e-commerce trends?”
  • “What’s the customer conversion rate and how can we improve it?”
  • “Show me the regional breakdown of sales”

Next Steps

Generative UI

Learn more about creating custom generative UI components

Multi-Agent Systems

Build more complex applications with multiple coordinating agents

useAgentContext

Deep dive into making data available to AI

Backend Actions

Learn more about implementing secure backend actions

Troubleshooting

Make sure your .env file is in the project root and contains valid API keys:
OPENAI_API_KEY=sk-...
TAVILY_API_KEY=tvly-...
Restart the development server after adding environment variables.
Verify that:
  1. Your Tavily API key is valid
  2. The backend action is properly configured in app/api/copilotkit/route.ts
  3. The frontend render function is set up with useRenderToolCall