name: copilotkit-setup description: > Use when adding CopilotKit to an existing project or bootstrapping a new CopilotKit project from scratch. Covers framework detection, package installation, runtime wiring, provider setup, and first working chat integration. version: 1.1.2
CopilotKit Setup
Prerequisites
Live Documentation (MCP)
This plugin includes an MCP server (copilotkit-docs) that provides search-docs and search-code tools for querying live CopilotKit documentation and source code.
- Claude Code: Auto-configured by the plugin's
.mcp.json-- no setup needed. - Codex: Requires manual configuration. See the copilotkit-debug skill for setup instructions.
Environment
Before starting setup, verify:
- Node.js >= 18 (required for
fetchglobals used by the runtime) - An AI provider API key (one of:
OPENAI_API_KEY,ANTHROPIC_API_KEY,GOOGLE_API_KEY) - A React-based frontend (Next.js App Router, Next.js Pages Router, Vite + React, or Angular)
- A backend capable of running the runtime (same Next.js app via API routes, or a standalone Express/Hono server)
Framework Detection
Before generating any code, detect the project's framework by checking files in the project root. See references/framework-detection.md for the full decision tree.
Quick summary:
| Signal File | Framework |
|---|---|
next.config.{js,ts,mjs} + app/ directory |
Next.js App Router |
next.config.{js,ts,mjs} + pages/ directory |
Next.js Pages Router |
angular.json |
Angular |
vite.config.{js,ts} + React deps in package.json |
Vite + React |
Setup Workflow
Step 1: Install packages
All packages use the @copilotkit namespace. The v2 API lives as subpath exports on the published packages.
Frontend + backend in the same Next.js app:
npm install @copilotkit/react-core @copilotkit/runtime hono
Frontend only:
npm install @copilotkit/react-core
Backend runtime only:
npm install @copilotkit/runtime hono
For standalone Express backends, install Express adapter dependencies instead of hono:
npm install @copilotkit/runtime express dotenv zod
npm install -D @types/express tsx typescript
(createCopilotExpressHandler enables CORS internally, so you do not need to
install cors yourself. dotenv and zod are used by the example asset.)
Step 2: Configure the runtime
The runtime is the server-side component that manages agent execution. See references/runtime-architecture.md for details.
There are two endpoint styles:
- Multi-route (Hono) -- uses
createCopilotHonoHandler. Requires a catch-all route ([[...slug]]in Next.js). Each operation (run, connect, stop, info, transcribe, threads) gets its own HTTP path. - Single-route (Hono or Express) -- uses
createCopilotHonoHandler({ ..., mode: "single-route" })orcreateCopilotExpressHandler({ ..., mode: "single-route" }). All operations go through a single POST endpoint with method multiplexing.
Next.js App Router (recommended: multi-route with Hono)
Create src/app/api/copilotkit/[[...slug]]/route.ts:
import {
CopilotRuntime,
createCopilotHonoHandler,
InMemoryAgentRunner,
BuiltInAgent,
} from "@copilotkit/runtime/v2";
import { handle } from "hono/vercel";
const agent = new BuiltInAgent({
model: "openai/gpt-4o",
prompt: "You are a helpful AI assistant.",
});
const runtime = new CopilotRuntime({
agents: {
default: agent,
},
runner: new InMemoryAgentRunner(),
});
const app = createCopilotHonoHandler({
runtime,
basePath: "/api/copilotkit",
});
export const GET = handle(app);
export const POST = handle(app);
// PATCH/DELETE are used by thread operations (useThreads); export them too
// so the multi-route handler can serve them when you enable Intelligence/threads.
export const PATCH = handle(app);
export const DELETE = handle(app);
Next.js App Router (alternative: single-route)
Create src/app/api/copilotkit/route.ts:
import {
CopilotRuntime,
createCopilotHonoHandler,
InMemoryAgentRunner,
BuiltInAgent,
} from "@copilotkit/runtime/v2";
import { handle } from "hono/vercel";
const agent = new BuiltInAgent({
model: "openai/gpt-4o",
prompt: "You are a helpful AI assistant.",
});
const runtime = new CopilotRuntime({
agents: {
default: agent,
},
runner: new InMemoryAgentRunner(),
});
const app = createCopilotHonoHandler({
runtime,
basePath: "/api/copilotkit",
mode: "single-route",
});
export const POST = handle(app);
When using single-route, the frontend must set useSingleEndpoint on the provider (see Step 3).
Standalone Express Server
Create src/index.ts:
import express from "express";
import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2";
import { createCopilotExpressHandler } from "@copilotkit/runtime/v2/express";
const agent = new BuiltInAgent({
model: "openai/gpt-4o",
});
const runtime = new CopilotRuntime({
agents: {
default: agent,
},
});
const app = express();
app.use(
"/api/copilotkit",
createCopilotExpressHandler({
runtime,
basePath: "/",
mode: "single-route",
}),
);
const port = Number(process.env.PORT ?? 4000);
app.listen(port, () => {
console.log(
`CopilotKit runtime listening at http://localhost:${port}/api/copilotkit`,
);
});
For multi-route Express, omit the mode option (multi-route is the default) -- createCopilotExpressHandler is the same factory for both styles (imported from @copilotkit/runtime/v2/express).
Standalone Hono Server (non-Vercel)
import {
CopilotRuntime,
createCopilotHonoHandler,
BuiltInAgent,
} from "@copilotkit/runtime/v2";
import { serve } from "@hono/node-server";
const runtime = new CopilotRuntime({
agents: {
default: new BuiltInAgent({ model: "openai/gpt-4o" }),
},
});
const app = createCopilotHonoHandler({
runtime,
basePath: "/api/copilotkit",
});
serve({ fetch: app.fetch, port: 8787 });
Requires @hono/node-server:
npm install hono @hono/node-server
Step 3: Set up the frontend provider
Wrap your application with CopilotKit from @copilotkit/react-core/v2.
Which provider component? Always use
CopilotKitimported from@copilotkit/react-core/v2. It is the compatibility bridge across v1 and v2 and a strict superset of the other provider APIs. Do not useCopilotKitfrom the package root (@copilotkit/react-core, legacy v1) orCopilotKitProviderfrom/v2(a subset of the functionality).
Important: Import the stylesheet in your root layout:
import "@copilotkit/react-core/v2/styles.css";
Next.js App Router
In src/app/page.tsx (or a client component):
"use client";
import { CopilotKit, CopilotChat } from "@copilotkit/react-core/v2";
export default function Home() {
return (
// useSingleEndpoint={false} matches the multi-route backend above.
// The v1-compat CopilotKit bridge defaults useSingleEndpoint to true,
// which would 404 against multi-route endpoints.
<CopilotKit runtimeUrl="/api/copilotkit" useSingleEndpoint={false}>
<div style={{ height: "100vh" }}>
<CopilotChat />
</div>
</CopilotKit>
);
}
Connecting to an external runtime
When the runtime runs on a separate server (e.g., Express on port 4000):
<CopilotKit runtimeUrl="http://localhost:4000/api/copilotkit" useSingleEndpoint>
{children}
</CopilotKit>
Set useSingleEndpoint when the backend uses single-route endpoints (createCopilotHonoHandler or createCopilotExpressHandler with mode: "single-route").
CopilotKit key props
| Prop | Type | Description |
|---|---|---|
runtimeUrl |
string |
URL of the CopilotKit runtime endpoint |
useSingleEndpoint |
boolean |
Set to true when using single-route endpoints |
headers |
Record<string, string> | (() => Record<string, string>) |
Custom headers sent with every request. The function form is evaluated per-request (useful for dynamic auth tokens). |
credentials |
RequestCredentials |
Fetch credentials mode (e.g., "include" for cookies) |
publicLicenseKey |
string |
CopilotKit Intelligence public license key (publicApiKey is a deprecated alias) |
showDevConsole |
boolean |
Show the dev console. Omit it to get the default behavior (shown on localhost only) |
renderToolCalls |
ReactToolCallRenderer[] |
Custom renderers for tool call UI |
frontendTools |
ReactFrontendTool[] |
Frontend-defined tools (declarative alternative to useFrontendTool) |
onError |
(event) => void |
Global error handler |
Step 4: Add a chat UI component
CopilotKit provides three pre-built chat layouts (all imported from @copilotkit/react-core/v2):
| Component | Usage |
|---|---|
CopilotChat |
Inline chat, fills its container |
CopilotSidebar |
Collapsible sidebar panel |
CopilotPopup |
Floating popup widget |
Example with sidebar:
import { CopilotKit, CopilotSidebar } from "@copilotkit/react-core/v2";
<CopilotKit runtimeUrl="/api/copilotkit" useSingleEndpoint={false}>
<YourApp />
<CopilotSidebar
defaultOpen
width="420px"
labels={{
modalHeaderTitle: "AI Assistant",
chatInputPlaceholder: "Ask me anything...",
}}
/>
</CopilotKit>;
Step 5: Set environment variables
Provider API keys are secrets. Store them in environment variables -- never hardcode them in source or commit them to version control. Create a .env.local (Next.js) or .env file:
OPENAI_API_KEY=<your-openai-api-key>
Make sure your .gitignore excludes env files (.env, .env.local, .env*.local) so keys are never committed. In production, supply keys through your platform's secret manager (Vercel/Netlify environment variables, AWS Secrets Manager, etc.) rather than a checked-in file.
The BuiltInAgent automatically resolves API keys from these environment variables based on the model prefix:
openai/*models readOPENAI_API_KEYanthropic/*models readANTHROPIC_API_KEYgoogle/*models readGOOGLE_API_KEY
If you need to pass apiKey explicitly, always source it from the environment (apiKey: process.env.OPENAI_API_KEY) -- never inline a literal key.
Step 6: Connect to CopilotKit Intelligence (telemetry)
CopilotKit uses telemetry to understand adoption, improve the product, and provide better support. Connecting to CopilotKit Intelligence gives you access to analytics and optional premium features.
- Ask the user if they'd like to connect to CopilotKit Intelligence (default: yes).
- If yes, run the CopilotKit CLI authentication flow (verify the exact command with
npx copilotkit --helpas it may vary by version):npx copilotkit auth - Guide the user through the browser-based authentication that opens.
- Once authentication completes, the CLI outputs a license key (a public, client-side project identifier -- not a secret).
- Store the license key in an environment variable and reference it from the
CopilotKitprovider -- this keeps it out of source and easy to rotate per environment:# .env.local (Next.js) NEXT_PUBLIC_COPILOTKIT_LICENSE_KEY=<your-license-key>
The<CopilotKit runtimeUrl="/api/copilotkit" publicLicenseKey={process.env.NEXT_PUBLIC_COPILOTKIT_LICENSE_KEY} >NEXT_PUBLIC_/VITE_prefix is required because the key is read on the client.
See references/telemetry-setup.md for full details on what the license key enables and how to opt out.
Step 7: Verify the setup
- Start the dev server
- Open the app in a browser
- The chat UI should render and connect to the runtime
- Send a test message -- you should receive an AI response
- Check the runtime's info endpoint to confirm it reports available agents. For multi-route handlers this is
GET /api/copilotkit/info; for single-route handlers (mode: "single-route", e.g. the Express example) it is aPOSTto the base path with body{ "method": "info" }(a plainGETwill not return agent info — the Hono single-route handler answers405, and the Express single-route router has noGETroute so it falls through to a404)
Security notes
Keep these in mind as you wire up a real deployment:
- Secrets stay server-side and in env vars. Provider API keys (
OPENAI_API_KEY, etc.) are read by the runtime/agent on the server. Never expose them to the browser, hardcode them, or commit them -- store them in environment variables or a secret manager (see Step 5). The CopilotKit license key is the one client-side value, and it is a public project identifier, not a secret. - Treat all chat input as untrusted. Chat messages flow from the frontend through the
CopilotRuntimeendpoint into the agent's LLM context. They are user-controlled and can attempt prompt injection -- including indirect injection via content the agent fetches (web pages, documents, tool results). Do not assume the model will only do what your system prompt intends. - Give server-side tools least privilege. A
defineTool'sexecutefunction runs with your server's authority. Validate every argument (thezodparametersschema is your first gate), scope each tool to the narrowest action it needs, and enforce your own authorization inside theexecutefunction for anything sensitive (database writes, payments, file access) rather than trusting that the model called it correctly. - Authenticate the runtime endpoint. The runtime route is a public HTTP endpoint by default. Put your app's auth in front of it so only authorized users can drive the agent and consume provider credits.
Quick Reference
Package map
| Package | Purpose |
|---|---|
@copilotkit/react-core |
React components, hooks, provider (import from @copilotkit/react-core/v2) |
@copilotkit/runtime |
Runtime, endpoint factories, agent runners, BuiltInAgent, defineTool (import from @copilotkit/runtime/v2) |
@copilotkit/shared |
Shared utilities, logger, types |
Endpoint factory functions
| Function | Import | Framework | Mode |
|---|---|---|---|
createCopilotHonoHandler |
@copilotkit/runtime/v2 |
Next.js App Router, Hono standalone | "multi-route" (default) or mode: "single-route" |
createCopilotExpressHandler |
@copilotkit/runtime/v2/express |
Express standalone | "multi-route" (default) or mode: "single-route" |
The
createCopilotEndpoint,createCopilotEndpointSingleRoute,createCopilotEndpointExpress, andcreateCopilotEndpointSingleRouteExpressnames are deprecated aliases of the two factories above. Prefer the handler factories with themodeoption.
Runtime classes
| Class | Use case |
|---|---|
CopilotRuntime |
Compatibility shim; auto-selects SSE or Intelligence mode |
CopilotSseRuntime |
Explicit SSE mode (default, in-memory threads) |
CopilotIntelligenceRuntime |
Intelligence mode (durable threads, realtime events) |
Agent runners
| Runner | Description |
|---|---|
InMemoryAgentRunner |
Default. Stores thread state in process memory. Suitable for development and single-instance deployments. |
IntelligenceAgentRunner |
Used automatically with CopilotIntelligenceRuntime. Connects to CopilotKit Intelligence Platform via WebSocket. |
Supported models (BuiltInAgent)
Format: "provider/model-name" string or a Vercel AI SDK LanguageModel instance.
OpenAI: openai/gpt-5, openai/gpt-5-mini, openai/gpt-4.1, openai/gpt-4.1-mini, openai/gpt-4.1-nano, openai/gpt-4o, openai/gpt-4o-mini, openai/o3, openai/o3-mini, openai/o4-mini
Anthropic: anthropic/claude-sonnet-4.5, anthropic/claude-sonnet-4, anthropic/claude-3.7-sonnet, anthropic/claude-opus-4.1, anthropic/claude-opus-4, anthropic/claude-3.5-haiku
Google: google/gemini-2.5-pro, google/gemini-2.5-flash, google/gemini-2.5-flash-lite
Any string is accepted (for custom/unlisted models); the provider is parsed from the prefix before /.