Tutorials
  • Tutorials
  • Set up your Agent
    • Set Up Your Agent Step by Step.
    • Create your Knowledge Base Step by Step.
    • Connect your RSS or Newsletter
  • Writing Clear and Effective Instructions
  • Integrations
    • Web
    • WhatsApp
    • Email
    • Telegram
    • Wordpress
    • Framer
    • API
    • Shopify
    • Slack
    • Webhook
    • Google Chat
  • Campaings
    • WhatsApp Campaigns
  • Alerts
    • Create an Alert
  • Tools
    • Create a Tool
  • Widgets
    • Web Widgets Documentation
  • Human Intervetion
    • How it works?
  • faq
    • How do I make my subscription payment and manage my invoices?
Powered by GitBook
On this page
  • Introduction
  • How does the LLM interact with widgets?
  • How to setup each default widget
  • Widget Form Fields
  • Create a Custom Widget
  1. Widgets

Web Widgets Documentation

How to create Widgets

PreviousCreate a ToolNextHow it works?

Last updated 1 month ago

Introduction

Widgets enhance the chat experience by allowing users to interact with rich, visual elements such as charts, forms, or interactive cards directly within the conversation. This is especially useful in cases where plain text isn't enough to convey complex information or guide a user through a task.

By integrating visual and interactive components, widgets improve usability and streamline workflows, making it easier for users to understand, explore, and act on information without leaving the chat.

One use case would be displaying a personalized calendar to check someone's availability and quickly and easily book an appointment or meeting.

There are two types of widgets:

  • Default: These are already configured to render specific information with easy implementation.

  • Advanced: These allow you to configure a widget from scratch for a specific need, giving you full control.

The key difference between predefined widgets and advanced widgets lies in how they're created. Predefined widgets come with built-in basic functionality, often requiring little to no additional setup. In contrast, advanced widgets offer complete flexibility, allowing you to define their functionality entirely based on how you configure them.


How does the LLM interact with widgets?

Widgets are designed to be dynamically rendered based on the information provided by the LLM. The LLM is always aware of which widgets are available and when to invoke them.

The process is the following:

  1. A widget is created with the necessary information to be rendered. This information may include data provided by the LLM if needed, specifically within the config and parameters sections.

  2. The LLM adds the widget’s identifier (as defined in its file) to the context and uses the widget's description to determine when it should be invoked for rendering.

  3. Once the widget is triggered, it will be displayed—either using additional data supplied by the LLM if required, or simply with its predefined configuration if no extra information is needed.

  4. When required, the LLM uses available to gather and provide data to the widget. For example, it may call an API endpoint and use the response to dynamically populate the widget with relevant information.

Note: This process is only possible if the web plugin is available.


How to setup each default widget

In this section, we will explore what each default widget does, how to configure it, and how it interacts with the agent. Each default widget is designed to address a specific need in a general way, with easy configuration.

Calendly

This widget allows you to display a Calendly calendar to book meetings or appointments based on the Calendly profile link attached to the widget.

The fields that need to be configured are:

  • Description: Describe to the agent when this widget will be displayed in the chat.

Sequence process:

  1. A widget will be created with description and configuration fields, which will include a URL.

  2. The LLM will retrieve this information and call the widget when needed, based on the provided description.

  3. The widget will be rendered via the URL in the configuration, but only if a web plugin is available. The widget does not function on WhatsApp

The LLM will retrieve the URL inserted through companion.widgetConfig?.url

Maps

This widget allows displaying a location on an interactive map (previously configured in the LLM instruction prompt) when the location is requested in the chat.

No fields is required, it is created directly.

Sequence process:

  1. The widget will be created with a parameter that initially has no value, which will later interact with a URL.

  2. The LLM will contain the URL information to be displayed and will call the widget as needed. This URL has to be the following structure: https://www.google.com/maps?q=LAT,LONG&z=15&output=embed and change the Latitude and Longitude.

  1. Once the widget is called, it will render the widget with the map by embedding the URL as the value of the configured parameter, but only if a web plugin is available. The widget does not function on WhatsApp.

The LLM will call the widget, embedding the value in the parameter through: companion.widgetProps?.map_url

Image Gallery

