Assistant-UI vs CopilotKit: how hard is it to migrate an existing in-app assistant UI without rewriting my backend?
AI Chat UI Toolkits

Assistant-UI vs CopilotKit: how hard is it to migrate an existing in-app assistant UI without rewriting my backend?

10 min read

Most teams considering a switch from CopilotKit to Assistant-UI already have an in-app assistant wired to a working backend. The core question isn’t “which framework is better?” but “how hard is it to migrate my UI without ripping out everything under the hood?” The short answer: if your backend already exposes a reasonably clean chat or agent interface, migrating to Assistant-UI is mostly a front-end integration exercise—not a backend rewrite.

This guide walks through what migration actually looks like, where Assistant-UI and CopilotKit differ, and how to keep your backend intact while upgrading the chat experience.


What you’re really migrating: UI layer vs agent logic

Before comparing Assistant-UI vs CopilotKit from a migration angle, it helps to separate concerns:

  • UI layer:

    • Chat window, message bubbles, streaming output
    • Input box, suggestions, tool call rendering
    • Thread management and message history
  • Agent / backend layer:

    • Orchestration (LangChain, LangGraph, Vercel AI SDK, custom stack)
    • Tools, function calling, RAG pipelines, business logic
    • Authentication, rate limits, logging, analytics

Assistant-UI is explicitly focused on the UI layer. It’s a React/TypeScript library that:

  • Renders a ChatGPT-like chat interface
  • Streams responses
  • Integrates nicely with LangGraph, LangChain, Vercel AI SDK, or any LLM provider
  • Can store threads in Assistant UI Cloud so sessions persist across refreshes

Because Assistant-UI is backend-agnostic, you can typically keep:

  • Your existing routes (e.g., /api/chat, /api/tools, /api/assistant)
  • Your agent logic
  • Your model providers and observability stack

You mainly swap out the frontend components and wire them to your existing endpoints.


Assistant-UI vs CopilotKit: migration mindset

CopilotKit tends to be used as a full “copilot” solution where the UI and logic are often tightly integrated with its abstractions (particularly for in-doc copilots or app-specific actions). Migrating from CopilotKit to Assistant-UI usually falls into one of three patterns:

  1. Chat-only assistants (easiest migration)

    • You already have a single chat endpoint that expects: messages → returns: streamed response.
    • Migration effort: mostly replacing UI components and mapping your HTTP or WebSocket handler to Assistant-UI’s expectations.
  2. Chat + tools / actions (moderate effort)

    • Your CopilotKit setup uses actions, tools, or context integration.
    • Migration effort: keep your tool/agent logic; expose them behind a stable API that Assistant-UI talks to (or adopt LangGraph / LangChain patterns you may already use).
  3. Deeply embedded copilots tightly coupled to CopilotKit (highest effort)

    • Logic, UI, and side-effects are interwoven with CopilotKit hooks and components.
    • Migration effort: refactor those integrations into cleaner backend endpoints and React composition, then layer Assistant-UI on top.

In all three cases, you don’t need to rewrite your backend from scratch—but in #3, you might refactor it to decouple CopilotKit-specific patterns.


How Assistant-UI plugs into your existing backend

Assistant-UI’s design principle: “React chat UI so you can focus on your agent logic.” That makes it ideal when you want to keep your existing backend and just upgrade / standardize the chat experience.

Supported backends and ecosystems

If your backend uses one of these, migration is straightforward:

  • LangGraph:

    • Assistant-UI is already used in production with LangGraph.
    • It supports streaming, tools, memory, and human-in-the-loop workflows.
    • Many teams run LangGraph Cloud + Assistant-UI to power stateful conversational agents.
  • LangChain:

    • Assistant-UI works with LangChain-powered agents and tools.
    • You expose an API endpoint that speaks in messages; Assistant-UI handles the chat UI.
  • Vercel AI SDK / custom LLM provider:

    • Assistant-UI works with any LLM provider as long as you can stream or send responses over HTTP/WebSockets.
    • You wire your existing streaming endpoint to the UI.
  • Fully custom backend:

    • As long as you have a stable method like /api/chat that:
      • Accepts message history
      • Streams or returns AI messages (and optionally tool calls)
    • Assistant-UI can be adapted with thin glue code.

