Note that for any of the window.duet functions to work, you must wait until the primary <script> is loaded. Consult the intro guide to see how to do that.

Passing in Metadata

If you want to send arbitrary metadata (e.g. other details about the user), you may call window.duet.setMetadata({...}). For example:

window.duet.setMetadata({
  email: "joe@example.com",
  username: "Zezima",
  fullName: "Joe Smith",
  isTrial: true,
  points: 6,
  token: "<jwt_token>",
  // any fields that you want
});

Note that you may pass in user tokens with the special token field, which will be redacted when stored in the database.

Additionally, you can configure the LLM that the agent uses by specifying a special model field. Set it to one of:

gpt-4
gpt-4o
gpt-4o-mini
gpt-4-turbo
o1-mini
o1-preview-2024-09-12
claude-3.5-haiku
claude-3.5-sonnet

You may call setMetadata multiple times if you’d like but know that each time you call it, the metadata will be set to exactly what you pass in. So if you drop fields in subsequent calls, they will be removed from the metadata. This is to give you control over deleting fields if you want to.

Tracking events

If you want to track events, you may set a listener via window.duet.setEventListener so that your callback is called every time there is a meaningful user action.

For example:

window.duet.setEventListener((event) => console.log(event));
// Here, `event` is of the form {eventName: "DUET_INITIALIZE"}

Here are the events we currently support:

  • User clicks the icon to open a chatbot window:

    {eventName: "DUET_INITIALIZE"}

  • User closes the chatbot window: {eventName: "DUET_DEINITIALIZE"}

  • User begins typing:

    {eventName: "DUET_USER_INPUT"}

  • User sends a message:

    {eventName: "DUET_USER_SEND"}

  • Bot responds:

    {eventName: "DUET_RESPONSE"}

Dynamically opening/closing the widget

This should rarely be needed, but you can dynamically open/close the widget using these functions:

// Open the widget
window.duet.open()

// Close the widget
window.duet.close()

Optionally, you may also specify that when the widget is closed, it should be hidden. Note that this will not affect the widget when it is open. You can toggle the hidden mode like so:

// Enable hidden mode
window.duet.hide()

// Disable hidden mode
window.duet.unhide()

Send a proactive message (or set the welcome message)

Use this to customize the initial message in a new conversation with a user. Set the 2nd argument to try if you want to trigger a proactive message bubble above the chat widget to invite the user to chat. The message will them appear as the welcome message in the chat when the widget is opened.

// Send a proactive trigger message
window.duet.setTriggerMessage("Hi there! It seems like you need help with...", true)

// Just customize the welcome message
window.duet.setTriggerMessage("Welcome to Apple Support! ...")

Pre-populate the initial message for the user

If you want to pre-populate a message in the user’s input box (for example, if they are coming from another product flow), you may use the following command.

window.duet.setInitialUserMessage("Hi I have an issue with...");

Setting a Metadata Request Callback

The window.duet.setMetadataRequestListener function allows you to handle metadata requests dynamically by setting a callback function. This function is called whenever there’s a need to fetch and return metadata based on specific criteria or actions within the widget.

API Definition:

window.duet.setMetadataRequestListener(function(callback)): Registers a callback function that will be invoked with two arguments: payload and callback. The payload object contains the details of the metadata request, and the callback function is used to return the response to the widget.

Usage:

You can set a callback function that will be executed to handle data requests. The callback receives two arguments: a payload object that contains details about the request, and a callback function to send the response back to the widget.

Example:

Here’s how you can set up a listener for metadata requests related to user orders:

window.duet.setMetadataRequestListener(async (payload, callback) => {
  const { subtype, params } = payload;
  if (subtype === "orders") {
    const orderId = params.orderId;
    const response = await fetch(
      `https://api.company.com/user/orders/${orderId}`,
      {
        method: "GET",
        credentials: "include",
      }
    );

    if (!response.ok) {
      callback({ ok: false, status: response.status });
    } else {
      const data = await response.json();
      callback({ orders: data.orders, ok: true });
    }
  }
});

This function listens for a subtype of ‘orders’ in the metadata request. If detected, it fetches the order details from a specified URL. The fetched data is then returned via the callback function, where the orders key contains the data retrieved and ok indicates the success status of the operation.

This allows you to set “metadata requests” so that the AI can make requests through your frontend. In the example, Decagon asks for “orders”. Your frontend can then make the request to the relevant endpoint for orders (using your existing auth framework) and then just pass the response back to Decagon. You can create as many subtypes as you want.