
Copilotkit Develop
- 469 installs
- 35 repo stars
- Updated June 3, 2026
- copilotkit/skills
This is a copy of copilotkit-develop by copilotkit - installs and ranking accrue to the original listing.
copilotkit-develop is an agent skill that implements CopilotKit v2 copilots—runtime, chat UI, frontend tools, and shared context—for developers embedding AG-UI agents in React apps.
About
copilotkit-develop is version 1.0.0 skill in copilotkit/skills for building AI-powered features with CopilotKit v2 on the AG-UI protocol. It documents a seven-step workflow: set up CopilotRuntime with createCopilotEndpoint or Express adapters, wrap apps in CopilotKitProvider, add CopilotChat or popup/sidebar UIs, register frontend tools via useFrontendTool, share JSON context with useAgentContext, handle interrupts with useInterrupt, and render tool calls through useRenderTool. Quick references list 14 React hooks—including useHumanInTheLoop, useSuggestions, and useThreads—and nine chat UI components from CopilotKitProvider through CopilotChatSuggestionView. The bundled copilotkit-docs MCP exposes search-docs and search-code for live references. Developers reach for copilotkit-develop when moving beyond scaffolds to production copilots with runtime routes, zod-validated tools, and agent-visible application state in Next.js or Express hosts. The skill also covers suggestion configuration, thread management on Intelligence runtimes, and custom tool renderers for richer in-chat UX during agent sessions.
- Action and readable state design
- Copilot runtime integration patterns
- Prompt and context shaping
- Tool-call orchestration in apps
- Reusable copilot feature structure
Copilotkit Develop by the numbers
- 469 all-time installs (skills.sh)
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/copilotkit/skills --skill copilotkit-developAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 469 |
|---|---|
| repo stars | ★ 35 |
| Last updated | June 3, 2026 |
| Repository | copilotkit/skills ↗ |
How do you build CopilotKit v2 copilot features?
Implement CopilotKit copilots end to end: define actions, readable state, prompts, runtime hooks, and app-specific agent behavior beyond initial scaffold and one-off integrations.
Who is it for?
React developers embedding CopilotKit v2 copilots who need runtime, hooks, and chat components wired beyond initial scaffold.
Skip if: Teams not using CopilotKit or AG-UI in React apps should skip copilotkit-develop.
When should I use this skill?
User adds CopilotKit chat, frontend tools, shared agent context, interrupts, or CopilotRuntime server routes.
What you get
CopilotRuntime endpoint, CopilotKitProvider setup, registered frontend tools, and chat UI with interrupt handling.
- CopilotRuntime API route
- CopilotKit chat UI integration
- Registered frontend tools and shared context
By the numbers
- Version 1.0.0 with a 7-step CopilotKit v2 development workflow
- Documents 14 React hooks and 9 chat UI components
Files
CopilotKit v2 Development Skill
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.
Architecture Overview
CopilotKit v2 is built on the AG-UI protocol (@ag-ui/client / @ag-ui/core). The stack has three layers:
1. Runtime (@copilotkit/runtime) -- Server-side. Hosts agents, handles SSE/Intelligence transport, middleware, transcription. 2. Core (@copilotkit/core) -- Shared state management, tool registry, suggestion engine. Not imported directly by apps. 3. React (@copilotkit/react) -- Provider, chat components, hooks. Re-exports everything from @ag-ui/client so apps need only one import.
Workflow
1. Set Up the Runtime (Server)
Create a CopilotRuntime (or the explicit CopilotSseRuntime / CopilotIntelligenceRuntime) and expose it via createCopilotEndpoint (Hono) or createCopilotEndpointExpress (Express).
import { CopilotRuntime, createCopilotEndpoint } from "@copilotkit/runtime";
import { LangGraphAgent } from "@ag-ui/langgraph";
const runtime = new CopilotRuntime({
agents: {
myAgent: new LangGraphAgent({ /* ... */ }),
},
});
const app = createCopilotEndpoint({
runtime,
basePath: "/api/copilotkit",
});2. Wrap Your App with the Provider (Client)
import { CopilotKitProvider } from "@copilotkit/react";
function App() {
return (
<CopilotKitProvider runtimeUrl="/api/copilotkit">
<YourApp />
</CopilotKitProvider>
);
}3. Add a Chat UI
Use <CopilotChat>, <CopilotPopup>, or <CopilotSidebar>:
import { CopilotChat } from "@copilotkit/react";
function ChatPage() {
return <CopilotChat agentId="myAgent" />;
}4. Register Frontend Tools
Let the agent call functions in the browser:
import { useFrontendTool } from "@copilotkit/react";
import { z } from "zod";
useFrontendTool({
name: "highlightCell",
description: "Highlight a spreadsheet cell",
parameters: z.object({ row: z.number(), col: z.number() }),
handler: async ({ row, col }) => {
highlightCell(row, col);
return "done";
},
});5. Share Application Context
Provide runtime data to the agent:
import { useAgentContext } from "@copilotkit/react";
useAgentContext({
description: "The user's current shopping cart",
value: cart, // any JSON-serializable value
});6. Handle Agent Interrupts
When an agent pauses for human input:
import { useInterrupt } from "@copilotkit/react";
useInterrupt({
render: ({ event, resolve }) => (
<div>
<p>{event.value.question}</p>
<button onClick={() => resolve({ approved: true })}>Approve</button>
</div>
),
});7. Render Tool Calls in Chat
Show custom UI when tools execute:
import { useRenderTool } from "@copilotkit/react";
import { z } from "zod";
useRenderTool({
name: "searchDocs",
parameters: z.object({ query: z.string() }),
render: ({ status, parameters, result }) => {
if (status === "executing") return <Spinner>Searching {parameters.query}...</Spinner>;
if (status === "complete") return <Results data={result} />;
return <div>Preparing...</div>;
},
}, []);Quick Reference: Hooks
| Hook | Purpose |
|---|---|
useFrontendTool | Register a tool the agent can call in the browser |
useComponent | Register a React component as a chat-rendered tool (convenience wrapper around useFrontendTool) |
useAgentContext | Share JSON-serializable application state with the agent |
useAgent | Get the AbstractAgent instance for an agent ID; subscribe to message/state/run-status changes |
useInterrupt | Handle on_interrupt events from agents with render + optional handler/filter |
useHumanInTheLoop | Register a tool that pauses execution until the user responds via a rendered UI |
useRenderTool | Register a renderer for tool calls (by name or wildcard "*") |
useDefaultRenderTool | Register a wildcard "*" renderer using the built-in expandable card UI |
useRenderToolCall | Internal hook returning a function to resolve the correct renderer for a given tool call |
useRenderActivityMessage | Internal hook for rendering activity messages by type |
useRenderCustomMessages | Internal hook for rendering custom message decorators |
useSuggestions | Read the current suggestion list and control reload/clear |
useConfigureSuggestions | Register static or dynamic (LLM-generated) suggestion configs |
useThreads | List, rename, archive, and delete Intelligence platform threads |
Quick Reference: Components
| Component | Purpose |
|---|---|
CopilotKitProvider | Root provider -- configures runtime URL, headers, agents, error handler |
CopilotChat | Full chat interface connected to an agent (inline layout) |
CopilotPopup | Chat in a floating popup with toggle button |
CopilotSidebar | Chat in a collapsible sidebar with toggle button |
CopilotChatView | Headless chat view with slots for message view, input, scroll, suggestions |
CopilotChatInput | Chat input textarea with send/stop/transcribe controls |
CopilotChatMessageView | Renders the message list |
CopilotChatSuggestionView | Renders suggestion pills |
Quick Reference: Runtime
| Export | Purpose |
|---|---|
CopilotRuntime | Auto-detecting runtime (delegates to SSE or Intelligence) |
CopilotSseRuntime | Explicit SSE-mode runtime |
CopilotIntelligenceRuntime | Intelligence-mode runtime with durable threads |
createCopilotEndpoint | Create a Hono app with all CopilotKit routes |
createCopilotEndpointExpress | Create an Express router with all CopilotKit routes |
CopilotKitIntelligence | Intelligence platform client configuration |
version: "1"
defaults:
agent: claude
provider: docker
trials: 3
timeout: 300
threshold: 0.8
docker:
base: node:20-slim
setup: |
apt-get update && apt-get install -y git jq
tasks:
- name: add-chat-interface
description: "Add a chat interface to an existing CopilotKit project"
instruction: "Add a CopilotChat component to this existing CopilotKit project. The chat should appear as a sidebar."
graders:
- type: deterministic
check: file_contains
path: "src/app/page.tsx"
pattern: "CopilotSidebar"
- type: deterministic
check: file_contains
path: "src/app/page.tsx"
pattern: "CopilotKitProvider"
- type: llm_rubric
prompt: "Is CopilotSidebar properly imported from @copilotkit/react and rendered within a CopilotKitProvider that has a runtimeUrl configured?"
- name: add-popup-chat
description: "Add a floating popup chat to a CopilotKit project"
instruction: "Add a CopilotPopup chat interface to this project. It should be open by default and have a custom header title of 'AI Assistant'."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "CopilotPopup"
- type: llm_rubric
prompt: "Does the code use CopilotPopup from @copilotkit/react with defaultOpen={true} and a custom labels prop setting modalHeaderTitle to 'AI Assistant'?"
- name: register-frontend-tool
description: "Register a frontend tool for the AI to use"
instruction: "Add a frontend tool called 'setTheme' that lets the AI change the app theme between 'light' and 'dark'. The tool should accept a 'theme' parameter validated with Zod."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useFrontendTool"
- type: deterministic
check: file_contains
path: "src/"
pattern: "setTheme"
- type: llm_rubric
prompt: "Does the code correctly use useFrontendTool with name 'setTheme', a Zod schema defining a 'theme' parameter constrained to 'light' or 'dark', a description, and a handler function?"
- name: share-agent-context
description: "Share application state with the agent using useAgentContext"
instruction: "Use useAgentContext to share the current user's profile and shopping cart data with the AI agent so it can reference them in conversation."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useAgentContext"
- type: llm_rubric
prompt: "Does the code call useAgentContext with a description and a JSON-serializable value containing user profile and cart data? Is the context properly structured so the agent understands what it represents?"
- name: handle-agent-interrupt
description: "Handle an agent interrupt with a confirmation UI"
instruction: "Add interrupt handling so when the agent triggers an interrupt, the user sees a confirmation dialog with 'Approve' and 'Reject' buttons that resolve the interrupt."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useInterrupt"
- type: llm_rubric
prompt: "Does the code use useInterrupt with a render function that displays the interrupt event, provides both Approve and Reject buttons, and calls resolve() with the user's decision?"
- name: render-tool-calls
description: "Add custom rendering for tool calls in the chat"
instruction: "Use useRenderTool to show a custom UI when the 'searchDocs' tool executes. Show a spinner during execution and formatted results on completion."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useRenderTool"
- type: deterministic
check: file_contains
path: "src/"
pattern: "searchDocs"
- type: llm_rubric
prompt: "Does the code register a renderer for 'searchDocs' using useRenderTool with a Zod parameters schema, and handle all three statuses (inProgress, executing, complete) with appropriate UI for each?"
- name: setup-runtime-nextjs
description: "Set up a CopilotKit runtime endpoint in Next.js"
instruction: "Create a Next.js API route at app/api/copilotkit/[[...path]]/route.ts that sets up a CopilotRuntime with a LangGraphAgent and exposes it via createCopilotEndpoint."
graders:
- type: deterministic
check: file_exists
path: "app/api/copilotkit/[[...path]]/route.ts"
- type: deterministic
check: file_contains
path: "app/api/copilotkit/[[...path]]/route.ts"
pattern: "CopilotRuntime"
- type: deterministic
check: file_contains
path: "app/api/copilotkit/[[...path]]/route.ts"
pattern: "createCopilotEndpoint"
- type: llm_rubric
prompt: "Does the route file create a CopilotRuntime with agents, call createCopilotEndpoint with the correct basePath, and export GET and POST handlers from app.fetch?"
- name: setup-runtime-express
description: "Set up a CopilotKit runtime with Express"
instruction: "Create an Express server that sets up a CopilotRuntime and mounts it using createCopilotEndpointExpress at /api/copilotkit."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "createCopilotEndpointExpress"
- type: deterministic
check: file_contains
path: "src/"
pattern: "CopilotRuntime"
- type: llm_rubric
prompt: "Does the code create an Express app, instantiate CopilotRuntime with agents, and mount createCopilotEndpointExpress with basePath '/api/copilotkit' using app.use()?"
- name: human-in-the-loop
description: "Add a human-in-the-loop tool for agent approval workflows"
instruction: "Register a human-in-the-loop tool called 'approveOrder' that pauses agent execution and shows the order details with approve/reject options until the user responds."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useHumanInTheLoop"
- type: deterministic
check: file_contains
path: "src/"
pattern: "approveOrder"
- type: llm_rubric
prompt: "Does the code use useHumanInTheLoop with name 'approveOrder', a parameters schema, and a render function that handles the 'executing' status with a respond callback for approve/reject?"
- name: customize-chat-labels
description: "Customize chat UI text and labels"
instruction: "Customize the CopilotChat labels to change the input placeholder to 'Ask me about your data...', the welcome message to 'Welcome! I can help analyze your data.', and the header title to 'Data Assistant'."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "labels"
- type: llm_rubric
prompt: "Does the code pass a labels prop to CopilotChat with chatInputPlaceholder, welcomeMessageText, and modalHeaderTitle set to the specified custom values?"
- name: configure-suggestions
description: "Set up AI-generated chat suggestions"
instruction: "Configure dynamic LLM-generated suggestions for the chat that suggest follow-up questions about the user's data. Show up to 3 suggestions, available after the first message."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useConfigureSuggestions"
- type: llm_rubric
prompt: "Does the code call useConfigureSuggestions with instructions, maxSuggestions set to 3, and available set to 'after-first-message'?"
- name: register-component-tool
description: "Register a React component as a visual tool in chat"
instruction: "Use useComponent to register a 'dataChart' component that the agent can invoke to display a bar chart in the chat. It should accept a title and data array as parameters."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "useComponent"
- type: deterministic
check: file_contains
path: "src/"
pattern: "dataChart"
- type: llm_rubric
prompt: "Does the code use useComponent with name 'dataChart', a parameters schema with title and data fields, and a render function that displays a chart component?"
- name: add-middleware
description: "Add request middleware to the CopilotKit runtime"
instruction: "Add beforeRequestMiddleware to the CopilotRuntime that logs incoming requests and validates an API key from the Authorization header."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "beforeRequestMiddleware"
- type: llm_rubric
prompt: "Does the code configure beforeRequestMiddleware on CopilotRuntime that accesses the request, logs the path, and checks the Authorization header for a valid API key?"
- name: error-handling
description: "Set up error handling at provider and chat levels"
instruction: "Configure error handling for CopilotKit at both the provider level (global error logging) and the chat level (showing a toast notification to the user)."
graders:
- type: deterministic
check: file_contains
path: "src/"
pattern: "onError"
- type: llm_rubric
prompt: "Does the code set onError on both CopilotKitProvider (for global error logging) and CopilotChat (for user-facing notifications), with both handlers receiving error, code, and context?"
CopilotKit v2 Public API Reference
Package imports: @copilotkit/react, @copilotkit/runtime, @copilotkit/core.
Note: @copilotkit/react re-exports everything from @ag-ui/client (which itself re-exports @ag-ui/core), so applications typically only need @copilotkit/react and @copilotkit/runtime.
---
Hooks (@copilotkit/react)
useFrontendTool
function useFrontendTool<T extends Record<string, unknown>>(
tool: ReactFrontendTool<T>,
deps?: ReadonlyArray<unknown>,
): void;Registers a tool that the agent can invoke in the browser. The tool object has these fields:
name: string-- Tool name (must be unique per agentId scope).description?: string-- Human/model-readable description.parameters?: StandardSchemaV1<any, T>-- Schema for tool arguments (Zod, Valibot, ArkType, etc.).handler?: (args: T, context: FrontendToolHandlerContext) => Promise<unknown>-- Function called when the agent invokes the tool.render?: React.ComponentType<...>-- Optional inline renderer for the tool call in chat.agentId?: string-- Constrain to a specific agent.available?: boolean-- Toggle visibility without unregistering. Defaults totrue.followUp?: boolean-- Whether the agent should follow up after tool execution.
Re-registers when tool.name, tool.available, or any value in deps changes.
---
useComponent
function useComponent<TSchema extends StandardSchemaV1 | undefined = undefined>(
config: {
name: string;
description?: string;
parameters?: TSchema;
render: ComponentType<InferRenderProps<TSchema>>;
agentId?: string;
},
deps?: ReadonlyArray<unknown>,
): void;Convenience wrapper around useFrontendTool. Registers a React component as a visual tool in chat. The model is told to use the tool to "display the component." Render props are inferred from the parameters schema.
---
useAgentContext
function useAgentContext(context: AgentContextInput): void;
interface AgentContextInput {
description: string;
value: JsonSerializable; // string | number | boolean | null | array | object
}Shares application state with the agent. The value is serialized to JSON and registered as context. Context is removed on unmount.
---
useAgent
function useAgent(props?: UseAgentProps): { agent: AbstractAgent };
interface UseAgentProps {
agentId?: string;
updates?: UseAgentUpdate[];
}
enum UseAgentUpdate {
OnMessagesChanged = "OnMessagesChanged",
OnStateChanged = "OnStateChanged",
OnRunStatusChanged = "OnRunStatusChanged",
}Returns the AbstractAgent instance for the given agentId (defaults to "default"). Subscribes to the specified update categories to trigger re-renders. By default subscribes to all three.
While the runtime is connecting, returns a provisional ProxiedCopilotRuntimeAgent to prevent crashes.
---
useInterrupt
function useInterrupt<TResult = never, TRenderInChat extends boolean | undefined = undefined>(
config: UseInterruptConfig<any, TResult, TRenderInChat>,
): React.ReactElement | null | void;
interface UseInterruptConfig<TValue, TResult, TRenderInChat> {
render: (props: InterruptRenderProps<TValue, TResult | null>) => React.ReactElement;
handler?: (props: InterruptHandlerProps<TValue>) => TResult | PromiseLike<TResult>;
enabled?: (event: InterruptEvent<TValue>) => boolean;
agentId?: string;
renderInChat?: TRenderInChat; // default: true
}
interface InterruptEvent<TValue = unknown> {
name: string;
value: TValue;
}
interface InterruptRenderProps<TValue, TResult> {
event: InterruptEvent<TValue>;
result: TResult;
resolve: (response: unknown) => void;
}Handles agent on_interrupt events. When renderInChat is true (default), the element is published into <CopilotChat> and the hook returns void. When false, it returns the element for manual placement. Call resolve() from your render to resume the agent.
---
useHumanInTheLoop
function useHumanInTheLoop<T extends Record<string, unknown>>(
tool: ReactHumanInTheLoop<T>,
deps?: ReadonlyArray<unknown>,
): void;Registers a tool that pauses agent execution until the user responds. The render component receives a respond callback during the "executing" phase. Built on top of useFrontendTool with a promise-based handler.
type ReactHumanInTheLoop<T> = Omit<FrontendTool<T>, "handler"> & {
render: React.ComponentType<
| { status: "inProgress"; args: Partial<T>; respond: undefined }
| { status: "executing"; args: T; respond: (result: unknown) => Promise<void> }
| { status: "complete"; args: T; result: string; respond: undefined }
>;
};---
useRenderTool
// Named tool renderer with typed parameters
function useRenderTool<S extends StandardSchemaV1>(
config: {
name: string;
parameters: S;
render: (props: RenderToolProps<S>) => React.ReactElement;
agentId?: string;
},
deps?: ReadonlyArray<unknown>,
): void;
// Wildcard renderer (fallback for unregistered tools)
function useRenderTool(
config: {
name: "*";
render: (props: any) => React.ReactElement;
agentId?: string;
},
deps?: ReadonlyArray<unknown>,
): void;
type RenderToolProps<S> =
| { name: string; parameters: Partial<InferSchemaOutput<S>>; status: "inProgress"; result: undefined }
| { name: string; parameters: InferSchemaOutput<S>; status: "executing"; result: undefined }
| { name: string; parameters: InferSchemaOutput<S>; status: "complete"; result: string };Registers a visual renderer for tool calls in the chat. Renderers are deduplicated by agentId:name. The renderer is intentionally NOT removed on unmount so historical tool calls can still render.
---
useDefaultRenderTool
function useDefaultRenderTool(
config?: { render?: (props: DefaultRenderProps) => React.ReactElement },
deps?: ReadonlyArray<unknown>,
): void;Registers a wildcard "*" renderer via useRenderTool. With no arguments, uses the built-in expandable card UI showing tool name, status badge, arguments, and result.
---
useSuggestions
function useSuggestions(options?: { agentId?: string }): UseSuggestionsResult;
interface UseSuggestionsResult {
suggestions: Suggestion[];
reloadSuggestions: () => void;
clearSuggestions: () => void;
isLoading: boolean;
}
type Suggestion = {
title: string;
message: string;
isLoading: boolean;
};Reads the current suggestion list for an agent. Subscribes to real-time updates.
---
useConfigureSuggestions
function useConfigureSuggestions(
config: SuggestionsConfigInput | null | undefined,
deps?: ReadonlyArray<unknown>,
): void;Registers a suggestion configuration. Two modes:
Dynamic (LLM-generated):
{
instructions: "Suggest follow-up questions about the data",
minSuggestions?: number, // default 1
maxSuggestions?: number, // default 3
available?: "before-first-message" | "after-first-message" | "always" | "disabled",
providerAgentId?: string,
consumerAgentId?: string, // default "*"
}Static:
{
suggestions: [{ title: "...", message: "..." }],
available?: SuggestionAvailability,
consumerAgentId?: string,
}---
useThreads
function useThreads(input: UseThreadsInput): UseThreadsResult;
interface UseThreadsInput {
userId: string;
agentId: string;
}
interface UseThreadsResult {
threads: Thread[];
isLoading: boolean;
error: Error | null;
renameThread: (threadId: string, name: string) => Promise<void>;
archiveThread: (threadId: string) => Promise<void>;
deleteThread: (threadId: string) => Promise<void>;
}
interface Thread {
id: string;
name?: string;
createdAt: string;
updatedAt: string;
}Lists and manages Intelligence platform threads. Uses a realtime WebSocket subscription when available.
---
useRenderToolCall (internal)
function useRenderToolCall(): (props: {
toolCall: ToolCall;
toolMessage?: ToolMessage;
}) => React.ReactElement | null;Returns a function that resolves the correct renderer for a tool call. Priority: exact name match (prefer agent-scoped) > wildcard "*".
---
useRenderActivityMessage (internal)
function useRenderActivityMessage(): {
renderActivityMessage: (message: ActivityMessage) => React.ReactElement | null;
findRenderer: (activityType: string) => ReactActivityMessageRenderer | null;
};Resolves and renders activity messages by type. Matches by activityType with agent-scoping, falls back to wildcard "*".
---
useRenderCustomMessages (internal)
Returns a function to render custom message decorators at "before" or "after" positions relative to each message.
---
Components (@copilotkit/react)
CopilotKitProvider
<CopilotKitProvider
runtimeUrl?: string
headers?: Record<string, string>
credentials?: RequestCredentials
publicApiKey?: string // alias: publicLicenseKey
properties?: Record<string, unknown>
agents__unsafe_dev_only?: Record<string, AbstractAgent>
selfManagedAgents?: Record<string, AbstractAgent>
renderToolCalls?: ReactToolCallRenderer[]
renderActivityMessages?: ReactActivityMessageRenderer[]
renderCustomMessages?: ReactCustomMessageRenderer[]
frontendTools?: ReactFrontendTool[]
humanInTheLoop?: ReactHumanInTheLoop[]
showDevConsole?: boolean | "auto"
useSingleEndpoint?: boolean
onError?: (event: { error: Error; code: CopilotKitCoreErrorCode; context: Record<string, any> }) => void
a2ui?: { theme?: A2UITheme }
>
{children}
</CopilotKitProvider>Root provider. Configures the runtime connection, registers static tool renderers and tools, and provides the CopilotKit context to all descendant hooks and components.
---
CopilotChat
<CopilotChat
agentId?: string // default: "default"
threadId?: string // auto-generated if omitted
labels?: Partial<CopilotChatLabels>
chatView?: SlotValue<typeof CopilotChatView>
onError?: (event: { error: Error; code: CopilotKitCoreErrorCode; context: Record<string, any> }) => void
// Plus all CopilotChatViewProps (messageView, input, suggestionView, welcomeScreen, etc.)
/>Full chat interface. Connects to the agent on mount, handles message submission, suggestion selection, stop, and audio transcription.
---
CopilotPopup
<CopilotPopup
// All CopilotChat props, plus:
header?: SlotValue
toggleButton?: SlotValue
defaultOpen?: boolean
width?: number | string
height?: number | string
clickOutsideToClose?: boolean
/>Chat in a floating popup with a toggle button.
---
CopilotSidebar
<CopilotSidebar
// All CopilotChat props, plus:
header?: SlotValue
toggleButton?: SlotValue
defaultOpen?: boolean
width?: number | string
/>Chat in a collapsible sidebar panel.
---
CopilotChatView
Headless chat view with a slot-based architecture. Accepts slots for messageView, scrollView, input, suggestionView, and welcomeScreen. Also exposes sub-components: CopilotChatView.ScrollView, CopilotChatView.Feather, CopilotChatView.WelcomeScreen, CopilotChatView.WelcomeMessage, CopilotChatView.ScrollToBottomButton.
---
Other Chat Sub-Components
CopilotChatInput-- Textarea with send, stop, and transcription controls.CopilotChatMessageView-- Renders the message list.CopilotChatAssistantMessage-- Single assistant message bubble.CopilotChatUserMessage-- Single user message bubble.CopilotChatReasoningMessage-- Reasoning/thinking message display.CopilotChatSuggestionView-- Renders suggestion pills.CopilotChatSuggestionPill-- Individual suggestion pill.CopilotChatToolCallsView-- Renders tool call results in a message.CopilotChatToggleButton-- Open/close toggle for popup/sidebar.CopilotModalHeader-- Header bar for popup/sidebar modals.CopilotPopupView-- Popup layout wrapper.CopilotSidebarView-- Sidebar layout wrapper.CopilotKitInspector-- Dev console overlay (controlled byshowDevConsole).MCPAppsActivityRenderer-- Built-in renderer for MCP Apps activity messages.WildcardToolCallRender-- Built-in wildcard tool call renderer component.
---
Types (@copilotkit/react)
ReactFrontendTool
type ReactFrontendTool<T> = FrontendTool<T> & {
render?: ReactToolCallRenderer<T>["render"];
};ReactToolCallRenderer
interface ReactToolCallRenderer<T> {
name: string;
args: StandardSchemaV1<any, T>;
agentId?: string;
render: React.ComponentType<
| { name: string; args: Partial<T>; status: "inProgress"; result: undefined }
| { name: string; args: T; status: "executing"; result: undefined }
| { name: string; args: T; status: "complete"; result: string }
>;
}ReactHumanInTheLoop
See useHumanInTheLoop above.
ReactActivityMessageRenderer
interface ReactActivityMessageRenderer<TActivityContent> {
activityType: string; // or "*" for wildcard
agentId?: string;
content: StandardSchemaV1<any, TActivityContent>;
render: React.ComponentType<{
activityType: string;
content: TActivityContent;
message: ActivityMessage;
agent: AbstractAgent | undefined;
}>;
}ToolCallStatus
enum ToolCallStatus {
InProgress = "inProgress",
Executing = "executing",
Complete = "complete",
}FrontendToolHandlerContext
type FrontendToolHandlerContext = {
toolCall: ToolCall;
agent: AbstractAgent;
};---
Runtime (@copilotkit/runtime)
See runtime-api.md for full runtime reference.
CopilotChat Customization Reference
CopilotChat Props
CopilotChat is the primary chat component. It wraps CopilotChatView and handles agent connection, message submission, suggestions, stop, and audio transcription.
interface CopilotChatProps {
// Agent configuration
agentId?: string; // Agent to connect to. Default: "default"
threadId?: string; // Thread ID. Auto-generated UUID if omitted.
// Labels and text customization
labels?: Partial<CopilotChatLabels>;
// Layout override
chatView?: SlotValue<typeof CopilotChatView>;
// Error handling (scoped to this chat's agent)
onError?: (event: {
error: Error;
code: CopilotKitCoreErrorCode;
context: Record<string, any>;
}) => void;
// All CopilotChatViewProps are also accepted (see below)
}CopilotChatView Props (Layout Slots)
CopilotChatView uses a slot-based architecture. Each slot can be:
- Omitted (uses the default component)
- A props object (merges with the default component)
- A custom React component (replaces the default)
interface CopilotChatViewProps {
// Slot overrides
messageView?: SlotValue<typeof CopilotChatMessageView>;
scrollView?: SlotValue<typeof CopilotChatView.ScrollView>;
input?: SlotValue<typeof CopilotChatInput>;
suggestionView?: SlotValue<typeof CopilotChatSuggestionView>;
// Welcome screen: true (default), false (disabled), or custom component
welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;
// Data (usually provided by CopilotChat, not set directly)
messages?: Message[];
isRunning?: boolean;
suggestions?: Suggestion[];
autoScroll?: boolean; // Default: true
// Input behavior (usually provided by CopilotChat)
onSubmitMessage?: (value: string) => void;
onStop?: () => void;
inputMode?: "input" | "transcribe" | "processing";
inputValue?: string;
onInputChange?: (value: string) => void;
// Transcription handlers
onStartTranscribe?: () => void;
onCancelTranscribe?: () => void;
onFinishTranscribe?: () => void;
onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;
// Standard HTML div props
className?: string;
// ...rest HTMLAttributes<HTMLDivElement>
}Labels (Text Customization)
All user-visible text can be customized via the labels prop:
const CopilotChatDefaultLabels = {
chatInputPlaceholder: "Type a message...",
chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
chatInputToolbarAddButtonLabel: "Add photos or files",
chatInputToolbarToolsButtonLabel: "Tools",
assistantMessageToolbarCopyCodeLabel: "Copy",
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
assistantMessageToolbarCopyMessageLabel: "Copy",
assistantMessageToolbarThumbsUpLabel: "Good response",
assistantMessageToolbarThumbsDownLabel: "Bad response",
assistantMessageToolbarReadAloudLabel: "Read aloud",
assistantMessageToolbarRegenerateLabel: "Regenerate",
userMessageToolbarCopyMessageLabel: "Copy",
userMessageToolbarEditMessageLabel: "Edit",
chatDisclaimerText: "AI can make mistakes. Please verify important information.",
chatToggleOpenLabel: "Open chat",
chatToggleCloseLabel: "Close chat",
modalHeaderTitle: "CopilotKit Chat",
welcomeMessageText: "How can I help you today?",
};Example:
<CopilotChat
agentId="myAgent"
labels={{
chatInputPlaceholder: "Ask me anything...",
welcomeMessageText: "Welcome! How can I assist you?",
modalHeaderTitle: "AI Assistant",
}}
/>CopilotPopup Props
interface CopilotPopupProps extends CopilotChatProps {
header?: SlotValue; // Custom header component
toggleButton?: SlotValue; // Custom toggle button
defaultOpen?: boolean; // Start open? Default: true
width?: number | string; // Popup width
height?: number | string; // Popup height
clickOutsideToClose?: boolean; // Close on outside click
}CopilotSidebar Props
interface CopilotSidebarProps extends CopilotChatProps {
header?: SlotValue; // Custom header component
toggleButton?: SlotValue; // Custom toggle button
defaultOpen?: boolean; // Start open? Default: true
width?: number | string; // Sidebar width
}Styling
CopilotKit v2 uses Tailwind CSS with a cpk: prefix namespace. All internal classes use this prefix to avoid conflicts with your application's styles.
CSS Data Attributes
The chat container exposes data attributes for CSS targeting:
[data-copilotkit]-- Present on the root chat element.[data-testid="copilot-chat"]-- The main chat container.[data-copilot-running="true"]-- While the agent is running.[data-testid="copilot-welcome-screen"]-- The welcome screen container.[data-sidebar-chat]-- On sidebar layout wrapper.[data-popup-chat]-- On popup layout wrapper.
Dark Mode
The components support dark mode through Tailwind's dark: variant. All internal components include cpk:dark: color variants. Enable dark mode by adding the dark class to a parent element per Tailwind convention.
Slot-Based Customization
Every visual sub-component is a "slot" that can be replaced or extended:
// Override the input component with custom props
<CopilotChat
input={{ className: "my-custom-input" }}
/>
// Replace the input entirely
<CopilotChat
input={MyCustomInput}
/>
// Override welcome screen
<CopilotChat
welcomeScreen={({ input, suggestionView }) => (
<div className="my-welcome">
<h1>Hello!</h1>
{input}
{suggestionView}
</div>
)}
/>
// Disable welcome screen
<CopilotChat welcomeScreen={false} />CopilotChatView Sub-Components
These can be used directly when building fully custom layouts:
CopilotChatView.ScrollView-- Scroll container with auto-scroll (usesuse-stick-to-bottom).CopilotChatView.ScrollToBottomButton-- Floating "scroll to bottom" button.CopilotChatView.Feather-- Bottom gradient overlay.CopilotChatView.WelcomeScreen-- Default welcome layout.CopilotChatView.WelcomeMessage-- Welcome heading text.
CopilotChatInput Slots
The input component has its own slots:
textArea-- The textarea element.sendButton-- Send/stop button.startTranscribeButton-- Microphone button.cancelTranscribeButton-- Cancel recording button.finishTranscribeButton-- Finish recording button.addMenuButton-- File attachment button.audioRecorder-- Audio recording component.disclaimer-- Disclaimer text below the input.
System Prompt / Agent Context
CopilotKit v2 does not have a systemPrompt prop on the chat component. Instead, context is provided to agents through:
1. `useAgentContext` -- Share structured application data. 2. Agent configuration -- System prompts are configured on the agent itself (server-side), not on the React chat component.
Error Handling
Errors can be handled at two levels:
// Provider-level: catches all errors
<CopilotKitProvider
runtimeUrl="/api/copilotkit"
onError={({ error, code, context }) => {
console.error("CopilotKit error:", code, error.message);
}}
>
{/* Chat-level: catches errors for this specific agent */}
<CopilotChat
agentId="myAgent"
onError={({ error, code }) => {
showToast(`Agent error: ${error.message}`);
}}
/>
</CopilotKitProvider>The chat-level onError fires in addition to (not instead of) the provider-level handler. It only receives errors whose context.agentId matches the chat's agent.
CopilotKit v2 Runtime API Reference
Package: @copilotkit/runtime
---
Runtime Classes
CopilotRuntime
Compatibility shim that auto-detects the mode based on whether intelligence is provided. Delegates to CopilotSseRuntime or CopilotIntelligenceRuntime.
import { CopilotRuntime } from "@copilotkit/runtime";
const runtime = new CopilotRuntime({
agents: { myAgent: new LangGraphAgent({ ... }) },
// If intelligence is provided, uses Intelligence mode; otherwise SSE mode
});CopilotSseRuntime
Explicit SSE-mode runtime. Agents run in-memory via InMemoryAgentRunner.
import { CopilotSseRuntime } from "@copilotkit/runtime";
const runtime = new CopilotSseRuntime({
agents: { myAgent: agent },
runner?: AgentRunner, // default: InMemoryAgentRunner
});CopilotIntelligenceRuntime
Intelligence-mode runtime with durable threads, realtime events, and persistent state.
import {
CopilotIntelligenceRuntime,
CopilotKitIntelligence,
} from "@copilotkit/runtime";
const runtime = new CopilotIntelligenceRuntime({
agents: { myAgent: agent },
intelligence: new CopilotKitIntelligence({ ... }),
identifyUser: async (request) => ({ id: getUserIdFromRequest(request) }),
generateThreadNames?: boolean, // default: true
});---
Runtime Options
All runtime constructors accept these base options:
interface BaseCopilotRuntimeOptions {
// Map of available agents. Can be a promise for lazy loading.
agents: MaybePromise<Record<string, AbstractAgent>>;
// Optional transcription service for audio processing
transcriptionService?: TranscriptionService;
// Middleware hooks
beforeRequestMiddleware?: BeforeRequestMiddleware;
afterRequestMiddleware?: AfterRequestMiddleware;
// Auto-apply A2UI middleware to agents
a2ui?: {
agents?: string[]; // Limit to specific agents; omit for all
// ... A2UIMiddlewareConfig from @ag-ui/a2ui-middleware
};
// Auto-apply MCP Apps middleware
mcpApps?: {
servers: McpAppsServerConfig[];
};
}McpAppsServerConfig
type McpAppsServerConfig = MCPClientConfig & {
agentId?: string; // Bind to specific agent; omit for all agents
};---
Endpoint Factories
createCopilotEndpoint (Hono)
import { createCopilotEndpoint } from "@copilotkit/runtime";
const app = createCopilotEndpoint({
runtime: CopilotRuntimeLike,
basePath: string,
cors?: {
origin: string | string[] | ((origin: string) => string | null);
credentials?: boolean;
},
});Returns a Hono app instance with all CopilotKit routes mounted under basePath.
createCopilotEndpointExpress (Express)
import { createCopilotEndpointExpress } from "@copilotkit/runtime";
const router = createCopilotEndpointExpress({
runtime: CopilotRuntimeLike,
basePath: string,
});
// Use in Express app:
app.use(router);Returns an Express Router with all CopilotKit routes mounted under basePath.
---
HTTP Routes
Both endpoint factories create these routes under basePath:
| Method | Path | Description |
|---|---|---|
GET | /info | Runtime info: available agents, mode, capabilities |
POST | /agent/:agentId/run | Run an agent (SSE stream response) |
POST | /agent/:agentId/connect | Connect to an agent (initial handshake for existing threads) |
POST | /agent/:agentId/stop/:threadId | Stop a running agent |
POST | /transcribe | Transcribe audio file |
GET | /threads | List threads (Intelligence mode) |
POST | /threads/subscribe | Subscribe to thread updates (Intelligence mode) |
PATCH | /threads/:threadId | Update thread metadata |
POST | /threads/:threadId/archive | Archive a thread |
DELETE | /threads/:threadId | Permanently delete a thread |
---
Middleware
BeforeRequestMiddleware
Called before each request handler. Can modify or replace the request.
type BeforeRequestMiddleware = (params: {
runtime: CopilotRuntimeLike;
request: Request;
path: string;
}) => MaybePromise<Request | void>;If a Request is returned, it replaces the original request for the handler.
AfterRequestMiddleware
Called after each request handler. Receives the response and parsed SSE messages.
type AfterRequestMiddleware = (params: {
runtime: CopilotRuntimeLike;
response: Response;
path: string;
messages?: Message[]; // Reconstructed from SSE stream
threadId?: string; // From RUN_STARTED event
runId?: string; // From RUN_STARTED event
}) => MaybePromise<void>;Example
const runtime = new CopilotRuntime({
agents: { myAgent: agent },
beforeRequestMiddleware: async ({ request, path }) => {
console.log(`Incoming request to ${path}`);
// Optionally return a modified Request
},
afterRequestMiddleware: async ({ response, path, threadId, messages }) => {
console.log(`Response from ${path}, thread: ${threadId}, ${messages?.length} messages`);
},
});---
Intelligence Platform
CopilotKitIntelligence
Client for the CopilotKit Intelligence platform (durable threads, realtime WebSocket).
import { CopilotKitIntelligence } from "@copilotkit/runtime";
const intelligence = new CopilotKitIntelligence({
// Configuration for the Intelligence platform
// (API keys, URLs, etc.)
});identifyUser
Required for Intelligence mode. Resolves the authenticated user from the incoming request.
type IdentifyUserCallback = (request: Request) => MaybePromise<{ id: string }>;Thread Management Types
interface CreateThreadRequest { /* platform-specific */ }
interface ThreadSummary { /* id, name, timestamps */ }
interface ListThreadsResponse { /* thread list */ }
interface UpdateThreadRequest { /* name updates */ }
interface SubscribeToThreadsRequest { /* WebSocket subscription params */ }
interface SubscribeToThreadsResponse { /* realtime thread updates */ }---
Agent Runners
AgentRunner (abstract)
Base class for executing agents. Custom runners can be implemented for custom execution environments.
InMemoryAgentRunner
Default runner for SSE mode. Runs agents in the Node.js process.
IntelligenceAgentRunner
Runner for Intelligence mode. Delegates execution to the Intelligence platform via WebSocket.
---
Transcription Service
TranscriptionService (abstract)
interface TranscribeFileOptions {
audioFile: File;
mimeType?: string;
size?: number;
}
abstract class TranscriptionService {
abstract transcribeFile(options: TranscribeFileOptions): Promise<string>;
}Implement this class to provide audio-to-text transcription. The runtime exposes it via the /transcribe endpoint.
---
CORS Configuration
The Hono endpoint factory accepts explicit CORS configuration:
createCopilotEndpoint({
runtime,
basePath: "/api/copilotkit",
cors: {
origin: "https://myapp.com", // or array, or function
credentials: true, // for HTTP-only cookies
},
});When credentials is true, origin must be explicitly specified (cannot be "*").
The Express endpoint factory uses cors({ origin: "*" }) by default. Override by wrapping or configuring the Express cors middleware separately.
---
Complete Example: Next.js API Route (using Hono)
// app/api/copilotkit/[[...path]]/route.ts
import { CopilotRuntime, createCopilotEndpoint } from "@copilotkit/runtime";
import { LangGraphAgent } from "@ag-ui/langgraph";
const runtime = new CopilotRuntime({
agents: {
researcher: new LangGraphAgent({
graphId: "researcher",
url: process.env.LANGGRAPH_URL!,
}),
},
});
const app = createCopilotEndpoint({
runtime,
basePath: "/api/copilotkit",
});
export const GET = app.fetch;
export const POST = app.fetch;
export const PATCH = app.fetch;
export const DELETE = app.fetch;Complete Example: Express
import express from "express";
import {
CopilotRuntime,
createCopilotEndpointExpress,
} from "@copilotkit/runtime";
import { LangGraphAgent } from "@ag-ui/langgraph";
const app = express();
const runtime = new CopilotRuntime({
agents: {
researcher: new LangGraphAgent({
graphId: "researcher",
url: process.env.LANGGRAPH_URL!,
}),
},
});
app.use(
createCopilotEndpointExpress({
runtime,
basePath: "/api/copilotkit",
}),
);
app.listen(3000);Sources
Files read from the CopilotKit codebase to generate this skill's references.
api-surface.md
- packages/v2/react/src/hooks/use-frontend-tool.tsx
- packages/v2/react/src/hooks/use-component.tsx
- packages/v2/react/src/hooks/use-agent-context.tsx
- packages/v2/react/src/hooks/use-agent.tsx
- packages/v2/react/src/hooks/use-interrupt.tsx
- packages/v2/react/src/hooks/use-human-in-the-loop.tsx
- packages/v2/react/src/hooks/use-render-tool.tsx
- packages/v2/react/src/hooks/use-default-render-tool.tsx
- packages/v2/react/src/hooks/use-suggestions.tsx
- packages/v2/react/src/hooks/use-configure-suggestions.tsx
- packages/v2/react/src/hooks/use-threads.tsx
- packages/v2/react/src/hooks/use-render-tool-call.tsx
- packages/v2/react/src/hooks/use-render-activity-message.tsx
- packages/v2/react/src/hooks/use-render-custom-messages.tsx
- packages/v2/react/src/providers/CopilotKitProvider.tsx
- packages/v2/react/src/components/chat/copilot-chat.tsx
- packages/v2/react/src/components/chat/copilot-popup.tsx
- packages/v2/react/src/components/chat/copilot-sidebar.tsx
- packages/v2/react/src/components/chat/copilot-chat-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-input.tsx
- packages/v2/react/src/components/chat/copilot-chat-message-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-suggestion-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-toggle-button.tsx
- packages/v2/react/src/components/chat/copilot-modal-header.tsx
- packages/v2/react/src/components/chat/copilot-popup-view.tsx
- packages/v2/react/src/components/chat/copilot-sidebar-view.tsx
- packages/v2/react/src/components/CopilotKitInspector.tsx
- packages/v2/react/src/types/frontend-tool.ts
- packages/v2/react/src/types/tool-call-renderer.ts
- packages/v2/react/src/types/activity-message-renderer.ts
- packages/v2/core/src/types/tool-call.ts
chat-customization.md
- packages/v2/react/src/components/chat/copilot-chat.tsx
- packages/v2/react/src/components/chat/copilot-chat-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-input.tsx
- packages/v2/react/src/components/chat/copilot-popup.tsx
- packages/v2/react/src/components/chat/copilot-sidebar.tsx
- packages/v2/react/src/components/chat/copilot-popup-view.tsx
- packages/v2/react/src/components/chat/copilot-sidebar-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-message-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-suggestion-view.tsx
- packages/v2/react/src/components/chat/copilot-chat-toggle-button.tsx
- packages/v2/react/src/components/chat/copilot-modal-header.tsx
- packages/v2/react/src/types/labels.ts
- packages/v2/react/src/types/slot.ts
runtime-api.md
- packages/v2/runtime/src/runtime.ts
- packages/v2/runtime/src/endpoints/hono.ts
- packages/v2/runtime/src/endpoints/express.ts
- packages/v2/runtime/src/types/runtime-options.ts
- packages/v2/runtime/src/types/middleware.ts
- packages/v2/runtime/src/runner/agent-runner.ts
- packages/v2/runtime/src/runner/in-memory.ts
- packages/v2/runtime/src/runner/intelligence.ts
- packages/v2/runtime/src/intelligence-platform/client.ts
- packages/v2/runtime/src/transcription/transcription-service.ts
Related skills
How it compares
Pick copilotkit-develop over copilotkit-integrations when building CopilotKit UI and runtime features rather than wiring external agent frameworks.
FAQ
What stack does copilotkit-develop cover?
copilotkit-develop covers CopilotKit v2 on AG-UI with @copilotkit/runtime server endpoints, @copilotkit/react providers, chat components, and hooks like useFrontendTool and useAgentContext.
Which hooks does copilotkit-develop document?
copilotkit-develop documents 14 React hooks—including useFrontendTool, useAgentContext, useInterrupt, useHumanInTheLoop, useRenderTool, and useThreads—for CopilotKit v2 agent UIs.