Most in-app AI chatbots feel like they were superglued to the side of a web application ten minutes before an investor pitch. They sit in a lonely floating bubble in the bottom-right corner, completely blind to what the user is actually doing on screen. If you ask them to update a dashboard filter, adjust an invoice balance, or summarise the table you are currently viewing, they politely confess that they are merely a glorified API wrapper with zero access to the document object model.
CopilotKit is the open-source framework built to cure this exact brand of artificial incompetence. It provides the React components and backend runtime layers needed to turn generic LLMs into fully synchronised, context-aware copilots that can read application state and trigger native UI actions.
┌───────────────────────────────────────────────────────────┐
│ React Frontend │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ useCopilotReadable │ │ useCopilotAction │ │
│ │ (Provides App State) │ │ (Executes UI logic) │ │
│ └───────────┬───────────┘ └───────────▲───────────┘ │
└──────────────┼─────────────────────────────┼──────────────┘
│ Context Stream │ Tool Execution
▼ │
┌────────────────────────────────────────────┼──────────────┐
│ CopilotKit Runtime Node/Next.js Layer │ │
│ (Orchestrates tool schemas & handles LLM) │ │
└──────────────────────┬─────────────────────┼──────────────┘
▼ │
┌───────────────┐ │
│ LLM Provider │─────────────┘
│ (OpenAI/Anth) │
└───────────────┘
What is CopilotKit?
CopilotKit is an open-source TypeScript framework designed to integrate context-aware AI copilots, interactive sidebars, modal popups, and generative autocompleting textareas into modern React applications.
Unlike primitive chatbot embeds that rely on static system prompts, CopilotKit establishes a bidirectional bridge between your application's front-end state and the language model via custom React hooks (useCopilotReadable and useCopilotAction).
Key Architectural Layers
1. The React UI Layer (@copilotkit/react-ui): Prebuilt, stylable components including <CopilotSidebar />, <CopilotPopup />, and context-aware inputs like <CopilotTextarea />.
2. The React Core Layer (@copilotkit/react-core): State management hooks that register state slices with the LLM context window and expose frontend functions as executable LLM tools.
3. The Backend Runtime (@copilotkit/runtime): A server-side service (compatible with Next.js, Node, Express, or FastAPI) that streams tokens, handles function-calling execution loops, and secures API keys.
Hands-On Implementation
Integrating CopilotKit requires wiring up a client wrapper, registering state, and setting up an endpoint to handle LLM traffic.
1. Install Dependencies
In your React or Next.js project, install the client and runtime packages:
npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime
2. Set Up the Backend Runtime Route
In a Next.js App Router project, create a route handler at app/api/copilotkit/route.ts. This proxies user input to your model provider without exposing API keys to the browser.
import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/runtime";
import { NextRequest } from "next/server";
const runtime = new CopilotRuntime();
export async function POST(req: NextRequest) {
const { handleRequest } = runtime.streamHttpServerResponse(
req,
new OpenAIAdapter({ model: "gpt-4o" })
);
return handleRequest();
}
3. Wrap Your Application
Wrap your root layout or dashboard page in the <CopilotKit> provider pointing to your backend endpoint:
"use client";
import "@copilotkit/react-ui/styles.css";
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<CopilotKit runtimeUrl="/api/copilotkit">
<CopilotSidebar
defaultOpen={false}
labels={{
title: "Workspace Copilot",
initial: "Hi! How can I help you manage your tasks today?",
}}
>
{children}
</CopilotSidebar>
</CopilotKit>
);
}
4. Feed App State and Bind Actions
This is where the magic happens. Suppose you have a task board. You want the copilot to know what tasks exist, and you want it to be able to add a new task when requested by the user:
"use client";
import { useState } from "react";
import { useCopilotReadable, useCopilotAction } from "@copilotkit/react-core";
interface Task {
id: number;
title: string;
completed: boolean;
}
export function TaskBoard() {
const [tasks, setTasks] = useState<Task[]>([
{ id: 1, title: "Review quarterly PRs", completed: false },
]);
// 1. Give the copilot visibility into application state
useCopilotReadable({
description: "The list of tasks currently visible on the board",
value: tasks,
});
// 2. Allow the copilot to mutate application state via tool calling
useCopilotAction({
name: "createTask",
description: "Adds a new task to the user board",
parameters: [
{
name: "title",
type: "string",
description: "The title of the task to create",
required: true,
},
],
handler: async ({ title }) => {
const newTask = { id: Date.now(), title, completed: false };
setTasks((prev) => [...prev, newTask]);
return `Task "${title}" created successfully.`;
},
});
return (
<div className="p-6">
<h1 className="text-xl font-bold">Project Board</h1>
<ul className="mt-4 space-y-2">
{tasks.map((task) => (
<li key={task.id} className="p-2 border rounded">
{task.title}
</li>
))}
</ul>
</div>
);
}
If a user opens the sidebar and writes: "Add a task to audit OAuth scopes, then tell me what I have left to do," CopilotKit automatically translates that into a tool call for createTask, re-renders the list via React state, reads the updated state, and answers the user.
Architectural Comparison
| Capability | Generic Chatbot Embeds | Raw Vercel AI SDK | CopilotKit |
|---|---|---|---|
| Primary Focus | Standalone Q&A | Streaming text & primitives | Bidirectional in-app orchestration |
| Component Kit | Static iframe | DIY UI primitives | Drop-in sidebars, modals & textareas |
| Frontend State Sync | None | Manual parameter passing | Native (useCopilotReadable) |
| UI Action Triggering | Unsupported | Bespoke client-side tools | Native (useCopilotAction) |
| Inline Autocomplete | Unsupported | Custom text bindings | Turnkey <CopilotTextarea /> |
The Standout Feature: Contextual Textareas
While the sidebar copilot gets the bulk of marketing attention, <CopilotTextarea> is arguably the repository's sharpest utility. It replaces standard HTML <textarea> inputs with an autocomplete-capable editor that behaves like GitHub Copilot inside your own form inputs.
It uses two tiers of context: the local text before and after the cursor, plus any wider application state provided via useCopilotReadable. As users type, inline ghost text suggestions appear in real time based on the active user session, which users can accept with a tap of the Tab key.
Key Takeaways
- True State Awareness: Eliminates the disconnect between front-end UI state and LLMs by registering React hooks as dynamic context.
- Bi-Directional Action Execution: Models can execute functions directly inside the client component lifecycle, updating the DOM and local state natively.
- Modular Stack: Adopt high-level UI components directly, or write custom UI using core primitives and runtime middleware.
- Production-Ready Multi-Agent Support: CopilotKit supports integrations with LangChain, LangGraph, and external agent runtimes via Copilot Runtime Remote Endpoints.