This widget displays an image carousel that has been previously configured in the LLM prompt, which will insert it into the widget. There are no required fields, the widget will be created directly.

Sequence process:

  1. A widget is initialized with a parameter that is initially empty.

  2. The LLM generates a comma-separated list of image URLs based on a tool response when its called and passes this list to the widget as the parameter value.

  3. Once the widget receives the parameter, it renders a carousel displaying the images.

The LLM will call the widget, embedding the value in the parameter through: companion.widgetProps?.images

Typeform

This widget displays a Typeform form embedded via a provided URL, which has been previously configured in the LLM prompt and will be inserted into the widget.

The fields that need to be configured are:

  • Description: Describe to the agent when this widget will be displayed in the chat.

Sequence process:

  1. The widget will be created with description and configuration fields, which will include the Typeform URL.

  2. The LLM will retrieve this information and call the widget when needed, based on the provided description and LLM instruction.

  3. The widget will be rendered via the URL in the configuration, but only if a web plugin is available.

The LLM will retrieve the URL inserted through companion.widgetConfig?.url

Product Catalog

This widget renders a product catalog based on information provided by the LLM. It is fully customizable, allowing you to choose which information to display and how to style it—by default, it adopts the color scheme of the configured chatbot. The fields that need to be configured are:

  • Display Properties: Select what key information you want to display and whether those properties need to be renamed.

  • In Page Navigation: Decide whether you want to browse through the products on the page or open them in a new browser tab.

  • Style Properties: Set the colors the widget should use to match the desired appearance. By default, it uses the colors from the configured web plugin.

  • Description: Describe to the agent when this widget will be displayed in the chat.

Sequence process:

  1. The widget will be created with the required fields in its configuration, and additionally, a "products" parameter will be automatically assigned. This parameter will not have an initial value but will contain the information of the products to be displayed in the catalog.

  2. In the LLM prompt, the product widget will be called according to the required condition..

  3. When the widget is called, a tool will also be triggered beforehand, which will return the list of products to be rendered. This list will be assigned to the "products" parameter.

  4. When the widget is rendered, it will use the information from the "products" parameter to display the product catalog.


Widget Form Fields

  • Widget File: The required file that will render the widget with the code configured inside.

  • Name: The widget name that will be automatically introduced by the widget file attached

  • Description: The text that will detect the agent to invoke the widget when it will be requested

  • Location Selector: How the widget will be shown in the chat

    • Dialog: The widget will be shown in a pop up window inside the conversation

    • Page: The widget will be displayed in a chat window, within the full size of the web plugin

    • Bottom Sheet: The widget will be shown at the bottom of conversation as a overlaid box

    • Under Related Message: The widget will be shown inside of a chat message given by the agent response

  • Trigger Selector: When the widget is going to be displayed

    • Eager: The widget is going to be displayed instantly

    • Input Field: The widget is going to be displayed when click in a input button

    • Floating Action Button: The widget will be open clicking on a floating button at the bottom of the chat

    • In Message Action: The widget is going to be displayed when click in a message button

  • Configuration: Properties are created to provide additional information to the widget that modifies its behavior or display, allowing customization as desired using a key-value structure.

(Example: A property is created to provide a URL that the widget requires to be rendered based on that URL.)

  • Parameters: Objects with a predefined structure are created, which the widget will use to render the information based on their content. The widget will show this information when it is called. The object consists of:

    • Type: Select the value type that will have the parameter (STRING , BOOLEAN, INTEGER, FLOAT)

    • Name: The key name that will have the parameter

    • Description: The text that will say when the parameter will be used

    • Default Value: The initialized value that the parameter has when the is called

    • Required: Determine if the default value is mandatory or not.

(Example: When you want to render a product widget and display additional details not included in the widget file, the parameters will display those extra details.)


Create a Custom Widget

This section will explain how to create an advanced widget step by step, what its data structure is like, and what the relationship is between the LLM and the widget.

1

Create the Widget File

To start creating a widget, we first need to configure or create the file that will contain all the logic and code for the widget we want to render. This would be the basic structure of the code we’ll need:

import { React, ReactDOM } from "<https://cdn.skypack.dev/es-react@16.13.1>";
import htm from "<https://cdn.jsdelivr.net/npm/htm@3.1.1/dist/htm.module.js>";
const html = htm.bind(React.createElement);