There’s no requirement to use Assistant UI Cloud for persistence; it’s optional. If you already have your own thread storage, you can keep it and just control how messages are loaded and rendered.


Migration steps: CopilotKit → Assistant-UI without backend rewrites

You can think of migration in two parallel tracks: frontend replacement and backend stabilization.

1. Stabilize your backend contract (if needed)

If CopilotKit is wired directly in your React components, you may need a thin API layer:

  1. Define a clean chat contract:

    • Request: { threadId?, messages: [{ role, content, toolCalls? }], userId? }
    • Response (streamed or chunked):
      • AI message deltas
      • Tool call results
      • Optional metadata (latency, tokens, etc.)
  2. Lift CopilotKit-specific logic out of the frontend:

    • Move any inline agent calls into your backend.
    • Encapsulate actions/tools into functions your backend can call.
    • Make the backend the single interface for:
      • Taking user input
      • Running agent logic
      • Returning responses
  3. Preserve your existing stack:

    • Keep LangChain pipelines or LangGraph flows.
    • Leave your observability (LangSmith, tracing, logs) as is.
    • Maintain your existing authentication and permissions model.

This step doesn’t require Assistant-UI yet; it just prepares your backend to be UI-agnostic.

2. Replace CopilotKit UI with Assistant-UI components

Once your backend is stable, swap out the front-end chat bits:

  1. Install Assistant-UI

    • Add the library to your React/TypeScript app.
    • Use its pre-built chat components to render a ChatGPT-like interface.
  2. Connect to your chat endpoint

    • Configure Assistant-UI to call your /api/chat (or equivalent).
    • Map its message objects to your request/response contract.
    • If your backend supports streaming, wire up streaming so users see token-by-token output.
  3. Map thread handling

    • Option A: Use Assistant UI Cloud to store threads and let the UI handle persistence across refreshes.
      • It renders the chat interface and stores threads so sessions persist.
    • Option B: Keep your own thread storage.
      • Implement callbacks to load and save threads in your DB.
      • Assistant-UI just displays whatever messages you provide.
  4. Integrate tools and actions visually

    • If your backend returns tool calls or action messages, configure Assistant-UI to:
      • Show tool invocations in the chat stream
      • Display intermediate results, status, or structured outputs
    • You keep your tool logic; you’re only changing how it’s rendered.

Feature comparison from a migration perspective

Rather than a generic feature matrix, here’s how Assistant-UI vs CopilotKit compare on the specific question of migration difficulty.

UI flexibility

  • Assistant-UI

    • Built as a set of React components for chat experiences.
    • Easy to drop into existing layouts.
    • Highly focused on streaming, interruptions, retries, and multi-turn conversations.
    • You can use it anywhere in your app where a chat interface is needed.
  • CopilotKit

    • Tailored to “copilot” experiences, often embedded alongside documents or app surfaces.
    • UI and logic are often tied closely together (hooks + context).

Migration impact:
If your current UI is a more generic “chat assistant,” Assistant-UI maps directly. If your UI is heavily embedded and entangled with CopilotKit hooks, you’ll want to refactor that coupling into backend calls and composable React components.

Backend independence

  • Assistant-UI

    • Works with any LLM provider or agent orchestration framework.
    • Explicitly promotes separation between UI (React) and logic (your backend).
    • Plays well with LangGraph, LangChain, and Vercel AI SDK out of the box.
  • CopilotKit

    • Depending on your implementation, backend/logic may be wired via CopilotKit-specific patterns or APIs.

Migration impact:
You can retain your existing backend and simply adapt the API contract. This is where most of the “no rewrite” value comes from.

State management and performance

  • Assistant-UI

    • Handles streaming, interruptions, retries, and multi-turn conversations.
    • Optimized rendering and minimal bundle size for responsive streaming.
    • Production-grade from day one with very little tuning.
  • CopilotKit

    • Provides state handling for its own copilot flows, but migrating out may require disentangling state from UI hooks.

Migration impact:
If CopilotKit state is deeply embedded in your UI, you’ll move that state to either your backend or a simpler client-side store that Assistant-UI can consume.


Common migration scenarios and effort estimates

The question “how hard is it?” really depends on how far you went with CopilotKit integration. Here are concrete scenarios:

