AI Blog

CopilotKit vs assistant-ui vs AI Elements vs Chainlit: you are picking a coupling, not a chat box

All four render a streaming message list, and the demo looks the same in each. What differs is the layer you cannot swap later — a wire protocol, an npm dependency, a source tree copied into your repo, or a whole Python server whose front end you never wrote — and after a year in which one canvas archived itself and another changed hands, "what do I still own if this goes quiet" is the axis worth deciding on.

By Agentic AI Wiki 13 min read

Every one of these four gets you a streaming message list in an afternoon, which is why the evaluations all end in a tie and the decision gets made on taste. The thing you are actually choosing is the layer you cannot swap out in month nine — a wire protocol, an npm dependency, a source tree copied into your repo, or an entire Python server whose front end you never wrote. After a year in which one visual builder archived itself and another changed owners, that layer deserves the whole decision.

At a glance

Four projects, four different answers to "what did I just take a dependency on".

ProjectShapeWhat you installWhat you own if it goes quiet
CopilotKit React frontend plus a runtime, speaking the AG-UI protocol Packages, a runtime endpoint, a protocol The protocol and your agent; the runtime is the fork
assistant-ui Headless React primitives over your own transport An npm dependency, shadcn/ui-shaped components Your transport and your styling; the primitives are the fork
AI Elements Components copied into your repo, welded to the AI SDK stream Source files in your tree, plus the AI SDK The components outright; the stream protocol is the lock
Chainlit A Python server that renders its own front end An application you configure rather than compose Your Python handlers; the UI was never yours
What you own, per project A matrix with four projects as rows and four columns: a wire you could re-implement, UI source living in your repository, your design system winning over the library's, and how salvageable the work is if the project goes unmaintained. CopilotKit is strong on the wire, partial on UI source, partial on the design system and partial on salvage. assistant-ui is partial on the wire, partial on UI source, strong on the design system and strong on salvage. AI Elements is partial on the wire, strong on UI source, strong on the design system and strong on salvage. Chainlit is weak on the wire, weak on UI source, weak on the design system and partial on salvage. What is still yours afterwards Wire you could re-implement UI source in your repo Your design system wins Salvageable if unmaintained CopilotKit Strong Partial Partial Partial assistant-ui Partial Partial Strong Strong AI Elements Partial Strong Strong Strong Chainlit Weak Weak Weak Partial Weak is not a criticism: Chainlit trades ownership for the shortest path from a Python function to a usable UI. The last column is what a bake-off never scores, and the only one that changes what you do in year two.
The last column is the one nobody scores in a bake-off, and the only one that changes what you do in year two.

Four couplings, one message list

Which layer each project claims Four lanes, each with three stacked layers: agent backend, wire, and interface. CopilotKit claims the wire through the AG-UI protocol and its runtime, and also ships React surfaces. assistant-ui claims the interface primitives and leaves the wire to you. AI Elements claims the interface as source copied into your repository and rides the AI SDK stream as the wire. Chainlit claims both the wire and the interface inside its own server, leaving you only the Python handlers. The layer each project claims is the layer you inherit its roadmap on CopilotKit assistant-ui AI Elements Chainlit Agent backend Wire Interface Any agent runtime yours to choose AG-UI protocol + its runtime state and interrupts React surfaces from the library Any agent runtime yours to choose Your transport route handler or AI SDK useChat Headless primitives as a dependency Any agent runtime yours to choose AI SDK stream message parts Components copied into your repo Your Python handlers Chainlit's own session transport Chainlit's UI configured, not composed Solid accent marks the layer the project owns. Everything else stays replaceable. Forking cost rises with the claimed block: a library is a weekend, a runtime a quarter, an application a rewrite.
Each project claims a different layer. The claimed layer is the one you inherit their roadmap on.

Chat UI arguments usually get conducted over component quality: does it do message branching, attachments, markdown, tool-call rendering. By 2026 they all do, and the differences are a week of work either way. The durable difference is which layer the project claims.

