Back to Copilotkit

CopilotKit v2 Breaking Changes

skills/copilotkit-upgrade/references/breaking-changes.md

1.62.115.7 KB
Original Source

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

PackageStatus
@copilotkit/react-textareaNo v2 equivalent. The v1 package stays installable; remove it only after migrating off CopilotTextarea.
@copilotkit/runtime-client-gqlReplaced by @ag-ui/client (re-exported from @copilotkit/react-core/v2)
@copilotkit/sdk-jsRemoved. 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 Propv2 StatusNotes
runtimeUrlKeptSame behavior
headersKeptSame behavior
publicApiKeyKept (deprecated)publicLicenseKey is the canonical name
propertiesKeptSame behavior
agentsRemovedUse selfManagedAgents or agents__unsafe_dev_only
guardrails_cKept (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
childrenKeptSame behavior
--Added: credentialsRequestCredentials for fetch (e.g., "include" for cookies)
--Added: selfManagedAgentsRecord<string, AbstractAgent> for client-side agents
--Added: renderToolCallsReactToolCallRenderer[] for provider-level tool renderers
--Added: renderActivityMessagesReactActivityMessageRenderer[] for activity renderers
--Added: useSingleEndpointBoolean 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.

ts
// 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:

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

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

Render props change:

ts
// 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:

ts
// 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.

ts
// 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.

ts
// 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 Adapterv2 Alternative
OpenAIAdapterUse BuiltInAgent({ model: "openai/gpt-4o" })
AnthropicAdapterUse BuiltInAgent({ model: "anthropic/claude-sonnet-4.5" })
GoogleGenerativeAIAdapterUse BuiltInAgent({ model: "google/gemini-2.5-pro" })
LangChainAdapterUse a custom AbstractAgent implementation
GroqAdapterUse a custom AbstractAgent (pass a Groq LanguageModel instance)
UnifyAdapterUse a custom AbstractAgent implementation
OpenAIAssistantAdapterUse a custom AbstractAgent implementation
BedrockAdapterUse a custom AbstractAgent implementation
OllamaAdapterUse a custom AbstractAgent implementation
EmptyAdapterNot needed

Runtime constructor changes

ts
// 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 Integrationv2 Replacement
copilotRuntimeNextJSAppRouterEndpointcreateCopilotHonoHandler (Hono, works with Next.js)
copilotRuntimeNextJSPagesRouterEndpointcreateCopilotHonoHandler (Hono)
CopilotRuntimeNodeExpressEndpointcreateCopilotExpressHandler (@copilotkit/runtime/v2/express)
CopilotRuntimeNestEndpointUse Hono adapter or Express endpoint
CopilotRuntimeNodeHttpEndpointUse Hono or Express endpoint

Endpoint configuration

ts
// 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

ts
// 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:

ts
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 Typev2 Type
TextMessageMessage with text content
ActionExecutionMessageToolCall
ResultMessageToolMessage
MessageRoleAG-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