const WidgetComponent= ({ companion }) => {
  return html``;
};

function renderWidget(companion) {
  ReactDOM.render(
    html`<${WidgetComponent} companion=${companion} />`,
    window.loader.container()
  );
}

function unrenderWidget() {
  ReactDOM.render("", window.loader.container());
}

window.loader.register("widget_name", renderWidget, unrenderWidget);

Now let's go through each part of the code and explain what it is and what its functionality is.

  • Importing React and ReactDOM:

    The code imports React and ReactDOM from a CDN using the es-react package, which offers lightweight React bindings ideal for embedding widgets.

  • Importing HTM:

    The htm library is imported, allowing the use of HTML-like syntax in JavaScript without requiring JSX or a build process.

  • Binding HTM to React:

    htm is bound to React.createElement, enabling the use of tagged template literals to write React components in a cleaner and more flexible way.

This file is not tied to any specific framework—you can use any JavaScript framework or library to build your widget. React is just one example.

import { React, ReactDOM } from "<https://cdn.skypack.dev/es-react@16.13.1>";
import htm from "<https://cdn.jsdelivr.net/npm/htm@3.1.1/dist/htm.module.js>";
const html = htm.bind(React.createElement);

In this block of code, we define the component or function that will contain the information and logic for what we want to render. In this case, it will render a card with the name of a car, its image, and several details related to that car.

Access to the config and parameters info is available via companion prop, enabling extension of the code implementation as needed.

  • To access config, use companion.widgetConfig?.property_name

  • To access parameters, use companion.widgetProps?.parameter_name

/*
//Base Component 

const WidgetComponent= ({ companion }) => {
  return html``;
};

*/

const CarWidget = ({ companion }) => {

// Use case with a config property to enter the name car in widgets page
const carName = companion.widgetConfig?.car_name
const carInfo = companion.widgetProps?.car_info

/* 
car_info = `{
  "engine": "2.3L EcoBoost® Engine with 315 HP",
  "additionalInfo": "Selectable Drive Modes",
  "features": "12.4” Digital Instrument Cluster and 13.2” Touchscreen" 
}`

*/

  return html`
    <div
      style=${{
        display: "flex",
        flexDirection: "column",
        justifyContent: "flex-start",
        alignItems: "center",
        width: "400px",
        boxShadow: "0px 4px 8px rgba(0, 0, 0, 0.1)",
        backgroundColor: "whitesmoke",
        borderRadius: "12px",
      }}
    >
      <p style=${{ fontSize: "2rem" }}>${carName || "Ford Mustang"}</p>

      <div style=${{ width: "100%", objectFit: "contain" }}>
        <img
          style=${{ width: "100%" }}
          src="<https://www.vdm.ford.com/content/dam/na/ford/en_us/images/mustang/2025/jellybeans/Ford_Mustang_2025_100A_PYZ_88D_89W_13A_COU_64F_99H_44U_EBST_DEFAULT_EXT_4.png>"
        />
      </div>

      <div
        style=${{
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          gap: "6px",
          maxWidth: "90%",
          textAlign: "center",
        }}
      >
        <p style=${{ margin: 0 }}>${carInfo.engine}</p>
        <p style=${{ margin: 0 }}>${carInfo.additionalInfo}</p>
        <p style=${{ margin: 0 }}>${carInfo.features}</p>
      </div>
    </div>
  `
}

This block of code has renderWidget function that is responsible for rendering the widget into the DOM.

  • It receives a companion object as a parameter, which contains the data that will be passed to the widget.

  • Inside the function, ReactDOM.render() is used to render the WidgetComponent and inject it into the DOM element returned by window.loader.container().

  • The companion object is passed as a prop to the WidgetComponent, allowing it to use that data when rendering its content.

function renderWidget(companion) {
  ReactDOM.render(
    html`<${CarWidget} companion=${companion} />`,
    window.loader.container()
  )
}

The unrenderWidget function is responsible for removing the rendered widget from the DOM.

  • It uses ReactDOM.render() to render an empty string (""), which essentially removes the existing content inside the container.

  • The second argument, window.loader.container(), specifies the DOM element where the widget was originally rendered. This ensures that the content is removed from the same location.