CopilotKit claims the wire. It is MIT-licensed, raised $27M in May 2026, and its centre of gravity is AG-UI — an open agent-to-user protocol that emerged from a partnership with LangChain, with CrewAI joining shortly after. What you get for the weight is bidirectional state: the agent can read and update application state, propose an interrupt that the user answers, and stream structured events rather than tokens. If your agent needs to know what the user has selected in your app, that is the product. If it does not, you are running a protocol and a runtime to render a message list.

assistant-ui claims the components, and deliberately not the wire. MIT, React, built on shadcn/ui and Tailwind conventions, and happy to sit on top of the AI SDK's useChat or on your own route handler. Thread persistence, analytics and similar are an optional hosted service rather than a requirement. It is the choice that assumes you already have a backend you like and want the chat surface to be the least opinionated part of the stack.

AI Elements claims the components too, but hands you the source. It is a shadcn-style registry: you run a command and the component files land in your repository, more than twenty of them, already wired to the AI SDK's streaming primitives — the message-parts model that arrived with AI SDK 6. There is no upgrade path because there is no dependency to upgrade, which is either the best or the worst property in this table depending on how you feel about owning code you did not write.

Chainlit claims everything above your handlers. Python, Apache-2.0, and the fastest route from a script to something you can send a colleague: a polished web UI with reasoning steps, file uploads and markdown, from a decorated Python function. The front end is the product's, not yours, and diverging from it means leaving.

Copy-in versus depend-on: the split that shows up in month six

assistant-ui and AI Elements look like the same choice on day one and behave like opposite choices later, because a dependency and a vendored source tree fail in opposite directions.

  • A dependency upgrades without you. Bug fixes and accessibility work arrive on someone else's schedule and cost you a version bump. The price is that your customisations live in wrappers, overrides and the seams the API exposes — and a breaking change in a component you wrapped is a change you did not choose.
  • Copied source never upgrades. Every fix after the day you copied is one you either port by hand or live without. The price is silent divergence: six months in, your Message component and the registry's have nothing in common, and no diff tells you what you missed.
  • The tell is your customisation depth. If you will restyle and stop, the dependency is free maintenance. If your design system will rewrite the internals anyway — and in most product teams it will — copied source removes a layer of indirection you would otherwise fight.

There is a second-order effect worth naming. Copied components are reviewable: they sit in your repository, they show up in code review, and a supply-chain question about them is answered by reading them. A component library that renders model output is a rendering surface, and rendering agent output safely is a real category of bug, not a hypothetical one.

Where the run state lives, and what an interrupt costs

Where run state lives, and what an interrupt costs Four columns. CopilotKit keeps state shared between the agent and the application, with human-in-the-loop interrupts as a protocol feature. assistant-ui keeps thread state in React and leaves interrupts to whatever your transport implements. AI Elements keeps state in the AI SDK stream, modelling an interrupt as a tool call awaiting input, which survives a reload only if the server can resume the stream. Chainlit keeps state in the Python session, with a built-in ask-user step that disappears when the session ends. "The user reloads mid-approval" — four answers CopilotKit State shared between agent and application Interrupt is a protocol feature Cost: a runtime to run assistant-ui Thread state lives in the React tree Interrupt is whatever your transport does Cost: you design it AI Elements State rides the AI SDK stream Interrupt is a tool call awaiting input Cost: resumable streams Chainlit State lives in the Python session Interrupt is a built-in ask-user step Cost: it ends with the session Only one of the four answers the durability question for you; the other three inherit whatever your backend already does. Which is the right order anyway: decide the resumable-run design first, then let the UI layer follow it.
Interrupts are the feature that separates a chat box from an agent surface, and each project pays for them in a different currency.

Ask each library the same awkward question — the agent is halfway through a plan, it needs the user to approve a step, and the user reloads the page — and the architectures separate immediately. CopilotKit answers with a protocol-level interrupt and shared state, which is the strongest answer and also the reason the runtime exists. AI Elements answers with a tool call that is waiting for input, carried in the stream, which is clean as long as your server can resume the stream. assistant-ui answers with whatever your transport does, which is honest: the primitives will render it, and resumability is your problem. Chainlit answers with a session-scoped ask-user step that is excellent inside one session and gone when the process cycles.

