> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thesys.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrating C1 with Vercel AI SDK

> Build Generative UI applications powered by Vercel AI SDK

Vercel AI SDK provides a robust framework for building AI applications with tool calling capabilities.
This guide demonstrates how to integrate C1 by Thesys with Vercel AI SDK to build Generative UI agents.

<Note>
  This guide assumes you have basic knowledge of Vercel AI SDK and React.
  You'll also need a Thesys API key from the [C1 Console](https://console.thesys.dev/keys).
</Note>

<Tabs>
  <Tab title="Building an agent">
    Integrating Thesys C1 with `useCompletion` from Vercel AI SDK allows you to easily create
    Generative UI based capabilities for your agent. `useCompletion` enables the streaming of text completions from your AI provider, manages the input state,
    and updates the UI automatically as new messages are received.

    <Steps>
      <Step title="Create a new Vercel project">
        ```bash theme={null}
        npx create-next-app@latest thesys-vercel-ai-sdk
        ```
      </Step>

      <Step title="Initiate the backend endpoint">
        ```bash theme={null}
        npm install --save ai @ai-sdk/openai
        ```

        ```ts app/api/completion/route.ts theme={null}
        import { streamText } from "ai";
        import { createOpenAI } from "@ai-sdk/openai";

        // Allow streaming responses up to 30 seconds
        export const maxDuration = 30;

        export async function POST(req: Request) {
          const { prompt }: { prompt: string } = await req.json();

          const result = streamText({
            model: createOpenAI({
              apiKey: process.env.THESYS_API_KEY,
              baseURL: "https://api.thesys.dev/v1/embed",
            }).chat("c1/anthropic/claude-sonnet-4/v-20250815"),
            prompt,
          });

          return result.toUIMessageStreamResponse();
        }

        ```
      </Step>

      <Step title="Render the response">
        ```bash theme={null}
        npm install --save @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core
        ```

        ```tsx app/page.tsx [expandable] theme={null}
        "use client";

        import { useChat } from "@ai-sdk/react";
        import { DefaultChatTransport } from "ai";
        import { useState } from "react";
        import { C1Component, ThemeProvider } from "@thesysai/genui-sdk";
        import "@crayonai/react-ui/styles/index.css";

        export default function Page() {
          const { messages, sendMessage, status } = useChat({
            transport: new DefaultChatTransport({
              api: "/api/chat",
            }),
          });
          const [input, setInput] = useState("");

          const handleC1Action = ({ llmFriendlyMessage, humanFriendlyMessage }) => {
            sendMessage({
              text: llmFriendlyMessage,
              metadata: { humanFriendlyMessage },
            });
          };

          return (
            <ThemeProvider>
              <div className="h-screen flex flex-col">
                <div className="flex-1 flex justify-center overflow-auto">
                  <div className="w-full max-w-3xl p-4">
                    <div className="space-y-3">
                      {messages.map((message) => {
                        const text = message.parts
                          .filter((part) => part.type === "text")
                          .map((part) => part.text)
                          .join("");
                        return (
                          <div key={message.id} className="p-3 rounded-lg bg-gray-50">
                            {message.role === "user" ? (
                              <div className="text-sm text-gray-700">
                                {message.metadata?.humanFriendlyMessage || text}
                              </div>
                            ) : (
                              <C1Component
                                isStreaming={status === "streaming"}
                                c1Response={text}
                                onAction={handleC1Action}
                              />
                            )}
                          </div>
                        );
                      })}
                    </div>
                  </div>
                </div>

                <div className="p-4">
                  <div className="max-w-lg mx-auto">
                    <form
                      onSubmit={(e) => {
                        e.preventDefault();
                        if (input.trim()) {
                          sendMessage({ text: input });
                          setInput("");
                        }
                      }}
                      className="flex gap-2"
                    >
                      <input
                        value={input}
                        onChange={(e) => setInput(e.target.value)}
                        disabled={status !== "ready"}
                        placeholder="Say something..."
                        className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
                      />
                      <button
                        type="submit"
                        disabled={status !== "ready"}
                        className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50"
                      >
                        Send
                      </button>
                    </form>
                  </div>
                </div>
              </div>
            </ThemeProvider>
          );
        }

        ```
      </Step>

      <Step title="Run the app">
        ```bash theme={null}
        export THESYS_API_KEY=<your-api-key>
        npm run dev
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Building a chatbot">
    Integrating Thesys C1 with `useChat` from Vercel AI SDK allows you to easily create a conversational user interface.
    `useChat` enables the streaming of chat messages from your AI provider, manages the chat state,
    and updates the UI automatically as new messages are received.

    <Steps>
      <Step title="Create a new Vercel project">
        ```bash theme={null}
        npx create-next-app@latest thesys-vercel-ai-sdk
        ```
      </Step>

      <Step title="Initiate the backend endpoint">
        ```bash theme={null}
        npm install --save ai @ai-sdk/openai
        ```

        ```ts app/api/chat/route.ts theme={null}
        import { convertToModelMessages, streamText, UIMessage } from "ai";
        import { createOpenAI } from "@ai-sdk/openai";

        // Allow streaming responses up to 30 seconds
        export const maxDuration = 30;

        export async function POST(req: Request) {
          const { messages }: { messages: UIMessage[] } = await req.json();
          const model = createOpenAI({
            apiKey: process.env.THESYS_API_KEY,
            baseURL: "https://api.thesys.dev/v1/embed",
          }).chat("c1/anthropic/claude-sonnet-4/v-20250815");
          const result = streamText({
            model: model,
            messages: convertToModelMessages(messages),
          });

          return result.toUIMessageStreamResponse();
        }

        ```
      </Step>

      <Step title="Render the chat UI">
        ```bash theme={null}
        npm install --save @thesysai/genui-sdk @crayonai/react-ui @crayonai/react-core
        ```

        ```tsx app/page.tsx [expandable] theme={null}
        "use client";

        import { useChat } from "@ai-sdk/react";
        import { DefaultChatTransport } from "ai";
        import { useState } from "react";
        import { C1Component, ThemeProvider } from "@thesysai/genui-sdk";
        import "@crayonai/react-ui/styles/index.css";

        export default function Page() {
          const { messages, sendMessage, status } = useChat({
            transport: new DefaultChatTransport({
              api: "/api/chat",
            }),
          });
          const [input, setInput] = useState("");

          const handleC1Action = ({ llmFriendlyMessage, humanFriendlyMessage }) => {
            sendMessage({
              text: llmFriendlyMessage,
              metadata: { humanFriendlyMessage },
            });
          };

          return (
            <ThemeProvider>
              <div className="h-screen flex flex-col">
                <div className="flex-1 flex justify-center overflow-auto">
                  <div className="w-full max-w-3xl p-4">
                    <div className="space-y-3">
                      {messages.map((message) => {
                        const text = message.parts
                          .filter((part) => part.type === "text")
                          .map((part) => part.text)
                          .join("");
                        return (
                          <div key={message.id} className="p-3 rounded-lg bg-gray-50">
                            {message.role === "user" ? (
                              <div className="text-sm text-gray-700">
                                {message.metadata?.humanFriendlyMessage || text}
                              </div>
                            ) : (
                              <C1Component
                                isStreaming={status === "streaming"}
                                c1Response={text}
                                onAction={handleC1Action}
                              />
                            )}
                          </div>
                        );
                      })}
                    </div>
                  </div>
                </div>

                <div className="p-4">
                  <div className="max-w-lg mx-auto">
                    <form
                      onSubmit={(e) => {
                        e.preventDefault();
                        if (input.trim()) {
                          sendMessage({ text: input });
                          setInput("");
                        }
                      }}
                      className="flex gap-2"
                    >
                      <input
                        value={input}
                        onChange={(e) => setInput(e.target.value)}
                        disabled={status !== "ready"}
                        placeholder="Say something..."
                        className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
                      />
                      <button
                        type="submit"
                        disabled={status !== "ready"}
                        className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50"
                      >
                        Send
                      </button>
                    </form>
                  </div>
                </div>
              </div>
            </ThemeProvider>
          );
        }
        ```
      </Step>

      <Step title="Run the app">
        ```bash theme={null}
        export THESYS_API_KEY=<your-api-key>
        npm run dev
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>

<Card title="View the code" icon="github" href="https://github.com/thesysdev/examples/tree/main/vercel-ai-sdk">
  Find more examples and complete code on our GitHub repository.
</Card>
