In a Generative UI application, you can build interactive components that allow users to interact with the UI beyond just text input. For example, lets say we are building a search app that allows users to search for companies.

After the search results are generated, we instruct C1 via a prompt to also generate two buttons: “Products” and “Locations”.

  • If the user clicks on the “Products” button, we want to show a list of products the company offers.
  • If the user clicks on the “Locations” button, we want to show a list of locations the company has.

Conceptual Overview

At a high level, the interaction between the user and the backend is as follows:

  1. User clicks on the “Products” button.
  2. The system invokes the onAction callback with 2 arguments: llmFriendlyMessage and humanFriendlyMessage.
    • The llmFriendlyMessage is the text that will be sent to the backend to fetch the products.
    • The humanFriendlyMessage is the text that will can be shown to the user if needed.
  3. UI makes a call to the backend with the llmFriendlyMessage and previousMessages that contains the current state of the UI.
    The current state of the UI is helpful for the LLM to understand the context of the user’s request. For example, lets say the user has already searched for apple.com and clicked on the Products button. Given this context, the LLM can use this information to fetch Products for apple.com.
  4. The backend will generate a response and send it back to the frontend.
  5. The frontend will update the UI with the new response which contains the products or locations based on what the user clicked on.
  6. The new generation might again contain more buttons or forms and this process continues.

Implementation

This guide will show you how to build this interactive component.

1

Add buttons to the Generated UI

src/api/route.tsx

const runToolsResponse = client.beta.chat.completions.runTools({
  ...
  messages: [
    {
      role: "system",
      content: `You are a business research assistant just like crunchbase. You answer questions about a company or domain.
given a company name or domain, you will search the web for the latest information.

At the end of your response, add two buttons: "Products" and "Locations" that show a list of products and locations for the given company.
`,
    },
    ...previousMessages,
  ],
  ...
})
2

Add a button handler

Pass in the onAction callback to the C1Component. This callback will be called when the user clicks on the button. The argument to the callback is an object with two properties: llmFriendlyMessage and humanFriendlyMessage where

  • llmFriendlyMessage is the text that will be sent to the backend to fetch the products
  • humanFriendlyMessage is the text that will can be shown to the user (if needed, for example in chatbots)
src/app/page.tsx
const [c1Response, setC1Response] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
...
  <C1Component
    c1Response={c1Response}
    isStreaming={isLoading}
    onAction={({ llmFriendlyMessage }) => {
      ...
    }}
  />
...
3

Call the backend endpoint and update the UI with the response

src/app/page.tsx
...
  <C1Component
    c1Response={c1Response}
    isStreaming={isLoading}
    onAction={({ llmFriendlyMessage }) => {
      if (!isLoading) {
        // Make a call to the backend with the llmFriendlyMessage and
        // current state of the UI.
        makeApiCall(llmFriendlyMessage, c1Response);
      }
    }}
  />
...