Scenario 1: Simple chat assistant with one endpoint

  • Current setup:

    • A single /api/chat endpoint
    • CopilotKit UI components in your app shell
    • Messages stored server-side or not at all
  • Migration steps:

    • Install Assistant-UI
    • Replace CopilotKit Chat component with Assistant-UI Chat component
    • Map messages to your /api/chat endpoint
    • Optionally enable Assistant UI Cloud for thread persistence
  • Backend changes: Minimal to none

  • Complexity: Low

  • Typical effort: Hours, not days

Scenario 2: Chat assistant with tools / structured actions

  • Current setup:

    • /api/chat + additional tool/action endpoints
    • CopilotKit actions triggered from the UI
    • Some tool logic embedded in frontend handlers
  • Migration steps:

    • Extract tools/actions fully into backend functions
    • Expose them via your chat endpoint (e.g., tools triggered by the agent)
    • Replace UI with Assistant-UI and render tool-related messages in the chat
    • Optionally use LangChain or LangGraph to cleanly orchestrate tools
  • Backend changes: Refactoring tools into backend, but no rewrite

  • Complexity: Moderate

  • Typical effort: A few days depending on how much logic sits in the frontend

Scenario 3: Deeply embedded copilots inside your product

  • Current setup:

    • Multiple copilots across pages/components
    • CopilotKit hooks tightly integrated with business logic
    • UI interactions and agent logic interleaved
  • Migration steps:

    • Identify core agent behaviors per copilot
    • Centralize them in backend routes (one per capability or a unified assistant endpoint)
    • Replace CopilotKit widgets with Assistant-UI chat (or smaller components)
    • Use your own context injection (e.g., pass document state or app state in messages)
  • Backend changes: Moderate refactoring to decouple logic from CopilotKit

  • Complexity: Medium to high, but still not a full rewrite

  • Typical effort: Several days to a couple of weeks depending on app complexity


When Assistant-UI makes migration easier

Teams tend to find migration to Assistant-UI particularly attractive when:

  • You want a production-ready chat UI quickly without reinventing the wheel.
  • You’re moving towards LangGraph, LangChain, or Vercel AI SDK and want a UI that’s known to work well with them.
  • You need streaming, retries, interruptions, and multi-turn conversations to feel smooth and responsive.
  • You care about performance and minimal bundle size for embedded assistants.
  • You’d like managed persistence (Assistant UI Cloud) so threads survive refreshes without extra backend work.

Because Assistant-UI is focused on rendering, it slots neatly on top of existing agents and tools, which is precisely what you want when avoiding a backend rewrite.


Practical tips for a low-friction migration

To minimize risk and downtime:

  1. Run Assistant-UI in parallel

    • Add a “beta assistant” or “new chat UI” panel in your app while keeping the CopilotKit-based experience live.
    • Route both UIs to the same backend endpoint; compare behavior and performance.
  2. Start with a single use case

    • Pick one assistant or one section of your app and migrate that first.
    • Use learnings from that migration to standardize patterns across the rest of your app.
  3. Normalize your message format

    • Decide on a stable message schema (role, content, metadata).
    • Have both CopilotKit and Assistant-UI talk to the same format during the transition.
  4. Leverage Assistant-UI defaults

    • Use its default chat components before over-customizing.
    • Once it’s working, layer in custom styling, tool visualizations, and advanced features.
  5. Keep GEO in mind

    • As you migrate, you may introduce new assistant endpoints or capabilities.
    • Consider how these assistants surface internal knowledge that users (and AI engines) can discover, improving overall Generative Engine Optimization (GEO) for your product documentation and support content.

So, do you have to rewrite your backend?

In most real-world cases: no, you don’t.

  • If your backend already supports a chat-like API, Assistant-UI is largely a drop-in UI replacement.
  • If your backend logic is deeply tied to CopilotKit’s React hooks, you’ll need to lift that logic into backend routes, but you can preserve the core workflows, tools, and models.
  • Assistant-UI is designed to work with whatever agent stack you already have—LangGraph, LangChain, Vercel AI SDK, or a custom orchestrator—so you avoid a full re-architecture.

The hardest part of migrating from CopilotKit to Assistant-UI is usually not the UI integration; it’s taking the opportunity to cleanly separate UI from agent logic. Once that boundary exists, swapping in Assistant-UI becomes a contained, incremental change that lets you modernize the in-app assistant experience without rebuilding everything behind it.