UNPKG

@copilotkit/react-core

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

327 lines (249 loc) 8.24 kB
# CopilotKit Provider Setup (React) Mount `CopilotKitProvider` once near the root of the React tree. Every CopilotKit hook (`useAgent`, `useFrontendTool`, `useRenderTool`, etc.) and every chat component (`CopilotChat`, `CopilotPopup`, `CopilotSidebar`) must be rendered inside this provider. All v2 imports use the `@copilotkit/react-core/v2` subpath. Imports from the package root are v1 and will not work with v2 hooks or components. ## Setup ### Next.js App Router (and any RSC-based framework) `@copilotkit/react-core/v2` is marked `"use client"`. You must mount the provider from a client component, not a server component. The cleanest pattern is a dedicated client-only `providers.tsx`. ```tsx // app/providers.tsx "use client"; import { CopilotKitProvider } from "@copilotkit/react-core/v2"; import "@copilotkit/react-core/v2/styles.css"; export function Providers({ children }: { children: React.ReactNode }) { return ( <CopilotKitProvider runtimeUrl="/api/copilotkit" credentials="include" onError={({ code, error, context }) => { console.error("[copilotkit]", code, error, context); }} > {children} </CopilotKitProvider> ); } ``` For auth headers that change over the session (rotating bearer tokens, refreshed cookies), see the "Stable headers for rotating auth tokens" pattern below. Avoid putting a `useMemo(() => ({ Authorization: ... }), [])` on the provider — an empty deps array captures the token at mount and never refreshes. ```tsx // app/layout.tsx — server component import { Providers } from "./providers"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> <Providers>{children}</Providers> </body> </html> ); } ``` ### Vite / React Router v7 / SPA ```tsx import { CopilotKitProvider } from "@copilotkit/react-core/v2"; import "@copilotkit/react-core/v2/styles.css"; export function App({ children }: { children: React.ReactNode }) { return ( <CopilotKitProvider runtimeUrl="/api/copilotkit"> {children} </CopilotKitProvider> ); } ``` ### SPA with CopilotKit Cloud (no self-hosted runtime) ```tsx <CopilotKitProvider publicApiKey="ck_pub_..." /> ``` `publicApiKey` is the canonical prop for running CopilotKit from a pure client bundle. `publicLicenseKey` is an alias that resolves to the same value (`publicApiKey ?? publicLicenseKey`) — accept in old code, but always write `publicApiKey` in new code. ## Core Patterns ### Stable headers for rotating auth tokens For tokens that change during the session, use the imperative setter instead of re-rendering the provider with a new `headers` prop. ```tsx "use client"; import { useCopilotKit } from "@copilotkit/react-core/v2"; import { useEffect } from "react"; export function AuthTokenSync({ token }: { token: string }) { const { copilotkit } = useCopilotKit(); useEffect(() => { copilotkit.setHeaders({ Authorization: `Bearer ${token}` }); }, [copilotkit, token]); return null; } ``` ### Global error handler `onError` fires for every `CopilotKitCoreErrorCode` emitted by core. Keeps UI from getting stuck in "connecting..." when the runtime URL is wrong or CORS is misconfigured. ```tsx <CopilotKitProvider runtimeUrl="/api/copilotkit" onError={({ code, error, context }) => { telemetry.capture({ code, message: error.message, context }); }} /> ``` ### Sharing app properties with every run `properties` flows to the runtime on each agent run — useful for tenant IDs, feature flags, or anything the server needs. ```tsx const properties = useMemo( () => ({ tenantId: user.tenantId, locale: user.locale }), [user.tenantId, user.locale], ); <CopilotKitProvider runtimeUrl="/api/copilotkit" properties={properties} />; ``` ## Common Mistakes ### CRITICAL — Mounting the provider from a Server Component Wrong: ```tsx // app/page.tsx (server component — no "use client") import { CopilotKitProvider } from "@copilotkit/react-core/v2"; export default function Page() { return ( <CopilotKitProvider runtimeUrl="/api/copilotkit">...</CopilotKitProvider> ); } ``` Correct: ```tsx // app/providers.tsx "use client"; import { CopilotKitProvider } from "@copilotkit/react-core/v2"; export function Providers({ children }: { children: React.ReactNode }) { return ( <CopilotKitProvider runtimeUrl="/api/copilotkit"> {children} </CopilotKitProvider> ); } // app/layout.tsx imports <Providers>. ``` `@copilotkit/react-core/v2` begins with `"use client"`. Importing it from a server component silently strips interactivity — the provider renders but none of the hooks wire up. Source: `packages/react-core/src/v2/index.ts:1` ### CRITICAL — Using `agents__unsafe_dev_only` or `selfManagedAgents` in production Wrong: ```tsx <CopilotKitProvider agents__unsafe_dev_only={{ default: new BuiltInAgent({ apiKey: process.env.OPENAI_KEY! }), }} /> // or the alias (same thing): <CopilotKitProvider selfManagedAgents={{ default: new BuiltInAgent({ apiKey: "..." }) }} /> ``` Correct: ```tsx // Route through a runtime that keeps secrets server-side: <CopilotKitProvider runtimeUrl="/api/copilotkit" /> // Or for a pure SPA, use CopilotKit Cloud: <CopilotKitProvider publicApiKey="ck_pub_..." /> ``` Both props are aliases for the same dev-only mechanism and ship any embedded credentials to the browser bundle. Never use either for production agents. Source: `packages/react-core/src/v2/providers/CopilotKitProvider.tsx:136-138,393` ### HIGH — Inline object props rebuilt every render Wrong: ```tsx <CopilotKitProvider runtimeUrl="/api/copilotkit" headers={{ Authorization: `Bearer ${token}` }} properties={{ tenantId: user.tenantId }} /> ``` Correct: ```tsx const headers = useMemo(() => ({ Authorization: `Bearer ${token}` }), [token]); const properties = useMemo( () => ({ tenantId: user.tenantId }), [user.tenantId], ); <CopilotKitProvider runtimeUrl="/api/copilotkit" headers={headers} properties={properties} />; ``` New object identity on every render causes the provider to diff-churn internal state and may thrash tool/renderer registration. `useStableArrayProp` also logs a `console.error` when array-prop shape changes without memoization. Source: `packages/react-core/src/v2/providers/CopilotKitProvider.tsx:324-340,399-410` ### HIGH — Missing `onError` leaves users stuck in "connecting..." Wrong: ```tsx <CopilotKitProvider runtimeUrl="/api/copilotkit" /> ``` Correct: ```tsx <CopilotKitProvider runtimeUrl="/api/copilotkit" onError={({ code, error, context }) => { telemetry.capture({ code, error, context }); }} /> ``` Without `onError`, connection failures (bad runtime URL, CORS, network) keep the provider in a provisional state with `ProxiedCopilotRuntimeAgent` instances that never resolve. The chat UI keeps showing "connecting..." forever and users never see the actual error. Source: `packages/react-core/src/v2/providers/CopilotKitProvider.tsx:638-660` ### HIGH — Writing `publicLicenseKey` in new code Wrong: ```tsx <CopilotKitProvider publicLicenseKey="ck_pub_..." /> ``` Correct: ```tsx <CopilotKitProvider publicApiKey="ck_pub_..." /> ``` `publicLicenseKey` still works as an alias, but `publicApiKey` is the canonical name in v2. The provider resolves `publicApiKey ?? publicLicenseKey`. Always write the canonical form in new code. Source: `packages/react-core/src/v2/providers/CopilotKitProvider.tsx:122-128,391` ### MEDIUM — Putting the provider below a layout that uses CopilotKit Wrong: ```tsx <html> <body> <Header>{/* Header uses useFrontendTool internally */}</Header> <CopilotKitProvider>{children}</CopilotKitProvider> </body> </html> ``` Correct: ```tsx <html> <body> <CopilotKitProvider> <Header /> {children} </CopilotKitProvider> </body> </html> ``` Any component that calls `useCopilotKit`, `useFrontendTool`, `useAgent`, or any other CopilotKit hook must be a descendant of `CopilotKitProvider`. Placing the provider beside or below a consumer throws at mount. Source: `packages/react-core/src/v2/providers/CopilotKitProvider.tsx` (context)