Files
2026-07-13 12:58:18 +08:00

16 KiB

CopilotKit v2 Breaking Changes

Package Structure

Consolidated React packages

v1 split React functionality across three packages:

  • @copilotkit/react-core -- provider, hooks, types
  • @copilotkit/react-ui -- chat components (CopilotChat, CopilotPopup, CopilotSidebar)
  • @copilotkit/react-textarea -- CopilotTextarea component

v2 consolidates the React surface under the /v2 subpath of the same @copilotkit/react-core package (there is no @copilotkit/react package):

  • @copilotkit/react-core/v2 -- provider, hooks, types, chat components, and AG-UI re-exports (@copilotkit/react-core/v2/styles.css for styles)

Same package names, new subpath

The v2 API is exposed through the same @copilotkit/* packages -- no package name changes are required when upgrading. The v2 symbols live under the /v2 subpath (@copilotkit/react-core/v2, @copilotkit/runtime/v2, @copilotkit/runtime/v2/express).

Removed packages

Package Status
@copilotkit/react-textarea No v2 equivalent. The v1 package stays installable; remove it only after migrating off CopilotTextarea.
@copilotkit/runtime-client-gql Replaced by @ag-ui/client (re-exported from @copilotkit/react-core/v2)
@copilotkit/sdk-js Removed. BuiltInAgent and agent definitions ship from @copilotkit/runtime/v2

Protocol Change: GraphQL to AG-UI

The most fundamental breaking change is the protocol layer. v1 used a GraphQL-based protocol (@copilotkit/runtime-client-gql). v2 uses the AG-UI protocol (@ag-ui/client / @ag-ui/core), which is SSE-based.

Impact:

  • All GraphQL message types (TextMessage, ActionExecutionMessage, ResultMessage, etc.) are replaced by AG-UI event types (TextMessageChunkEvent, ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolCallResultEvent, etc.)
  • The MessageRole enum is replaced by AG-UI message roles
  • Custom GraphQL queries/mutations against the runtime are no longer possible
  • The runtime no longer exposes a GraphQL endpoint

Provider Changes

Component import path change

The provider keeps the name CopilotKit; the import path changes from the package root (@copilotkit/react-core, legacy v1) to the /v2 subpath (@copilotkit/react-core/v2). The /v2 subpath also exports a CopilotKitProvider component -- do not migrate to it. It is a functionality subset of CopilotKit, which is the compatibility bridge across v1 and v2 (its CopilotKitProps extends Omit<CopilotKitProviderProps, "children"> with a narrowed children type, so every non-children CopilotKitProvider prop works on it).

Props changes

v1 Prop v2 Status Notes
runtimeUrl Kept Same behavior
headers Kept Same behavior
publicApiKey Kept (deprecated) publicLicenseKey is the canonical name
properties Kept Same behavior
agents Removed Use selfManagedAgents or agents__unsafe_dev_only
guardrails_c Kept (CopilotCloud only) Marked @internal/defunct in source, but still wired into the legacy CopilotCloud restrictToTopic config when a cloud key (publicApiKey) is set; has no effect on the v2 AG-UI runtime path
children Kept Same behavior
-- Added: credentials RequestCredentials for fetch (e.g., "include" for cookies)
-- Added: selfManagedAgents Record<string, AbstractAgent> for client-side agents
-- Added: renderToolCalls ReactToolCallRenderer[] for provider-level tool renderers
-- Added: renderActivityMessages ReactActivityMessageRenderer[] for activity renderers
-- Added: useSingleEndpoint Boolean to use single-route endpoint mode

Context hook rename

useCopilotContext is replaced by useCopilotKit (imported from @copilotkit/react-core/v2/context), which returns { copilotkit: CopilotKitCoreReact, executingToolCallIds: ReadonlySet<string> }.


Hook Renames and API Changes

useCopilotAction -> useFrontendTool

Parameter definition change: v1 used a custom parameter descriptor format. v2 uses Zod schemas.

// v1 parameters
parameters: [
  { name: "city", type: "string", description: "City name", required: true },
  { name: "units", type: "string", enum: ["celsius", "fahrenheit"] },
];

// v2 parameters (Zod)
parameters: z.object({
  city: z.string().describe("City name"),
  units: z.enum(["celsius", "fahrenheit"]).optional(),
});

Handler signature change:

// v1
handler: ({ city, units }) => { ... }

// v2
handler: async (args) => { ... }  // args is typed from the Zod schema

Render props change:

// v1 render status: the string literals "inProgress" | "executing" | "complete"
// v1 uses `respond()` callback for interactive actions

// v2 render status: the `ToolCallStatus` enum (ToolCallStatus.InProgress | .Executing | .Complete).
// Its values ARE those same strings, so `status === "inProgress"` still works;
// prefer comparing against the enum members.
// v2 render props: { name, toolCallId, args, status, result }

Availability change:

// v1
disabled: true;

// v2 — `available` is a boolean (defaults to true; set false to hide the tool)
available: false;

useCopilotReadable -> useAgentContext

Breaking: The parentId parameter for hierarchical context is removed. Flatten nested contexts.

// v1 (hierarchical)
const parentId = useCopilotReadable({ description: "Parent", value: "..." });
useCopilotReadable({ description: "Child", value: "...", parentId });

// v2 (flat)
useAgentContext({
  description: "Parent - Child context",
  value: { parent: "...", child: "..." },
});

useCoAgent -> useAgent

Breaking: Completely different return type.

// v1 returns
{
  (name, nodeName, state, setState, running, start, stop, run);
}

// v2 returns
AbstractAgent; // AG-UI agent instance with run(), stop(), etc.
  • name -> agentId (in props)
  • initialState -> removed (no client-side state initialization)
  • setState -> removed (state flows via AG-UI events)
  • nodeName -> removed
  • state -> accessed through AG-UI StateSnapshotEvent / StateDeltaEvent

useLangGraphInterrupt -> useInterrupt

Breaking: Different API shape.

  • agentName -> agentId
  • nodeName -> removed (use enabled predicate to filter)
  • render props change: v2 receives InterruptRenderProps<TValue, TResult> = { event, resolve, result } (still includes event/resolve, adds result)
  • New renderInChat prop (default true) controls whether interrupt renders inside CopilotChat
  • New handler prop for programmatic handling before rendering
  • New enabled predicate prop for filtering interrupts

useCopilotChat -> removed

Replaced by useAgent for agent interaction. The headless chat API (appendMessage, visibleMessages, etc.) is replaced by the AG-UI agent event stream.

useCopilotChatSuggestions -> useConfigureSuggestions + useSuggestions

Split into two hooks: one for configuration, one for reading state.

useCoAgentStateRender -> useRenderToolCall / useRenderActivityMessage

Split into two hooks based on the type of rendering needed.

useCopilotAdditionalInstructions -> useAgentContext

Use useAgentContext with an appropriate description to provide instructions.

useMakeCopilotDocumentReadable -> useAgentContext

Use useAgentContext to pass document content. The DocumentPointer type and category-based filtering are removed.


Runtime Breaking Changes

Service adapters removed

All service adapters are removed from the runtime:

Removed Adapter v2 Alternative
OpenAIAdapter Use BuiltInAgent({ model: "openai/gpt-4o" })
AnthropicAdapter Use BuiltInAgent({ model: "anthropic/claude-sonnet-4.5" })
GoogleGenerativeAIAdapter Use BuiltInAgent({ model: "google/gemini-2.5-pro" })
LangChainAdapter Use a custom AbstractAgent implementation
GroqAdapter Use a custom AbstractAgent (pass a Groq LanguageModel instance)
UnifyAdapter Use a custom AbstractAgent implementation
OpenAIAssistantAdapter Use a custom AbstractAgent implementation
BedrockAdapter Use a custom AbstractAgent implementation
OllamaAdapter Use a custom AbstractAgent implementation
EmptyAdapter Not needed

Runtime constructor changes

// v1
new CopilotRuntime({
  actions: [...],                    // Removed
  remoteEndpoints: [...],            // Removed
  remoteActions: [...],              // Removed
  onBeforeRequest: (options) => {},  // Deprecated
  onAfterRequest: (options) => {},   // Deprecated
})

// v2
new CopilotRuntime({
  agents: { ... },                         // Required: Record<string, AbstractAgent>
  transcriptionService: ...,               // Optional: TranscriptionService
  beforeRequestMiddleware: ...,            // Optional: BeforeRequestMiddleware
  afterRequestMiddleware: ...,             // Optional: AfterRequestMiddleware
  a2ui: { ... },                           // Optional: A2UIMiddleware config
  mcpApps: { servers: [...] },             // Optional: MCP Apps middleware
  // Intelligence mode only:
  intelligence: new CopilotKitIntelligence({ ... }),
  identifyUser: (request) => ({ id: "..." }),
  generateThreadNames: true,
})

Framework integrations removed

v1 had built-in integrations for Next.js (App Router, Pages Router), Express, NestJS, and Node HTTP. v2 uses Hono as the standard HTTP layer:

v1 Integration v2 Replacement
copilotRuntimeNextJSAppRouterEndpoint createCopilotHonoHandler (Hono, works with Next.js)
copilotRuntimeNextJSPagesRouterEndpoint createCopilotHonoHandler (Hono)
CopilotRuntimeNodeExpressEndpoint createCopilotExpressHandler (@copilotkit/runtime/v2/express)
CopilotRuntimeNestEndpoint Use Hono adapter or Express endpoint
CopilotRuntimeNodeHttpEndpoint Use Hono or Express endpoint

Endpoint configuration

// v1 (Next.js App Router example)
import { copilotRuntimeNextJSAppRouterEndpoint } from "@copilotkit/runtime";

export const POST = copilotRuntimeNextJSAppRouterEndpoint({
  runtime,
  serviceAdapter,
  endpoint: "/api/copilotkit",
});

// v2 -- use createCopilotHonoHandler (createCopilotEndpoint is a deprecated alias)
import { createCopilotHonoHandler } from "@copilotkit/runtime/v2";

const app = createCopilotHonoHandler({
  runtime,
  basePath: "/api/copilotkit",
  cors: {
    origin: "https://myapp.com",
    credentials: true,
  },
});

// For Next.js App Router, export the Hono app's fetch handler
export const POST = app.fetch;
export const GET = app.fetch;

LangGraph agent configuration

// v1 (remote endpoint)
new CopilotRuntime({
  remoteEndpoints: [
    {
      url: "http://localhost:8000/copilotkit",
      type: "langgraph",
    },
  ],
});

// v2 (direct agent instance)
import { LangGraphAgent } from "@copilotkit/runtime/langgraph";

new CopilotRuntime({
  agents: {
    myAgent: new LangGraphAgent({
      deploymentUrl: "http://localhost:8000",
      graphId: "my-graph",
    }),
  },
});

Type System Changes

Parameter types

v1 used a custom Parameter type for defining tool parameters:

type Parameter = {
  name: string;
  type:
    | "string"
    | "number"
    | "boolean"
    | "object"
    | "string[]"
    | "number[]"
    | "boolean[]"
    | "object[]";
  description?: string;
  required?: boolean;
  enum?: string[];
  attributes?: Parameter[]; // for object types
};

v2 uses Zod schemas (z.object(...)) or Standard Schema V1 (StandardSchemaV1).

Message types

v1 GraphQL types from @copilotkit/runtime-client-gql are replaced by AG-UI types:

v1 Type v2 Type
TextMessage Message with text content
ActionExecutionMessage ToolCall
ResultMessage ToolMessage
MessageRole AG-UI role types

Event types

v2 introduces AG-UI event types for streaming:

  • RunStartedEvent, RunFinishedEvent, RunErrorEvent
  • TextMessageChunkEvent
  • ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolCallResultEvent
  • StateSnapshotEvent, StateDeltaEvent
  • ReasoningStartEvent, ReasoningMessageStartEvent, ReasoningMessageContentEvent, ReasoningMessageEndEvent, ReasoningEndEvent