chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
---
|
||||
name: copilotkit-develop
|
||||
description: "Use when building AI-powered features with CopilotKit v2 -- adding chat interfaces, registering frontend tools, sharing application context with agents, handling agent interrupts, and working with the CopilotKit runtime."
|
||||
version: 1.0.0
|
||||
---
|
||||
|
||||
# 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](../copilotkit-debug/SKILL.md#mcp-setup) 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`, v2 symbols under `@copilotkit/runtime/v2`) -- 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-core`, v2 symbols under `@copilotkit/react-core/v2`) -- 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 `createCopilotHonoHandler` (Hono) or `createCopilotExpressHandler` (Express).
|
||||
|
||||
```ts
|
||||
import {
|
||||
CopilotRuntime,
|
||||
createCopilotHonoHandler,
|
||||
} from "@copilotkit/runtime/v2";
|
||||
import { LangGraphAgent } from "@copilotkit/runtime/langgraph";
|
||||
import { handle } from "hono/vercel";
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: {
|
||||
myAgent: new LangGraphAgent({
|
||||
/* ... */
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const app = createCopilotHonoHandler({
|
||||
runtime,
|
||||
basePath: "/api/copilotkit",
|
||||
});
|
||||
|
||||
// Multi-route (the default): export every method the runtime serves.
|
||||
// useThreads needs them all — rename via PATCH, delete via DELETE; archive
|
||||
// uses the already-exported POST.
|
||||
export const GET = handle(app);
|
||||
export const POST = handle(app);
|
||||
export const PATCH = handle(app);
|
||||
export const DELETE = handle(app);
|
||||
```
|
||||
|
||||
### 2. Wrap Your App with the Provider (Client)
|
||||
|
||||
Use the `CopilotKit` provider (from `@copilotkit/react-core/v2`). It is the compatibility bridge across v1 and v2 and a strict superset of the legacy `CopilotKitProvider` -- all `CopilotKitProvider` props work on it.
|
||||
|
||||
```tsx
|
||||
import { CopilotKit } from "@copilotkit/react-core/v2";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
// useSingleEndpoint={false} matches the multi-route backend above. The
|
||||
// v1-compat CopilotKit bridge defaults it to true (single transport),
|
||||
// which would 404 against a multi-route handler.
|
||||
<CopilotKit runtimeUrl="/api/copilotkit" useSingleEndpoint={false}>
|
||||
<YourApp />
|
||||
</CopilotKit>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Add a Chat UI
|
||||
|
||||
Use `<CopilotChat>`, `<CopilotPopup>`, or `<CopilotSidebar>`:
|
||||
|
||||
```tsx
|
||||
import { CopilotChat } from "@copilotkit/react-core/v2";
|
||||
|
||||
function ChatPage() {
|
||||
return <CopilotChat agentId="myAgent" />;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Register Frontend Tools
|
||||
|
||||
Let the agent call functions in the browser:
|
||||
|
||||
```tsx
|
||||
import { useFrontendTool } from "@copilotkit/react-core/v2";
|
||||
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:
|
||||
|
||||
```tsx
|
||||
import { useAgentContext } from "@copilotkit/react-core/v2";
|
||||
|
||||
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:
|
||||
|
||||
```tsx
|
||||
import { useInterrupt } from "@copilotkit/react-core/v2";
|
||||
|
||||
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:
|
||||
|
||||
```tsx
|
||||
import { useRenderTool } from "@copilotkit/react-core/v2";
|
||||
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/`enabled` predicate |
|
||||
| `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 |
|
||||
| --------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| `CopilotKit` | Root provider (from `@copilotkit/react-core/v2`) -- 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
|
||||
|
||||
All v2 runtime symbols import from `@copilotkit/runtime/v2` (`createCopilotExpressHandler` from `@copilotkit/runtime/v2/express`).
|
||||
|
||||
| Export | Purpose |
|
||||
| ----------------------------- | --------------------------------------------------------- |
|
||||
| `CopilotRuntime` | Auto-detecting runtime (delegates to SSE or Intelligence) |
|
||||
| `CopilotSseRuntime` | Explicit SSE-mode runtime |
|
||||
| `CopilotIntelligenceRuntime` | Intelligence-mode runtime with durable threads |
|
||||
| `createCopilotHonoHandler` | Create a Hono app with all CopilotKit routes |
|
||||
| `createCopilotExpressHandler` | Create an Express router with all CopilotKit routes |
|
||||
| `CopilotKitIntelligence` | Intelligence platform client configuration |
|
||||
@@ -0,0 +1,199 @@
|
||||
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"
|
||||
# Matches <CopilotKit and legacy <CopilotKitProvider
|
||||
pattern: "<CopilotKit"
|
||||
- type: llm_rubric
|
||||
prompt: "Is CopilotSidebar properly imported and rendered within the CopilotKit provider (the `CopilotKit` component from @copilotkit/react-core/v2; the legacy `CopilotKitProvider` is also acceptable) 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 the CopilotKit provider (the `CopilotKit` component from @copilotkit/react-core/v2, or the legacy `CopilotKitProvider`) for global error logging and CopilotChat for user-facing notifications, with both handlers receiving error, code, and context?"
|
||||
@@ -0,0 +1,533 @@
|
||||
# CopilotKit v2 Public API Reference
|
||||
|
||||
Package imports: `@copilotkit/react-core/v2`, `@copilotkit/runtime/v2`, `@copilotkit/core`.
|
||||
|
||||
Note: `@copilotkit/react-core/v2` re-exports everything from `@ag-ui/client` (which itself re-exports `@ag-ui/core`), so applications typically only need `@copilotkit/react-core/v2` and `@copilotkit/runtime/v2`.
|
||||
|
||||
---
|
||||
|
||||
## Hooks (`@copilotkit/react-core/v2`)
|
||||
|
||||
### useFrontendTool
|
||||
|
||||
```ts
|
||||
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 to `true`.
|
||||
- `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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
// 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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
function useConfigureSuggestions(
|
||||
config: SuggestionsConfigInput | null | undefined,
|
||||
deps?: ReadonlyArray<unknown>,
|
||||
): void;
|
||||
```
|
||||
|
||||
Registers a suggestion configuration. Two modes:
|
||||
|
||||
**Dynamic** (LLM-generated):
|
||||
|
||||
```ts
|
||||
{
|
||||
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**:
|
||||
|
||||
```ts
|
||||
{
|
||||
suggestions: [{ title: "...", message: "..." }],
|
||||
available?: SuggestionAvailability,
|
||||
consumerAgentId?: string,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### useThreads
|
||||
|
||||
```ts
|
||||
function useThreads(input: UseThreadsInput): UseThreadsResult;
|
||||
|
||||
interface UseThreadsInput {
|
||||
agentId: string;
|
||||
includeArchived?: boolean; // default: false
|
||||
limit?: number; // enables cursor-based pagination when set
|
||||
}
|
||||
|
||||
interface UseThreadsResult {
|
||||
threads: Thread[];
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
hasMoreThreads: boolean;
|
||||
isFetchingMoreThreads: boolean;
|
||||
fetchMoreThreads: () => void;
|
||||
renameThread: (threadId: string, name: string) => Promise<void>;
|
||||
archiveThread: (threadId: string) => Promise<void>;
|
||||
deleteThread: (threadId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
interface Thread {
|
||||
id: string;
|
||||
agentId: string;
|
||||
name: string | null;
|
||||
archived: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
lastRunAt?: string; // last agent run; prefer over updatedAt for "last activity"
|
||||
}
|
||||
```
|
||||
|
||||
Lists and manages Intelligence platform threads. Thread operations are scoped to the runtime-authenticated user (no `userId` input) and the given `agentId`. Uses a realtime WebSocket subscription when available.
|
||||
|
||||
---
|
||||
|
||||
### useRenderToolCall (internal)
|
||||
|
||||
```ts
|
||||
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)
|
||||
|
||||
```ts
|
||||
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-core/v2`)
|
||||
|
||||
### CopilotKit (provider)
|
||||
|
||||
Import from `@copilotkit/react-core/v2`. The recommended root provider -- a compatibility bridge across v1 and v2 and a strict superset of the legacy `CopilotKitProvider` (all props below work on it).
|
||||
|
||||
```tsx
|
||||
<CopilotKit
|
||||
runtimeUrl?: string
|
||||
headers?: Record<string, string>
|
||||
credentials?: RequestCredentials
|
||||
publicLicenseKey?: string // deprecated alias: publicApiKey
|
||||
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}
|
||||
</CopilotKit>
|
||||
```
|
||||
|
||||
Root provider. Configures the runtime connection, registers static tool renderers and tools, and provides the CopilotKit context to all descendant hooks and components.
|
||||
|
||||
---
|
||||
|
||||
### CopilotChat
|
||||
|
||||
```tsx
|
||||
<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
|
||||
|
||||
```tsx
|
||||
<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
|
||||
|
||||
```tsx
|
||||
<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 by `showDevConsole`).
|
||||
- `MCPAppsActivityRenderer` -- Built-in renderer for MCP Apps activity messages.
|
||||
- `WildcardToolCallRender` -- Built-in wildcard tool call renderer component.
|
||||
|
||||
---
|
||||
|
||||
## Types (`@copilotkit/react-core/v2`)
|
||||
|
||||
### ReactFrontendTool
|
||||
|
||||
```ts
|
||||
type ReactFrontendTool<T> = FrontendTool<T> & {
|
||||
render?: ReactToolCallRenderer<T>["render"];
|
||||
};
|
||||
```
|
||||
|
||||
### ReactToolCallRenderer
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
enum ToolCallStatus {
|
||||
InProgress = "inProgress",
|
||||
Executing = "executing",
|
||||
Complete = "complete",
|
||||
}
|
||||
```
|
||||
|
||||
### FrontendToolHandlerContext
|
||||
|
||||
```ts
|
||||
type FrontendToolHandlerContext = {
|
||||
toolCall: ToolCall;
|
||||
agent: AbstractAgent;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Runtime (`@copilotkit/runtime/v2`)
|
||||
|
||||
See [runtime-api.md](./runtime-api.md) for full runtime reference.
|
||||
@@ -0,0 +1,242 @@
|
||||
# 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.
|
||||
|
||||
```tsx
|
||||
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)
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
<CopilotChat
|
||||
agentId="myAgent"
|
||||
labels={{
|
||||
chatInputPlaceholder: "Ask me anything...",
|
||||
welcomeMessageText: "Welcome! How can I assist you?",
|
||||
modalHeaderTitle: "AI Assistant",
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## CopilotPopup Props
|
||||
|
||||
```tsx
|
||||
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
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
// 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 (uses `use-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:
|
||||
|
||||
```tsx
|
||||
// Provider-level: catches all errors
|
||||
<CopilotKit
|
||||
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}`);
|
||||
}}
|
||||
/>
|
||||
</CopilotKit>
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,370 @@
|
||||
# CopilotKit v2 Runtime API Reference
|
||||
|
||||
Package: `@copilotkit/runtime/v2` (`createCopilotExpressHandler` from `@copilotkit/runtime/v2/express`)
|
||||
|
||||
---
|
||||
|
||||
## Runtime Classes
|
||||
|
||||
### CopilotRuntime
|
||||
|
||||
Compatibility shim that auto-detects the mode based on whether `intelligence` is provided. Delegates to `CopilotSseRuntime` or `CopilotIntelligenceRuntime`.
|
||||
|
||||
```ts
|
||||
import { CopilotRuntime } from "@copilotkit/runtime/v2";
|
||||
|
||||
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`.
|
||||
|
||||
```ts
|
||||
import { CopilotSseRuntime } from "@copilotkit/runtime/v2";
|
||||
|
||||
const runtime = new CopilotSseRuntime({
|
||||
agents: { myAgent: agent },
|
||||
runner?: AgentRunner, // default: InMemoryAgentRunner
|
||||
});
|
||||
```
|
||||
|
||||
### CopilotIntelligenceRuntime
|
||||
|
||||
Intelligence-mode runtime with durable threads, realtime events, and persistent state.
|
||||
|
||||
```ts
|
||||
import {
|
||||
CopilotIntelligenceRuntime,
|
||||
CopilotKitIntelligence,
|
||||
} from "@copilotkit/runtime/v2";
|
||||
|
||||
const runtime = new CopilotIntelligenceRuntime({
|
||||
agents: { myAgent: agent },
|
||||
intelligence: new CopilotKitIntelligence({ ... }),
|
||||
identifyUser: async (request) => ({
|
||||
id: getUserIdFromRequest(request),
|
||||
name: getUserNameFromRequest(request),
|
||||
}),
|
||||
generateThreadNames?: boolean, // default: true
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Runtime Options
|
||||
|
||||
All runtime constructors accept these base options:
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
type McpAppsServerConfig = MCPClientConfig & {
|
||||
agentId?: string; // Bind to specific agent; omit for all agents
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoint Factories
|
||||
|
||||
### createCopilotHonoHandler (Hono)
|
||||
|
||||
```ts
|
||||
import { createCopilotHonoHandler } from "@copilotkit/runtime/v2";
|
||||
|
||||
const app = createCopilotHonoHandler({
|
||||
runtime: CopilotRuntimeLike,
|
||||
basePath: string,
|
||||
mode?: "multi-route" | "single-route", // default: "multi-route"
|
||||
cors?: {
|
||||
origin: string | string[] | ((origin: string) => string | null);
|
||||
credentials?: boolean;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Returns a Hono app instance with all CopilotKit routes mounted under `basePath`. Defaults to multi-route mode; pass `mode: "single-route"` to expose a single combined route.
|
||||
|
||||
### createCopilotExpressHandler (Express)
|
||||
|
||||
```ts
|
||||
import { createCopilotExpressHandler } from "@copilotkit/runtime/v2/express";
|
||||
|
||||
const router = createCopilotExpressHandler({
|
||||
runtime: CopilotRuntimeLike,
|
||||
basePath: string,
|
||||
mode?: "multi-route" | "single-route", // default: "multi-route"
|
||||
});
|
||||
|
||||
// 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.
|
||||
|
||||
```ts
|
||||
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.
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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).
|
||||
|
||||
```ts
|
||||
import { CopilotKitIntelligence } from "@copilotkit/runtime/v2";
|
||||
|
||||
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.
|
||||
|
||||
```ts
|
||||
type IdentifyUserCallback = (
|
||||
request: Request,
|
||||
) => MaybePromise<{ id: string; name: string }>;
|
||||
```
|
||||
|
||||
### Thread Management Types
|
||||
|
||||
```ts
|
||||
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)
|
||||
|
||||
```ts
|
||||
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:
|
||||
|
||||
```ts
|
||||
createCopilotHonoHandler({
|
||||
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)
|
||||
|
||||
```ts
|
||||
// app/api/copilotkit/[[...path]]/route.ts
|
||||
import {
|
||||
CopilotRuntime,
|
||||
createCopilotHonoHandler,
|
||||
} from "@copilotkit/runtime/v2";
|
||||
import { LangGraphAgent } from "@copilotkit/runtime/langgraph";
|
||||
import { handle } from "hono/vercel";
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: {
|
||||
researcher: new LangGraphAgent({
|
||||
graphId: "researcher",
|
||||
deploymentUrl: process.env.LANGGRAPH_URL!,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const app = createCopilotHonoHandler({
|
||||
runtime,
|
||||
basePath: "/api/copilotkit",
|
||||
});
|
||||
|
||||
export const GET = handle(app);
|
||||
export const POST = handle(app);
|
||||
export const PATCH = handle(app);
|
||||
export const DELETE = handle(app);
|
||||
```
|
||||
|
||||
## Complete Example: Express
|
||||
|
||||
```ts
|
||||
import express from "express";
|
||||
import { CopilotRuntime } from "@copilotkit/runtime/v2";
|
||||
import { createCopilotExpressHandler } from "@copilotkit/runtime/v2/express";
|
||||
import { LangGraphAgent } from "@copilotkit/runtime/langgraph";
|
||||
|
||||
const app = express();
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: {
|
||||
researcher: new LangGraphAgent({
|
||||
graphId: "researcher",
|
||||
deploymentUrl: process.env.LANGGRAPH_URL!,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
app.use(
|
||||
createCopilotExpressHandler({
|
||||
runtime,
|
||||
basePath: "/api/copilotkit",
|
||||
}),
|
||||
);
|
||||
|
||||
app.listen(3000);
|
||||
```
|
||||
@@ -0,0 +1,66 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user