This guide demonstrates how to integrate C1 by Thesys with CopilotKit - the open-source Agentic Application Framework for building in-app AI Copilots, CoAgents, and Generative UI agents. Leveraging Agentic Generative UI, shared state, human-in-the-loop (HITL) patterns, and the AG-UI protocol, this integration enables the creation of customizable, real-time, and production-ready AI copilots within your application.
1

Create a new CopilotKit project

npx create-next-app@latest my-copilot-app
2

Install CopilotKit Runtime with OpenAI

npm install --save @copilotkit/runtime openai@4.85.1
app/api/completion/route.ts
import {
  CopilotRuntime,
  OpenAIAdapter,
  copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import OpenAI from "openai";

import { NextRequest } from "next/server";

const openai = new OpenAI({
  baseURL: "https://api.thesys.dev/v1/embed",
  apiKey: process.env.THESYS_API_KEY,
});
const serviceAdapter = new OpenAIAdapter({
  openai,
  model: "c1/anthropic/claude-sonnet-4/v-20250815",
});
const runtime = new CopilotRuntime();

export const POST = async (req: NextRequest) => {
  const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime,
    serviceAdapter,
    endpoint: "/api/chat",
  });

  return handleRequest(req);
};
3

Create a Copilot

In this guide we will be using the CopilotSidebar component to create a sidebar copilot. But you can easily replace it with CopilotChat or CopilotPopup to create a chat or popup copilot.
npm install --save @thesysai/genui-sdk @crayonai/react-ui @copilotkit/react-core @copilotkit/react-ui
app/layout.tsx
import "./globals.css";
import { ReactNode } from "react";
import { CopilotKit } from "@copilotkit/react-core";

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>
        <CopilotKit runtimeUrl="/api/chat">{children}</CopilotKit>
      </body>
    </html>
  );
}
app/page.tsx
"use client";

import { C1Component, ThemeProvider } from "@thesysai/genui-sdk";
import {
  CopilotSidebar,
  ImageRenderer,
  UserMessage,
} from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
import "@crayonai/react-ui/styles/index.css";
import { useCopilotChat } from "@copilotkit/react-core";
import { MessageRole, TextMessage } from "@copilotkit/runtime-client-gql";

const AssistantMessageRenderer = ({ message, isGenerating }: any) => {
  const { appendMessage } = useCopilotChat();
  // In the Assistant Message, render the C1Component rather than rendering a markdown message.
  return (
    <C1Component
      c1Response={message?.content || ""}
      isStreaming={isGenerating}
      onAction={(action) => {
        appendMessage(
          new TextMessage({
            role: MessageRole.User,
            // Action is a object with 2 keys: llmFriendlyMessage and humanFriendlyMessage.
            // We stringify it because the content field of CopilotKit is a string.
            content: JSON.stringify(action),
          })
        );
      }}
    />
  );
};

const UserMessageRenderer = ({ message }: any) => {
  // Since content can either be a string or a json object (in the case of an Action)
  // we need to parse it and extract the humanFriendlyMessage incase its a json object.
  let content = message?.content;
  try {
    const { humanFriendlyMessage } = JSON.parse(message?.content || "{}");
    content = humanFriendlyMessage;
  } catch (error) {}
  return (
    <UserMessage
      message={{ ...message, content }}
      ImageRenderer={ImageRenderer}
      rawData=""
    />
  );
};

export default function Page() {
  return (
    <ThemeProvider>
      <CopilotSidebar
        defaultOpen
        instructions={
          "You are assisting the user as best as you can. Answer in the best way possible given the data you have."
        }
        // Override the default UserMessage and AssistantMessage components to install
        // C1 Components.
        UserMessage={UserMessageRenderer}
        AssistantMessage={AssistantMessageRenderer}
      />
    </ThemeProvider>
  );
}