function unrenderWidget() {
  ReactDOM.render("", window.loader.container())
}

This method window.loader.register is used to register the widget with a loader, allowing it to be managed dynamically (e.g., shown or removed based on some conditions).

  • "show_car": This is the name or identifier for the widget. It's essentially a label that the loader will use to recognize and manage this widget.

  • renderWidget: This is the function that will be called when the widget needs to be rendered (i.e., displayed on the page). It contains the logic to inject the widget into the DOM.

  • unrenderWidget: This is the function that will be called when the widget needs to be removed from the page. It contains the logic to clear the widget from the DOM.

window.loader.register("show_car", renderWidget, unrenderWidget)
2

Complete the required fields

When a valid JavaScript file for the widget has been attached, an input field will appear displaying the identifier name of the widget that has been configured in the file:

Now, you need to write a description of the widget, which will explain when it will be invoked by the agent.

Prompt examples for description:

  • When the user is interested in Ford Mustang car call this widget

  • When user shows interest in booking a meet call this widget

  • When user ask for a location call this widget

Also, select the modes for how the widget will be displayed (Location Selector) and how the widget will be opened (Trigger Selector), with the option to hide the trigger if desired.

3

(Optional) - Add extra information

And as the last step, if desired, extra information can be added in Config and Parameters, which will enhance the widget's potential according to the needs.

Once the widget has been successfully created, you can interact with the agent, and depending on how it's configured, it will call the widget whenever it's needed in the conversation:

When a widget is created has the following structure:

{
  "id": "abc-abc-abc-abc-abc",
  "created": "2025-04-03T07:15:31.286405Z",
  "modified": "2025-04-03T07:15:31.286405Z",
  "parent": "message",
  "trigger": "ima",
  "source": "https://file-in-cloud.com",
  "description": "When this widget is going to be used",
  "name": "widget_name",
  "config": {
    "car_name": "Ford Mustang",
  },
  "parameters": {
   "car_info": {
      "id": "abc-abc-abc-abc-abc",
      "key": "car_info",
      "type": "string",
      "default": "",
      "required": false,
      "placement": "data",
      "properties": {},
      "description": "The info of the car"
    }
  },
  "active": null,
  "project": "abc-abc-abc-abc-abc",
  "user": "abc-abc-abc-abc-abc"
}
interface Widget {
  id: string;
  created: string;
  modified: string;
  parent: "message" | "dialog" | "sheet" | "page";
  trigger: "eager" | "ima" | "input" | "fab";
  source: File; // File attached as FormData
  description: string;
  name: string;
  config: null | Record<string, unknown>; // Transform to JSON
  parameters: null | Record<string, { // Transform to JSON
    id: string;
    key: string;
    type: "string" | "boolean" | "integer" | "float";
    required: null | string | number | boolean;
    placement: "data";
    properties: {};
    description: string;
    default: string;
  }>;
  active: null;
  project: string;
  user: string;
}
  • id: Unique widget identifier, automatically assigned by the Caleida API.

  • created: The timestamp indicating when the widget was initially created. Set automatically by the Caleida API.

  • modified: The timestamp of the most recent update to the widget, also set automatically by the Caleida API.

  • parent (Location Selector): Specifies how and where the widget will appear when invoked.

  • trigger (Trigger Selector): Defines the mechanism or event that opens the widget.

  • source (Widget File): The uploaded file containing the widget's rendering code.

  • description: A text prompt that helps the agent determine when to invoke the widget.

  • name: The name of the widget, automatically extracted from the attached widget file.

  • config: A list of properties that provide additional metadata or settings for the widget.

  • parameters: A list of objects used to supply additional contextual information when the widget is triggered.

  • active: Indicates whether the widget is currently active or not.

  • project: Identifier of the project where the widget was created; set automatically by the Caleida API.

  • user: Identifier of the user who created the widget; also automatically set by the Caleida API.

URL: This sets the link to the Calendly calendar that will be displayed. For example:

Prompt Example: Use this URL: when asking about the location of Plaza de España in Seville.

URL: This sets the link to the Typeform form that will be displayed. For example: xampleID

Tools
https://calendly.com/example-profile
https://www.google.com/maps?q=37.3770029,-5.989754&z=15&output=embed
https://form.typeform.com/to/e