A windswept bonsai on a floating island

Get to know Cadenya

We’re developers who love to build. We set out to create a yes-code platform that makes building agents feel like the best parts of building software.

CopilotKit vs assistant-ui vs AG-UI for AI agent chat UIs (2026)

Chat UI

By Cadenya

AG-UI is the protocol, and CopilotKit and assistant-ui are chat UI kits that speak it: the AG-UI protocol carries frontend tools, state, and the events that let an agent drive the UI, while CopilotKit and assistant-ui render the chat. CopilotKit created AG-UI and ships frontends for React, Angular, and Vue. assistant-ui is a React library first, with Vue, React Native, and terminal bindings, and an AG-UI adapter.

So pick CopilotKit when you want one vendor for the protocol, the runtime, and the components. Pick assistant-ui when you want composable React primitives in front of the backend you already have (AI SDK, LangGraph, or AG-UI). Pick AG-UI on its own when you’re writing the client yourself, in plain JavaScript or anything else. And if you’d rather run no agent server at all, Cadenya is a hosted agent loop with a chat widget and a browser SDK, so there’s nothing to host, and a coding agent can set it up with no account, in a temporary workspace you claim later. What it offers is at the end.

Every price and limit below comes from each vendor’s own pages, checked on October 13, 2026.

CopilotKit vs assistant-ui vs AG-UI side by side

The Vercel AI SDK’s UI hooks show up in the same searches, so they get a column too.

CopilotKitassistant-uiAG-UIAI SDK UICadenya
What it isFrontend SDKs, a runtime, and prebuilt chat componentsA TypeScript/React library of chat primitivesAn open, event-based protocol between agent and appHooks: useChat, useCompletion, useObjectA hosted agent loop with a chat widget and a browser SDK
LicenseMITMITMITApache-2.0Server SDKs under Apache-2.0
FrontendsReact, Angular, Vue, React NativeReact, Vue, React Native, terminal (React Ink)Any client that reads the event streamReact, Vue, Svelte, Angular, SolidJS (community)React (@cadenya/widgets-ui-react), or any UI through @cadenya/widgets
Frontend toolsuseFrontendToolToolkits (defineToolkit), replacing makeAssistantToolClient-defined tools in RunAgentInput.toolsonToolCall plus addToolOutputBare tools, whose result the page supplies
Human in the loopuseHumanInTheLoop, useInterruptInline approvals in tool UIsInterrupt outcome on RUN_FINISHED, resumed by a new runTool execution approvaltoolApprovalRequested, approved or denied in the browser
Server you runCopilot Runtime in your app serverYour backend, through a runtime adapterAn AG-UI server or a framework with AG-UI built inYour route that streams a UI message streamNone. Your backend only mints a widget session
Thread historyCopilotKit Intelligence or a persisting AgentRunnerAssistant Cloud or your own storeA serialization format you storeYour storageEach conversation is an objective, with no store to set up
Hosted add-on priceFree, $39 a month, $100 a seat a monthFree, $50 a month for 500 active usersNone neededNone neededFree for 1 widget and 1,000 loops a month, $49 a month for 5 widgets and 50,000 loops

AG-UI protocol 1.0: frontend tools and the agent driving the UI

AG-UI reached 1.0 in September: @ag-ui/core 1.0.0 went out on September 17, 2026, and 1.0.2 is the latest. The 1.0 changelog says it plainly: “0.x defined shapes; behaviour lived in the TypeScript client.” Now the spec defines the behavior too.

Everything the agent says arrives as events in eight families: runs and steps, text messages, tool calls, reasoning, state, activity, subagents, and passthrough. That’s 31 event types. State travels as STATE_SNAPSHOT and STATE_DELTA (a JSON Patch), and structured progress travels as ACTIVITY_SNAPSHOT and ACTIVITY_DELTA. Only the run lifecycle is mandatory for a producer.

The agent drives the UI through frontend tools. The client passes its own tools in RunAgentInput.tools, the agent calls one, and the client runs it and sends the result back. The protocol docs name the use cases: “UI actions, approvals, or user-mediated workflows.”

Here’s the “without React” version, built from the @ag-ui/client docs. HttpAgent posts the run and turns the SSE stream into events you subscribe to:

import { HttpAgent } from "@ag-ui/client"

const agent = new HttpAgent({ url: "https://api.example.com/agent" })

const userConfirmationTool = {
  name: "confirmAction",
  description: "Ask the user to confirm a specific action before proceeding",
  parameters: {
    type: "object",
    properties: {
      action: { type: "string", description: "The action that needs user confirmation" },
    },
    required: ["action"],
  },
}

agent.subscribe({
  onTextMessageContentEvent: ({ textMessageBuffer }) => {
    // Plain DOM, no framework: the buffer holds the reply so far.
    document.querySelector("#reply").textContent = textMessageBuffer
  },
})

await agent.runAgent({ tools: [userConfirmationTool] })

(The message history and the code that answers confirmAction are left out.)

Human-in-the-loop pauses work the same way across clients. A run ends with an interrupt outcome, and “the client starts a new run carrying per-interrupt responses.”

CopilotKit useFrontendTool and human in the loop

CopilotKit’s v2 hooks live under @copilotkit/react-core/v2. A frontend tool runs “entirely in the user’s browser”, and useFrontendTool registers one:

import { z } from "zod";
import { useFrontendTool } from "@copilotkit/react-core/v2";

export function Page() {
  useFrontendTool({
    name: "sayHello",
    description: "Say hello to the user",
    parameters: z.object({
      name: z.string().describe("The name of the user to say hello to"),
    }),
    handler: async ({ name }) => {
      alert(`Hello, ${name}!`);
      return `Said hello to ${name}!`;
    },
  });

  // ...
}

For human in the loop, CopilotKit ships two patterns. With useHumanInTheLoop, the model decides to ask: it calls a client-side tool, your render function shows a component, and respond sends the answer back as the tool result. With useInterrupt, the graph decides: a LangGraph node calls interrupt(...) on the server.

CopilotKit is a three-layer stack: frontend, runtime, and agent. The runtime is “a request handler mounted in your app server (Next.js, Express, Hono, Bun, Deno, Workers).” For Python, Go, Ruby, or .NET servers, the docs say “those runtimes require Intelligence”, CopilotKit’s hosted platform.

assistant-ui makeAssistantTool and frontend tools

If you searched for makeAssistantTool, here’s the news: assistant-ui deprecated it, along with useAssistantTool, makeAssistantToolUI, and useAssistantToolUI. The replacement is a toolkit registered with Tools({ toolkit }), which keeps “the model contract, browser execution, and tool-call rendering in one named map.” A tool that runs in the browser marks its execute function with "use client".

assistant-ui reaches your agent through a runtime adapter: @assistant-ui/ai-sdk for the AI SDK, @assistant-ui/react-langgraph for LangGraph, @assistant-ui/react-data-stream for a custom backend, and @assistant-ui/react-ag-ui for AG-UI. The AG-UI adapter takes an HttpAgent from @ag-ui/client and talks to “any AG-UI-compliant agent server, including CopilotKit-based backends.” It needs React 18 or 19.

So assistant-ui and CopilotKit aren’t either/or. You can put assistant-ui’s components in front of a CopilotKit backend over AG-UI.

Without React: CopilotKit and assistant-ui on Vue, Angular and vanilla JavaScript

Both kits started in React, and both now go further.

CopilotKit ships @copilotkit/vue (Vue 3.3 or later, Node.js 20 or later) and @copilotkit/angular (Angular 22, Node.js 22). Both talk to a Copilot Runtime on your server, which “keeps model credentials out of the browser.” For a page with no framework, CopilotKit ships one web component today, <copilotkit-threads-drawer>, which “imports no React, Angular, or @copilotkit/core code.”

assistant-ui ships @assistant-ui/vue for Vue 3.5 and Nuxt. It “runs the same runtime as @assistant-ui/react”, with composables and unstyled primitives. A few pieces stay React only: voice and dictation, mentions and slash commands, quoting, the assistant modal, and DevTools.

For vanilla JavaScript, the documented path is AG-UI itself. @ag-ui/client has no UI framework in it: you subscribe to events and render them however you like (see the snippet above). The AI SDK covers the most frameworks of all: React, Vue, Svelte, Angular, and SolidJS through a community package. It also has its own way for the server to drive the client, typed data- parts in the message stream, sent over SSE.

AG-UI protocol Go SDK, Ruby and Java servers

AG-UI’s docs carry SDK references for TypeScript, Python, and .NET. Its SDK table adds community SDKs for Go, Java, Kotlin, Ruby, Rust, Dart, and C++.

The Go SDK installs with:

go get github.com/ag-ui-protocol/ag-ui/sdks/community/go

It connects Go applications to AG-UI agents over SSE. The Ruby gem, ag-ui-protocol, gives you typed events and an encoder “for building AG-UI compatible agent servers.” Java has its own getting-started page in the AG-UI repo.

Many agent frameworks also speak AG-UI already, so you may not write a server at all. The docs list LangChain, CrewAI, Microsoft Agent Framework, Google ADK, AWS Strands Agents, Mastra, Pydantic AI, Agno, LlamaIndex, and AG2.

Thread persistence, resume and reconnect

This is the part every kit hands back to you, in a different way.

AG-UI’s HTTP and SSE binding has “no stream resumption: SSE’s Last-Event-ID mechanism is not used, and a broken stream cannot be re-entered.” A retry is a new run. AG-UI does define serialization, a portable event history “for storage in databases, files, or logs”, but the storage is yours.

CopilotKit replays a thread only when “a server-side store is configured (CopilotKit Intelligence, or a persisting AgentRunner).” The docs mention a SQLite runner. “A runtime with no persistence layer keeps nothing server-side.” Intelligence adds AG-UI Streams “for reconnection, catch-up, and delivery across devices.”

assistant-ui gets resumable streams from assistant-stream/resumable, where “the server keeps writing to a store while the original request is in flight.” You implement the store on Postgres, Cloudflare Durable Objects, Upstash, or similar. Assistant Cloud keeps threads for you, priced by active users: free for 200 active users a month, and $50 a month for 500.

The AI SDK says the same thing in one line: “The AI SDK provides tools to connect to storage, but you need to set up the storage yourself.” Hosted agent runtimes compared covers which hosted backends run the loop and resume a dropped stream.

What does Cadenya offer that CopilotKit, assistant-ui and AG-UI don’t?

CopilotKit, assistant-ui, and AG-UI give you the chat UI and the wire format, and the agent, the runtime, and the thread store behind them are yours to run or to buy separately. Cadenya runs the agent loop and serves the chat to the browser, so your backend only mints a session. Here’s what that covers:

  1. Nothing else to run. No Copilot Runtime, no AG-UI server, no stream store. Each widget gets its own host, the browser talks to it directly, and your backend has “one job in the live conversation path: authenticate the visitor and mint a Widget Session.” Your Cadenya API key stays on your server.
  2. A whole chat UI in one component. ConversationsPanel from @cadenya/widgets-ui-react “supplies the conversation list, message thread, composer, tool approvals, and live event stream.” <WidgetTools> adds questions, cards, and page context.
  3. Your own interface, React or not. For a custom UI, the lower-level @cadenya/widgets SDK exposes the widget config, conversations, events, tool approvals, browser-supplied tool results, and feedback. Underneath it, the Widgets API is plain HTTP and server-sent events.
  4. Frontend tools, built in. A Bare tool waits for the page to supply its result, so the agent drives your UI the same way a frontend tool does. Approvals arrive as toolApprovalRequested, and the browser approves or denies the call.
  5. Resume after a dropped connection. The event stream gives each durable event an ID. Pass the last one in Last-Event-ID and the stream picks up where it left off.
  6. Thread history with no store to set up. Each conversation is an objective, and sessions with the same tenant and subject share conversation history across tabs and new sessions.
  7. Your backend in four languages. The widget docs mint sessions from Next.js, Fastify, Rails, and Go. The server SDKs for TypeScript, Python, Ruby, and Go are all at 1.9.0 under Apache-2.0, and the TypeScript SDK has shipped 113 versions since April 2026.
  8. Deploys that don’t break open chats. Changing a widget’s agent or pinned variation affects new sessions, and each objective keeps its variation’s configuration snapshot, so a conversation finishes on the setup it started with.
  9. Acting as the signed-in user. A session can carry the user’s short-lived token as a secret that overrides the shared credential, and pinned parameters fix IDs the model can’t change. The browser never chooses either.
  10. Any model, one price. The model is a setting on a variation, on your own provider keys. The free plan includes 1 widget and 1,000 loops a month, and Growth is $49 a month for 5 widgets and 50,000 loops. There are no seats.

The widgets guide walks through minting a session and adding ConversationsPanel, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with cadenya workspaces create --temporary, run its first objectives there, and hand you a link to claim it, as auth.md explains. To create an account, sign up at app.cadenya.com/signup, then copy your API key from the API keys page at app.cadenya.com/account/apiKeys.

Grow wherever AI goes next.

Start shipping agents that are equipped to evolve.

A pine bonsai overlooking a mountain lake