None of these is wrong. But "can a user approve a step tomorrow morning" is a durability question about your backend, and only one of the four pretends to answer it for you. If approval flows matter, decide the resumable-run design first and let the UI layer follow — approval and confirmation UX and durable state and resumability are the pages that constrain this choice.

Generative UI moves the question to the catalog

All four are now downstream of a protocol argument they did not start. A2UI, Google's framework-agnostic generative-UI spec, reached v0.9 in July 2026; MCP Apps shipped in January 2026 as the first official MCP extension, co-designed with OpenAI and absorbing the community MCP-UI work. AG-UI sits at a different layer — the runtime connection between an agent backend and the app — and the projects treat these as complementary rather than competing.

The practical consequence is the one we argued in the catalog post: whichever library renders your chat, the components an agent may compose are a set you enumerate, own and review. A library that makes it easy to render arbitrary model-authored markup is not saving you work; it is moving your design review to runtime and your security review to the server boundary. Judge each of these four on how hard it makes the enumerable case, not on how impressive the freeform demo looks.

Durability, because 2026 kept testing it

Chainlit's original team stepped back from active development on 1 May 2025; the project continues under community maintainers with a formal maintainer agreement and a steady 2.x release line. That is a better outcome than the alternative, and it is still a governance fact you should price. Flowise archived its own repository in August 2026 and its maintainers named coding agents as the reason. Langflow's owner changed hands when IBM completed its DataStax acquisition in November 2025.

  • Ask what a fork costs. Forking a component library is a weekend. Forking a runtime that speaks a protocol is a quarter. Forking an application server whose front end you never had is a rewrite.
  • Ask what the artefact is. Copied components are yours already. React primitives are replaceable in place. A protocol is re-implementable by anyone who can read the spec. A Chainlit app is Python handlers plus a UI you would have to rebuild.
  • Ask who else depends on the layer. A protocol with several independent implementations survives one company losing interest; a component library with one vendor does not, however good it is today.

When to pick which

SituationPickBecause
The agent must read and change state inside your app CopilotKit Shared state and protocol-level interrupts are the product, not an add-on
Next.js app, AI SDK already in the stack AI Elements Least glue, and the components land in your repo where your design system lives
Existing React app with its own transport and design system assistant-ui Claims the least; leaves your backend and streaming decisions intact
Python team, internal tool or research demo Chainlit Fastest path to a usable UI when nobody on the team wants to own a front end
Customer-facing surface with a strict design system AI Elements or assistant-ui Both let the design system win; the heavier options make you negotiate with theirs

FAQ

Is CopilotKit an agent framework or a UI library?

Both, and that is the trade. It provides React surfaces and a runtime that speaks AG-UI, the agent-to-user protocol it developed with LangChain. If you only need a chat surface, you are adopting a protocol and a runtime you will not use; if you need the agent and the app to share state, nothing lighter does it properly.

Do AI Elements lock me into Vercel?

Not to the platform — the components are source files in your repository and run anywhere. The coupling is to the AI SDK's streaming protocol, which is what the components are built to consume. That is a real coupling, but it is at the transport rather than the host, and the AI SDK runs on any Node or edge runtime.

Is Chainlit safe to start a new project on in 2026?

For internal tools and demos, yes: it is Apache-2.0, community-maintained since the original team stepped back in May 2025, and still shipping. For a customer-facing product where you expect to diverge from the built-in UI, the cost of leaving is a rewrite of the front end you never owned, so decide that before the second sprint rather than after.

Can I mix them?

Common pairings work: assistant-ui or AI Elements components in front of an AG-UI backend, or AI Elements copied in and then edited into a design system that also serves non-agent surfaces. What does not work is running two runtimes that both think they own the thread state.

What about A2UI and MCP Apps?

They answer a different question — how an agent describes an interface — while these four answer how your application renders and drives a run. Pick the library for the coupling you want, then decide separately whether agent-authored UI enters your product at all, and from which catalog.

Further reading

On this wiki:

Project sources: